dinput: Use BOOL type where appropriate.
[wine.git] / dlls / inetcomm / mimeole.c
blob38acd4952fdd1f63d45daea23c685eedb0b7c165
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 | MPF_HASPARAMS, VT_LPSTR},
73 {"To", PID_HDR_TO, MPF_ADDRESS, VT_LPSTR},
74 {"Cc", PID_HDR_CC, MPF_ADDRESS, VT_LPSTR},
75 {"Sender", PID_HDR_SENDER, MPF_ADDRESS, VT_LPSTR},
76 {"In-Reply-To", PID_HDR_INREPLYTO, 0, VT_LPSTR},
77 {NULL, 0, 0, 0}
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 IMimeBody IMimeBody_iface;
98 LONG ref;
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 CONTAINING_RECORD(iface, MimeBody, IMimeBody_iface);
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 LONG ref = InterlockedIncrement(&This->ref);
531 TRACE("(%p) ref=%d\n", This, ref);
533 return ref;
536 static ULONG WINAPI MimeBody_Release(IMimeBody *iface)
538 MimeBody *This = impl_from_IMimeBody(iface);
539 LONG ref = InterlockedDecrement(&This->ref);
541 TRACE("(%p) ref=%d\n", This, ref);
543 if (!ref)
545 empty_header_list(&This->headers);
546 empty_new_prop_list(&This->new_props);
548 HeapFree(GetProcessHeap(), 0, This->content_pri_type);
549 HeapFree(GetProcessHeap(), 0, This->content_sub_type);
551 release_data(&This->data_iid, This->data);
553 HeapFree(GetProcessHeap(), 0, This);
556 return ref;
559 static HRESULT WINAPI MimeBody_GetClassID(
560 IMimeBody* iface,
561 CLSID* pClassID)
563 FIXME("stub\n");
564 return E_NOTIMPL;
568 static HRESULT WINAPI MimeBody_IsDirty(
569 IMimeBody* iface)
571 FIXME("stub\n");
572 return E_NOTIMPL;
575 static HRESULT WINAPI MimeBody_Load(IMimeBody *iface, IStream *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(IMimeBody *iface, IStream *pStm, BOOL fClearDirty)
584 FIXME("stub\n");
585 return E_NOTIMPL;
588 static HRESULT WINAPI MimeBody_GetSizeMax(
589 IMimeBody* iface,
590 ULARGE_INTEGER* pcbSize)
592 FIXME("stub\n");
593 return E_NOTIMPL;
596 static HRESULT WINAPI MimeBody_InitNew(
597 IMimeBody* iface)
599 TRACE("%p->()\n", iface);
600 return S_OK;
603 static HRESULT WINAPI MimeBody_GetPropInfo(
604 IMimeBody* iface,
605 LPCSTR pszName,
606 LPMIMEPROPINFO pInfo)
608 FIXME("stub\n");
609 return E_NOTIMPL;
612 static HRESULT WINAPI MimeBody_SetPropInfo(
613 IMimeBody* iface,
614 LPCSTR pszName,
615 LPCMIMEPROPINFO pInfo)
617 FIXME("stub\n");
618 return E_NOTIMPL;
621 static HRESULT WINAPI MimeBody_GetProp(
622 IMimeBody* iface,
623 LPCSTR pszName,
624 DWORD dwFlags,
625 LPPROPVARIANT pValue)
627 MimeBody *This = impl_from_IMimeBody(iface);
628 TRACE("(%p)->(%s, %d, %p)\n", This, pszName, dwFlags, pValue);
630 if(!strcasecmp(pszName, "att:pri-content-type"))
632 PropVariantClear(pValue);
633 pValue->vt = VT_LPSTR;
634 pValue->u.pszVal = strdupA(This->content_pri_type);
635 return S_OK;
638 FIXME("stub!\n");
639 return E_FAIL;
642 static HRESULT WINAPI MimeBody_SetProp(
643 IMimeBody* iface,
644 LPCSTR pszName,
645 DWORD dwFlags,
646 LPCPROPVARIANT pValue)
648 FIXME("stub\n");
649 return E_NOTIMPL;
652 static HRESULT WINAPI MimeBody_AppendProp(
653 IMimeBody* iface,
654 LPCSTR pszName,
655 DWORD dwFlags,
656 LPPROPVARIANT pValue)
658 FIXME("stub\n");
659 return E_NOTIMPL;
662 static HRESULT WINAPI MimeBody_DeleteProp(
663 IMimeBody* iface,
664 LPCSTR pszName)
666 FIXME("stub\n");
667 return E_NOTIMPL;
670 static HRESULT WINAPI MimeBody_CopyProps(
671 IMimeBody* iface,
672 ULONG cNames,
673 LPCSTR* prgszName,
674 IMimePropertySet* pPropertySet)
676 FIXME("stub\n");
677 return E_NOTIMPL;
680 static HRESULT WINAPI MimeBody_MoveProps(
681 IMimeBody* iface,
682 ULONG cNames,
683 LPCSTR* prgszName,
684 IMimePropertySet* pPropertySet)
686 FIXME("stub\n");
687 return E_NOTIMPL;
690 static HRESULT WINAPI MimeBody_DeleteExcept(
691 IMimeBody* iface,
692 ULONG cNames,
693 LPCSTR* prgszName)
695 FIXME("stub\n");
696 return E_NOTIMPL;
699 static HRESULT WINAPI MimeBody_QueryProp(
700 IMimeBody* iface,
701 LPCSTR pszName,
702 LPCSTR pszCriteria,
703 boolean fSubString,
704 boolean fCaseSensitive)
706 FIXME("stub\n");
707 return E_NOTIMPL;
710 static HRESULT WINAPI MimeBody_GetCharset(
711 IMimeBody* iface,
712 LPHCHARSET phCharset)
714 FIXME("stub\n");
715 *phCharset = NULL;
716 return S_OK;
719 static HRESULT WINAPI MimeBody_SetCharset(
720 IMimeBody* iface,
721 HCHARSET hCharset,
722 CSETAPPLYTYPE applytype)
724 FIXME("stub\n");
725 return E_NOTIMPL;
728 static HRESULT WINAPI MimeBody_GetParameters(
729 IMimeBody* iface,
730 LPCSTR pszName,
731 ULONG* pcParams,
732 LPMIMEPARAMINFO* pprgParam)
734 MimeBody *This = impl_from_IMimeBody(iface);
735 HRESULT hr;
736 header_t *header;
738 TRACE("(%p)->(%s, %p, %p)\n", iface, debugstr_a(pszName), pcParams, pprgParam);
740 *pprgParam = NULL;
741 *pcParams = 0;
743 hr = find_prop(This, pszName, &header);
744 if(hr != S_OK) return hr;
746 *pcParams = list_count(&header->params);
747 if(*pcParams)
749 IMimeAllocator *alloc;
750 param_t *param;
751 MIMEPARAMINFO *info;
753 MimeOleGetAllocator(&alloc);
755 *pprgParam = info = IMimeAllocator_Alloc(alloc, *pcParams * sizeof(**pprgParam));
756 LIST_FOR_EACH_ENTRY(param, &header->params, param_t, entry)
758 int len;
760 len = strlen(param->name) + 1;
761 info->pszName = IMimeAllocator_Alloc(alloc, len);
762 memcpy(info->pszName, param->name, len);
763 len = strlen(param->value) + 1;
764 info->pszData = IMimeAllocator_Alloc(alloc, len);
765 memcpy(info->pszData, param->value, len);
766 info++;
768 IMimeAllocator_Release(alloc);
770 return S_OK;
773 static HRESULT WINAPI MimeBody_IsContentType(
774 IMimeBody* iface,
775 LPCSTR pszPriType,
776 LPCSTR pszSubType)
778 MimeBody *This = impl_from_IMimeBody(iface);
780 TRACE("(%p)->(%s, %s)\n", This, debugstr_a(pszPriType), debugstr_a(pszSubType));
781 if(pszPriType)
783 const char *pri = This->content_pri_type;
784 if(!pri) pri = "text";
785 if(strcasecmp(pri, pszPriType)) return S_FALSE;
788 if(pszSubType)
790 const char *sub = This->content_sub_type;
791 if(!sub) sub = "plain";
792 if(strcasecmp(sub, pszSubType)) return S_FALSE;
795 return S_OK;
798 static HRESULT WINAPI MimeBody_BindToObject(
799 IMimeBody* iface,
800 REFIID riid,
801 void** ppvObject)
803 FIXME("stub\n");
804 return E_NOTIMPL;
807 static HRESULT WINAPI MimeBody_Clone(
808 IMimeBody* iface,
809 IMimePropertySet** ppPropertySet)
811 FIXME("stub\n");
812 return E_NOTIMPL;
815 static HRESULT WINAPI MimeBody_SetOption(
816 IMimeBody* iface,
817 const TYPEDID oid,
818 LPCPROPVARIANT pValue)
820 HRESULT hr = E_NOTIMPL;
821 TRACE("(%p)->(%08x, %p)\n", iface, oid, pValue);
823 if(pValue->vt != TYPEDID_TYPE(oid))
825 WARN("Called with vartype %04x and oid %08x\n", pValue->vt, oid);
826 return E_INVALIDARG;
829 switch(oid)
831 case OID_SECURITY_HWND_OWNER:
832 FIXME("OID_SECURITY_HWND_OWNER (value %08x): ignoring\n", pValue->u.ulVal);
833 hr = S_OK;
834 break;
835 default:
836 FIXME("Unhandled oid %08x\n", oid);
839 return hr;
842 static HRESULT WINAPI MimeBody_GetOption(
843 IMimeBody* iface,
844 const TYPEDID oid,
845 LPPROPVARIANT pValue)
847 FIXME("(%p)->(%08x, %p): stub\n", iface, oid, pValue);
848 return E_NOTIMPL;
851 static HRESULT WINAPI MimeBody_EnumProps(
852 IMimeBody* iface,
853 DWORD dwFlags,
854 IMimeEnumProperties** ppEnum)
856 FIXME("stub\n");
857 return E_NOTIMPL;
860 static HRESULT WINAPI MimeBody_IsType(
861 IMimeBody* iface,
862 IMSGBODYTYPE bodytype)
864 MimeBody *This = impl_from_IMimeBody(iface);
866 TRACE("(%p)->(%d)\n", iface, bodytype);
867 switch(bodytype)
869 case IBT_EMPTY:
870 return This->data ? S_FALSE : S_OK;
871 default:
872 FIXME("Unimplemented bodytype %d - returning S_OK\n", bodytype);
874 return S_OK;
877 static HRESULT WINAPI MimeBody_SetDisplayName(
878 IMimeBody* iface,
879 LPCSTR pszDisplay)
881 FIXME("stub\n");
882 return E_NOTIMPL;
885 static HRESULT WINAPI MimeBody_GetDisplayName(
886 IMimeBody* iface,
887 LPSTR* ppszDisplay)
889 FIXME("stub\n");
890 return E_NOTIMPL;
893 static HRESULT WINAPI MimeBody_GetOffsets(
894 IMimeBody* iface,
895 LPBODYOFFSETS pOffsets)
897 MimeBody *This = impl_from_IMimeBody(iface);
898 TRACE("(%p)->(%p)\n", This, pOffsets);
900 *pOffsets = This->body_offsets;
902 if(This->body_offsets.cbBodyEnd == 0) return MIME_E_NO_DATA;
903 return S_OK;
906 static HRESULT WINAPI MimeBody_GetCurrentEncoding(
907 IMimeBody* iface,
908 ENCODINGTYPE* pietEncoding)
910 MimeBody *This = impl_from_IMimeBody(iface);
912 TRACE("(%p)->(%p)\n", This, pietEncoding);
914 *pietEncoding = This->encoding;
915 return S_OK;
918 static HRESULT WINAPI MimeBody_SetCurrentEncoding(
919 IMimeBody* iface,
920 ENCODINGTYPE ietEncoding)
922 MimeBody *This = impl_from_IMimeBody(iface);
924 TRACE("(%p)->(%d)\n", This, ietEncoding);
926 This->encoding = ietEncoding;
927 return S_OK;
930 static HRESULT WINAPI MimeBody_GetEstimatedSize(
931 IMimeBody* iface,
932 ENCODINGTYPE ietEncoding,
933 ULONG* pcbSize)
935 FIXME("stub\n");
936 return E_NOTIMPL;
939 static HRESULT WINAPI MimeBody_GetDataHere(
940 IMimeBody* iface,
941 ENCODINGTYPE ietEncoding,
942 IStream* pStream)
944 FIXME("stub\n");
945 return E_NOTIMPL;
948 static HRESULT WINAPI MimeBody_GetData(
949 IMimeBody* iface,
950 ENCODINGTYPE ietEncoding,
951 IStream** ppStream)
953 MimeBody *This = impl_from_IMimeBody(iface);
954 FIXME("(%p)->(%d, %p). Ignoring encoding type.\n", This, ietEncoding, ppStream);
956 *ppStream = This->data;
957 IStream_AddRef(*ppStream);
958 return S_OK;
961 static HRESULT WINAPI MimeBody_SetData(
962 IMimeBody* iface,
963 ENCODINGTYPE ietEncoding,
964 LPCSTR pszPriType,
965 LPCSTR pszSubType,
966 REFIID riid,
967 LPVOID pvObject)
969 MimeBody *This = impl_from_IMimeBody(iface);
970 TRACE("(%p)->(%d, %s, %s, %s %p)\n", This, ietEncoding, debugstr_a(pszPriType), debugstr_a(pszSubType),
971 debugstr_guid(riid), pvObject);
973 if(IsEqualIID(riid, &IID_IStream))
974 IStream_AddRef((IStream *)pvObject);
975 else
977 FIXME("Unhandled object type %s\n", debugstr_guid(riid));
978 return E_INVALIDARG;
981 if(This->data)
982 FIXME("release old data\n");
984 This->data_iid = *riid;
985 This->data = pvObject;
987 IMimeBody_SetCurrentEncoding(iface, ietEncoding);
989 /* FIXME: Update the content type.
990 If pszPriType == NULL use 'application'
991 If pszSubType == NULL use 'octet-stream' */
993 return S_OK;
996 static HRESULT WINAPI MimeBody_EmptyData(
997 IMimeBody* iface)
999 FIXME("stub\n");
1000 return E_NOTIMPL;
1003 static HRESULT WINAPI MimeBody_CopyTo(
1004 IMimeBody* iface,
1005 IMimeBody* pBody)
1007 FIXME("stub\n");
1008 return E_NOTIMPL;
1011 static HRESULT WINAPI MimeBody_GetTransmitInfo(
1012 IMimeBody* iface,
1013 LPTRANSMITINFO pTransmitInfo)
1015 FIXME("stub\n");
1016 return E_NOTIMPL;
1019 static HRESULT WINAPI MimeBody_SaveToFile(
1020 IMimeBody* iface,
1021 ENCODINGTYPE ietEncoding,
1022 LPCSTR pszFilePath)
1024 FIXME("stub\n");
1025 return E_NOTIMPL;
1028 static HRESULT WINAPI MimeBody_GetHandle(
1029 IMimeBody* iface,
1030 LPHBODY phBody)
1032 MimeBody *This = impl_from_IMimeBody(iface);
1033 TRACE("(%p)->(%p)\n", iface, phBody);
1035 *phBody = This->handle;
1036 return This->handle ? S_OK : MIME_E_NO_DATA;
1039 static IMimeBodyVtbl body_vtbl =
1041 MimeBody_QueryInterface,
1042 MimeBody_AddRef,
1043 MimeBody_Release,
1044 MimeBody_GetClassID,
1045 MimeBody_IsDirty,
1046 MimeBody_Load,
1047 MimeBody_Save,
1048 MimeBody_GetSizeMax,
1049 MimeBody_InitNew,
1050 MimeBody_GetPropInfo,
1051 MimeBody_SetPropInfo,
1052 MimeBody_GetProp,
1053 MimeBody_SetProp,
1054 MimeBody_AppendProp,
1055 MimeBody_DeleteProp,
1056 MimeBody_CopyProps,
1057 MimeBody_MoveProps,
1058 MimeBody_DeleteExcept,
1059 MimeBody_QueryProp,
1060 MimeBody_GetCharset,
1061 MimeBody_SetCharset,
1062 MimeBody_GetParameters,
1063 MimeBody_IsContentType,
1064 MimeBody_BindToObject,
1065 MimeBody_Clone,
1066 MimeBody_SetOption,
1067 MimeBody_GetOption,
1068 MimeBody_EnumProps,
1069 MimeBody_IsType,
1070 MimeBody_SetDisplayName,
1071 MimeBody_GetDisplayName,
1072 MimeBody_GetOffsets,
1073 MimeBody_GetCurrentEncoding,
1074 MimeBody_SetCurrentEncoding,
1075 MimeBody_GetEstimatedSize,
1076 MimeBody_GetDataHere,
1077 MimeBody_GetData,
1078 MimeBody_SetData,
1079 MimeBody_EmptyData,
1080 MimeBody_CopyTo,
1081 MimeBody_GetTransmitInfo,
1082 MimeBody_SaveToFile,
1083 MimeBody_GetHandle
1086 static HRESULT MimeBody_set_offsets(MimeBody *body, const BODYOFFSETS *offsets)
1088 TRACE("setting offsets to %d, %d, %d, %d\n", offsets->cbBoundaryStart,
1089 offsets->cbHeaderStart, offsets->cbBodyStart, offsets->cbBodyEnd);
1091 body->body_offsets = *offsets;
1092 return S_OK;
1095 #define FIRST_CUSTOM_PROP_ID 0x100
1097 static MimeBody *mimebody_create(void)
1099 MimeBody *This;
1100 BODYOFFSETS body_offsets;
1102 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1103 if (!This)
1104 return NULL;
1106 This->IMimeBody_iface.lpVtbl = &body_vtbl;
1107 This->ref = 1;
1108 This->handle = NULL;
1109 list_init(&This->headers);
1110 list_init(&This->new_props);
1111 This->next_prop_id = FIRST_CUSTOM_PROP_ID;
1112 This->content_pri_type = NULL;
1113 This->content_sub_type = NULL;
1114 This->encoding = IET_7BIT;
1115 This->data = NULL;
1116 This->data_iid = IID_NULL;
1118 body_offsets.cbBoundaryStart = body_offsets.cbHeaderStart = 0;
1119 body_offsets.cbBodyStart = body_offsets.cbBodyEnd = 0;
1120 MimeBody_set_offsets(This, &body_offsets);
1122 return This;
1125 HRESULT MimeBody_create(IUnknown *outer, void **ppv)
1127 MimeBody *mb;
1129 if(outer)
1130 return CLASS_E_NOAGGREGATION;
1132 if ((mb = mimebody_create()))
1134 *ppv = &mb->IMimeBody_iface;
1135 return S_OK;
1137 else
1139 *ppv = NULL;
1140 return E_OUTOFMEMORY;
1146 typedef struct
1148 IStream IStream_iface;
1149 LONG ref;
1150 IStream *base;
1151 ULARGE_INTEGER pos, start, length;
1152 } sub_stream_t;
1154 static inline sub_stream_t *impl_from_IStream(IStream *iface)
1156 return CONTAINING_RECORD(iface, sub_stream_t, IStream_iface);
1159 static HRESULT WINAPI sub_stream_QueryInterface(IStream *iface, REFIID riid, void **ppv)
1161 sub_stream_t *This = impl_from_IStream(iface);
1163 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
1164 *ppv = NULL;
1166 if(IsEqualIID(riid, &IID_IUnknown) ||
1167 IsEqualIID(riid, &IID_ISequentialStream) ||
1168 IsEqualIID(riid, &IID_IStream))
1170 IStream_AddRef(iface);
1171 *ppv = iface;
1172 return S_OK;
1174 return E_NOINTERFACE;
1177 static ULONG WINAPI sub_stream_AddRef(IStream *iface)
1179 sub_stream_t *This = impl_from_IStream(iface);
1180 LONG ref = InterlockedIncrement(&This->ref);
1182 TRACE("(%p) ref=%d\n", This, ref);
1184 return ref;
1187 static ULONG WINAPI sub_stream_Release(IStream *iface)
1189 sub_stream_t *This = impl_from_IStream(iface);
1190 LONG ref = InterlockedDecrement(&This->ref);
1192 TRACE("(%p) ref=%d\n", This, ref);
1194 if(!ref)
1196 IStream_Release(This->base);
1197 HeapFree(GetProcessHeap(), 0, This);
1199 return ref;
1202 static HRESULT WINAPI sub_stream_Read(
1203 IStream* iface,
1204 void *pv,
1205 ULONG cb,
1206 ULONG *pcbRead)
1208 sub_stream_t *This = impl_from_IStream(iface);
1209 HRESULT hr;
1210 ULARGE_INTEGER base_pos;
1211 LARGE_INTEGER tmp_pos;
1213 TRACE("(%p, %d, %p)\n", pv, cb, pcbRead);
1215 tmp_pos.QuadPart = 0;
1216 IStream_Seek(This->base, tmp_pos, STREAM_SEEK_CUR, &base_pos);
1217 tmp_pos.QuadPart = This->pos.QuadPart + This->start.QuadPart;
1218 IStream_Seek(This->base, tmp_pos, STREAM_SEEK_SET, NULL);
1220 if(This->pos.QuadPart + cb > This->length.QuadPart)
1221 cb = This->length.QuadPart - This->pos.QuadPart;
1223 hr = IStream_Read(This->base, pv, cb, pcbRead);
1225 This->pos.QuadPart += *pcbRead;
1227 tmp_pos.QuadPart = base_pos.QuadPart;
1228 IStream_Seek(This->base, tmp_pos, STREAM_SEEK_SET, NULL);
1230 return hr;
1233 static HRESULT WINAPI sub_stream_Write(
1234 IStream* iface,
1235 const void *pv,
1236 ULONG cb,
1237 ULONG *pcbWritten)
1239 FIXME("stub\n");
1240 return E_NOTIMPL;
1243 static HRESULT WINAPI sub_stream_Seek(
1244 IStream* iface,
1245 LARGE_INTEGER dlibMove,
1246 DWORD dwOrigin,
1247 ULARGE_INTEGER *plibNewPosition)
1249 sub_stream_t *This = impl_from_IStream(iface);
1250 LARGE_INTEGER new_pos;
1252 TRACE("(%08x.%08x, %x, %p)\n", dlibMove.u.HighPart, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
1254 switch(dwOrigin)
1256 case STREAM_SEEK_SET:
1257 new_pos = dlibMove;
1258 break;
1259 case STREAM_SEEK_CUR:
1260 new_pos.QuadPart = This->pos.QuadPart + dlibMove.QuadPart;
1261 break;
1262 case STREAM_SEEK_END:
1263 new_pos.QuadPart = This->length.QuadPart + dlibMove.QuadPart;
1264 break;
1265 default:
1266 return STG_E_INVALIDFUNCTION;
1269 if(new_pos.QuadPart < 0) new_pos.QuadPart = 0;
1270 else if(new_pos.QuadPart > This->length.QuadPart) new_pos.QuadPart = This->length.QuadPart;
1272 This->pos.QuadPart = new_pos.QuadPart;
1274 if(plibNewPosition) *plibNewPosition = This->pos;
1275 return S_OK;
1278 static HRESULT WINAPI sub_stream_SetSize(
1279 IStream* iface,
1280 ULARGE_INTEGER libNewSize)
1282 FIXME("stub\n");
1283 return E_NOTIMPL;
1286 static HRESULT WINAPI sub_stream_CopyTo(
1287 IStream* iface,
1288 IStream *pstm,
1289 ULARGE_INTEGER cb,
1290 ULARGE_INTEGER *pcbRead,
1291 ULARGE_INTEGER *pcbWritten)
1293 HRESULT hr = S_OK;
1294 BYTE tmpBuffer[128];
1295 ULONG bytesRead, bytesWritten, copySize;
1296 ULARGE_INTEGER totalBytesRead;
1297 ULARGE_INTEGER totalBytesWritten;
1299 TRACE("(%p)->(%p, %d, %p, %p)\n", iface, pstm, cb.u.LowPart, pcbRead, pcbWritten);
1301 totalBytesRead.QuadPart = 0;
1302 totalBytesWritten.QuadPart = 0;
1304 while ( cb.QuadPart > 0 )
1306 if ( cb.QuadPart >= sizeof(tmpBuffer) )
1307 copySize = sizeof(tmpBuffer);
1308 else
1309 copySize = cb.u.LowPart;
1311 hr = IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
1312 if (FAILED(hr)) break;
1314 totalBytesRead.QuadPart += bytesRead;
1316 if (bytesRead)
1318 hr = IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
1319 if (FAILED(hr)) break;
1320 totalBytesWritten.QuadPart += bytesWritten;
1323 if (bytesRead != copySize)
1324 cb.QuadPart = 0;
1325 else
1326 cb.QuadPart -= bytesRead;
1329 if (pcbRead) pcbRead->QuadPart = totalBytesRead.QuadPart;
1330 if (pcbWritten) pcbWritten->QuadPart = totalBytesWritten.QuadPart;
1332 return hr;
1335 static HRESULT WINAPI sub_stream_Commit(
1336 IStream* iface,
1337 DWORD grfCommitFlags)
1339 FIXME("stub\n");
1340 return E_NOTIMPL;
1343 static HRESULT WINAPI sub_stream_Revert(
1344 IStream* iface)
1346 FIXME("stub\n");
1347 return E_NOTIMPL;
1350 static HRESULT WINAPI sub_stream_LockRegion(
1351 IStream* iface,
1352 ULARGE_INTEGER libOffset,
1353 ULARGE_INTEGER cb,
1354 DWORD dwLockType)
1356 FIXME("stub\n");
1357 return E_NOTIMPL;
1360 static HRESULT WINAPI sub_stream_UnlockRegion(
1361 IStream* iface,
1362 ULARGE_INTEGER libOffset,
1363 ULARGE_INTEGER cb,
1364 DWORD dwLockType)
1366 FIXME("stub\n");
1367 return E_NOTIMPL;
1370 static HRESULT WINAPI sub_stream_Stat(
1371 IStream* iface,
1372 STATSTG *pstatstg,
1373 DWORD grfStatFlag)
1375 sub_stream_t *This = impl_from_IStream(iface);
1376 FIXME("(%p)->(%p, %08x)\n", This, pstatstg, grfStatFlag);
1377 memset(pstatstg, 0, sizeof(*pstatstg));
1378 pstatstg->cbSize = This->length;
1379 return S_OK;
1382 static HRESULT WINAPI sub_stream_Clone(
1383 IStream* iface,
1384 IStream **ppstm)
1386 FIXME("stub\n");
1387 return E_NOTIMPL;
1390 static struct IStreamVtbl sub_stream_vtbl =
1392 sub_stream_QueryInterface,
1393 sub_stream_AddRef,
1394 sub_stream_Release,
1395 sub_stream_Read,
1396 sub_stream_Write,
1397 sub_stream_Seek,
1398 sub_stream_SetSize,
1399 sub_stream_CopyTo,
1400 sub_stream_Commit,
1401 sub_stream_Revert,
1402 sub_stream_LockRegion,
1403 sub_stream_UnlockRegion,
1404 sub_stream_Stat,
1405 sub_stream_Clone
1408 static HRESULT create_sub_stream(IStream *stream, ULARGE_INTEGER start, ULARGE_INTEGER length, IStream **out)
1410 sub_stream_t *This;
1412 *out = NULL;
1413 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1414 if(!This) return E_OUTOFMEMORY;
1416 This->IStream_iface.lpVtbl = &sub_stream_vtbl;
1417 This->ref = 1;
1418 This->start = start;
1419 This->length = length;
1420 This->pos.QuadPart = 0;
1421 IStream_AddRef(stream);
1422 This->base = stream;
1424 *out = &This->IStream_iface;
1425 return S_OK;
1429 typedef struct body_t
1431 struct list entry;
1432 DWORD index;
1433 MimeBody *mime_body;
1435 struct body_t *parent;
1436 struct list children;
1437 } body_t;
1439 typedef struct MimeMessage
1441 IMimeMessage IMimeMessage_iface;
1442 LONG ref;
1443 IStream *stream;
1445 struct list body_tree;
1446 DWORD next_index;
1447 } MimeMessage;
1449 static inline MimeMessage *impl_from_IMimeMessage(IMimeMessage *iface)
1451 return CONTAINING_RECORD(iface, MimeMessage, IMimeMessage_iface);
1454 static HRESULT WINAPI MimeMessage_QueryInterface(IMimeMessage *iface, REFIID riid, void **ppv)
1456 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1458 if (IsEqualIID(riid, &IID_IUnknown) ||
1459 IsEqualIID(riid, &IID_IPersist) ||
1460 IsEqualIID(riid, &IID_IPersistStreamInit) ||
1461 IsEqualIID(riid, &IID_IMimeMessageTree) ||
1462 IsEqualIID(riid, &IID_IMimeMessage))
1464 *ppv = iface;
1465 IMimeMessage_AddRef(iface);
1466 return S_OK;
1469 FIXME("no interface for %s\n", debugstr_guid(riid));
1470 *ppv = NULL;
1471 return E_NOINTERFACE;
1474 static ULONG WINAPI MimeMessage_AddRef(IMimeMessage *iface)
1476 MimeMessage *This = impl_from_IMimeMessage(iface);
1477 ULONG ref = InterlockedIncrement(&This->ref);
1479 TRACE("(%p) ref=%d\n", This, ref);
1481 return ref;
1484 static void empty_body_list(struct list *list)
1486 body_t *body, *cursor2;
1487 LIST_FOR_EACH_ENTRY_SAFE(body, cursor2, list, body_t, entry)
1489 empty_body_list(&body->children);
1490 list_remove(&body->entry);
1491 IMimeBody_Release(&body->mime_body->IMimeBody_iface);
1492 HeapFree(GetProcessHeap(), 0, body);
1496 static ULONG WINAPI MimeMessage_Release(IMimeMessage *iface)
1498 MimeMessage *This = impl_from_IMimeMessage(iface);
1499 ULONG ref = InterlockedDecrement(&This->ref);
1501 TRACE("(%p) ref=%d\n", This, ref);
1503 if (!ref)
1505 empty_body_list(&This->body_tree);
1507 if(This->stream) IStream_Release(This->stream);
1508 HeapFree(GetProcessHeap(), 0, This);
1511 return ref;
1514 /*** IPersist methods ***/
1515 static HRESULT WINAPI MimeMessage_GetClassID(
1516 IMimeMessage *iface,
1517 CLSID *pClassID)
1519 FIXME("(%p)->(%p)\n", iface, pClassID);
1520 return E_NOTIMPL;
1523 /*** IPersistStreamInit methods ***/
1524 static HRESULT WINAPI MimeMessage_IsDirty(
1525 IMimeMessage *iface)
1527 FIXME("(%p)->()\n", iface);
1528 return E_NOTIMPL;
1531 static body_t *new_body_entry(MimeBody *mime_body, DWORD index, body_t *parent)
1533 body_t *body = HeapAlloc(GetProcessHeap(), 0, sizeof(*body));
1534 if(body)
1536 body->mime_body = mime_body;
1537 body->index = index;
1538 list_init(&body->children);
1539 body->parent = parent;
1541 return body;
1544 typedef struct
1546 struct list entry;
1547 BODYOFFSETS offsets;
1548 } offset_entry_t;
1550 static HRESULT create_body_offset_list(IStream *stm, const char *boundary, struct list *body_offsets)
1552 HRESULT hr;
1553 DWORD read;
1554 int boundary_len = strlen(boundary);
1555 char *buf, *nl_boundary, *ptr, *overlap;
1556 DWORD start = 0, overlap_no;
1557 offset_entry_t *cur_body = NULL;
1558 ULARGE_INTEGER cur;
1559 LARGE_INTEGER zero;
1561 list_init(body_offsets);
1562 nl_boundary = HeapAlloc(GetProcessHeap(), 0, 4 + boundary_len + 1);
1563 memcpy(nl_boundary, "\r\n--", 4);
1564 memcpy(nl_boundary + 4, boundary, boundary_len + 1);
1566 overlap_no = boundary_len + 5;
1568 overlap = buf = HeapAlloc(GetProcessHeap(), 0, overlap_no + PARSER_BUF_SIZE + 1);
1570 zero.QuadPart = 0;
1571 hr = IStream_Seek(stm, zero, STREAM_SEEK_CUR, &cur);
1572 start = cur.u.LowPart;
1574 do {
1575 hr = IStream_Read(stm, overlap, PARSER_BUF_SIZE, &read);
1576 if(FAILED(hr)) goto end;
1577 if(read == 0) break;
1578 overlap[read] = '\0';
1580 ptr = buf;
1581 do {
1582 ptr = strstr(ptr, nl_boundary);
1583 if(ptr)
1585 DWORD boundary_start = start + ptr - buf;
1586 char *end = ptr + boundary_len + 4;
1588 if(*end == '\0' || *(end + 1) == '\0')
1589 break;
1591 if(*end == '\r' && *(end + 1) == '\n')
1593 if(cur_body)
1595 cur_body->offsets.cbBodyEnd = boundary_start;
1596 list_add_tail(body_offsets, &cur_body->entry);
1598 cur_body = HeapAlloc(GetProcessHeap(), 0, sizeof(*cur_body));
1599 cur_body->offsets.cbBoundaryStart = boundary_start + 2; /* doesn't including the leading \r\n */
1600 cur_body->offsets.cbHeaderStart = boundary_start + boundary_len + 6;
1602 else if(*end == '-' && *(end + 1) == '-')
1604 if(cur_body)
1606 cur_body->offsets.cbBodyEnd = boundary_start;
1607 list_add_tail(body_offsets, &cur_body->entry);
1608 goto end;
1611 ptr = end + 2;
1613 } while(ptr);
1615 if(overlap == buf) /* 1st iteration */
1617 memcpy(buf, buf + PARSER_BUF_SIZE - overlap_no, overlap_no);
1618 overlap = buf + overlap_no;
1619 start += read - overlap_no;
1621 else
1623 memcpy(buf, buf + PARSER_BUF_SIZE, overlap_no);
1624 start += read;
1626 } while(1);
1628 end:
1629 HeapFree(GetProcessHeap(), 0, nl_boundary);
1630 HeapFree(GetProcessHeap(), 0, buf);
1631 return hr;
1634 static body_t *create_sub_body(MimeMessage *msg, IStream *pStm, BODYOFFSETS *offset, body_t *parent)
1636 MimeBody *mime_body;
1637 HRESULT hr;
1638 body_t *body;
1639 ULARGE_INTEGER cur;
1640 LARGE_INTEGER zero;
1642 mime_body = mimebody_create();
1643 IMimeBody_Load(&mime_body->IMimeBody_iface, pStm);
1644 zero.QuadPart = 0;
1645 hr = IStream_Seek(pStm, zero, STREAM_SEEK_CUR, &cur);
1646 offset->cbBodyStart = cur.u.LowPart + offset->cbHeaderStart;
1647 if (parent) MimeBody_set_offsets(mime_body, offset);
1648 IMimeBody_SetData(&mime_body->IMimeBody_iface, IET_BINARY, NULL, NULL, &IID_IStream, pStm);
1649 body = new_body_entry(mime_body, msg->next_index++, parent);
1651 if(IMimeBody_IsContentType(&mime_body->IMimeBody_iface, "multipart", NULL) == S_OK)
1653 MIMEPARAMINFO *param_info;
1654 ULONG count, i;
1655 IMimeAllocator *alloc;
1657 hr = IMimeBody_GetParameters(&mime_body->IMimeBody_iface, "Content-Type", &count,
1658 &param_info);
1659 if(hr != S_OK || count == 0) return body;
1661 MimeOleGetAllocator(&alloc);
1663 for(i = 0; i < count; i++)
1665 if(!strcasecmp(param_info[i].pszName, "boundary"))
1667 struct list offset_list;
1668 offset_entry_t *cur, *cursor2;
1669 hr = create_body_offset_list(pStm, param_info[i].pszData, &offset_list);
1670 LIST_FOR_EACH_ENTRY_SAFE(cur, cursor2, &offset_list, offset_entry_t, entry)
1672 body_t *sub_body;
1673 IStream *sub_stream;
1674 ULARGE_INTEGER start, length;
1676 start.QuadPart = cur->offsets.cbHeaderStart;
1677 length.QuadPart = cur->offsets.cbBodyEnd - cur->offsets.cbHeaderStart;
1678 create_sub_stream(pStm, start, length, &sub_stream);
1679 sub_body = create_sub_body(msg, sub_stream, &cur->offsets, body);
1680 IStream_Release(sub_stream);
1681 list_add_tail(&body->children, &sub_body->entry);
1682 list_remove(&cur->entry);
1683 HeapFree(GetProcessHeap(), 0, cur);
1685 break;
1688 IMimeAllocator_FreeParamInfoArray(alloc, count, param_info, TRUE);
1689 IMimeAllocator_Release(alloc);
1691 return body;
1694 static HRESULT WINAPI MimeMessage_Load(IMimeMessage *iface, IStream *pStm)
1696 MimeMessage *This = impl_from_IMimeMessage(iface);
1697 body_t *root_body;
1698 BODYOFFSETS offsets;
1699 ULARGE_INTEGER cur;
1700 LARGE_INTEGER zero;
1702 TRACE("(%p)->(%p)\n", iface, pStm);
1704 if(This->stream)
1706 FIXME("already loaded a message\n");
1707 return E_FAIL;
1710 IStream_AddRef(pStm);
1711 This->stream = pStm;
1712 offsets.cbBoundaryStart = offsets.cbHeaderStart = 0;
1713 offsets.cbBodyStart = offsets.cbBodyEnd = 0;
1715 root_body = create_sub_body(This, pStm, &offsets, NULL);
1717 zero.QuadPart = 0;
1718 IStream_Seek(pStm, zero, STREAM_SEEK_END, &cur);
1719 offsets.cbBodyEnd = cur.u.LowPart;
1720 MimeBody_set_offsets(root_body->mime_body, &offsets);
1722 list_add_head(&This->body_tree, &root_body->entry);
1724 return S_OK;
1727 static HRESULT WINAPI MimeMessage_Save(IMimeMessage *iface, IStream *pStm, BOOL fClearDirty)
1729 FIXME("(%p)->(%p, %s)\n", iface, pStm, fClearDirty ? "TRUE" : "FALSE");
1730 return E_NOTIMPL;
1733 static HRESULT WINAPI MimeMessage_GetSizeMax(
1734 IMimeMessage *iface,
1735 ULARGE_INTEGER *pcbSize)
1737 FIXME("(%p)->(%p)\n", iface, pcbSize);
1738 return E_NOTIMPL;
1741 static HRESULT WINAPI MimeMessage_InitNew(
1742 IMimeMessage *iface)
1744 FIXME("(%p)->()\n", iface);
1745 return E_NOTIMPL;
1748 /*** IMimeMessageTree methods ***/
1749 static HRESULT WINAPI MimeMessage_GetMessageSource(IMimeMessage *iface, IStream **ppStream,
1750 DWORD dwFlags)
1752 MimeMessage *This = impl_from_IMimeMessage(iface);
1754 FIXME("(%p)->(%p, 0x%x)\n", iface, ppStream, dwFlags);
1756 IStream_AddRef(This->stream);
1757 *ppStream = This->stream;
1758 return S_OK;
1761 static HRESULT WINAPI MimeMessage_GetMessageSize(
1762 IMimeMessage *iface,
1763 ULONG *pcbSize,
1764 DWORD dwFlags)
1766 FIXME("(%p)->(%p, 0x%x)\n", iface, pcbSize, dwFlags);
1767 return E_NOTIMPL;
1770 static HRESULT WINAPI MimeMessage_LoadOffsetTable(
1771 IMimeMessage *iface,
1772 IStream *pStream)
1774 FIXME("(%p)->(%p)\n", iface, pStream);
1775 return E_NOTIMPL;
1778 static HRESULT WINAPI MimeMessage_SaveOffsetTable(
1779 IMimeMessage *iface,
1780 IStream *pStream,
1781 DWORD dwFlags)
1783 FIXME("(%p)->(%p, 0x%x)\n", iface, pStream, dwFlags);
1784 return E_NOTIMPL;
1788 static HRESULT WINAPI MimeMessage_GetFlags(
1789 IMimeMessage *iface,
1790 DWORD *pdwFlags)
1792 FIXME("(%p)->(%p)\n", iface, pdwFlags);
1793 return E_NOTIMPL;
1796 static HRESULT WINAPI MimeMessage_Commit(
1797 IMimeMessage *iface,
1798 DWORD dwFlags)
1800 FIXME("(%p)->(0x%x)\n", iface, dwFlags);
1801 return E_NOTIMPL;
1805 static HRESULT WINAPI MimeMessage_HandsOffStorage(
1806 IMimeMessage *iface)
1808 FIXME("(%p)->()\n", iface);
1809 return E_NOTIMPL;
1812 static HRESULT find_body(struct list *list, HBODY hbody, body_t **body)
1814 body_t *cur;
1815 HRESULT hr;
1817 if(hbody == HBODY_ROOT)
1819 *body = LIST_ENTRY(list_head(list), body_t, entry);
1820 return S_OK;
1823 LIST_FOR_EACH_ENTRY(cur, list, body_t, entry)
1825 if(cur->index == HandleToUlong(hbody))
1827 *body = cur;
1828 return S_OK;
1830 hr = find_body(&cur->children, hbody, body);
1831 if(hr == S_OK) return S_OK;
1833 return S_FALSE;
1836 static HRESULT WINAPI MimeMessage_BindToObject(IMimeMessage *iface, const HBODY hBody, REFIID riid,
1837 void **ppvObject)
1839 MimeMessage *This = impl_from_IMimeMessage(iface);
1840 HRESULT hr;
1841 body_t *body;
1843 TRACE("(%p)->(%p, %s, %p)\n", iface, hBody, debugstr_guid(riid), ppvObject);
1845 hr = find_body(&This->body_tree, hBody, &body);
1847 if(hr != S_OK) return hr;
1849 if(IsEqualIID(riid, &IID_IMimeBody))
1851 IMimeBody_AddRef(&body->mime_body->IMimeBody_iface);
1852 *ppvObject = &body->mime_body->IMimeBody_iface;
1853 return S_OK;
1856 return E_NOINTERFACE;
1859 static HRESULT WINAPI MimeMessage_SaveBody(
1860 IMimeMessage *iface,
1861 HBODY hBody,
1862 DWORD dwFlags,
1863 IStream *pStream)
1865 FIXME("(%p)->(%p, 0x%x, %p)\n", iface, hBody, dwFlags, pStream);
1866 return E_NOTIMPL;
1869 static HRESULT get_body(MimeMessage *msg, BODYLOCATION location, HBODY pivot, body_t **out)
1871 body_t *root = LIST_ENTRY(list_head(&msg->body_tree), body_t, entry);
1872 body_t *body;
1873 HRESULT hr;
1874 struct list *list;
1876 if(location == IBL_ROOT)
1878 *out = root;
1879 return S_OK;
1882 hr = find_body(&msg->body_tree, pivot, &body);
1884 if(hr == S_OK)
1886 switch(location)
1888 case IBL_PARENT:
1889 *out = body->parent;
1890 break;
1892 case IBL_FIRST:
1893 list = list_head(&body->children);
1894 if(list)
1895 *out = LIST_ENTRY(list, body_t, entry);
1896 else
1897 hr = MIME_E_NOT_FOUND;
1898 break;
1900 case IBL_LAST:
1901 list = list_tail(&body->children);
1902 if(list)
1903 *out = LIST_ENTRY(list, body_t, entry);
1904 else
1905 hr = MIME_E_NOT_FOUND;
1906 break;
1908 case IBL_NEXT:
1909 list = list_next(&body->parent->children, &body->entry);
1910 if(list)
1911 *out = LIST_ENTRY(list, body_t, entry);
1912 else
1913 hr = MIME_E_NOT_FOUND;
1914 break;
1916 case IBL_PREVIOUS:
1917 list = list_prev(&body->parent->children, &body->entry);
1918 if(list)
1919 *out = LIST_ENTRY(list, body_t, entry);
1920 else
1921 hr = MIME_E_NOT_FOUND;
1922 break;
1924 default:
1925 hr = E_FAIL;
1926 break;
1930 return hr;
1934 static HRESULT WINAPI MimeMessage_InsertBody(
1935 IMimeMessage *iface,
1936 BODYLOCATION location,
1937 HBODY hPivot,
1938 LPHBODY phBody)
1940 FIXME("(%p)->(%d, %p, %p)\n", iface, location, hPivot, phBody);
1941 return E_NOTIMPL;
1944 static HRESULT WINAPI MimeMessage_GetBody(IMimeMessage *iface, BODYLOCATION location, HBODY hPivot,
1945 HBODY *phBody)
1947 MimeMessage *This = impl_from_IMimeMessage(iface);
1948 body_t *body;
1949 HRESULT hr;
1951 TRACE("(%p)->(%d, %p, %p)\n", iface, location, hPivot, phBody);
1953 hr = get_body(This, location, hPivot, &body);
1955 if(hr == S_OK) *phBody = UlongToHandle(body->index);
1957 return hr;
1960 static HRESULT WINAPI MimeMessage_DeleteBody(
1961 IMimeMessage *iface,
1962 HBODY hBody,
1963 DWORD dwFlags)
1965 FIXME("(%p)->(%p, %08x)\n", iface, hBody, dwFlags);
1966 return E_NOTIMPL;
1969 static HRESULT WINAPI MimeMessage_MoveBody(
1970 IMimeMessage *iface,
1971 HBODY hBody,
1972 BODYLOCATION location)
1974 FIXME("(%p)->(%d)\n", iface, location);
1975 return E_NOTIMPL;
1978 static void count_children(body_t *body, boolean recurse, ULONG *count)
1980 body_t *child;
1982 LIST_FOR_EACH_ENTRY(child, &body->children, body_t, entry)
1984 (*count)++;
1985 if(recurse) count_children(child, recurse, count);
1989 static HRESULT WINAPI MimeMessage_CountBodies(IMimeMessage *iface, HBODY hParent, boolean fRecurse,
1990 ULONG *pcBodies)
1992 HRESULT hr;
1993 MimeMessage *This = impl_from_IMimeMessage(iface);
1994 body_t *body;
1996 TRACE("(%p)->(%p, %s, %p)\n", iface, hParent, fRecurse ? "TRUE" : "FALSE", pcBodies);
1998 hr = find_body(&This->body_tree, hParent, &body);
1999 if(hr != S_OK) return hr;
2001 *pcBodies = 1;
2002 count_children(body, fRecurse, pcBodies);
2004 return S_OK;
2007 static HRESULT find_next(MimeMessage *This, body_t *body, FINDBODY *find, HBODY *out)
2009 struct list *ptr;
2010 HBODY next;
2012 for (;;)
2014 if (!body) ptr = list_head( &This->body_tree );
2015 else
2017 ptr = list_head( &body->children );
2018 while (!ptr)
2020 if (!body->parent) return MIME_E_NOT_FOUND;
2021 if (!(ptr = list_next( &body->parent->children, &body->entry ))) body = body->parent;
2025 body = LIST_ENTRY( ptr, body_t, entry );
2026 next = UlongToHandle( body->index );
2027 find->dwReserved = body->index;
2028 if (IMimeBody_IsContentType(&body->mime_body->IMimeBody_iface, find->pszPriType,
2029 find->pszSubType) == S_OK)
2031 *out = next;
2032 return S_OK;
2035 return MIME_E_NOT_FOUND;
2038 static HRESULT WINAPI MimeMessage_FindFirst(IMimeMessage *iface, FINDBODY *pFindBody, HBODY *phBody)
2040 MimeMessage *This = impl_from_IMimeMessage(iface);
2042 TRACE("(%p)->(%p, %p)\n", iface, pFindBody, phBody);
2044 pFindBody->dwReserved = 0;
2045 return find_next(This, NULL, pFindBody, phBody);
2048 static HRESULT WINAPI MimeMessage_FindNext(IMimeMessage *iface, FINDBODY *pFindBody, HBODY *phBody)
2050 MimeMessage *This = impl_from_IMimeMessage(iface);
2051 body_t *body;
2052 HRESULT hr;
2054 TRACE("(%p)->(%p, %p)\n", iface, pFindBody, phBody);
2056 hr = find_body( &This->body_tree, UlongToHandle( pFindBody->dwReserved ), &body );
2057 if (hr != S_OK) return MIME_E_NOT_FOUND;
2058 return find_next(This, body, pFindBody, phBody);
2061 static HRESULT WINAPI MimeMessage_ResolveURL(
2062 IMimeMessage *iface,
2063 HBODY hRelated,
2064 LPCSTR pszBase,
2065 LPCSTR pszURL,
2066 DWORD dwFlags,
2067 LPHBODY phBody)
2069 FIXME("(%p)->(%p, %s, %s, 0x%x, %p)\n", iface, hRelated, pszBase, pszURL, dwFlags, phBody);
2070 return E_NOTIMPL;
2073 static HRESULT WINAPI MimeMessage_ToMultipart(
2074 IMimeMessage *iface,
2075 HBODY hBody,
2076 LPCSTR pszSubType,
2077 LPHBODY phMultipart)
2079 FIXME("(%p)->(%p, %s, %p)\n", iface, hBody, pszSubType, phMultipart);
2080 return E_NOTIMPL;
2083 static HRESULT WINAPI MimeMessage_GetBodyOffsets(
2084 IMimeMessage *iface,
2085 HBODY hBody,
2086 LPBODYOFFSETS pOffsets)
2088 FIXME("(%p)->(%p, %p)\n", iface, hBody, pOffsets);
2089 return E_NOTIMPL;
2092 static HRESULT WINAPI MimeMessage_GetCharset(
2093 IMimeMessage *iface,
2094 LPHCHARSET phCharset)
2096 FIXME("(%p)->(%p)\n", iface, phCharset);
2097 *phCharset = NULL;
2098 return S_OK;
2101 static HRESULT WINAPI MimeMessage_SetCharset(
2102 IMimeMessage *iface,
2103 HCHARSET hCharset,
2104 CSETAPPLYTYPE applytype)
2106 FIXME("(%p)->(%p, %d)\n", iface, hCharset, applytype);
2107 return E_NOTIMPL;
2110 static HRESULT WINAPI MimeMessage_IsBodyType(
2111 IMimeMessage *iface,
2112 HBODY hBody,
2113 IMSGBODYTYPE bodytype)
2115 HRESULT hr;
2116 IMimeBody *mime_body;
2117 TRACE("(%p)->(%p, %d)\n", iface, hBody, bodytype);
2119 hr = IMimeMessage_BindToObject(iface, hBody, &IID_IMimeBody, (void**)&mime_body);
2120 if(hr != S_OK) return hr;
2122 hr = IMimeBody_IsType(mime_body, bodytype);
2123 MimeBody_Release(mime_body);
2124 return hr;
2127 static HRESULT WINAPI MimeMessage_IsContentType(
2128 IMimeMessage *iface,
2129 HBODY hBody,
2130 LPCSTR pszPriType,
2131 LPCSTR pszSubType)
2133 HRESULT hr;
2134 IMimeBody *mime_body;
2135 TRACE("(%p)->(%p, %s, %s)\n", iface, hBody, debugstr_a(pszPriType),
2136 debugstr_a(pszSubType));
2138 hr = IMimeMessage_BindToObject(iface, hBody, &IID_IMimeBody, (void**)&mime_body);
2139 if(FAILED(hr)) return hr;
2141 hr = IMimeBody_IsContentType(mime_body, pszPriType, pszSubType);
2142 IMimeBody_Release(mime_body);
2143 return hr;
2146 static HRESULT WINAPI MimeMessage_QueryBodyProp(
2147 IMimeMessage *iface,
2148 HBODY hBody,
2149 LPCSTR pszName,
2150 LPCSTR pszCriteria,
2151 boolean fSubString,
2152 boolean fCaseSensitive)
2154 FIXME("(%p)->(%p, %s, %s, %s, %s)\n", iface, hBody, pszName, pszCriteria, fSubString ? "TRUE" : "FALSE", fCaseSensitive ? "TRUE" : "FALSE");
2155 return E_NOTIMPL;
2158 static HRESULT WINAPI MimeMessage_GetBodyProp(
2159 IMimeMessage *iface,
2160 HBODY hBody,
2161 LPCSTR pszName,
2162 DWORD dwFlags,
2163 LPPROPVARIANT pValue)
2165 HRESULT hr;
2166 IMimeBody *mime_body;
2168 TRACE("(%p)->(%p, %s, 0x%x, %p)\n", iface, hBody, pszName, dwFlags, pValue);
2170 hr = IMimeMessage_BindToObject(iface, hBody, &IID_IMimeBody, (void**)&mime_body);
2171 if(hr != S_OK) return hr;
2173 hr = IMimeBody_GetProp(mime_body, pszName, dwFlags, pValue);
2174 IMimeBody_Release(mime_body);
2176 return hr;
2179 static HRESULT WINAPI MimeMessage_SetBodyProp(
2180 IMimeMessage *iface,
2181 HBODY hBody,
2182 LPCSTR pszName,
2183 DWORD dwFlags,
2184 LPCPROPVARIANT pValue)
2186 FIXME("(%p)->(%p, %s, 0x%x, %p)\n", iface, hBody, pszName, dwFlags, pValue);
2187 return E_NOTIMPL;
2190 static HRESULT WINAPI MimeMessage_DeleteBodyProp(
2191 IMimeMessage *iface,
2192 HBODY hBody,
2193 LPCSTR pszName)
2195 FIXME("(%p)->(%p, %s)\n", iface, hBody, pszName);
2196 return E_NOTIMPL;
2199 static HRESULT WINAPI MimeMessage_SetOption(
2200 IMimeMessage *iface,
2201 const TYPEDID oid,
2202 LPCPROPVARIANT pValue)
2204 HRESULT hr = E_NOTIMPL;
2205 TRACE("(%p)->(%08x, %p)\n", iface, oid, pValue);
2207 if(pValue->vt != TYPEDID_TYPE(oid))
2209 WARN("Called with vartype %04x and oid %08x\n", pValue->vt, oid);
2210 return E_INVALIDARG;
2213 switch(oid)
2215 case OID_HIDE_TNEF_ATTACHMENTS:
2216 FIXME("OID_HIDE_TNEF_ATTACHMENTS (value %d): ignoring\n", pValue->u.boolVal);
2217 hr = S_OK;
2218 break;
2219 case OID_SHOW_MACBINARY:
2220 FIXME("OID_SHOW_MACBINARY (value %d): ignoring\n", pValue->u.boolVal);
2221 hr = S_OK;
2222 break;
2223 default:
2224 FIXME("Unhandled oid %08x\n", oid);
2227 return hr;
2230 static HRESULT WINAPI MimeMessage_GetOption(
2231 IMimeMessage *iface,
2232 const TYPEDID oid,
2233 LPPROPVARIANT pValue)
2235 FIXME("(%p)->(%08x, %p)\n", iface, oid, pValue);
2236 return E_NOTIMPL;
2239 /*** IMimeMessage methods ***/
2240 static HRESULT WINAPI MimeMessage_CreateWebPage(
2241 IMimeMessage *iface,
2242 IStream *pRootStm,
2243 LPWEBPAGEOPTIONS pOptions,
2244 IMimeMessageCallback *pCallback,
2245 IMoniker **ppMoniker)
2247 FIXME("(%p)->(%p, %p, %p, %p)\n", iface, pRootStm, pOptions, pCallback, ppMoniker);
2248 *ppMoniker = NULL;
2249 return E_NOTIMPL;
2252 static HRESULT WINAPI MimeMessage_GetProp(
2253 IMimeMessage *iface,
2254 LPCSTR pszName,
2255 DWORD dwFlags,
2256 LPPROPVARIANT pValue)
2258 FIXME("(%p)->(%s, 0x%x, %p)\n", iface, pszName, dwFlags, pValue);
2259 return E_NOTIMPL;
2262 static HRESULT WINAPI MimeMessage_SetProp(
2263 IMimeMessage *iface,
2264 LPCSTR pszName,
2265 DWORD dwFlags,
2266 LPCPROPVARIANT pValue)
2268 FIXME("(%p)->(%s, 0x%x, %p)\n", iface, pszName, dwFlags, pValue);
2269 return E_NOTIMPL;
2272 static HRESULT WINAPI MimeMessage_DeleteProp(
2273 IMimeMessage *iface,
2274 LPCSTR pszName)
2276 FIXME("(%p)->(%s)\n", iface, pszName);
2277 return E_NOTIMPL;
2280 static HRESULT WINAPI MimeMessage_QueryProp(
2281 IMimeMessage *iface,
2282 LPCSTR pszName,
2283 LPCSTR pszCriteria,
2284 boolean fSubString,
2285 boolean fCaseSensitive)
2287 FIXME("(%p)->(%s, %s, %s, %s)\n", iface, pszName, pszCriteria, fSubString ? "TRUE" : "FALSE", fCaseSensitive ? "TRUE" : "FALSE");
2288 return E_NOTIMPL;
2291 static HRESULT WINAPI MimeMessage_GetTextBody(
2292 IMimeMessage *iface,
2293 DWORD dwTxtType,
2294 ENCODINGTYPE ietEncoding,
2295 IStream **pStream,
2296 LPHBODY phBody)
2298 HRESULT hr;
2299 HBODY hbody;
2300 FINDBODY find_struct;
2301 IMimeBody *mime_body;
2302 static char text[] = "text";
2303 static char plain[] = "plain";
2304 static char html[] = "html";
2306 TRACE("(%p)->(%d, %d, %p, %p)\n", iface, dwTxtType, ietEncoding, pStream, phBody);
2308 find_struct.pszPriType = text;
2310 switch(dwTxtType)
2312 case TXT_PLAIN:
2313 find_struct.pszSubType = plain;
2314 break;
2315 case TXT_HTML:
2316 find_struct.pszSubType = html;
2317 break;
2318 default:
2319 return MIME_E_INVALID_TEXT_TYPE;
2322 hr = IMimeMessage_FindFirst(iface, &find_struct, &hbody);
2323 if(hr != S_OK)
2325 TRACE("not found hr %08x\n", hr);
2326 *phBody = NULL;
2327 return hr;
2330 IMimeMessage_BindToObject(iface, hbody, &IID_IMimeBody, (void**)&mime_body);
2332 IMimeBody_GetData(mime_body, ietEncoding, pStream);
2333 *phBody = hbody;
2334 IMimeBody_Release(mime_body);
2335 return hr;
2338 static HRESULT WINAPI MimeMessage_SetTextBody(
2339 IMimeMessage *iface,
2340 DWORD dwTxtType,
2341 ENCODINGTYPE ietEncoding,
2342 HBODY hAlternative,
2343 IStream *pStream,
2344 LPHBODY phBody)
2346 FIXME("(%p)->(%d, %d, %p, %p, %p)\n", iface, dwTxtType, ietEncoding, hAlternative, pStream, phBody);
2347 return E_NOTIMPL;
2350 static HRESULT WINAPI MimeMessage_AttachObject(
2351 IMimeMessage *iface,
2352 REFIID riid,
2353 void *pvObject,
2354 LPHBODY phBody)
2356 FIXME("(%p)->(%s, %p, %p)\n", iface, debugstr_guid(riid), pvObject, phBody);
2357 return E_NOTIMPL;
2360 static HRESULT WINAPI MimeMessage_AttachFile(
2361 IMimeMessage *iface,
2362 LPCSTR pszFilePath,
2363 IStream *pstmFile,
2364 LPHBODY phBody)
2366 FIXME("(%p)->(%s, %p, %p)\n", iface, pszFilePath, pstmFile, phBody);
2367 return E_NOTIMPL;
2370 static HRESULT WINAPI MimeMessage_AttachURL(
2371 IMimeMessage *iface,
2372 LPCSTR pszBase,
2373 LPCSTR pszURL,
2374 DWORD dwFlags,
2375 IStream *pstmURL,
2376 LPSTR *ppszCIDURL,
2377 LPHBODY phBody)
2379 FIXME("(%p)->(%s, %s, 0x%x, %p, %p, %p)\n", iface, pszBase, pszURL, dwFlags, pstmURL, ppszCIDURL, phBody);
2380 return E_NOTIMPL;
2383 static HRESULT WINAPI MimeMessage_GetAttachments(
2384 IMimeMessage *iface,
2385 ULONG *pcAttach,
2386 LPHBODY *pprghAttach)
2388 HRESULT hr;
2389 FINDBODY find_struct;
2390 HBODY hbody;
2391 LPHBODY array;
2392 ULONG size = 10;
2394 TRACE("(%p)->(%p, %p)\n", iface, pcAttach, pprghAttach);
2396 *pcAttach = 0;
2397 array = CoTaskMemAlloc(size * sizeof(HBODY));
2399 find_struct.pszPriType = find_struct.pszSubType = NULL;
2400 hr = IMimeMessage_FindFirst(iface, &find_struct, &hbody);
2401 while(hr == S_OK)
2403 hr = IMimeMessage_IsContentType(iface, hbody, "multipart", NULL);
2404 TRACE("IsCT rets %08x %d\n", hr, *pcAttach);
2405 if(hr != S_OK)
2407 if(*pcAttach + 1 > size)
2409 size *= 2;
2410 array = CoTaskMemRealloc(array, size * sizeof(HBODY));
2412 array[*pcAttach] = hbody;
2413 (*pcAttach)++;
2415 hr = IMimeMessage_FindNext(iface, &find_struct, &hbody);
2418 *pprghAttach = array;
2419 return S_OK;
2422 static HRESULT WINAPI MimeMessage_GetAddressTable(
2423 IMimeMessage *iface,
2424 IMimeAddressTable **ppTable)
2426 FIXME("(%p)->(%p)\n", iface, ppTable);
2427 return E_NOTIMPL;
2430 static HRESULT WINAPI MimeMessage_GetSender(
2431 IMimeMessage *iface,
2432 LPADDRESSPROPS pAddress)
2434 FIXME("(%p)->(%p)\n", iface, pAddress);
2435 return E_NOTIMPL;
2438 static HRESULT WINAPI MimeMessage_GetAddressTypes(
2439 IMimeMessage *iface,
2440 DWORD dwAdrTypes,
2441 DWORD dwProps,
2442 LPADDRESSLIST pList)
2444 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, dwProps, pList);
2445 return E_NOTIMPL;
2448 static HRESULT WINAPI MimeMessage_GetAddressFormat(
2449 IMimeMessage *iface,
2450 DWORD dwAdrTypes,
2451 ADDRESSFORMAT format,
2452 LPSTR *ppszFormat)
2454 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, format, ppszFormat);
2455 return E_NOTIMPL;
2458 static HRESULT WINAPI MimeMessage_EnumAddressTypes(
2459 IMimeMessage *iface,
2460 DWORD dwAdrTypes,
2461 DWORD dwProps,
2462 IMimeEnumAddressTypes **ppEnum)
2464 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, dwProps, ppEnum);
2465 return E_NOTIMPL;
2468 static HRESULT WINAPI MimeMessage_SplitMessage(
2469 IMimeMessage *iface,
2470 ULONG cbMaxPart,
2471 IMimeMessageParts **ppParts)
2473 FIXME("(%p)->(%d, %p)\n", iface, cbMaxPart, ppParts);
2474 return E_NOTIMPL;
2477 static HRESULT WINAPI MimeMessage_GetRootMoniker(
2478 IMimeMessage *iface,
2479 IMoniker **ppMoniker)
2481 FIXME("(%p)->(%p)\n", iface, ppMoniker);
2482 return E_NOTIMPL;
2485 static const IMimeMessageVtbl MimeMessageVtbl =
2487 MimeMessage_QueryInterface,
2488 MimeMessage_AddRef,
2489 MimeMessage_Release,
2490 MimeMessage_GetClassID,
2491 MimeMessage_IsDirty,
2492 MimeMessage_Load,
2493 MimeMessage_Save,
2494 MimeMessage_GetSizeMax,
2495 MimeMessage_InitNew,
2496 MimeMessage_GetMessageSource,
2497 MimeMessage_GetMessageSize,
2498 MimeMessage_LoadOffsetTable,
2499 MimeMessage_SaveOffsetTable,
2500 MimeMessage_GetFlags,
2501 MimeMessage_Commit,
2502 MimeMessage_HandsOffStorage,
2503 MimeMessage_BindToObject,
2504 MimeMessage_SaveBody,
2505 MimeMessage_InsertBody,
2506 MimeMessage_GetBody,
2507 MimeMessage_DeleteBody,
2508 MimeMessage_MoveBody,
2509 MimeMessage_CountBodies,
2510 MimeMessage_FindFirst,
2511 MimeMessage_FindNext,
2512 MimeMessage_ResolveURL,
2513 MimeMessage_ToMultipart,
2514 MimeMessage_GetBodyOffsets,
2515 MimeMessage_GetCharset,
2516 MimeMessage_SetCharset,
2517 MimeMessage_IsBodyType,
2518 MimeMessage_IsContentType,
2519 MimeMessage_QueryBodyProp,
2520 MimeMessage_GetBodyProp,
2521 MimeMessage_SetBodyProp,
2522 MimeMessage_DeleteBodyProp,
2523 MimeMessage_SetOption,
2524 MimeMessage_GetOption,
2525 MimeMessage_CreateWebPage,
2526 MimeMessage_GetProp,
2527 MimeMessage_SetProp,
2528 MimeMessage_DeleteProp,
2529 MimeMessage_QueryProp,
2530 MimeMessage_GetTextBody,
2531 MimeMessage_SetTextBody,
2532 MimeMessage_AttachObject,
2533 MimeMessage_AttachFile,
2534 MimeMessage_AttachURL,
2535 MimeMessage_GetAttachments,
2536 MimeMessage_GetAddressTable,
2537 MimeMessage_GetSender,
2538 MimeMessage_GetAddressTypes,
2539 MimeMessage_GetAddressFormat,
2540 MimeMessage_EnumAddressTypes,
2541 MimeMessage_SplitMessage,
2542 MimeMessage_GetRootMoniker,
2545 HRESULT MimeMessage_create(IUnknown *outer, void **obj)
2547 MimeMessage *This;
2549 TRACE("(%p, %p)\n", outer, obj);
2551 if (outer)
2553 FIXME("outer unknown not supported yet\n");
2554 return E_NOTIMPL;
2557 *obj = NULL;
2559 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2560 if (!This) return E_OUTOFMEMORY;
2562 This->IMimeMessage_iface.lpVtbl = &MimeMessageVtbl;
2563 This->ref = 1;
2564 This->stream = NULL;
2565 list_init(&This->body_tree);
2566 This->next_index = 1;
2568 *obj = &This->IMimeMessage_iface;
2569 return S_OK;
2572 /***********************************************************************
2573 * MimeOleCreateMessage (INETCOMM.@)
2575 HRESULT WINAPI MimeOleCreateMessage(IUnknown *pUnkOuter, IMimeMessage **ppMessage)
2577 TRACE("(%p, %p)\n", pUnkOuter, ppMessage);
2578 return MimeMessage_create(NULL, (void **)ppMessage);
2581 /***********************************************************************
2582 * MimeOleSetCompatMode (INETCOMM.@)
2584 HRESULT WINAPI MimeOleSetCompatMode(DWORD dwMode)
2586 FIXME("(0x%x)\n", dwMode);
2587 return S_OK;
2590 /***********************************************************************
2591 * MimeOleCreateVirtualStream (INETCOMM.@)
2593 HRESULT WINAPI MimeOleCreateVirtualStream(IStream **ppStream)
2595 HRESULT hr;
2596 FIXME("(%p)\n", ppStream);
2598 hr = CreateStreamOnHGlobal(NULL, TRUE, ppStream);
2599 return hr;
2602 typedef struct MimeSecurity
2604 IMimeSecurity IMimeSecurity_iface;
2605 LONG ref;
2606 } MimeSecurity;
2608 static inline MimeSecurity *impl_from_IMimeSecurity(IMimeSecurity *iface)
2610 return CONTAINING_RECORD(iface, MimeSecurity, IMimeSecurity_iface);
2613 static HRESULT WINAPI MimeSecurity_QueryInterface(IMimeSecurity *iface, REFIID riid, void **ppv)
2615 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2617 if (IsEqualIID(riid, &IID_IUnknown) ||
2618 IsEqualIID(riid, &IID_IMimeSecurity))
2620 *ppv = iface;
2621 IMimeSecurity_AddRef(iface);
2622 return S_OK;
2625 FIXME("no interface for %s\n", debugstr_guid(riid));
2626 *ppv = NULL;
2627 return E_NOINTERFACE;
2630 static ULONG WINAPI MimeSecurity_AddRef(IMimeSecurity *iface)
2632 MimeSecurity *This = impl_from_IMimeSecurity(iface);
2633 LONG ref = InterlockedIncrement(&This->ref);
2635 TRACE("(%p) ref=%d\n", This, ref);
2637 return ref;
2640 static ULONG WINAPI MimeSecurity_Release(IMimeSecurity *iface)
2642 MimeSecurity *This = impl_from_IMimeSecurity(iface);
2643 LONG ref = InterlockedDecrement(&This->ref);
2645 TRACE("(%p) ref=%d\n", This, ref);
2647 if (!ref)
2648 HeapFree(GetProcessHeap(), 0, This);
2650 return ref;
2653 static HRESULT WINAPI MimeSecurity_InitNew(
2654 IMimeSecurity* iface)
2656 FIXME("(%p)->(): stub\n", iface);
2657 return S_OK;
2660 static HRESULT WINAPI MimeSecurity_CheckInit(
2661 IMimeSecurity* iface)
2663 FIXME("(%p)->(): stub\n", iface);
2664 return E_NOTIMPL;
2667 static HRESULT WINAPI MimeSecurity_EncodeMessage(
2668 IMimeSecurity* iface,
2669 IMimeMessageTree* pTree,
2670 DWORD dwFlags)
2672 FIXME("(%p)->(%p, %08x): stub\n", iface, pTree, dwFlags);
2673 return E_NOTIMPL;
2676 static HRESULT WINAPI MimeSecurity_EncodeBody(
2677 IMimeSecurity* iface,
2678 IMimeMessageTree* pTree,
2679 HBODY hEncodeRoot,
2680 DWORD dwFlags)
2682 FIXME("(%p)->(%p, %p, %08x): stub\n", iface, pTree, hEncodeRoot, dwFlags);
2683 return E_NOTIMPL;
2686 static HRESULT WINAPI MimeSecurity_DecodeMessage(
2687 IMimeSecurity* iface,
2688 IMimeMessageTree* pTree,
2689 DWORD dwFlags)
2691 FIXME("(%p)->(%p, %08x): stub\n", iface, pTree, dwFlags);
2692 return E_NOTIMPL;
2695 static HRESULT WINAPI MimeSecurity_DecodeBody(
2696 IMimeSecurity* iface,
2697 IMimeMessageTree* pTree,
2698 HBODY hDecodeRoot,
2699 DWORD dwFlags)
2701 FIXME("(%p)->(%p, %p, %08x): stub\n", iface, pTree, hDecodeRoot, dwFlags);
2702 return E_NOTIMPL;
2705 static HRESULT WINAPI MimeSecurity_EnumCertificates(
2706 IMimeSecurity* iface,
2707 HCAPICERTSTORE hc,
2708 DWORD dwUsage,
2709 PCX509CERT pPrev,
2710 PCX509CERT* ppCert)
2712 FIXME("(%p)->(%p, %08x, %p, %p): stub\n", iface, hc, dwUsage, pPrev, ppCert);
2713 return E_NOTIMPL;
2716 static HRESULT WINAPI MimeSecurity_GetCertificateName(
2717 IMimeSecurity* iface,
2718 const PCX509CERT pX509Cert,
2719 const CERTNAMETYPE cn,
2720 LPSTR* ppszName)
2722 FIXME("(%p)->(%p, %08x, %p): stub\n", iface, pX509Cert, cn, ppszName);
2723 return E_NOTIMPL;
2726 static HRESULT WINAPI MimeSecurity_GetMessageType(
2727 IMimeSecurity* iface,
2728 const HWND hwndParent,
2729 IMimeBody* pBody,
2730 DWORD* pdwSecType)
2732 FIXME("(%p)->(%p, %p, %p): stub\n", iface, hwndParent, pBody, pdwSecType);
2733 return E_NOTIMPL;
2736 static HRESULT WINAPI MimeSecurity_GetCertData(
2737 IMimeSecurity* iface,
2738 const PCX509CERT pX509Cert,
2739 const CERTDATAID dataid,
2740 LPPROPVARIANT pValue)
2742 FIXME("(%p)->(%p, %x, %p): stub\n", iface, pX509Cert, dataid, pValue);
2743 return E_NOTIMPL;
2747 static const IMimeSecurityVtbl MimeSecurityVtbl =
2749 MimeSecurity_QueryInterface,
2750 MimeSecurity_AddRef,
2751 MimeSecurity_Release,
2752 MimeSecurity_InitNew,
2753 MimeSecurity_CheckInit,
2754 MimeSecurity_EncodeMessage,
2755 MimeSecurity_EncodeBody,
2756 MimeSecurity_DecodeMessage,
2757 MimeSecurity_DecodeBody,
2758 MimeSecurity_EnumCertificates,
2759 MimeSecurity_GetCertificateName,
2760 MimeSecurity_GetMessageType,
2761 MimeSecurity_GetCertData
2764 HRESULT MimeSecurity_create(IUnknown *outer, void **obj)
2766 MimeSecurity *This;
2768 *obj = NULL;
2770 if (outer) return CLASS_E_NOAGGREGATION;
2772 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2773 if (!This) return E_OUTOFMEMORY;
2775 This->IMimeSecurity_iface.lpVtbl = &MimeSecurityVtbl;
2776 This->ref = 1;
2778 *obj = &This->IMimeSecurity_iface;
2779 return S_OK;
2782 /***********************************************************************
2783 * MimeOleCreateSecurity (INETCOMM.@)
2785 HRESULT WINAPI MimeOleCreateSecurity(IMimeSecurity **ppSecurity)
2787 return MimeSecurity_create(NULL, (void **)ppSecurity);
2790 static HRESULT WINAPI MimeAlloc_QueryInterface(
2791 IMimeAllocator* iface,
2792 REFIID riid,
2793 void **obj)
2795 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), obj);
2797 if (IsEqualIID(riid, &IID_IUnknown) ||
2798 IsEqualIID(riid, &IID_IMalloc) ||
2799 IsEqualIID(riid, &IID_IMimeAllocator))
2801 *obj = iface;
2802 IMimeAllocator_AddRef(iface);
2803 return S_OK;
2806 FIXME("no interface for %s\n", debugstr_guid(riid));
2807 *obj = NULL;
2808 return E_NOINTERFACE;
2811 static ULONG WINAPI MimeAlloc_AddRef(
2812 IMimeAllocator* iface)
2814 return 2;
2817 static ULONG WINAPI MimeAlloc_Release(
2818 IMimeAllocator* iface)
2820 return 1;
2823 static LPVOID WINAPI MimeAlloc_Alloc(
2824 IMimeAllocator* iface,
2825 ULONG cb)
2827 return CoTaskMemAlloc(cb);
2830 static LPVOID WINAPI MimeAlloc_Realloc(
2831 IMimeAllocator* iface,
2832 LPVOID pv,
2833 ULONG cb)
2835 return CoTaskMemRealloc(pv, cb);
2838 static void WINAPI MimeAlloc_Free(
2839 IMimeAllocator* iface,
2840 LPVOID pv)
2842 CoTaskMemFree(pv);
2845 static ULONG WINAPI MimeAlloc_GetSize(
2846 IMimeAllocator* iface,
2847 LPVOID pv)
2849 FIXME("stub\n");
2850 return 0;
2853 static int WINAPI MimeAlloc_DidAlloc(
2854 IMimeAllocator* iface,
2855 LPVOID pv)
2857 FIXME("stub\n");
2858 return 0;
2861 static void WINAPI MimeAlloc_HeapMinimize(
2862 IMimeAllocator* iface)
2864 FIXME("stub\n");
2865 return;
2868 static HRESULT WINAPI MimeAlloc_FreeParamInfoArray(
2869 IMimeAllocator* iface,
2870 ULONG cParams,
2871 LPMIMEPARAMINFO prgParam,
2872 boolean fFreeArray)
2874 ULONG i;
2875 TRACE("(%p)->(%d, %p, %d)\n", iface, cParams, prgParam, fFreeArray);
2877 for(i = 0; i < cParams; i++)
2879 IMimeAllocator_Free(iface, prgParam[i].pszName);
2880 IMimeAllocator_Free(iface, prgParam[i].pszData);
2882 if(fFreeArray) IMimeAllocator_Free(iface, prgParam);
2883 return S_OK;
2886 static HRESULT WINAPI MimeAlloc_FreeAddressList(
2887 IMimeAllocator* iface,
2888 LPADDRESSLIST pList)
2890 FIXME("stub\n");
2891 return E_NOTIMPL;
2894 static HRESULT WINAPI MimeAlloc_FreeAddressProps(
2895 IMimeAllocator* iface,
2896 LPADDRESSPROPS pAddress)
2898 FIXME("stub\n");
2899 return E_NOTIMPL;
2902 static HRESULT WINAPI MimeAlloc_ReleaseObjects(
2903 IMimeAllocator* iface,
2904 ULONG cObjects,
2905 IUnknown **prgpUnknown,
2906 boolean fFreeArray)
2908 FIXME("stub\n");
2909 return E_NOTIMPL;
2913 static HRESULT WINAPI MimeAlloc_FreeEnumHeaderRowArray(
2914 IMimeAllocator* iface,
2915 ULONG cRows,
2916 LPENUMHEADERROW prgRow,
2917 boolean fFreeArray)
2919 FIXME("stub\n");
2920 return E_NOTIMPL;
2923 static HRESULT WINAPI MimeAlloc_FreeEnumPropertyArray(
2924 IMimeAllocator* iface,
2925 ULONG cProps,
2926 LPENUMPROPERTY prgProp,
2927 boolean fFreeArray)
2929 FIXME("stub\n");
2930 return E_NOTIMPL;
2933 static HRESULT WINAPI MimeAlloc_FreeThumbprint(
2934 IMimeAllocator* iface,
2935 THUMBBLOB *pthumbprint)
2937 FIXME("stub\n");
2938 return E_NOTIMPL;
2942 static HRESULT WINAPI MimeAlloc_PropVariantClear(
2943 IMimeAllocator* iface,
2944 LPPROPVARIANT pProp)
2946 FIXME("stub\n");
2947 return E_NOTIMPL;
2950 static IMimeAllocatorVtbl mime_alloc_vtbl =
2952 MimeAlloc_QueryInterface,
2953 MimeAlloc_AddRef,
2954 MimeAlloc_Release,
2955 MimeAlloc_Alloc,
2956 MimeAlloc_Realloc,
2957 MimeAlloc_Free,
2958 MimeAlloc_GetSize,
2959 MimeAlloc_DidAlloc,
2960 MimeAlloc_HeapMinimize,
2961 MimeAlloc_FreeParamInfoArray,
2962 MimeAlloc_FreeAddressList,
2963 MimeAlloc_FreeAddressProps,
2964 MimeAlloc_ReleaseObjects,
2965 MimeAlloc_FreeEnumHeaderRowArray,
2966 MimeAlloc_FreeEnumPropertyArray,
2967 MimeAlloc_FreeThumbprint,
2968 MimeAlloc_PropVariantClear
2971 static IMimeAllocator mime_allocator =
2973 &mime_alloc_vtbl
2976 HRESULT MimeAllocator_create(IUnknown *outer, void **obj)
2978 if(outer) return CLASS_E_NOAGGREGATION;
2980 *obj = &mime_allocator;
2981 return S_OK;
2984 HRESULT WINAPI MimeOleGetAllocator(IMimeAllocator **alloc)
2986 return MimeAllocator_create(NULL, (void**)alloc);
2989 HRESULT VirtualStream_create(IUnknown *outer, void **obj)
2991 FIXME("(%p, %p)\n", outer, obj);
2993 *obj = NULL;
2994 if (outer) return CLASS_E_NOAGGREGATION;
2996 return MimeOleCreateVirtualStream((IStream **)obj);