msi: Read the disk prompt source list property from the user-unmanaged context.
[wine.git] / dlls / inetcomm / mimeole.c
blobe986e7fa6125cc12db22a7e5e08488cb456522e6
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 MimeBody *This = impl_from_IMimeBody(iface);
631 TRACE("(%p)->(%s, %d, %p)\n", This, pszName, dwFlags, pValue);
633 if(!strcasecmp(pszName, "att:pri-content-type"))
635 PropVariantClear(pValue);
636 pValue->vt = VT_LPSTR;
637 pValue->u.pszVal = strdupA(This->content_pri_type);
638 return S_OK;
641 FIXME("stub!\n");
642 return E_FAIL;
645 static HRESULT WINAPI MimeBody_SetProp(
646 IMimeBody* iface,
647 LPCSTR pszName,
648 DWORD dwFlags,
649 LPCPROPVARIANT pValue)
651 FIXME("stub\n");
652 return E_NOTIMPL;
655 static HRESULT WINAPI MimeBody_AppendProp(
656 IMimeBody* iface,
657 LPCSTR pszName,
658 DWORD dwFlags,
659 LPPROPVARIANT pValue)
661 FIXME("stub\n");
662 return E_NOTIMPL;
665 static HRESULT WINAPI MimeBody_DeleteProp(
666 IMimeBody* iface,
667 LPCSTR pszName)
669 FIXME("stub\n");
670 return E_NOTIMPL;
673 static HRESULT WINAPI MimeBody_CopyProps(
674 IMimeBody* iface,
675 ULONG cNames,
676 LPCSTR* prgszName,
677 IMimePropertySet* pPropertySet)
679 FIXME("stub\n");
680 return E_NOTIMPL;
683 static HRESULT WINAPI MimeBody_MoveProps(
684 IMimeBody* iface,
685 ULONG cNames,
686 LPCSTR* prgszName,
687 IMimePropertySet* pPropertySet)
689 FIXME("stub\n");
690 return E_NOTIMPL;
693 static HRESULT WINAPI MimeBody_DeleteExcept(
694 IMimeBody* iface,
695 ULONG cNames,
696 LPCSTR* prgszName)
698 FIXME("stub\n");
699 return E_NOTIMPL;
702 static HRESULT WINAPI MimeBody_QueryProp(
703 IMimeBody* iface,
704 LPCSTR pszName,
705 LPCSTR pszCriteria,
706 boolean fSubString,
707 boolean fCaseSensitive)
709 FIXME("stub\n");
710 return E_NOTIMPL;
713 static HRESULT WINAPI MimeBody_GetCharset(
714 IMimeBody* iface,
715 LPHCHARSET phCharset)
717 FIXME("stub\n");
718 *phCharset = NULL;
719 return S_OK;
722 static HRESULT WINAPI MimeBody_SetCharset(
723 IMimeBody* iface,
724 HCHARSET hCharset,
725 CSETAPPLYTYPE applytype)
727 FIXME("stub\n");
728 return E_NOTIMPL;
731 static HRESULT WINAPI MimeBody_GetParameters(
732 IMimeBody* iface,
733 LPCSTR pszName,
734 ULONG* pcParams,
735 LPMIMEPARAMINFO* pprgParam)
737 MimeBody *This = impl_from_IMimeBody(iface);
738 HRESULT hr;
739 header_t *header;
741 TRACE("(%p)->(%s, %p, %p)\n", iface, debugstr_a(pszName), pcParams, pprgParam);
743 *pprgParam = NULL;
744 *pcParams = 0;
746 hr = find_prop(This, pszName, &header);
747 if(hr != S_OK) return hr;
749 *pcParams = list_count(&header->params);
750 if(*pcParams)
752 IMimeAllocator *alloc;
753 param_t *param;
754 MIMEPARAMINFO *info;
756 MimeOleGetAllocator(&alloc);
758 *pprgParam = info = IMimeAllocator_Alloc(alloc, *pcParams * sizeof(**pprgParam));
759 LIST_FOR_EACH_ENTRY(param, &header->params, param_t, entry)
761 int len;
763 len = strlen(param->name) + 1;
764 info->pszName = IMimeAllocator_Alloc(alloc, len);
765 memcpy(info->pszName, param->name, len);
766 len = strlen(param->value) + 1;
767 info->pszData = IMimeAllocator_Alloc(alloc, len);
768 memcpy(info->pszData, param->value, len);
769 info++;
771 IMimeAllocator_Release(alloc);
773 return S_OK;
776 static HRESULT WINAPI MimeBody_IsContentType(
777 IMimeBody* iface,
778 LPCSTR pszPriType,
779 LPCSTR pszSubType)
781 MimeBody *This = impl_from_IMimeBody(iface);
783 TRACE("(%p)->(%s, %s)\n", This, debugstr_a(pszPriType), debugstr_a(pszSubType));
784 if(pszPriType)
786 const char *pri = This->content_pri_type;
787 if(!pri) pri = "text";
788 if(strcasecmp(pri, pszPriType)) return S_FALSE;
791 if(pszSubType)
793 const char *sub = This->content_sub_type;
794 if(!sub) sub = "plain";
795 if(strcasecmp(sub, pszSubType)) return S_FALSE;
798 return S_OK;
801 static HRESULT WINAPI MimeBody_BindToObject(
802 IMimeBody* iface,
803 REFIID riid,
804 void** ppvObject)
806 FIXME("stub\n");
807 return E_NOTIMPL;
810 static HRESULT WINAPI MimeBody_Clone(
811 IMimeBody* iface,
812 IMimePropertySet** ppPropertySet)
814 FIXME("stub\n");
815 return E_NOTIMPL;
818 static HRESULT WINAPI MimeBody_SetOption(
819 IMimeBody* iface,
820 const TYPEDID oid,
821 LPCPROPVARIANT pValue)
823 FIXME("(%p)->(%08x, %p): stub\n", iface, oid, pValue);
824 return E_NOTIMPL;
827 static HRESULT WINAPI MimeBody_GetOption(
828 IMimeBody* iface,
829 const TYPEDID oid,
830 LPPROPVARIANT pValue)
832 FIXME("(%p)->(%08x, %p): stub\n", iface, oid, pValue);
833 return E_NOTIMPL;
836 static HRESULT WINAPI MimeBody_EnumProps(
837 IMimeBody* iface,
838 DWORD dwFlags,
839 IMimeEnumProperties** ppEnum)
841 FIXME("stub\n");
842 return E_NOTIMPL;
845 static HRESULT WINAPI MimeBody_IsType(
846 IMimeBody* iface,
847 IMSGBODYTYPE bodytype)
849 FIXME("(%p)->(%d): stub\n", iface, bodytype);
850 return E_NOTIMPL;
853 static HRESULT WINAPI MimeBody_SetDisplayName(
854 IMimeBody* iface,
855 LPCSTR pszDisplay)
857 FIXME("stub\n");
858 return E_NOTIMPL;
861 static HRESULT WINAPI MimeBody_GetDisplayName(
862 IMimeBody* iface,
863 LPSTR* ppszDisplay)
865 FIXME("stub\n");
866 return E_NOTIMPL;
869 static HRESULT WINAPI MimeBody_GetOffsets(
870 IMimeBody* iface,
871 LPBODYOFFSETS pOffsets)
873 MimeBody *This = impl_from_IMimeBody(iface);
874 TRACE("(%p)->(%p)\n", This, pOffsets);
876 *pOffsets = This->body_offsets;
878 if(This->body_offsets.cbBodyEnd == 0) return MIME_E_NO_DATA;
879 return S_OK;
882 static HRESULT WINAPI MimeBody_GetCurrentEncoding(
883 IMimeBody* iface,
884 ENCODINGTYPE* pietEncoding)
886 MimeBody *This = impl_from_IMimeBody(iface);
888 TRACE("(%p)->(%p)\n", This, pietEncoding);
890 *pietEncoding = This->encoding;
891 return S_OK;
894 static HRESULT WINAPI MimeBody_SetCurrentEncoding(
895 IMimeBody* iface,
896 ENCODINGTYPE ietEncoding)
898 MimeBody *This = impl_from_IMimeBody(iface);
900 TRACE("(%p)->(%d)\n", This, ietEncoding);
902 This->encoding = ietEncoding;
903 return S_OK;
906 static HRESULT WINAPI MimeBody_GetEstimatedSize(
907 IMimeBody* iface,
908 ENCODINGTYPE ietEncoding,
909 ULONG* pcbSize)
911 FIXME("stub\n");
912 return E_NOTIMPL;
915 static HRESULT WINAPI MimeBody_GetDataHere(
916 IMimeBody* iface,
917 ENCODINGTYPE ietEncoding,
918 IStream* pStream)
920 FIXME("stub\n");
921 return E_NOTIMPL;
924 static HRESULT WINAPI MimeBody_GetData(
925 IMimeBody* iface,
926 ENCODINGTYPE ietEncoding,
927 IStream** ppStream)
929 MimeBody *This = impl_from_IMimeBody(iface);
930 FIXME("(%p)->(%d, %p). Ignoring encoding type.\n", This, ietEncoding, ppStream);
932 *ppStream = This->data;
933 IStream_AddRef(*ppStream);
934 return S_OK;
937 static HRESULT WINAPI MimeBody_SetData(
938 IMimeBody* iface,
939 ENCODINGTYPE ietEncoding,
940 LPCSTR pszPriType,
941 LPCSTR pszSubType,
942 REFIID riid,
943 LPVOID pvObject)
945 MimeBody *This = impl_from_IMimeBody(iface);
946 TRACE("(%p)->(%d, %s, %s, %s %p)\n", This, ietEncoding, debugstr_a(pszPriType), debugstr_a(pszSubType),
947 debugstr_guid(riid), pvObject);
949 if(IsEqualIID(riid, &IID_IStream))
950 IStream_AddRef((IStream *)pvObject);
951 else
953 FIXME("Unhandled object type %s\n", debugstr_guid(riid));
954 return E_INVALIDARG;
957 if(This->data)
958 FIXME("release old data\n");
960 This->data_iid = *riid;
961 This->data = pvObject;
963 IMimeBody_SetCurrentEncoding(iface, ietEncoding);
965 /* FIXME: Update the content type.
966 If pszPriType == NULL use 'application'
967 If pszSubType == NULL use 'octet-stream' */
969 return S_OK;
972 static HRESULT WINAPI MimeBody_EmptyData(
973 IMimeBody* iface)
975 FIXME("stub\n");
976 return E_NOTIMPL;
979 static HRESULT WINAPI MimeBody_CopyTo(
980 IMimeBody* iface,
981 IMimeBody* pBody)
983 FIXME("stub\n");
984 return E_NOTIMPL;
987 static HRESULT WINAPI MimeBody_GetTransmitInfo(
988 IMimeBody* iface,
989 LPTRANSMITINFO pTransmitInfo)
991 FIXME("stub\n");
992 return E_NOTIMPL;
995 static HRESULT WINAPI MimeBody_SaveToFile(
996 IMimeBody* iface,
997 ENCODINGTYPE ietEncoding,
998 LPCSTR pszFilePath)
1000 FIXME("stub\n");
1001 return E_NOTIMPL;
1004 static HRESULT WINAPI MimeBody_GetHandle(
1005 IMimeBody* iface,
1006 LPHBODY phBody)
1008 MimeBody *This = impl_from_IMimeBody(iface);
1009 TRACE("(%p)->(%p)\n", iface, phBody);
1011 *phBody = This->handle;
1012 return This->handle ? S_OK : MIME_E_NO_DATA;
1015 static IMimeBodyVtbl body_vtbl =
1017 MimeBody_QueryInterface,
1018 MimeBody_AddRef,
1019 MimeBody_Release,
1020 MimeBody_GetClassID,
1021 MimeBody_IsDirty,
1022 MimeBody_Load,
1023 MimeBody_Save,
1024 MimeBody_GetSizeMax,
1025 MimeBody_InitNew,
1026 MimeBody_GetPropInfo,
1027 MimeBody_SetPropInfo,
1028 MimeBody_GetProp,
1029 MimeBody_SetProp,
1030 MimeBody_AppendProp,
1031 MimeBody_DeleteProp,
1032 MimeBody_CopyProps,
1033 MimeBody_MoveProps,
1034 MimeBody_DeleteExcept,
1035 MimeBody_QueryProp,
1036 MimeBody_GetCharset,
1037 MimeBody_SetCharset,
1038 MimeBody_GetParameters,
1039 MimeBody_IsContentType,
1040 MimeBody_BindToObject,
1041 MimeBody_Clone,
1042 MimeBody_SetOption,
1043 MimeBody_GetOption,
1044 MimeBody_EnumProps,
1045 MimeBody_IsType,
1046 MimeBody_SetDisplayName,
1047 MimeBody_GetDisplayName,
1048 MimeBody_GetOffsets,
1049 MimeBody_GetCurrentEncoding,
1050 MimeBody_SetCurrentEncoding,
1051 MimeBody_GetEstimatedSize,
1052 MimeBody_GetDataHere,
1053 MimeBody_GetData,
1054 MimeBody_SetData,
1055 MimeBody_EmptyData,
1056 MimeBody_CopyTo,
1057 MimeBody_GetTransmitInfo,
1058 MimeBody_SaveToFile,
1059 MimeBody_GetHandle
1062 static HRESULT MimeBody_set_offsets(MimeBody *body, const BODYOFFSETS *offsets)
1064 TRACE("setting offsets to %d, %d, %d, %d\n", offsets->cbBoundaryStart,
1065 offsets->cbHeaderStart, offsets->cbBodyStart, offsets->cbBodyEnd);
1067 body->body_offsets = *offsets;
1068 return S_OK;
1071 #define FIRST_CUSTOM_PROP_ID 0x100
1073 HRESULT MimeBody_create(IUnknown *outer, void **obj)
1075 MimeBody *This;
1076 BODYOFFSETS body_offsets;
1078 *obj = NULL;
1080 if(outer) return CLASS_E_NOAGGREGATION;
1082 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1083 if (!This) return E_OUTOFMEMORY;
1085 This->lpVtbl = &body_vtbl;
1086 This->refs = 1;
1087 This->handle = NULL;
1088 list_init(&This->headers);
1089 list_init(&This->new_props);
1090 This->next_prop_id = FIRST_CUSTOM_PROP_ID;
1091 This->content_pri_type = NULL;
1092 This->content_sub_type = NULL;
1093 This->encoding = IET_7BIT;
1094 This->data = NULL;
1095 This->data_iid = IID_NULL;
1097 body_offsets.cbBoundaryStart = body_offsets.cbHeaderStart = 0;
1098 body_offsets.cbBodyStart = body_offsets.cbBodyEnd = 0;
1099 MimeBody_set_offsets(This, &body_offsets);
1101 *obj = (IMimeBody *)&This->lpVtbl;
1102 return S_OK;
1105 typedef struct
1107 IStreamVtbl *lpVtbl;
1108 LONG refs;
1110 IStream *base;
1111 ULARGE_INTEGER pos, start, length;
1112 } sub_stream_t;
1114 static inline sub_stream_t *impl_from_IStream( IStream *iface )
1116 return (sub_stream_t *)((char*)iface - FIELD_OFFSET(sub_stream_t, lpVtbl));
1119 static HRESULT WINAPI sub_stream_QueryInterface(
1120 IStream* iface,
1121 REFIID riid,
1122 void **ppvObject)
1124 sub_stream_t *This = impl_from_IStream(iface);
1126 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
1127 *ppvObject = NULL;
1129 if(IsEqualIID(riid, &IID_IUnknown) ||
1130 IsEqualIID(riid, &IID_ISequentialStream) ||
1131 IsEqualIID(riid, &IID_IStream))
1133 IStream_AddRef(iface);
1134 *ppvObject = iface;
1135 return S_OK;
1137 return E_NOINTERFACE;
1140 static ULONG WINAPI sub_stream_AddRef(
1141 IStream* iface)
1143 sub_stream_t *This = impl_from_IStream(iface);
1145 TRACE("(%p)\n", This);
1146 return InterlockedIncrement(&This->refs);
1149 static ULONG WINAPI sub_stream_Release(
1150 IStream* iface)
1152 sub_stream_t *This = impl_from_IStream(iface);
1153 LONG refs;
1155 TRACE("(%p)\n", This);
1156 refs = InterlockedDecrement(&This->refs);
1157 if(!refs)
1159 IStream_Release(This->base);
1160 HeapFree(GetProcessHeap(), 0, This);
1162 return refs;
1165 static HRESULT WINAPI sub_stream_Read(
1166 IStream* iface,
1167 void *pv,
1168 ULONG cb,
1169 ULONG *pcbRead)
1171 sub_stream_t *This = impl_from_IStream(iface);
1172 HRESULT hr;
1173 ULARGE_INTEGER base_pos;
1174 LARGE_INTEGER tmp_pos;
1176 TRACE("(%p, %d, %p)\n", pv, cb, pcbRead);
1178 tmp_pos.QuadPart = 0;
1179 IStream_Seek(This->base, tmp_pos, STREAM_SEEK_CUR, &base_pos);
1180 tmp_pos.QuadPart = This->pos.QuadPart + This->start.QuadPart;
1181 IStream_Seek(This->base, tmp_pos, STREAM_SEEK_SET, NULL);
1183 if(This->pos.QuadPart + cb > This->length.QuadPart)
1184 cb = This->length.QuadPart - This->pos.QuadPart;
1186 hr = IStream_Read(This->base, pv, cb, pcbRead);
1188 This->pos.QuadPart += *pcbRead;
1190 tmp_pos.QuadPart = base_pos.QuadPart;
1191 IStream_Seek(This->base, tmp_pos, STREAM_SEEK_SET, NULL);
1193 return hr;
1196 static HRESULT WINAPI sub_stream_Write(
1197 IStream* iface,
1198 const void *pv,
1199 ULONG cb,
1200 ULONG *pcbWritten)
1202 FIXME("stub\n");
1203 return E_NOTIMPL;
1206 static HRESULT WINAPI sub_stream_Seek(
1207 IStream* iface,
1208 LARGE_INTEGER dlibMove,
1209 DWORD dwOrigin,
1210 ULARGE_INTEGER *plibNewPosition)
1212 sub_stream_t *This = impl_from_IStream(iface);
1213 LARGE_INTEGER new_pos;
1215 TRACE("(%08x.%08x, %x, %p)\n", dlibMove.u.HighPart, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
1217 switch(dwOrigin)
1219 case STREAM_SEEK_SET:
1220 new_pos = dlibMove;
1221 break;
1222 case STREAM_SEEK_CUR:
1223 new_pos.QuadPart = This->pos.QuadPart + dlibMove.QuadPart;
1224 break;
1225 case STREAM_SEEK_END:
1226 new_pos.QuadPart = This->length.QuadPart + dlibMove.QuadPart;
1227 break;
1230 if(new_pos.QuadPart < 0) new_pos.QuadPart = 0;
1231 else if(new_pos.QuadPart > This->length.QuadPart) new_pos.QuadPart = This->length.QuadPart;
1233 This->pos.QuadPart = new_pos.QuadPart;
1235 if(plibNewPosition) *plibNewPosition = This->pos;
1236 return S_OK;
1239 static HRESULT WINAPI sub_stream_SetSize(
1240 IStream* iface,
1241 ULARGE_INTEGER libNewSize)
1243 FIXME("stub\n");
1244 return E_NOTIMPL;
1247 static HRESULT WINAPI sub_stream_CopyTo(
1248 IStream* iface,
1249 IStream *pstm,
1250 ULARGE_INTEGER cb,
1251 ULARGE_INTEGER *pcbRead,
1252 ULARGE_INTEGER *pcbWritten)
1254 HRESULT hr = S_OK;
1255 BYTE tmpBuffer[128];
1256 ULONG bytesRead, bytesWritten, copySize;
1257 ULARGE_INTEGER totalBytesRead;
1258 ULARGE_INTEGER totalBytesWritten;
1260 TRACE("(%p)->(%p, %d, %p, %p)\n", iface, pstm, cb.u.LowPart, pcbRead, pcbWritten);
1262 totalBytesRead.QuadPart = 0;
1263 totalBytesWritten.QuadPart = 0;
1265 while ( cb.QuadPart > 0 )
1267 if ( cb.QuadPart >= sizeof(tmpBuffer) )
1268 copySize = sizeof(tmpBuffer);
1269 else
1270 copySize = cb.u.LowPart;
1272 hr = IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
1273 if (FAILED(hr)) break;
1275 totalBytesRead.QuadPart += bytesRead;
1277 if (bytesRead)
1279 hr = IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
1280 if (FAILED(hr)) break;
1281 totalBytesWritten.QuadPart += bytesWritten;
1284 if (bytesRead != copySize)
1285 cb.QuadPart = 0;
1286 else
1287 cb.QuadPart -= bytesRead;
1290 if (pcbRead) pcbRead->QuadPart = totalBytesRead.QuadPart;
1291 if (pcbWritten) pcbWritten->QuadPart = totalBytesWritten.QuadPart;
1293 return hr;
1296 static HRESULT WINAPI sub_stream_Commit(
1297 IStream* iface,
1298 DWORD grfCommitFlags)
1300 FIXME("stub\n");
1301 return E_NOTIMPL;
1304 static HRESULT WINAPI sub_stream_Revert(
1305 IStream* iface)
1307 FIXME("stub\n");
1308 return E_NOTIMPL;
1311 static HRESULT WINAPI sub_stream_LockRegion(
1312 IStream* iface,
1313 ULARGE_INTEGER libOffset,
1314 ULARGE_INTEGER cb,
1315 DWORD dwLockType)
1317 FIXME("stub\n");
1318 return E_NOTIMPL;
1321 static HRESULT WINAPI sub_stream_UnlockRegion(
1322 IStream* iface,
1323 ULARGE_INTEGER libOffset,
1324 ULARGE_INTEGER cb,
1325 DWORD dwLockType)
1327 FIXME("stub\n");
1328 return E_NOTIMPL;
1331 static HRESULT WINAPI sub_stream_Stat(
1332 IStream* iface,
1333 STATSTG *pstatstg,
1334 DWORD grfStatFlag)
1336 sub_stream_t *This = impl_from_IStream(iface);
1337 FIXME("(%p)->(%p, %08x)\n", This, pstatstg, grfStatFlag);
1338 memset(pstatstg, 0, sizeof(*pstatstg));
1339 pstatstg->cbSize = This->length;
1340 return S_OK;
1343 static HRESULT WINAPI sub_stream_Clone(
1344 IStream* iface,
1345 IStream **ppstm)
1347 FIXME("stub\n");
1348 return E_NOTIMPL;
1351 static struct IStreamVtbl sub_stream_vtbl =
1353 sub_stream_QueryInterface,
1354 sub_stream_AddRef,
1355 sub_stream_Release,
1356 sub_stream_Read,
1357 sub_stream_Write,
1358 sub_stream_Seek,
1359 sub_stream_SetSize,
1360 sub_stream_CopyTo,
1361 sub_stream_Commit,
1362 sub_stream_Revert,
1363 sub_stream_LockRegion,
1364 sub_stream_UnlockRegion,
1365 sub_stream_Stat,
1366 sub_stream_Clone
1369 static HRESULT create_sub_stream(IStream *stream, ULARGE_INTEGER start, ULARGE_INTEGER length, IStream **out)
1371 sub_stream_t *This;
1373 *out = NULL;
1374 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1375 if(!This) return E_OUTOFMEMORY;
1377 This->lpVtbl = &sub_stream_vtbl;
1378 This->refs = 1;
1379 This->start = start;
1380 This->length = length;
1381 This->pos.QuadPart = 0;
1382 IStream_AddRef(stream);
1383 This->base = stream;
1385 *out = (IStream*)&This->lpVtbl;
1386 return S_OK;
1390 typedef struct body_t
1392 struct list entry;
1393 HBODY hbody;
1394 IMimeBody *mime_body;
1396 struct body_t *parent;
1397 struct list children;
1398 } body_t;
1400 typedef struct MimeMessage
1402 const IMimeMessageVtbl *lpVtbl;
1404 LONG refs;
1405 IStream *stream;
1407 struct list body_tree;
1408 HBODY next_hbody;
1409 } MimeMessage;
1411 static HRESULT WINAPI MimeMessage_QueryInterface(IMimeMessage *iface, REFIID riid, void **ppv)
1413 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1415 if (IsEqualIID(riid, &IID_IUnknown) ||
1416 IsEqualIID(riid, &IID_IPersist) ||
1417 IsEqualIID(riid, &IID_IPersistStreamInit) ||
1418 IsEqualIID(riid, &IID_IMimeMessageTree) ||
1419 IsEqualIID(riid, &IID_IMimeMessage))
1421 *ppv = iface;
1422 IUnknown_AddRef(iface);
1423 return S_OK;
1426 FIXME("no interface for %s\n", debugstr_guid(riid));
1427 *ppv = NULL;
1428 return E_NOINTERFACE;
1431 static ULONG WINAPI MimeMessage_AddRef(IMimeMessage *iface)
1433 MimeMessage *This = (MimeMessage *)iface;
1434 TRACE("(%p)->()\n", iface);
1435 return InterlockedIncrement(&This->refs);
1438 static void empty_body_list(struct list *list)
1440 body_t *body, *cursor2;
1441 LIST_FOR_EACH_ENTRY_SAFE(body, cursor2, list, body_t, entry)
1443 empty_body_list(&body->children);
1444 list_remove(&body->entry);
1445 IMimeBody_Release(body->mime_body);
1446 HeapFree(GetProcessHeap(), 0, body);
1450 static ULONG WINAPI MimeMessage_Release(IMimeMessage *iface)
1452 MimeMessage *This = (MimeMessage *)iface;
1453 ULONG refs;
1455 TRACE("(%p)->()\n", iface);
1457 refs = InterlockedDecrement(&This->refs);
1458 if (!refs)
1460 empty_body_list(&This->body_tree);
1462 if(This->stream) IStream_Release(This->stream);
1463 HeapFree(GetProcessHeap(), 0, This);
1466 return refs;
1469 /*** IPersist methods ***/
1470 static HRESULT WINAPI MimeMessage_GetClassID(
1471 IMimeMessage *iface,
1472 CLSID *pClassID)
1474 FIXME("(%p)->(%p)\n", iface, pClassID);
1475 return E_NOTIMPL;
1478 /*** IPersistStreamInit methods ***/
1479 static HRESULT WINAPI MimeMessage_IsDirty(
1480 IMimeMessage *iface)
1482 FIXME("(%p)->()\n", iface);
1483 return E_NOTIMPL;
1486 static body_t *new_body_entry(IMimeBody *mime_body, HBODY hbody, body_t *parent)
1488 body_t *body = HeapAlloc(GetProcessHeap(), 0, sizeof(*body));
1489 if(body)
1491 body->mime_body = mime_body;
1492 body->hbody = hbody;
1493 list_init(&body->children);
1494 body->parent = parent;
1496 return body;
1499 typedef struct
1501 struct list entry;
1502 BODYOFFSETS offsets;
1503 } offset_entry_t;
1505 static HRESULT create_body_offset_list(IStream *stm, const char *boundary, struct list *body_offsets)
1507 HRESULT hr;
1508 DWORD read;
1509 int boundary_len = strlen(boundary);
1510 char *buf, *nl_boundary, *ptr, *overlap;
1511 DWORD total_read = 0;
1512 DWORD start = 0, overlap_no;
1513 offset_entry_t *cur_body = NULL;
1514 ULARGE_INTEGER cur;
1515 LARGE_INTEGER zero;
1517 list_init(body_offsets);
1518 nl_boundary = HeapAlloc(GetProcessHeap(), 0, 4 + boundary_len + 1);
1519 memcpy(nl_boundary, "\r\n--", 4);
1520 memcpy(nl_boundary + 4, boundary, boundary_len + 1);
1522 overlap_no = boundary_len + 5;
1524 overlap = buf = HeapAlloc(GetProcessHeap(), 0, overlap_no + PARSER_BUF_SIZE + 1);
1526 zero.QuadPart = 0;
1527 hr = IStream_Seek(stm, zero, STREAM_SEEK_CUR, &cur);
1528 start = cur.u.LowPart;
1530 do {
1531 hr = IStream_Read(stm, overlap, PARSER_BUF_SIZE, &read);
1532 if(FAILED(hr)) goto end;
1533 if(read == 0) break;
1534 total_read += read;
1535 overlap[read] = '\0';
1537 ptr = buf;
1538 do {
1539 ptr = strstr(ptr, nl_boundary);
1540 if(ptr)
1542 DWORD boundary_start = start + ptr - buf;
1543 char *end = ptr + boundary_len + 4;
1545 if(*end == '\0' || *(end + 1) == '\0')
1546 break;
1548 if(*end == '\r' && *(end + 1) == '\n')
1550 if(cur_body)
1552 cur_body->offsets.cbBodyEnd = boundary_start;
1553 list_add_tail(body_offsets, &cur_body->entry);
1555 cur_body = HeapAlloc(GetProcessHeap(), 0, sizeof(*cur_body));
1556 cur_body->offsets.cbBoundaryStart = boundary_start + 2; /* doesn't including the leading \r\n */
1557 cur_body->offsets.cbHeaderStart = boundary_start + boundary_len + 6;
1559 else if(*end == '-' && *(end + 1) == '-')
1561 if(cur_body)
1563 cur_body->offsets.cbBodyEnd = boundary_start;
1564 list_add_tail(body_offsets, &cur_body->entry);
1565 goto end;
1568 ptr = end + 2;
1570 } while(ptr);
1572 if(overlap == buf) /* 1st iteration */
1574 memcpy(buf, buf + PARSER_BUF_SIZE - overlap_no, overlap_no);
1575 overlap = buf + overlap_no;
1576 start += read - overlap_no;
1578 else
1580 memcpy(buf, buf + PARSER_BUF_SIZE, overlap_no);
1581 start += read;
1583 } while(1);
1585 end:
1586 HeapFree(GetProcessHeap(), 0, buf);
1587 return hr;
1590 static body_t *create_sub_body(MimeMessage *msg, IStream *pStm, BODYOFFSETS *offset, body_t *parent)
1592 IMimeBody *mime_body;
1593 HRESULT hr;
1594 body_t *body;
1595 ULARGE_INTEGER cur;
1596 LARGE_INTEGER zero;
1598 MimeBody_create(NULL, (void**)&mime_body);
1599 IMimeBody_Load(mime_body, pStm);
1600 zero.QuadPart = 0;
1601 hr = IStream_Seek(pStm, zero, STREAM_SEEK_CUR, &cur);
1602 offset->cbBodyStart = cur.u.LowPart + offset->cbHeaderStart;
1603 if(parent) MimeBody_set_offsets(impl_from_IMimeBody(mime_body), offset);
1604 IMimeBody_SetData(mime_body, IET_BINARY, NULL, NULL, &IID_IStream, pStm);
1605 body = new_body_entry(mime_body, msg->next_hbody, parent);
1606 msg->next_hbody = (HBODY)((DWORD)msg->next_hbody + 1);
1608 if(IMimeBody_IsContentType(mime_body, "multipart", NULL) == S_OK)
1610 MIMEPARAMINFO *param_info;
1611 ULONG count, i;
1612 IMimeAllocator *alloc;
1614 hr = IMimeBody_GetParameters(mime_body, "Content-Type", &count, &param_info);
1615 if(hr != S_OK || count == 0) return body;
1617 MimeOleGetAllocator(&alloc);
1619 for(i = 0; i < count; i++)
1621 if(!strcasecmp(param_info[i].pszName, "boundary"))
1623 struct list offset_list;
1624 offset_entry_t *cur, *cursor2;
1625 hr = create_body_offset_list(pStm, param_info[i].pszData, &offset_list);
1626 LIST_FOR_EACH_ENTRY_SAFE(cur, cursor2, &offset_list, offset_entry_t, entry)
1628 body_t *sub_body;
1629 IStream *sub_stream;
1630 ULARGE_INTEGER start, length;
1632 start.u.LowPart = cur->offsets.cbHeaderStart;
1633 length.u.LowPart = cur->offsets.cbBodyEnd - cur->offsets.cbHeaderStart;
1634 create_sub_stream(pStm, start, length, &sub_stream);
1635 sub_body = create_sub_body(msg, sub_stream, &cur->offsets, body);
1636 IStream_Release(sub_stream);
1637 list_add_tail(&body->children, &sub_body->entry);
1638 list_remove(&cur->entry);
1639 HeapFree(GetProcessHeap(), 0, cur);
1641 break;
1644 IMimeAllocator_FreeParamInfoArray(alloc, count, param_info, TRUE);
1645 IMimeAllocator_Release(alloc);
1647 return body;
1650 static HRESULT WINAPI MimeMessage_Load(
1651 IMimeMessage *iface,
1652 LPSTREAM pStm)
1654 MimeMessage *This = (MimeMessage *)iface;
1655 body_t *root_body;
1656 BODYOFFSETS offsets;
1657 ULARGE_INTEGER cur;
1658 LARGE_INTEGER zero;
1660 TRACE("(%p)->(%p)\n", iface, pStm);
1662 if(This->stream)
1664 FIXME("already loaded a message\n");
1665 return E_FAIL;
1668 IStream_AddRef(pStm);
1669 This->stream = pStm;
1670 offsets.cbBoundaryStart = offsets.cbHeaderStart = 0;
1671 offsets.cbBodyStart = offsets.cbBodyEnd = 0;
1673 root_body = create_sub_body(This, pStm, &offsets, NULL);
1675 zero.QuadPart = 0;
1676 IStream_Seek(pStm, zero, STREAM_SEEK_END, &cur);
1677 offsets.cbBodyEnd = cur.u.LowPart;
1678 MimeBody_set_offsets(impl_from_IMimeBody(root_body->mime_body), &offsets);
1680 list_add_head(&This->body_tree, &root_body->entry);
1682 return S_OK;
1685 static HRESULT WINAPI MimeMessage_Save(
1686 IMimeMessage *iface,
1687 LPSTREAM pStm,
1688 BOOL fClearDirty)
1690 FIXME("(%p)->(%p, %s)\n", iface, pStm, fClearDirty ? "TRUE" : "FALSE");
1691 return E_NOTIMPL;
1694 static HRESULT WINAPI MimeMessage_GetSizeMax(
1695 IMimeMessage *iface,
1696 ULARGE_INTEGER *pcbSize)
1698 FIXME("(%p)->(%p)\n", iface, pcbSize);
1699 return E_NOTIMPL;
1702 static HRESULT WINAPI MimeMessage_InitNew(
1703 IMimeMessage *iface)
1705 FIXME("(%p)->()\n", iface);
1706 return E_NOTIMPL;
1709 /*** IMimeMessageTree methods ***/
1710 static HRESULT WINAPI MimeMessage_GetMessageSource(
1711 IMimeMessage *iface,
1712 IStream **ppStream,
1713 DWORD dwFlags)
1715 MimeMessage *This = (MimeMessage *)iface;
1716 FIXME("(%p)->(%p, 0x%x)\n", iface, ppStream, dwFlags);
1718 IStream_AddRef(This->stream);
1719 *ppStream = This->stream;
1720 return S_OK;
1723 static HRESULT WINAPI MimeMessage_GetMessageSize(
1724 IMimeMessage *iface,
1725 ULONG *pcbSize,
1726 DWORD dwFlags)
1728 FIXME("(%p)->(%p, 0x%x)\n", iface, pcbSize, dwFlags);
1729 return E_NOTIMPL;
1732 static HRESULT WINAPI MimeMessage_LoadOffsetTable(
1733 IMimeMessage *iface,
1734 IStream *pStream)
1736 FIXME("(%p)->(%p)\n", iface, pStream);
1737 return E_NOTIMPL;
1740 static HRESULT WINAPI MimeMessage_SaveOffsetTable(
1741 IMimeMessage *iface,
1742 IStream *pStream,
1743 DWORD dwFlags)
1745 FIXME("(%p)->(%p, 0x%x)\n", iface, pStream, dwFlags);
1746 return E_NOTIMPL;
1750 static HRESULT WINAPI MimeMessage_GetFlags(
1751 IMimeMessage *iface,
1752 DWORD *pdwFlags)
1754 FIXME("(%p)->(%p)\n", iface, pdwFlags);
1755 return E_NOTIMPL;
1758 static HRESULT WINAPI MimeMessage_Commit(
1759 IMimeMessage *iface,
1760 DWORD dwFlags)
1762 FIXME("(%p)->(0x%x)\n", iface, dwFlags);
1763 return E_NOTIMPL;
1767 static HRESULT WINAPI MimeMessage_HandsOffStorage(
1768 IMimeMessage *iface)
1770 FIXME("(%p)->()\n", iface);
1771 return E_NOTIMPL;
1774 static HRESULT find_body(struct list *list, HBODY hbody, body_t **body)
1776 body_t *cur;
1777 HRESULT hr;
1779 if(hbody == HBODY_ROOT)
1781 *body = LIST_ENTRY(list_head(list), body_t, entry);
1782 return S_OK;
1785 LIST_FOR_EACH_ENTRY(cur, list, body_t, entry)
1787 if(cur->hbody == hbody)
1789 *body = cur;
1790 return S_OK;
1792 hr = find_body(&cur->children, hbody, body);
1793 if(hr == S_OK) return S_OK;
1795 return S_FALSE;
1798 static HRESULT WINAPI MimeMessage_BindToObject(
1799 IMimeMessage *iface,
1800 const HBODY hBody,
1801 REFIID riid,
1802 void **ppvObject)
1804 MimeMessage *This = (MimeMessage *)iface;
1805 HRESULT hr;
1806 body_t *body;
1808 TRACE("(%p)->(%p, %s, %p)\n", iface, hBody, debugstr_guid(riid), ppvObject);
1810 hr = find_body(&This->body_tree, hBody, &body);
1812 if(hr != S_OK) return hr;
1814 if(IsEqualIID(riid, &IID_IMimeBody))
1816 IMimeBody_AddRef(body->mime_body);
1817 *ppvObject = body->mime_body;
1818 return S_OK;
1821 return E_NOINTERFACE;
1824 static HRESULT WINAPI MimeMessage_SaveBody(
1825 IMimeMessage *iface,
1826 HBODY hBody,
1827 DWORD dwFlags,
1828 IStream *pStream)
1830 FIXME("(%p)->(%p, 0x%x, %p)\n", iface, hBody, dwFlags, pStream);
1831 return E_NOTIMPL;
1834 static HRESULT get_body(MimeMessage *msg, BODYLOCATION location, HBODY pivot, body_t **out)
1836 body_t *root = LIST_ENTRY(list_head(&msg->body_tree), body_t, entry);
1837 body_t *body;
1838 HRESULT hr;
1839 struct list *list;
1841 if(location == IBL_ROOT)
1843 *out = root;
1844 return S_OK;
1847 hr = find_body(&msg->body_tree, pivot, &body);
1849 if(hr == S_OK)
1851 switch(location)
1853 case IBL_PARENT:
1854 *out = body->parent;
1855 break;
1857 case IBL_FIRST:
1858 list = list_head(&body->children);
1859 if(list)
1860 *out = LIST_ENTRY(list, body_t, entry);
1861 else
1862 hr = MIME_E_NOT_FOUND;
1863 break;
1865 case IBL_LAST:
1866 list = list_tail(&body->children);
1867 if(list)
1868 *out = LIST_ENTRY(list, body_t, entry);
1869 else
1870 hr = MIME_E_NOT_FOUND;
1871 break;
1873 case IBL_NEXT:
1874 list = list_next(&body->parent->children, &body->entry);
1875 if(list)
1876 *out = LIST_ENTRY(list, body_t, entry);
1877 else
1878 hr = MIME_E_NOT_FOUND;
1879 break;
1881 case IBL_PREVIOUS:
1882 list = list_prev(&body->parent->children, &body->entry);
1883 if(list)
1884 *out = LIST_ENTRY(list, body_t, entry);
1885 else
1886 hr = MIME_E_NOT_FOUND;
1887 break;
1889 default:
1890 hr = E_FAIL;
1891 break;
1895 return hr;
1899 static HRESULT WINAPI MimeMessage_InsertBody(
1900 IMimeMessage *iface,
1901 BODYLOCATION location,
1902 HBODY hPivot,
1903 LPHBODY phBody)
1905 FIXME("(%p)->(%d, %p, %p)\n", iface, location, hPivot, phBody);
1906 return E_NOTIMPL;
1909 static HRESULT WINAPI MimeMessage_GetBody(
1910 IMimeMessage *iface,
1911 BODYLOCATION location,
1912 HBODY hPivot,
1913 LPHBODY phBody)
1915 MimeMessage *This = (MimeMessage *)iface;
1916 body_t *body;
1917 HRESULT hr;
1919 TRACE("(%p)->(%d, %p, %p)\n", iface, location, hPivot, phBody);
1921 hr = get_body(This, location, hPivot, &body);
1923 if(hr == S_OK) *phBody = body->hbody;
1925 return hr;
1928 static HRESULT WINAPI MimeMessage_DeleteBody(
1929 IMimeMessage *iface,
1930 HBODY hBody,
1931 DWORD dwFlags)
1933 FIXME("(%p)->(%p, %08x)\n", iface, hBody, dwFlags);
1934 return E_NOTIMPL;
1937 static HRESULT WINAPI MimeMessage_MoveBody(
1938 IMimeMessage *iface,
1939 HBODY hBody,
1940 BODYLOCATION location)
1942 FIXME("(%p)->(%d)\n", iface, location);
1943 return E_NOTIMPL;
1946 static void count_children(body_t *body, boolean recurse, ULONG *count)
1948 body_t *child;
1950 LIST_FOR_EACH_ENTRY(child, &body->children, body_t, entry)
1952 (*count)++;
1953 if(recurse) count_children(child, recurse, count);
1957 static HRESULT WINAPI MimeMessage_CountBodies(
1958 IMimeMessage *iface,
1959 HBODY hParent,
1960 boolean fRecurse,
1961 ULONG *pcBodies)
1963 HRESULT hr;
1964 MimeMessage *This = (MimeMessage *)iface;
1965 body_t *body;
1967 TRACE("(%p)->(%p, %s, %p)\n", iface, hParent, fRecurse ? "TRUE" : "FALSE", pcBodies);
1969 hr = find_body(&This->body_tree, hParent, &body);
1970 if(hr != S_OK) return hr;
1972 *pcBodies = 1;
1973 count_children(body, fRecurse, pcBodies);
1975 return S_OK;
1978 static HRESULT find_next(IMimeMessage *msg, LPFINDBODY find_body, HBODY *out)
1980 HRESULT hr;
1981 IMimeBody *mime_body;
1982 HBODY next;
1984 if(find_body->dwReserved == 0)
1985 find_body->dwReserved = (DWORD)HBODY_ROOT;
1986 else
1988 hr = IMimeMessage_GetBody(msg, IBL_FIRST, (HBODY)find_body->dwReserved, &next);
1989 if(hr == S_OK)
1990 find_body->dwReserved = (DWORD)next;
1991 else
1993 hr = IMimeMessage_GetBody(msg, IBL_NEXT, (HBODY)find_body->dwReserved, &next);
1994 if(hr == S_OK)
1995 find_body->dwReserved = (DWORD)next;
1996 else
1997 return MIME_E_NOT_FOUND;
2001 hr = IMimeMessage_BindToObject(msg, (HBODY)find_body->dwReserved, &IID_IMimeBody, (void**)&mime_body);
2002 if(IMimeBody_IsContentType(mime_body, find_body->pszPriType, find_body->pszSubType) == S_OK)
2004 IMimeBody_Release(mime_body);
2005 *out = (HBODY)find_body->dwReserved;
2006 return S_OK;
2008 IMimeBody_Release(mime_body);
2009 return find_next(msg, find_body, out);
2012 static HRESULT WINAPI MimeMessage_FindFirst(
2013 IMimeMessage *iface,
2014 LPFINDBODY pFindBody,
2015 LPHBODY phBody)
2017 TRACE("(%p)->(%p, %p)\n", iface, pFindBody, phBody);
2019 pFindBody->dwReserved = 0;
2020 return find_next(iface, pFindBody, phBody);
2023 static HRESULT WINAPI MimeMessage_FindNext(
2024 IMimeMessage *iface,
2025 LPFINDBODY pFindBody,
2026 LPHBODY phBody)
2028 TRACE("(%p)->(%p, %p)\n", iface, pFindBody, phBody);
2030 return find_next(iface, pFindBody, phBody);
2033 static HRESULT WINAPI MimeMessage_ResolveURL(
2034 IMimeMessage *iface,
2035 HBODY hRelated,
2036 LPCSTR pszBase,
2037 LPCSTR pszURL,
2038 DWORD dwFlags,
2039 LPHBODY phBody)
2041 FIXME("(%p)->(%p, %s, %s, 0x%x, %p)\n", iface, hRelated, pszBase, pszURL, dwFlags, phBody);
2042 return E_NOTIMPL;
2045 static HRESULT WINAPI MimeMessage_ToMultipart(
2046 IMimeMessage *iface,
2047 HBODY hBody,
2048 LPCSTR pszSubType,
2049 LPHBODY phMultipart)
2051 FIXME("(%p)->(%p, %s, %p)\n", iface, hBody, pszSubType, phMultipart);
2052 return E_NOTIMPL;
2055 static HRESULT WINAPI MimeMessage_GetBodyOffsets(
2056 IMimeMessage *iface,
2057 HBODY hBody,
2058 LPBODYOFFSETS pOffsets)
2060 FIXME("(%p)->(%p, %p)\n", iface, hBody, pOffsets);
2061 return E_NOTIMPL;
2064 static HRESULT WINAPI MimeMessage_GetCharset(
2065 IMimeMessage *iface,
2066 LPHCHARSET phCharset)
2068 FIXME("(%p)->(%p)\n", iface, phCharset);
2069 *phCharset = NULL;
2070 return S_OK;
2073 static HRESULT WINAPI MimeMessage_SetCharset(
2074 IMimeMessage *iface,
2075 HCHARSET hCharset,
2076 CSETAPPLYTYPE applytype)
2078 FIXME("(%p)->(%p, %d)\n", iface, hCharset, applytype);
2079 return E_NOTIMPL;
2082 static HRESULT WINAPI MimeMessage_IsBodyType(
2083 IMimeMessage *iface,
2084 HBODY hBody,
2085 IMSGBODYTYPE bodytype)
2087 HRESULT hr;
2088 IMimeBody *mime_body;
2089 TRACE("(%p)->(%p, %d)\n", iface, hBody, bodytype);
2091 hr = IMimeMessage_BindToObject(iface, hBody, &IID_IMimeBody, (void**)&mime_body);
2092 if(hr != S_OK) return hr;
2094 hr = IMimeBody_IsType(mime_body, bodytype);
2095 MimeBody_Release(mime_body);
2096 return hr;
2099 static HRESULT WINAPI MimeMessage_IsContentType(
2100 IMimeMessage *iface,
2101 HBODY hBody,
2102 LPCSTR pszPriType,
2103 LPCSTR pszSubType)
2105 HRESULT hr;
2106 IMimeBody *mime_body;
2107 TRACE("(%p)->(%p, %s, %s)\n", iface, hBody, pszPriType, pszSubType);
2109 hr = IMimeMessage_BindToObject(iface, hBody, &IID_IMimeBody, (void**)&mime_body);
2110 if(FAILED(hr)) return hr;
2112 hr = IMimeBody_IsContentType(mime_body, pszPriType, pszSubType);
2113 IMimeBody_Release(mime_body);
2114 return hr;
2117 static HRESULT WINAPI MimeMessage_QueryBodyProp(
2118 IMimeMessage *iface,
2119 HBODY hBody,
2120 LPCSTR pszName,
2121 LPCSTR pszCriteria,
2122 boolean fSubString,
2123 boolean fCaseSensitive)
2125 FIXME("(%p)->(%p, %s, %s, %s, %s)\n", iface, hBody, pszName, pszCriteria, fSubString ? "TRUE" : "FALSE", fCaseSensitive ? "TRUE" : "FALSE");
2126 return E_NOTIMPL;
2129 static HRESULT WINAPI MimeMessage_GetBodyProp(
2130 IMimeMessage *iface,
2131 HBODY hBody,
2132 LPCSTR pszName,
2133 DWORD dwFlags,
2134 LPPROPVARIANT pValue)
2136 HRESULT hr;
2137 IMimeBody *mime_body;
2139 TRACE("(%p)->(%p, %s, 0x%x, %p)\n", iface, hBody, pszName, dwFlags, pValue);
2141 hr = IMimeMessage_BindToObject(iface, hBody, &IID_IMimeBody, (void**)&mime_body);
2142 if(hr != S_OK) return hr;
2144 hr = IMimeBody_GetProp(mime_body, pszName, dwFlags, pValue);
2145 IMimeBody_Release(mime_body);
2147 return hr;
2150 static HRESULT WINAPI MimeMessage_SetBodyProp(
2151 IMimeMessage *iface,
2152 HBODY hBody,
2153 LPCSTR pszName,
2154 DWORD dwFlags,
2155 LPCPROPVARIANT pValue)
2157 FIXME("(%p)->(%p, %s, 0x%x, %p)\n", iface, hBody, pszName, dwFlags, pValue);
2158 return E_NOTIMPL;
2161 static HRESULT WINAPI MimeMessage_DeleteBodyProp(
2162 IMimeMessage *iface,
2163 HBODY hBody,
2164 LPCSTR pszName)
2166 FIXME("(%p)->(%p, %s)\n", iface, hBody, pszName);
2167 return E_NOTIMPL;
2170 static HRESULT WINAPI MimeMessage_SetOption(
2171 IMimeMessage *iface,
2172 const TYPEDID oid,
2173 LPCPROPVARIANT pValue)
2175 FIXME("(%p)->(%08x, %p)\n", iface, oid, pValue);
2176 return E_NOTIMPL;
2179 static HRESULT WINAPI MimeMessage_GetOption(
2180 IMimeMessage *iface,
2181 const TYPEDID oid,
2182 LPPROPVARIANT pValue)
2184 FIXME("(%p)->(%08x, %p)\n", iface, oid, pValue);
2185 return E_NOTIMPL;
2188 /*** IMimeMessage methods ***/
2189 static HRESULT WINAPI MimeMessage_CreateWebPage(
2190 IMimeMessage *iface,
2191 IStream *pRootStm,
2192 LPWEBPAGEOPTIONS pOptions,
2193 IMimeMessageCallback *pCallback,
2194 IMoniker **ppMoniker)
2196 FIXME("(%p)->(%p, %p, %p, %p)\n", iface, pRootStm, pOptions, pCallback, ppMoniker);
2197 *ppMoniker = NULL;
2198 return E_NOTIMPL;
2201 static HRESULT WINAPI MimeMessage_GetProp(
2202 IMimeMessage *iface,
2203 LPCSTR pszName,
2204 DWORD dwFlags,
2205 LPPROPVARIANT pValue)
2207 FIXME("(%p)->(%s, 0x%x, %p)\n", iface, pszName, dwFlags, pValue);
2208 return E_NOTIMPL;
2211 static HRESULT WINAPI MimeMessage_SetProp(
2212 IMimeMessage *iface,
2213 LPCSTR pszName,
2214 DWORD dwFlags,
2215 LPCPROPVARIANT pValue)
2217 FIXME("(%p)->(%s, 0x%x, %p)\n", iface, pszName, dwFlags, pValue);
2218 return E_NOTIMPL;
2221 static HRESULT WINAPI MimeMessage_DeleteProp(
2222 IMimeMessage *iface,
2223 LPCSTR pszName)
2225 FIXME("(%p)->(%s)\n", iface, pszName);
2226 return E_NOTIMPL;
2229 static HRESULT WINAPI MimeMessage_QueryProp(
2230 IMimeMessage *iface,
2231 LPCSTR pszName,
2232 LPCSTR pszCriteria,
2233 boolean fSubString,
2234 boolean fCaseSensitive)
2236 FIXME("(%p)->(%s, %s, %s, %s)\n", iface, pszName, pszCriteria, fSubString ? "TRUE" : "FALSE", fCaseSensitive ? "TRUE" : "FALSE");
2237 return E_NOTIMPL;
2240 static HRESULT WINAPI MimeMessage_GetTextBody(
2241 IMimeMessage *iface,
2242 DWORD dwTxtType,
2243 ENCODINGTYPE ietEncoding,
2244 IStream **pStream,
2245 LPHBODY phBody)
2247 HRESULT hr;
2248 HBODY hbody;
2249 FINDBODY find_struct;
2250 IMimeBody *mime_body;
2251 static char text[] = "text";
2252 static char plain[] = "plain";
2253 static char html[] = "html";
2255 TRACE("(%p)->(%d, %d, %p, %p)\n", iface, dwTxtType, ietEncoding, pStream, phBody);
2257 find_struct.pszPriType = text;
2259 switch(dwTxtType)
2261 case TXT_PLAIN:
2262 find_struct.pszSubType = plain;
2263 break;
2264 case TXT_HTML:
2265 find_struct.pszSubType = html;
2266 break;
2267 default:
2268 return MIME_E_INVALID_TEXT_TYPE;
2271 hr = IMimeMessage_FindFirst(iface, &find_struct, &hbody);
2272 if(hr != S_OK)
2274 TRACE("not found hr %08x\n", hr);
2275 *phBody = NULL;
2276 return hr;
2279 IMimeMessage_BindToObject(iface, hbody, &IID_IMimeBody, (void**)&mime_body);
2281 IMimeBody_GetData(mime_body, ietEncoding, pStream);
2282 *phBody = hbody;
2283 IMimeBody_Release(mime_body);
2284 return hr;
2287 static HRESULT WINAPI MimeMessage_SetTextBody(
2288 IMimeMessage *iface,
2289 DWORD dwTxtType,
2290 ENCODINGTYPE ietEncoding,
2291 HBODY hAlternative,
2292 IStream *pStream,
2293 LPHBODY phBody)
2295 FIXME("(%p)->(%d, %d, %p, %p, %p)\n", iface, dwTxtType, ietEncoding, hAlternative, pStream, phBody);
2296 return E_NOTIMPL;
2299 static HRESULT WINAPI MimeMessage_AttachObject(
2300 IMimeMessage *iface,
2301 REFIID riid,
2302 void *pvObject,
2303 LPHBODY phBody)
2305 FIXME("(%p)->(%s, %p, %p)\n", iface, debugstr_guid(riid), pvObject, phBody);
2306 return E_NOTIMPL;
2309 static HRESULT WINAPI MimeMessage_AttachFile(
2310 IMimeMessage *iface,
2311 LPCSTR pszFilePath,
2312 IStream *pstmFile,
2313 LPHBODY phBody)
2315 FIXME("(%p)->(%s, %p, %p)\n", iface, pszFilePath, pstmFile, phBody);
2316 return E_NOTIMPL;
2319 static HRESULT WINAPI MimeMessage_AttachURL(
2320 IMimeMessage *iface,
2321 LPCSTR pszBase,
2322 LPCSTR pszURL,
2323 DWORD dwFlags,
2324 IStream *pstmURL,
2325 LPSTR *ppszCIDURL,
2326 LPHBODY phBody)
2328 FIXME("(%p)->(%s, %s, 0x%x, %p, %p, %p)\n", iface, pszBase, pszURL, dwFlags, pstmURL, ppszCIDURL, phBody);
2329 return E_NOTIMPL;
2332 static HRESULT WINAPI MimeMessage_GetAttachments(
2333 IMimeMessage *iface,
2334 ULONG *pcAttach,
2335 LPHBODY *pprghAttach)
2337 HRESULT hr;
2338 FINDBODY find_struct;
2339 HBODY hbody;
2340 LPHBODY array;
2341 ULONG size = 10;
2343 TRACE("(%p)->(%p, %p)\n", iface, pcAttach, pprghAttach);
2345 *pcAttach = 0;
2346 array = CoTaskMemAlloc(size * sizeof(HBODY));
2348 find_struct.pszPriType = find_struct.pszSubType = NULL;
2349 hr = IMimeMessage_FindFirst(iface, &find_struct, &hbody);
2350 while(hr == S_OK)
2352 hr = IMimeMessage_IsContentType(iface, hbody, "multipart", NULL);
2353 TRACE("IsCT rets %08x %d\n", hr, *pcAttach);
2354 if(hr != S_OK)
2356 if(*pcAttach + 1 > size)
2358 size *= 2;
2359 array = CoTaskMemRealloc(array, size * sizeof(HBODY));
2361 array[*pcAttach] = hbody;
2362 (*pcAttach)++;
2364 hr = IMimeMessage_FindNext(iface, &find_struct, &hbody);
2367 *pprghAttach = array;
2368 return S_OK;
2371 static HRESULT WINAPI MimeMessage_GetAddressTable(
2372 IMimeMessage *iface,
2373 IMimeAddressTable **ppTable)
2375 FIXME("(%p)->(%p)\n", iface, ppTable);
2376 return E_NOTIMPL;
2379 static HRESULT WINAPI MimeMessage_GetSender(
2380 IMimeMessage *iface,
2381 LPADDRESSPROPS pAddress)
2383 FIXME("(%p)->(%p)\n", iface, pAddress);
2384 return E_NOTIMPL;
2387 static HRESULT WINAPI MimeMessage_GetAddressTypes(
2388 IMimeMessage *iface,
2389 DWORD dwAdrTypes,
2390 DWORD dwProps,
2391 LPADDRESSLIST pList)
2393 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, dwProps, pList);
2394 return E_NOTIMPL;
2397 static HRESULT WINAPI MimeMessage_GetAddressFormat(
2398 IMimeMessage *iface,
2399 DWORD dwAdrTypes,
2400 ADDRESSFORMAT format,
2401 LPSTR *ppszFormat)
2403 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, format, ppszFormat);
2404 return E_NOTIMPL;
2407 static HRESULT WINAPI MimeMessage_EnumAddressTypes(
2408 IMimeMessage *iface,
2409 DWORD dwAdrTypes,
2410 DWORD dwProps,
2411 IMimeEnumAddressTypes **ppEnum)
2413 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, dwProps, ppEnum);
2414 return E_NOTIMPL;
2417 static HRESULT WINAPI MimeMessage_SplitMessage(
2418 IMimeMessage *iface,
2419 ULONG cbMaxPart,
2420 IMimeMessageParts **ppParts)
2422 FIXME("(%p)->(%d, %p)\n", iface, cbMaxPart, ppParts);
2423 return E_NOTIMPL;
2426 static HRESULT WINAPI MimeMessage_GetRootMoniker(
2427 IMimeMessage *iface,
2428 IMoniker **ppMoniker)
2430 FIXME("(%p)->(%p)\n", iface, ppMoniker);
2431 return E_NOTIMPL;
2434 static const IMimeMessageVtbl MimeMessageVtbl =
2436 MimeMessage_QueryInterface,
2437 MimeMessage_AddRef,
2438 MimeMessage_Release,
2439 MimeMessage_GetClassID,
2440 MimeMessage_IsDirty,
2441 MimeMessage_Load,
2442 MimeMessage_Save,
2443 MimeMessage_GetSizeMax,
2444 MimeMessage_InitNew,
2445 MimeMessage_GetMessageSource,
2446 MimeMessage_GetMessageSize,
2447 MimeMessage_LoadOffsetTable,
2448 MimeMessage_SaveOffsetTable,
2449 MimeMessage_GetFlags,
2450 MimeMessage_Commit,
2451 MimeMessage_HandsOffStorage,
2452 MimeMessage_BindToObject,
2453 MimeMessage_SaveBody,
2454 MimeMessage_InsertBody,
2455 MimeMessage_GetBody,
2456 MimeMessage_DeleteBody,
2457 MimeMessage_MoveBody,
2458 MimeMessage_CountBodies,
2459 MimeMessage_FindFirst,
2460 MimeMessage_FindNext,
2461 MimeMessage_ResolveURL,
2462 MimeMessage_ToMultipart,
2463 MimeMessage_GetBodyOffsets,
2464 MimeMessage_GetCharset,
2465 MimeMessage_SetCharset,
2466 MimeMessage_IsBodyType,
2467 MimeMessage_IsContentType,
2468 MimeMessage_QueryBodyProp,
2469 MimeMessage_GetBodyProp,
2470 MimeMessage_SetBodyProp,
2471 MimeMessage_DeleteBodyProp,
2472 MimeMessage_SetOption,
2473 MimeMessage_GetOption,
2474 MimeMessage_CreateWebPage,
2475 MimeMessage_GetProp,
2476 MimeMessage_SetProp,
2477 MimeMessage_DeleteProp,
2478 MimeMessage_QueryProp,
2479 MimeMessage_GetTextBody,
2480 MimeMessage_SetTextBody,
2481 MimeMessage_AttachObject,
2482 MimeMessage_AttachFile,
2483 MimeMessage_AttachURL,
2484 MimeMessage_GetAttachments,
2485 MimeMessage_GetAddressTable,
2486 MimeMessage_GetSender,
2487 MimeMessage_GetAddressTypes,
2488 MimeMessage_GetAddressFormat,
2489 MimeMessage_EnumAddressTypes,
2490 MimeMessage_SplitMessage,
2491 MimeMessage_GetRootMoniker,
2494 /***********************************************************************
2495 * MimeOleCreateMessage (INETCOMM.@)
2497 HRESULT WINAPI MimeOleCreateMessage(IUnknown *pUnkOuter, IMimeMessage **ppMessage)
2499 MimeMessage *This;
2501 TRACE("(%p, %p)\n", pUnkOuter, ppMessage);
2503 if (pUnkOuter)
2505 FIXME("outer unknown not supported yet\n");
2506 return E_NOTIMPL;
2509 *ppMessage = NULL;
2511 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2512 if (!This) return E_OUTOFMEMORY;
2514 This->lpVtbl = &MimeMessageVtbl;
2515 This->refs = 1;
2516 This->stream = NULL;
2517 list_init(&This->body_tree);
2518 This->next_hbody = (HBODY)1;
2520 *ppMessage = (IMimeMessage *)&This->lpVtbl;
2521 return S_OK;
2524 /***********************************************************************
2525 * MimeOleSetCompatMode (INETCOMM.@)
2527 HRESULT WINAPI MimeOleSetCompatMode(DWORD dwMode)
2529 FIXME("(0x%x)\n", dwMode);
2530 return S_OK;
2533 /***********************************************************************
2534 * MimeOleCreateVirtualStream (INETCOMM.@)
2536 HRESULT WINAPI MimeOleCreateVirtualStream(IStream **ppStream)
2538 HRESULT hr;
2539 FIXME("(%p)\n", ppStream);
2541 hr = CreateStreamOnHGlobal(NULL, TRUE, ppStream);
2542 return hr;
2545 typedef struct MimeSecurity
2547 const IMimeSecurityVtbl *lpVtbl;
2549 LONG refs;
2550 } MimeSecurity;
2552 static HRESULT WINAPI MimeSecurity_QueryInterface(
2553 IMimeSecurity* iface,
2554 REFIID riid,
2555 void** obj)
2557 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), obj);
2559 if (IsEqualIID(riid, &IID_IUnknown) ||
2560 IsEqualIID(riid, &IID_IMimeSecurity))
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 MimeSecurity_AddRef(
2573 IMimeSecurity* iface)
2575 MimeSecurity *This = (MimeSecurity *)iface;
2576 TRACE("(%p)->()\n", iface);
2577 return InterlockedIncrement(&This->refs);
2580 static ULONG WINAPI MimeSecurity_Release(
2581 IMimeSecurity* iface)
2583 MimeSecurity *This = (MimeSecurity *)iface;
2584 ULONG refs;
2586 TRACE("(%p)->()\n", iface);
2588 refs = InterlockedDecrement(&This->refs);
2589 if (!refs)
2591 HeapFree(GetProcessHeap(), 0, This);
2594 return refs;
2597 static HRESULT WINAPI MimeSecurity_InitNew(
2598 IMimeSecurity* iface)
2600 FIXME("(%p)->(): stub\n", iface);
2601 return S_OK;
2604 static HRESULT WINAPI MimeSecurity_CheckInit(
2605 IMimeSecurity* iface)
2607 FIXME("(%p)->(): stub\n", iface);
2608 return E_NOTIMPL;
2611 static HRESULT WINAPI MimeSecurity_EncodeMessage(
2612 IMimeSecurity* iface,
2613 IMimeMessageTree* pTree,
2614 DWORD dwFlags)
2616 FIXME("(%p)->(%p, %08x): stub\n", iface, pTree, dwFlags);
2617 return E_NOTIMPL;
2620 static HRESULT WINAPI MimeSecurity_EncodeBody(
2621 IMimeSecurity* iface,
2622 IMimeMessageTree* pTree,
2623 HBODY hEncodeRoot,
2624 DWORD dwFlags)
2626 FIXME("(%p)->(%p, %p, %08x): stub\n", iface, pTree, hEncodeRoot, dwFlags);
2627 return E_NOTIMPL;
2630 static HRESULT WINAPI MimeSecurity_DecodeMessage(
2631 IMimeSecurity* iface,
2632 IMimeMessageTree* pTree,
2633 DWORD dwFlags)
2635 FIXME("(%p)->(%p, %08x): stub\n", iface, pTree, dwFlags);
2636 return E_NOTIMPL;
2639 static HRESULT WINAPI MimeSecurity_DecodeBody(
2640 IMimeSecurity* iface,
2641 IMimeMessageTree* pTree,
2642 HBODY hDecodeRoot,
2643 DWORD dwFlags)
2645 FIXME("(%p)->(%p, %p, %08x): stub\n", iface, pTree, hDecodeRoot, dwFlags);
2646 return E_NOTIMPL;
2649 static HRESULT WINAPI MimeSecurity_EnumCertificates(
2650 IMimeSecurity* iface,
2651 HCAPICERTSTORE hc,
2652 DWORD dwUsage,
2653 PCX509CERT pPrev,
2654 PCX509CERT* ppCert)
2656 FIXME("(%p)->(%p, %08x, %p, %p): stub\n", iface, hc, dwUsage, pPrev, ppCert);
2657 return E_NOTIMPL;
2660 static HRESULT WINAPI MimeSecurity_GetCertificateName(
2661 IMimeSecurity* iface,
2662 const PCX509CERT pX509Cert,
2663 const CERTNAMETYPE cn,
2664 LPSTR* ppszName)
2666 FIXME("(%p)->(%p, %08x, %p): stub\n", iface, pX509Cert, cn, ppszName);
2667 return E_NOTIMPL;
2670 static HRESULT WINAPI MimeSecurity_GetMessageType(
2671 IMimeSecurity* iface,
2672 const HWND hwndParent,
2673 IMimeBody* pBody,
2674 DWORD* pdwSecType)
2676 FIXME("(%p)->(%p, %p, %p): stub\n", iface, hwndParent, pBody, pdwSecType);
2677 return E_NOTIMPL;
2680 static HRESULT WINAPI MimeSecurity_GetCertData(
2681 IMimeSecurity* iface,
2682 const PCX509CERT pX509Cert,
2683 const CERTDATAID dataid,
2684 LPPROPVARIANT pValue)
2686 FIXME("(%p)->(%p, %x, %p): stub\n", iface, pX509Cert, dataid, pValue);
2687 return E_NOTIMPL;
2691 static const IMimeSecurityVtbl MimeSecurityVtbl =
2693 MimeSecurity_QueryInterface,
2694 MimeSecurity_AddRef,
2695 MimeSecurity_Release,
2696 MimeSecurity_InitNew,
2697 MimeSecurity_CheckInit,
2698 MimeSecurity_EncodeMessage,
2699 MimeSecurity_EncodeBody,
2700 MimeSecurity_DecodeMessage,
2701 MimeSecurity_DecodeBody,
2702 MimeSecurity_EnumCertificates,
2703 MimeSecurity_GetCertificateName,
2704 MimeSecurity_GetMessageType,
2705 MimeSecurity_GetCertData
2708 /***********************************************************************
2709 * MimeOleCreateSecurity (INETCOMM.@)
2711 HRESULT WINAPI MimeOleCreateSecurity(IMimeSecurity **ppSecurity)
2713 MimeSecurity *This;
2715 TRACE("(%p)\n", ppSecurity);
2717 *ppSecurity = NULL;
2719 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2720 if (!This) return E_OUTOFMEMORY;
2722 This->lpVtbl = &MimeSecurityVtbl;
2723 This->refs = 1;
2725 *ppSecurity = (IMimeSecurity *)&This->lpVtbl;
2726 return S_OK;
2730 typedef struct
2732 IMimeAllocatorVtbl *lpVtbl;
2733 } MimeAllocator;
2735 static HRESULT WINAPI MimeAlloc_QueryInterface(
2736 IMimeAllocator* iface,
2737 REFIID riid,
2738 void **obj)
2740 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), obj);
2742 if (IsEqualIID(riid, &IID_IUnknown) ||
2743 IsEqualIID(riid, &IID_IMalloc) ||
2744 IsEqualIID(riid, &IID_IMimeAllocator))
2746 *obj = iface;
2747 IUnknown_AddRef(iface);
2748 return S_OK;
2751 FIXME("no interface for %s\n", debugstr_guid(riid));
2752 *obj = NULL;
2753 return E_NOINTERFACE;
2756 static ULONG WINAPI MimeAlloc_AddRef(
2757 IMimeAllocator* iface)
2759 return 2;
2762 static ULONG WINAPI MimeAlloc_Release(
2763 IMimeAllocator* iface)
2765 return 1;
2768 static LPVOID WINAPI MimeAlloc_Alloc(
2769 IMimeAllocator* iface,
2770 ULONG cb)
2772 return CoTaskMemAlloc(cb);
2775 static LPVOID WINAPI MimeAlloc_Realloc(
2776 IMimeAllocator* iface,
2777 LPVOID pv,
2778 ULONG cb)
2780 return CoTaskMemRealloc(pv, cb);
2783 static void WINAPI MimeAlloc_Free(
2784 IMimeAllocator* iface,
2785 LPVOID pv)
2787 return CoTaskMemFree(pv);
2790 static ULONG WINAPI MimeAlloc_GetSize(
2791 IMimeAllocator* iface,
2792 LPVOID pv)
2794 FIXME("stub\n");
2795 return 0;
2798 static int WINAPI MimeAlloc_DidAlloc(
2799 IMimeAllocator* iface,
2800 LPVOID pv)
2802 FIXME("stub\n");
2803 return 0;
2806 static void WINAPI MimeAlloc_HeapMinimize(
2807 IMimeAllocator* iface)
2809 FIXME("stub\n");
2810 return;
2813 static HRESULT WINAPI MimeAlloc_FreeParamInfoArray(
2814 IMimeAllocator* iface,
2815 ULONG cParams,
2816 LPMIMEPARAMINFO prgParam,
2817 boolean fFreeArray)
2819 ULONG i;
2820 TRACE("(%p)->(%d, %p, %d)\n", iface, cParams, prgParam, fFreeArray);
2822 for(i = 0; i < cParams; i++)
2824 IMimeAllocator_Free(iface, prgParam[i].pszName);
2825 IMimeAllocator_Free(iface, prgParam[i].pszData);
2827 if(fFreeArray) IMimeAllocator_Free(iface, prgParam);
2828 return S_OK;
2831 static HRESULT WINAPI MimeAlloc_FreeAddressList(
2832 IMimeAllocator* iface,
2833 LPADDRESSLIST pList)
2835 FIXME("stub\n");
2836 return E_NOTIMPL;
2839 static HRESULT WINAPI MimeAlloc_FreeAddressProps(
2840 IMimeAllocator* iface,
2841 LPADDRESSPROPS pAddress)
2843 FIXME("stub\n");
2844 return E_NOTIMPL;
2847 static HRESULT WINAPI MimeAlloc_ReleaseObjects(
2848 IMimeAllocator* iface,
2849 ULONG cObjects,
2850 IUnknown **prgpUnknown,
2851 boolean fFreeArray)
2853 FIXME("stub\n");
2854 return E_NOTIMPL;
2858 static HRESULT WINAPI MimeAlloc_FreeEnumHeaderRowArray(
2859 IMimeAllocator* iface,
2860 ULONG cRows,
2861 LPENUMHEADERROW prgRow,
2862 boolean fFreeArray)
2864 FIXME("stub\n");
2865 return E_NOTIMPL;
2868 static HRESULT WINAPI MimeAlloc_FreeEnumPropertyArray(
2869 IMimeAllocator* iface,
2870 ULONG cProps,
2871 LPENUMPROPERTY prgProp,
2872 boolean fFreeArray)
2874 FIXME("stub\n");
2875 return E_NOTIMPL;
2878 static HRESULT WINAPI MimeAlloc_FreeThumbprint(
2879 IMimeAllocator* iface,
2880 THUMBBLOB *pthumbprint)
2882 FIXME("stub\n");
2883 return E_NOTIMPL;
2887 static HRESULT WINAPI MimeAlloc_PropVariantClear(
2888 IMimeAllocator* iface,
2889 LPPROPVARIANT pProp)
2891 FIXME("stub\n");
2892 return E_NOTIMPL;
2895 static IMimeAllocatorVtbl mime_alloc_vtbl =
2897 MimeAlloc_QueryInterface,
2898 MimeAlloc_AddRef,
2899 MimeAlloc_Release,
2900 MimeAlloc_Alloc,
2901 MimeAlloc_Realloc,
2902 MimeAlloc_Free,
2903 MimeAlloc_GetSize,
2904 MimeAlloc_DidAlloc,
2905 MimeAlloc_HeapMinimize,
2906 MimeAlloc_FreeParamInfoArray,
2907 MimeAlloc_FreeAddressList,
2908 MimeAlloc_FreeAddressProps,
2909 MimeAlloc_ReleaseObjects,
2910 MimeAlloc_FreeEnumHeaderRowArray,
2911 MimeAlloc_FreeEnumPropertyArray,
2912 MimeAlloc_FreeThumbprint,
2913 MimeAlloc_PropVariantClear
2916 static MimeAllocator mime_allocator =
2918 &mime_alloc_vtbl
2921 HRESULT MimeAllocator_create(IUnknown *outer, void **obj)
2923 if(outer) return CLASS_E_NOAGGREGATION;
2925 *obj = &mime_allocator;
2926 return S_OK;
2929 HRESULT WINAPI MimeOleGetAllocator(IMimeAllocator **alloc)
2931 return MimeAllocator_create(NULL, (void**)alloc);
2934 HRESULT WINAPI MimeOleGetCharsetInfo(HCHARSET hCharset, LPINETCSETINFO pCsetInfo)
2936 FIXME("(%p, %p)\n", hCharset, pCsetInfo);
2937 if(!hCharset) return E_INVALIDARG;
2938 return E_FAIL;