powrprof: Stub PowerSetActiveScheme.
[wine.git] / dlls / inetcomm / mimeole.c
blob14739abda97931c859314cc6f970e98cb30489a4
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 typedef struct propschema
120 IMimePropertySchema IMimePropertySchema_iface;
121 LONG ref;
122 } propschema;
124 static inline propschema *impl_from_IMimePropertySchema(IMimePropertySchema *iface)
126 return CONTAINING_RECORD(iface, propschema, IMimePropertySchema_iface);
129 static LPSTR strdupA(LPCSTR str)
131 char *ret;
132 int len = strlen(str);
133 ret = HeapAlloc(GetProcessHeap(), 0, len + 1);
134 memcpy(ret, str, len + 1);
135 return ret;
138 #define PARSER_BUF_SIZE 1024
140 /*****************************************************
141 * copy_headers_to_buf [internal]
143 * Copies the headers into a '\0' terminated memory block and leave
144 * the stream's current position set to after the blank line.
146 static HRESULT copy_headers_to_buf(IStream *stm, char **ptr)
148 char *buf = NULL;
149 DWORD size = PARSER_BUF_SIZE, offset = 0, last_end = 0;
150 HRESULT hr;
151 BOOL done = FALSE;
153 *ptr = NULL;
157 char *end;
158 DWORD read;
160 if(!buf)
161 buf = HeapAlloc(GetProcessHeap(), 0, size + 1);
162 else
164 size *= 2;
165 buf = HeapReAlloc(GetProcessHeap(), 0, buf, size + 1);
167 if(!buf)
169 hr = E_OUTOFMEMORY;
170 goto fail;
173 hr = IStream_Read(stm, buf + offset, size - offset, &read);
174 if(FAILED(hr)) goto fail;
176 offset += read;
177 buf[offset] = '\0';
179 if(read == 0) done = TRUE;
181 while(!done && (end = strstr(buf + last_end, "\r\n")))
183 DWORD new_end = end - buf + 2;
184 if(new_end - last_end == 2)
186 LARGE_INTEGER off;
187 off.QuadPart = new_end;
188 IStream_Seek(stm, off, STREAM_SEEK_SET, NULL);
189 buf[new_end] = '\0';
190 done = TRUE;
192 else
193 last_end = new_end;
195 } while(!done);
197 *ptr = buf;
198 return S_OK;
200 fail:
201 HeapFree(GetProcessHeap(), 0, buf);
202 return hr;
205 static header_t *read_prop(MimeBody *body, char **ptr)
207 char *colon = strchr(*ptr, ':');
208 const property_t *prop;
209 header_t *ret;
211 if(!colon) return NULL;
213 *colon = '\0';
215 for(prop = default_props; prop->name; prop++)
217 if(!lstrcmpiA(*ptr, prop->name))
219 TRACE("%s: found match with default property id %d\n", *ptr, prop->id);
220 break;
224 if(!prop->name)
226 property_list_entry_t *prop_entry;
227 LIST_FOR_EACH_ENTRY(prop_entry, &body->new_props, property_list_entry_t, entry)
229 if(!lstrcmpiA(*ptr, prop_entry->prop.name))
231 TRACE("%s: found match with already added new property id %d\n", *ptr, prop_entry->prop.id);
232 prop = &prop_entry->prop;
233 break;
236 if(!prop->name)
238 prop_entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*prop_entry));
239 prop_entry->prop.name = strdupA(*ptr);
240 prop_entry->prop.id = body->next_prop_id++;
241 prop_entry->prop.flags = 0;
242 prop_entry->prop.default_vt = VT_LPSTR;
243 list_add_tail(&body->new_props, &prop_entry->entry);
244 prop = &prop_entry->prop;
245 TRACE("%s: allocating new prop id %d\n", *ptr, prop_entry->prop.id);
249 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(*ret));
250 ret->prop = prop;
251 PropVariantInit(&ret->value);
252 list_init(&ret->params);
253 *ptr = colon + 1;
255 return ret;
258 static void unfold_header(char *header, int len)
260 char *start = header, *cp = header;
262 do {
263 while(*cp == ' ' || *cp == '\t')
265 cp++;
266 len--;
268 if(cp != start)
269 memmove(start, cp, len + 1);
271 cp = strstr(start, "\r\n");
272 len -= (cp - start);
273 start = cp;
274 *start = ' ';
275 start++;
276 len--;
277 cp += 2;
278 } while(*cp == ' ' || *cp == '\t');
280 *(start - 1) = '\0';
283 static char *unquote_string(const char *str)
285 BOOL quoted = FALSE;
286 char *ret, *cp;
288 while(*str == ' ' || *str == '\t') str++;
290 if(*str == '"')
292 quoted = TRUE;
293 str++;
295 ret = strdupA(str);
296 for(cp = ret; *cp; cp++)
298 if(*cp == '\\')
299 memmove(cp, cp + 1, strlen(cp + 1) + 1);
300 else if(*cp == '"')
302 if(!quoted)
304 WARN("quote in unquoted string\n");
306 else
308 *cp = '\0';
309 break;
313 return ret;
316 static void add_param(header_t *header, const char *p)
318 const char *key = p, *value, *cp = p;
319 param_t *param;
320 char *name;
322 TRACE("got param %s\n", p);
324 while (*key == ' ' || *key == '\t' ) key++;
326 cp = strchr(key, '=');
327 if(!cp)
329 WARN("malformed parameter - skipping\n");
330 return;
333 name = HeapAlloc(GetProcessHeap(), 0, cp - key + 1);
334 memcpy(name, key, cp - key);
335 name[cp - key] = '\0';
337 value = cp + 1;
339 param = HeapAlloc(GetProcessHeap(), 0, sizeof(*param));
340 param->name = name;
341 param->value = unquote_string(value);
342 list_add_tail(&header->params, &param->entry);
345 static void split_params(header_t *header, char *value)
347 char *cp = value, *start = value;
348 BOOL in_quotes = FALSE, done_value = FALSE;
350 while(*cp)
352 if(!in_quotes && *cp == ';')
354 *cp = '\0';
355 if(done_value) add_param(header, start);
356 done_value = TRUE;
357 start = cp + 1;
359 else if(*cp == '"')
360 in_quotes = !in_quotes;
361 cp++;
363 if(done_value) add_param(header, start);
366 static void read_value(header_t *header, char **cur)
368 char *end = *cur, *value;
369 DWORD len;
371 do {
372 end = strstr(end, "\r\n");
373 end += 2;
374 } while(*end == ' ' || *end == '\t');
376 len = end - *cur;
377 value = HeapAlloc(GetProcessHeap(), 0, len + 1);
378 memcpy(value, *cur, len);
379 value[len] = '\0';
381 unfold_header(value, len);
382 TRACE("value %s\n", debugstr_a(value));
384 if(header->prop->flags & MPF_HASPARAMS)
386 split_params(header, value);
387 TRACE("value w/o params %s\n", debugstr_a(value));
390 header->value.vt = VT_LPSTR;
391 header->value.u.pszVal = value;
393 *cur = end;
396 static void init_content_type(MimeBody *body, header_t *header)
398 char *slash;
399 DWORD len;
401 if(header->prop->id != PID_HDR_CNTTYPE)
403 ERR("called with header %s\n", header->prop->name);
404 return;
407 slash = strchr(header->value.u.pszVal, '/');
408 if(!slash)
410 WARN("malformed context type value\n");
411 return;
413 len = slash - header->value.u.pszVal;
414 body->content_pri_type = HeapAlloc(GetProcessHeap(), 0, len + 1);
415 memcpy(body->content_pri_type, header->value.u.pszVal, len);
416 body->content_pri_type[len] = '\0';
417 body->content_sub_type = strdupA(slash + 1);
420 static HRESULT parse_headers(MimeBody *body, IStream *stm)
422 char *header_buf, *cur_header_ptr;
423 HRESULT hr;
424 header_t *header;
426 hr = copy_headers_to_buf(stm, &header_buf);
427 if(FAILED(hr)) return hr;
429 cur_header_ptr = header_buf;
430 while((header = read_prop(body, &cur_header_ptr)))
432 read_value(header, &cur_header_ptr);
433 list_add_tail(&body->headers, &header->entry);
435 if(header->prop->id == PID_HDR_CNTTYPE)
436 init_content_type(body, header);
439 HeapFree(GetProcessHeap(), 0, header_buf);
440 return hr;
443 static void empty_param_list(struct list *list)
445 param_t *param, *cursor2;
447 LIST_FOR_EACH_ENTRY_SAFE(param, cursor2, list, param_t, entry)
449 list_remove(&param->entry);
450 HeapFree(GetProcessHeap(), 0, param->name);
451 HeapFree(GetProcessHeap(), 0, param->value);
452 HeapFree(GetProcessHeap(), 0, param);
456 static void empty_header_list(struct list *list)
458 header_t *header, *cursor2;
460 LIST_FOR_EACH_ENTRY_SAFE(header, cursor2, list, header_t, entry)
462 list_remove(&header->entry);
463 PropVariantClear(&header->value);
464 empty_param_list(&header->params);
465 HeapFree(GetProcessHeap(), 0, header);
469 static void empty_new_prop_list(struct list *list)
471 property_list_entry_t *prop, *cursor2;
473 LIST_FOR_EACH_ENTRY_SAFE(prop, cursor2, list, property_list_entry_t, entry)
475 list_remove(&prop->entry);
476 HeapFree(GetProcessHeap(), 0, (char *)prop->prop.name);
477 HeapFree(GetProcessHeap(), 0, prop);
481 static void release_data(REFIID riid, void *data)
483 if(!data) return;
485 if(IsEqualIID(riid, &IID_IStream))
486 IStream_Release((IStream *)data);
487 else
488 FIXME("Unhandled data format %s\n", debugstr_guid(riid));
491 static HRESULT find_prop(MimeBody *body, const char *name, header_t **prop)
493 header_t *header;
495 *prop = NULL;
497 LIST_FOR_EACH_ENTRY(header, &body->headers, header_t, entry)
499 if(!lstrcmpiA(name, header->prop->name))
501 *prop = header;
502 return S_OK;
506 return MIME_E_NOT_FOUND;
509 static HRESULT WINAPI MimeBody_QueryInterface(IMimeBody* iface,
510 REFIID riid,
511 void** ppvObject)
513 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppvObject);
515 *ppvObject = NULL;
517 if (IsEqualIID(riid, &IID_IUnknown) ||
518 IsEqualIID(riid, &IID_IPersist) ||
519 IsEqualIID(riid, &IID_IPersistStreamInit) ||
520 IsEqualIID(riid, &IID_IMimePropertySet) ||
521 IsEqualIID(riid, &IID_IMimeBody))
523 *ppvObject = iface;
526 if(*ppvObject)
528 IUnknown_AddRef((IUnknown*)*ppvObject);
529 return S_OK;
532 FIXME("no interface for %s\n", debugstr_guid(riid));
533 return E_NOINTERFACE;
536 static ULONG WINAPI MimeBody_AddRef(IMimeBody *iface)
538 MimeBody *This = impl_from_IMimeBody(iface);
539 LONG ref = InterlockedIncrement(&This->ref);
541 TRACE("(%p) ref=%d\n", This, ref);
543 return ref;
546 static ULONG WINAPI MimeBody_Release(IMimeBody *iface)
548 MimeBody *This = impl_from_IMimeBody(iface);
549 LONG ref = InterlockedDecrement(&This->ref);
551 TRACE("(%p) ref=%d\n", This, ref);
553 if (!ref)
555 empty_header_list(&This->headers);
556 empty_new_prop_list(&This->new_props);
558 HeapFree(GetProcessHeap(), 0, This->content_pri_type);
559 HeapFree(GetProcessHeap(), 0, This->content_sub_type);
561 release_data(&This->data_iid, This->data);
563 HeapFree(GetProcessHeap(), 0, This);
566 return ref;
569 static HRESULT WINAPI MimeBody_GetClassID(
570 IMimeBody* iface,
571 CLSID* pClassID)
573 MimeBody *This = impl_from_IMimeBody(iface);
574 FIXME("(%p)->(%p) stub\n", This, pClassID);
575 return E_NOTIMPL;
579 static HRESULT WINAPI MimeBody_IsDirty(
580 IMimeBody* iface)
582 MimeBody *This = impl_from_IMimeBody(iface);
583 FIXME("(%p)->() stub\n", This);
584 return E_NOTIMPL;
587 static HRESULT WINAPI MimeBody_Load(IMimeBody *iface, IStream *pStm)
589 MimeBody *This = impl_from_IMimeBody(iface);
590 TRACE("(%p)->(%p)\n", This, pStm);
591 return parse_headers(This, pStm);
594 static HRESULT WINAPI MimeBody_Save(IMimeBody *iface, IStream *pStm, BOOL fClearDirty)
596 MimeBody *This = impl_from_IMimeBody(iface);
597 FIXME("(%p)->(%p, %d)\n", This, pStm, fClearDirty);
598 return E_NOTIMPL;
601 static HRESULT WINAPI MimeBody_GetSizeMax(
602 IMimeBody* iface,
603 ULARGE_INTEGER* pcbSize)
605 MimeBody *This = impl_from_IMimeBody(iface);
606 FIXME("(%p)->(%p) stub\n", This, pcbSize);
607 return E_NOTIMPL;
610 static HRESULT WINAPI MimeBody_InitNew(
611 IMimeBody* iface)
613 MimeBody *This = impl_from_IMimeBody(iface);
614 TRACE("(%p)->()\n", This);
615 return S_OK;
618 static HRESULT WINAPI MimeBody_GetPropInfo(
619 IMimeBody* iface,
620 LPCSTR pszName,
621 LPMIMEPROPINFO pInfo)
623 MimeBody *This = impl_from_IMimeBody(iface);
624 FIXME("(%p)->(%s, %p) stub\n", This, debugstr_a(pszName), pInfo);
625 return E_NOTIMPL;
628 static HRESULT WINAPI MimeBody_SetPropInfo(
629 IMimeBody* iface,
630 LPCSTR pszName,
631 LPCMIMEPROPINFO pInfo)
633 MimeBody *This = impl_from_IMimeBody(iface);
634 FIXME("(%p)->(%s, %p) stub\n", This, debugstr_a(pszName), pInfo);
635 return E_NOTIMPL;
638 static HRESULT WINAPI MimeBody_GetProp(
639 IMimeBody* iface,
640 LPCSTR pszName,
641 DWORD dwFlags,
642 LPPROPVARIANT pValue)
644 MimeBody *This = impl_from_IMimeBody(iface);
645 header_t *header;
646 HRESULT hr;
648 TRACE("(%p)->(%s, 0x%x, %p)\n", This, debugstr_a(pszName), dwFlags, pValue);
650 if(!pszName || !pValue)
651 return E_INVALIDARG;
653 if(!lstrcmpiA(pszName, "att:pri-content-type"))
655 PropVariantClear(pValue);
656 pValue->vt = VT_LPSTR;
657 pValue->u.pszVal = strdupA(This->content_pri_type);
658 return S_OK;
661 hr = find_prop(This, pszName, &header);
662 if(hr == S_OK)
664 PropVariantCopy(pValue, &header->value);
667 return hr;
670 static HRESULT WINAPI MimeBody_SetProp(
671 IMimeBody* iface,
672 LPCSTR pszName,
673 DWORD dwFlags,
674 LPCPROPVARIANT pValue)
676 MimeBody *This = impl_from_IMimeBody(iface);
677 header_t *header;
678 HRESULT hr;
680 TRACE("(%p)->(%s, 0x%x, %p)\n", This, debugstr_a(pszName), dwFlags, pValue);
682 if(!pszName || !pValue)
683 return E_INVALIDARG;
685 hr = find_prop(This, pszName, &header);
686 if(hr != S_OK)
688 property_list_entry_t *prop_entry;
689 const property_t *prop = NULL;
691 LIST_FOR_EACH_ENTRY(prop_entry, &This->new_props, property_list_entry_t, entry)
693 if(!lstrcmpiA(pszName, prop_entry->prop.name))
695 TRACE("Found match with already added new property id %d\n", prop_entry->prop.id);
696 prop = &prop_entry->prop;
697 break;
701 header = HeapAlloc(GetProcessHeap(), 0, sizeof(*header));
702 if(!header)
703 return E_OUTOFMEMORY;
705 if(!prop)
707 prop_entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*prop_entry));
708 if(!prop_entry)
710 HeapFree(GetProcessHeap(), 0, header);
711 return E_OUTOFMEMORY;
713 prop_entry->prop.name = strdupA(pszName);
714 prop_entry->prop.id = This->next_prop_id++;
715 prop_entry->prop.flags = 0;
716 prop_entry->prop.default_vt = pValue->vt;
717 list_add_tail(&This->new_props, &prop_entry->entry);
718 prop = &prop_entry->prop;
719 TRACE("Allocating new prop id %d\n", prop_entry->prop.id);
722 header->prop = prop;
723 PropVariantInit(&header->value);
724 list_init(&header->params);
725 list_add_tail(&This->headers, &header->entry);
728 PropVariantCopy(&header->value, pValue);
730 return S_OK;
733 static HRESULT WINAPI MimeBody_AppendProp(
734 IMimeBody* iface,
735 LPCSTR pszName,
736 DWORD dwFlags,
737 LPPROPVARIANT pValue)
739 MimeBody *This = impl_from_IMimeBody(iface);
740 FIXME("(%p)->(%s, 0x%x, %p) stub\n", This, debugstr_a(pszName), dwFlags, pValue);
741 return E_NOTIMPL;
744 static HRESULT WINAPI MimeBody_DeleteProp(
745 IMimeBody* iface,
746 LPCSTR pszName)
748 MimeBody *This = impl_from_IMimeBody(iface);
749 FIXME("(%p)->(%s) stub\n", This, debugstr_a(pszName));
750 return E_NOTIMPL;
753 static HRESULT WINAPI MimeBody_CopyProps(
754 IMimeBody* iface,
755 ULONG cNames,
756 LPCSTR* prgszName,
757 IMimePropertySet* pPropertySet)
759 MimeBody *This = impl_from_IMimeBody(iface);
760 FIXME("(%p)->(%d, %p, %p) stub\n", This, cNames, prgszName, pPropertySet);
761 return E_NOTIMPL;
764 static HRESULT WINAPI MimeBody_MoveProps(
765 IMimeBody* iface,
766 ULONG cNames,
767 LPCSTR* prgszName,
768 IMimePropertySet* pPropertySet)
770 MimeBody *This = impl_from_IMimeBody(iface);
771 FIXME("(%p)->(%d, %p, %p) stub\n", This, cNames, prgszName, pPropertySet);
772 return E_NOTIMPL;
775 static HRESULT WINAPI MimeBody_DeleteExcept(
776 IMimeBody* iface,
777 ULONG cNames,
778 LPCSTR* prgszName)
780 MimeBody *This = impl_from_IMimeBody(iface);
781 FIXME("(%p)->(%d, %p) stub\n", This, cNames, prgszName);
782 return E_NOTIMPL;
785 static HRESULT WINAPI MimeBody_QueryProp(
786 IMimeBody* iface,
787 LPCSTR pszName,
788 LPCSTR pszCriteria,
789 boolean fSubString,
790 boolean fCaseSensitive)
792 MimeBody *This = impl_from_IMimeBody(iface);
793 FIXME("(%p)->(%s, %s, %d, %d) stub\n", This, debugstr_a(pszName), debugstr_a(pszCriteria), fSubString, fCaseSensitive);
794 return E_NOTIMPL;
797 static HRESULT WINAPI MimeBody_GetCharset(
798 IMimeBody* iface,
799 LPHCHARSET phCharset)
801 MimeBody *This = impl_from_IMimeBody(iface);
802 FIXME("(%p)->(%p) stub\n", This, phCharset);
803 *phCharset = NULL;
804 return S_OK;
807 static HRESULT WINAPI MimeBody_SetCharset(
808 IMimeBody* iface,
809 HCHARSET hCharset,
810 CSETAPPLYTYPE applytype)
812 MimeBody *This = impl_from_IMimeBody(iface);
813 FIXME("(%p)->(%p, %d) stub\n", This, hCharset, applytype);
814 return E_NOTIMPL;
817 static HRESULT WINAPI MimeBody_GetParameters(
818 IMimeBody* iface,
819 LPCSTR pszName,
820 ULONG* pcParams,
821 LPMIMEPARAMINFO* pprgParam)
823 MimeBody *This = impl_from_IMimeBody(iface);
824 HRESULT hr;
825 header_t *header;
827 TRACE("(%p)->(%s, %p, %p)\n", iface, debugstr_a(pszName), pcParams, pprgParam);
829 *pprgParam = NULL;
830 *pcParams = 0;
832 hr = find_prop(This, pszName, &header);
833 if(hr != S_OK) return hr;
835 *pcParams = list_count(&header->params);
836 if(*pcParams)
838 IMimeAllocator *alloc;
839 param_t *param;
840 MIMEPARAMINFO *info;
842 MimeOleGetAllocator(&alloc);
844 *pprgParam = info = IMimeAllocator_Alloc(alloc, *pcParams * sizeof(**pprgParam));
845 LIST_FOR_EACH_ENTRY(param, &header->params, param_t, entry)
847 int len;
849 len = strlen(param->name) + 1;
850 info->pszName = IMimeAllocator_Alloc(alloc, len);
851 memcpy(info->pszName, param->name, len);
852 len = strlen(param->value) + 1;
853 info->pszData = IMimeAllocator_Alloc(alloc, len);
854 memcpy(info->pszData, param->value, len);
855 info++;
857 IMimeAllocator_Release(alloc);
859 return S_OK;
862 static HRESULT WINAPI MimeBody_IsContentType(
863 IMimeBody* iface,
864 LPCSTR pszPriType,
865 LPCSTR pszSubType)
867 MimeBody *This = impl_from_IMimeBody(iface);
869 TRACE("(%p)->(%s, %s)\n", This, debugstr_a(pszPriType), debugstr_a(pszSubType));
870 if(pszPriType)
872 const char *pri = This->content_pri_type;
873 if(!pri) pri = "text";
874 if(lstrcmpiA(pri, pszPriType)) return S_FALSE;
877 if(pszSubType)
879 const char *sub = This->content_sub_type;
880 if(!sub) sub = "plain";
881 if(lstrcmpiA(sub, pszSubType)) return S_FALSE;
884 return S_OK;
887 static HRESULT WINAPI MimeBody_BindToObject(
888 IMimeBody* iface,
889 REFIID riid,
890 void** ppvObject)
892 MimeBody *This = impl_from_IMimeBody(iface);
893 FIXME("(%p)->(%s, %p) stub\n", This, debugstr_guid(riid), ppvObject);
894 return E_NOTIMPL;
897 static HRESULT WINAPI MimeBody_Clone(
898 IMimeBody* iface,
899 IMimePropertySet** ppPropertySet)
901 MimeBody *This = impl_from_IMimeBody(iface);
902 FIXME("(%p)->(%p) stub\n", This, ppPropertySet);
903 return E_NOTIMPL;
906 static HRESULT WINAPI MimeBody_SetOption(
907 IMimeBody* iface,
908 const TYPEDID oid,
909 LPCPROPVARIANT pValue)
911 MimeBody *This = impl_from_IMimeBody(iface);
912 HRESULT hr = E_NOTIMPL;
913 TRACE("(%p)->(%08x, %p)\n", This, oid, pValue);
915 if(pValue->vt != TYPEDID_TYPE(oid))
917 WARN("Called with vartype %04x and oid %08x\n", pValue->vt, oid);
918 return E_INVALIDARG;
921 switch(oid)
923 case OID_SECURITY_HWND_OWNER:
924 FIXME("OID_SECURITY_HWND_OWNER (value %08x): ignoring\n", pValue->u.ulVal);
925 hr = S_OK;
926 break;
927 default:
928 FIXME("Unhandled oid %08x\n", oid);
931 return hr;
934 static HRESULT WINAPI MimeBody_GetOption(
935 IMimeBody* iface,
936 const TYPEDID oid,
937 LPPROPVARIANT pValue)
939 MimeBody *This = impl_from_IMimeBody(iface);
940 FIXME("(%p)->(%08x, %p): stub\n", This, oid, pValue);
941 return E_NOTIMPL;
944 static HRESULT WINAPI MimeBody_EnumProps(
945 IMimeBody* iface,
946 DWORD dwFlags,
947 IMimeEnumProperties** ppEnum)
949 MimeBody *This = impl_from_IMimeBody(iface);
950 FIXME("(%p)->(0x%x, %p) stub\n", This, dwFlags, ppEnum);
951 return E_NOTIMPL;
954 static HRESULT WINAPI MimeBody_IsType(
955 IMimeBody* iface,
956 IMSGBODYTYPE bodytype)
958 MimeBody *This = impl_from_IMimeBody(iface);
960 TRACE("(%p)->(%d)\n", This, bodytype);
961 switch(bodytype)
963 case IBT_EMPTY:
964 return This->data ? S_FALSE : S_OK;
965 default:
966 FIXME("Unimplemented bodytype %d - returning S_OK\n", bodytype);
968 return S_OK;
971 static HRESULT WINAPI MimeBody_SetDisplayName(
972 IMimeBody* iface,
973 LPCSTR pszDisplay)
975 MimeBody *This = impl_from_IMimeBody(iface);
976 FIXME("(%p)->(%s) stub\n", This, debugstr_a(pszDisplay));
977 return E_NOTIMPL;
980 static HRESULT WINAPI MimeBody_GetDisplayName(
981 IMimeBody* iface,
982 LPSTR* ppszDisplay)
984 MimeBody *This = impl_from_IMimeBody(iface);
985 FIXME("(%p)->(%p) stub\n", This, ppszDisplay);
986 return E_NOTIMPL;
989 static HRESULT WINAPI MimeBody_GetOffsets(
990 IMimeBody* iface,
991 LPBODYOFFSETS pOffsets)
993 MimeBody *This = impl_from_IMimeBody(iface);
994 TRACE("(%p)->(%p)\n", This, pOffsets);
996 *pOffsets = This->body_offsets;
998 if(This->body_offsets.cbBodyEnd == 0) return MIME_E_NO_DATA;
999 return S_OK;
1002 static HRESULT WINAPI MimeBody_GetCurrentEncoding(
1003 IMimeBody* iface,
1004 ENCODINGTYPE* pietEncoding)
1006 MimeBody *This = impl_from_IMimeBody(iface);
1008 TRACE("(%p)->(%p)\n", This, pietEncoding);
1010 *pietEncoding = This->encoding;
1011 return S_OK;
1014 static HRESULT WINAPI MimeBody_SetCurrentEncoding(
1015 IMimeBody* iface,
1016 ENCODINGTYPE ietEncoding)
1018 MimeBody *This = impl_from_IMimeBody(iface);
1020 TRACE("(%p)->(%d)\n", This, ietEncoding);
1022 This->encoding = ietEncoding;
1023 return S_OK;
1026 static HRESULT WINAPI MimeBody_GetEstimatedSize(
1027 IMimeBody* iface,
1028 ENCODINGTYPE ietEncoding,
1029 ULONG* pcbSize)
1031 MimeBody *This = impl_from_IMimeBody(iface);
1032 FIXME("(%p)->(%d, %p) stub\n", This, ietEncoding, pcbSize);
1033 return E_NOTIMPL;
1036 static HRESULT WINAPI MimeBody_GetDataHere(
1037 IMimeBody* iface,
1038 ENCODINGTYPE ietEncoding,
1039 IStream* pStream)
1041 MimeBody *This = impl_from_IMimeBody(iface);
1042 FIXME("(%p)->(%d, %p) stub\n", This, ietEncoding, pStream);
1043 return E_NOTIMPL;
1046 static HRESULT WINAPI MimeBody_GetData(
1047 IMimeBody* iface,
1048 ENCODINGTYPE ietEncoding,
1049 IStream** ppStream)
1051 MimeBody *This = impl_from_IMimeBody(iface);
1052 FIXME("(%p)->(%d, %p). Ignoring encoding type.\n", This, ietEncoding, ppStream);
1054 *ppStream = This->data;
1055 IStream_AddRef(*ppStream);
1056 return S_OK;
1059 static HRESULT WINAPI MimeBody_SetData(
1060 IMimeBody* iface,
1061 ENCODINGTYPE ietEncoding,
1062 LPCSTR pszPriType,
1063 LPCSTR pszSubType,
1064 REFIID riid,
1065 LPVOID pvObject)
1067 MimeBody *This = impl_from_IMimeBody(iface);
1068 TRACE("(%p)->(%d, %s, %s, %s %p)\n", This, ietEncoding, debugstr_a(pszPriType), debugstr_a(pszSubType),
1069 debugstr_guid(riid), pvObject);
1071 if(IsEqualIID(riid, &IID_IStream))
1072 IStream_AddRef((IStream *)pvObject);
1073 else
1075 FIXME("Unhandled object type %s\n", debugstr_guid(riid));
1076 return E_INVALIDARG;
1079 if(This->data)
1080 FIXME("release old data\n");
1082 This->data_iid = *riid;
1083 This->data = pvObject;
1085 IMimeBody_SetCurrentEncoding(iface, ietEncoding);
1087 /* FIXME: Update the content type.
1088 If pszPriType == NULL use 'application'
1089 If pszSubType == NULL use 'octet-stream' */
1091 return S_OK;
1094 static HRESULT WINAPI MimeBody_EmptyData(
1095 IMimeBody* iface)
1097 MimeBody *This = impl_from_IMimeBody(iface);
1098 FIXME("(%p)->() stub\n", This);
1099 return E_NOTIMPL;
1102 static HRESULT WINAPI MimeBody_CopyTo(
1103 IMimeBody* iface,
1104 IMimeBody* pBody)
1106 MimeBody *This = impl_from_IMimeBody(iface);
1107 FIXME("(%p)->(%p) stub\n", This, pBody);
1108 return E_NOTIMPL;
1111 static HRESULT WINAPI MimeBody_GetTransmitInfo(
1112 IMimeBody* iface,
1113 LPTRANSMITINFO pTransmitInfo)
1115 MimeBody *This = impl_from_IMimeBody(iface);
1116 FIXME("(%p)->(%p) stub\n", This, pTransmitInfo);
1117 return E_NOTIMPL;
1120 static HRESULT WINAPI MimeBody_SaveToFile(
1121 IMimeBody* iface,
1122 ENCODINGTYPE ietEncoding,
1123 LPCSTR pszFilePath)
1125 MimeBody *This = impl_from_IMimeBody(iface);
1126 FIXME("(%p)->(%d, %s) stub\n", This, ietEncoding, debugstr_a(pszFilePath));
1127 return E_NOTIMPL;
1130 static HRESULT WINAPI MimeBody_GetHandle(
1131 IMimeBody* iface,
1132 LPHBODY phBody)
1134 MimeBody *This = impl_from_IMimeBody(iface);
1135 TRACE("(%p)->(%p)\n", iface, phBody);
1137 *phBody = This->handle;
1138 return This->handle ? S_OK : MIME_E_NO_DATA;
1141 static IMimeBodyVtbl body_vtbl =
1143 MimeBody_QueryInterface,
1144 MimeBody_AddRef,
1145 MimeBody_Release,
1146 MimeBody_GetClassID,
1147 MimeBody_IsDirty,
1148 MimeBody_Load,
1149 MimeBody_Save,
1150 MimeBody_GetSizeMax,
1151 MimeBody_InitNew,
1152 MimeBody_GetPropInfo,
1153 MimeBody_SetPropInfo,
1154 MimeBody_GetProp,
1155 MimeBody_SetProp,
1156 MimeBody_AppendProp,
1157 MimeBody_DeleteProp,
1158 MimeBody_CopyProps,
1159 MimeBody_MoveProps,
1160 MimeBody_DeleteExcept,
1161 MimeBody_QueryProp,
1162 MimeBody_GetCharset,
1163 MimeBody_SetCharset,
1164 MimeBody_GetParameters,
1165 MimeBody_IsContentType,
1166 MimeBody_BindToObject,
1167 MimeBody_Clone,
1168 MimeBody_SetOption,
1169 MimeBody_GetOption,
1170 MimeBody_EnumProps,
1171 MimeBody_IsType,
1172 MimeBody_SetDisplayName,
1173 MimeBody_GetDisplayName,
1174 MimeBody_GetOffsets,
1175 MimeBody_GetCurrentEncoding,
1176 MimeBody_SetCurrentEncoding,
1177 MimeBody_GetEstimatedSize,
1178 MimeBody_GetDataHere,
1179 MimeBody_GetData,
1180 MimeBody_SetData,
1181 MimeBody_EmptyData,
1182 MimeBody_CopyTo,
1183 MimeBody_GetTransmitInfo,
1184 MimeBody_SaveToFile,
1185 MimeBody_GetHandle
1188 static HRESULT MimeBody_set_offsets(MimeBody *body, const BODYOFFSETS *offsets)
1190 TRACE("setting offsets to %d, %d, %d, %d\n", offsets->cbBoundaryStart,
1191 offsets->cbHeaderStart, offsets->cbBodyStart, offsets->cbBodyEnd);
1193 body->body_offsets = *offsets;
1194 return S_OK;
1197 #define FIRST_CUSTOM_PROP_ID 0x100
1199 static MimeBody *mimebody_create(void)
1201 MimeBody *This;
1202 BODYOFFSETS body_offsets;
1204 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1205 if (!This)
1206 return NULL;
1208 This->IMimeBody_iface.lpVtbl = &body_vtbl;
1209 This->ref = 1;
1210 This->handle = NULL;
1211 list_init(&This->headers);
1212 list_init(&This->new_props);
1213 This->next_prop_id = FIRST_CUSTOM_PROP_ID;
1214 This->content_pri_type = NULL;
1215 This->content_sub_type = NULL;
1216 This->encoding = IET_7BIT;
1217 This->data = NULL;
1218 This->data_iid = IID_NULL;
1220 body_offsets.cbBoundaryStart = body_offsets.cbHeaderStart = 0;
1221 body_offsets.cbBodyStart = body_offsets.cbBodyEnd = 0;
1222 MimeBody_set_offsets(This, &body_offsets);
1224 return This;
1227 HRESULT MimeBody_create(IUnknown *outer, void **ppv)
1229 MimeBody *mb;
1231 if(outer)
1232 return CLASS_E_NOAGGREGATION;
1234 if ((mb = mimebody_create()))
1236 *ppv = &mb->IMimeBody_iface;
1237 return S_OK;
1239 else
1241 *ppv = NULL;
1242 return E_OUTOFMEMORY;
1248 typedef struct
1250 IStream IStream_iface;
1251 LONG ref;
1252 IStream *base;
1253 ULARGE_INTEGER pos, start, length;
1254 } sub_stream_t;
1256 static inline sub_stream_t *impl_from_IStream(IStream *iface)
1258 return CONTAINING_RECORD(iface, sub_stream_t, IStream_iface);
1261 static HRESULT WINAPI sub_stream_QueryInterface(IStream *iface, REFIID riid, void **ppv)
1263 sub_stream_t *This = impl_from_IStream(iface);
1265 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
1266 *ppv = NULL;
1268 if(IsEqualIID(riid, &IID_IUnknown) ||
1269 IsEqualIID(riid, &IID_ISequentialStream) ||
1270 IsEqualIID(riid, &IID_IStream))
1272 IStream_AddRef(iface);
1273 *ppv = iface;
1274 return S_OK;
1276 return E_NOINTERFACE;
1279 static ULONG WINAPI sub_stream_AddRef(IStream *iface)
1281 sub_stream_t *This = impl_from_IStream(iface);
1282 LONG ref = InterlockedIncrement(&This->ref);
1284 TRACE("(%p) ref=%d\n", This, ref);
1286 return ref;
1289 static ULONG WINAPI sub_stream_Release(IStream *iface)
1291 sub_stream_t *This = impl_from_IStream(iface);
1292 LONG ref = InterlockedDecrement(&This->ref);
1294 TRACE("(%p) ref=%d\n", This, ref);
1296 if(!ref)
1298 IStream_Release(This->base);
1299 HeapFree(GetProcessHeap(), 0, This);
1301 return ref;
1304 static HRESULT WINAPI sub_stream_Read(
1305 IStream* iface,
1306 void *pv,
1307 ULONG cb,
1308 ULONG *pcbRead)
1310 sub_stream_t *This = impl_from_IStream(iface);
1311 HRESULT hr;
1312 ULARGE_INTEGER base_pos;
1313 LARGE_INTEGER tmp_pos;
1315 TRACE("(%p, %d, %p)\n", pv, cb, pcbRead);
1317 tmp_pos.QuadPart = 0;
1318 IStream_Seek(This->base, tmp_pos, STREAM_SEEK_CUR, &base_pos);
1319 tmp_pos.QuadPart = This->pos.QuadPart + This->start.QuadPart;
1320 IStream_Seek(This->base, tmp_pos, STREAM_SEEK_SET, NULL);
1322 if(This->pos.QuadPart + cb > This->length.QuadPart)
1323 cb = This->length.QuadPart - This->pos.QuadPart;
1325 hr = IStream_Read(This->base, pv, cb, pcbRead);
1327 This->pos.QuadPart += *pcbRead;
1329 tmp_pos.QuadPart = base_pos.QuadPart;
1330 IStream_Seek(This->base, tmp_pos, STREAM_SEEK_SET, NULL);
1332 return hr;
1335 static HRESULT WINAPI sub_stream_Write(
1336 IStream* iface,
1337 const void *pv,
1338 ULONG cb,
1339 ULONG *pcbWritten)
1341 FIXME("stub\n");
1342 return E_NOTIMPL;
1345 static HRESULT WINAPI sub_stream_Seek(
1346 IStream* iface,
1347 LARGE_INTEGER dlibMove,
1348 DWORD dwOrigin,
1349 ULARGE_INTEGER *plibNewPosition)
1351 sub_stream_t *This = impl_from_IStream(iface);
1352 LARGE_INTEGER new_pos;
1354 TRACE("(%08x.%08x, %x, %p)\n", dlibMove.u.HighPart, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
1356 switch(dwOrigin)
1358 case STREAM_SEEK_SET:
1359 new_pos = dlibMove;
1360 break;
1361 case STREAM_SEEK_CUR:
1362 new_pos.QuadPart = This->pos.QuadPart + dlibMove.QuadPart;
1363 break;
1364 case STREAM_SEEK_END:
1365 new_pos.QuadPart = This->length.QuadPart + dlibMove.QuadPart;
1366 break;
1367 default:
1368 return STG_E_INVALIDFUNCTION;
1371 if(new_pos.QuadPart < 0) new_pos.QuadPart = 0;
1372 else if(new_pos.QuadPart > This->length.QuadPart) new_pos.QuadPart = This->length.QuadPart;
1374 This->pos.QuadPart = new_pos.QuadPart;
1376 if(plibNewPosition) *plibNewPosition = This->pos;
1377 return S_OK;
1380 static HRESULT WINAPI sub_stream_SetSize(
1381 IStream* iface,
1382 ULARGE_INTEGER libNewSize)
1384 FIXME("stub\n");
1385 return E_NOTIMPL;
1388 static HRESULT WINAPI sub_stream_CopyTo(
1389 IStream* iface,
1390 IStream *pstm,
1391 ULARGE_INTEGER cb,
1392 ULARGE_INTEGER *pcbRead,
1393 ULARGE_INTEGER *pcbWritten)
1395 HRESULT hr = S_OK;
1396 BYTE tmpBuffer[128];
1397 ULONG bytesRead, bytesWritten, copySize;
1398 ULARGE_INTEGER totalBytesRead;
1399 ULARGE_INTEGER totalBytesWritten;
1401 TRACE("(%p)->(%p, %d, %p, %p)\n", iface, pstm, cb.u.LowPart, pcbRead, pcbWritten);
1403 totalBytesRead.QuadPart = 0;
1404 totalBytesWritten.QuadPart = 0;
1406 while ( cb.QuadPart > 0 )
1408 if ( cb.QuadPart >= sizeof(tmpBuffer) )
1409 copySize = sizeof(tmpBuffer);
1410 else
1411 copySize = cb.u.LowPart;
1413 hr = IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
1414 if (FAILED(hr)) break;
1416 totalBytesRead.QuadPart += bytesRead;
1418 if (bytesRead)
1420 hr = IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
1421 if (FAILED(hr)) break;
1422 totalBytesWritten.QuadPart += bytesWritten;
1425 if (bytesRead != copySize)
1426 cb.QuadPart = 0;
1427 else
1428 cb.QuadPart -= bytesRead;
1431 if (pcbRead) pcbRead->QuadPart = totalBytesRead.QuadPart;
1432 if (pcbWritten) pcbWritten->QuadPart = totalBytesWritten.QuadPart;
1434 return hr;
1437 static HRESULT WINAPI sub_stream_Commit(
1438 IStream* iface,
1439 DWORD grfCommitFlags)
1441 FIXME("stub\n");
1442 return E_NOTIMPL;
1445 static HRESULT WINAPI sub_stream_Revert(
1446 IStream* iface)
1448 FIXME("stub\n");
1449 return E_NOTIMPL;
1452 static HRESULT WINAPI sub_stream_LockRegion(
1453 IStream* iface,
1454 ULARGE_INTEGER libOffset,
1455 ULARGE_INTEGER cb,
1456 DWORD dwLockType)
1458 FIXME("stub\n");
1459 return E_NOTIMPL;
1462 static HRESULT WINAPI sub_stream_UnlockRegion(
1463 IStream* iface,
1464 ULARGE_INTEGER libOffset,
1465 ULARGE_INTEGER cb,
1466 DWORD dwLockType)
1468 FIXME("stub\n");
1469 return E_NOTIMPL;
1472 static HRESULT WINAPI sub_stream_Stat(
1473 IStream* iface,
1474 STATSTG *pstatstg,
1475 DWORD grfStatFlag)
1477 sub_stream_t *This = impl_from_IStream(iface);
1478 FIXME("(%p)->(%p, %08x)\n", This, pstatstg, grfStatFlag);
1479 memset(pstatstg, 0, sizeof(*pstatstg));
1480 pstatstg->cbSize = This->length;
1481 return S_OK;
1484 static HRESULT WINAPI sub_stream_Clone(
1485 IStream* iface,
1486 IStream **ppstm)
1488 FIXME("stub\n");
1489 return E_NOTIMPL;
1492 static struct IStreamVtbl sub_stream_vtbl =
1494 sub_stream_QueryInterface,
1495 sub_stream_AddRef,
1496 sub_stream_Release,
1497 sub_stream_Read,
1498 sub_stream_Write,
1499 sub_stream_Seek,
1500 sub_stream_SetSize,
1501 sub_stream_CopyTo,
1502 sub_stream_Commit,
1503 sub_stream_Revert,
1504 sub_stream_LockRegion,
1505 sub_stream_UnlockRegion,
1506 sub_stream_Stat,
1507 sub_stream_Clone
1510 static HRESULT create_sub_stream(IStream *stream, ULARGE_INTEGER start, ULARGE_INTEGER length, IStream **out)
1512 sub_stream_t *This;
1514 *out = NULL;
1515 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1516 if(!This) return E_OUTOFMEMORY;
1518 This->IStream_iface.lpVtbl = &sub_stream_vtbl;
1519 This->ref = 1;
1520 This->start = start;
1521 This->length = length;
1522 This->pos.QuadPart = 0;
1523 IStream_AddRef(stream);
1524 This->base = stream;
1526 *out = &This->IStream_iface;
1527 return S_OK;
1531 typedef struct body_t
1533 struct list entry;
1534 DWORD index;
1535 MimeBody *mime_body;
1537 struct body_t *parent;
1538 struct list children;
1539 } body_t;
1541 typedef struct MimeMessage
1543 IMimeMessage IMimeMessage_iface;
1544 LONG ref;
1545 IStream *stream;
1547 struct list body_tree;
1548 DWORD next_index;
1549 } MimeMessage;
1551 static inline MimeMessage *impl_from_IMimeMessage(IMimeMessage *iface)
1553 return CONTAINING_RECORD(iface, MimeMessage, IMimeMessage_iface);
1556 static HRESULT WINAPI MimeMessage_QueryInterface(IMimeMessage *iface, REFIID riid, void **ppv)
1558 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1560 if (IsEqualIID(riid, &IID_IUnknown) ||
1561 IsEqualIID(riid, &IID_IPersist) ||
1562 IsEqualIID(riid, &IID_IPersistStreamInit) ||
1563 IsEqualIID(riid, &IID_IMimeMessageTree) ||
1564 IsEqualIID(riid, &IID_IMimeMessage))
1566 *ppv = iface;
1567 IMimeMessage_AddRef(iface);
1568 return S_OK;
1571 FIXME("no interface for %s\n", debugstr_guid(riid));
1572 *ppv = NULL;
1573 return E_NOINTERFACE;
1576 static ULONG WINAPI MimeMessage_AddRef(IMimeMessage *iface)
1578 MimeMessage *This = impl_from_IMimeMessage(iface);
1579 ULONG ref = InterlockedIncrement(&This->ref);
1581 TRACE("(%p) ref=%d\n", This, ref);
1583 return ref;
1586 static void empty_body_list(struct list *list)
1588 body_t *body, *cursor2;
1589 LIST_FOR_EACH_ENTRY_SAFE(body, cursor2, list, body_t, entry)
1591 empty_body_list(&body->children);
1592 list_remove(&body->entry);
1593 IMimeBody_Release(&body->mime_body->IMimeBody_iface);
1594 HeapFree(GetProcessHeap(), 0, body);
1598 static ULONG WINAPI MimeMessage_Release(IMimeMessage *iface)
1600 MimeMessage *This = impl_from_IMimeMessage(iface);
1601 ULONG ref = InterlockedDecrement(&This->ref);
1603 TRACE("(%p) ref=%d\n", This, ref);
1605 if (!ref)
1607 empty_body_list(&This->body_tree);
1609 if(This->stream) IStream_Release(This->stream);
1610 HeapFree(GetProcessHeap(), 0, This);
1613 return ref;
1616 /*** IPersist methods ***/
1617 static HRESULT WINAPI MimeMessage_GetClassID(
1618 IMimeMessage *iface,
1619 CLSID *pClassID)
1621 FIXME("(%p)->(%p)\n", iface, pClassID);
1622 return E_NOTIMPL;
1625 /*** IPersistStreamInit methods ***/
1626 static HRESULT WINAPI MimeMessage_IsDirty(
1627 IMimeMessage *iface)
1629 FIXME("(%p)->()\n", iface);
1630 return E_NOTIMPL;
1633 static body_t *new_body_entry(MimeBody *mime_body, DWORD index, body_t *parent)
1635 body_t *body = HeapAlloc(GetProcessHeap(), 0, sizeof(*body));
1636 if(body)
1638 body->mime_body = mime_body;
1639 body->index = index;
1640 list_init(&body->children);
1641 body->parent = parent;
1643 return body;
1646 typedef struct
1648 struct list entry;
1649 BODYOFFSETS offsets;
1650 } offset_entry_t;
1652 static HRESULT create_body_offset_list(IStream *stm, const char *boundary, struct list *body_offsets)
1654 HRESULT hr;
1655 DWORD read;
1656 int boundary_len = strlen(boundary);
1657 char *buf, *nl_boundary, *ptr, *overlap;
1658 DWORD start = 0, overlap_no;
1659 offset_entry_t *cur_body = NULL;
1660 ULARGE_INTEGER cur;
1661 LARGE_INTEGER zero;
1663 list_init(body_offsets);
1664 nl_boundary = HeapAlloc(GetProcessHeap(), 0, 4 + boundary_len + 1);
1665 memcpy(nl_boundary, "\r\n--", 4);
1666 memcpy(nl_boundary + 4, boundary, boundary_len + 1);
1668 overlap_no = boundary_len + 5;
1670 overlap = buf = HeapAlloc(GetProcessHeap(), 0, overlap_no + PARSER_BUF_SIZE + 1);
1672 zero.QuadPart = 0;
1673 hr = IStream_Seek(stm, zero, STREAM_SEEK_CUR, &cur);
1674 start = cur.u.LowPart;
1676 do {
1677 hr = IStream_Read(stm, overlap, PARSER_BUF_SIZE, &read);
1678 if(FAILED(hr)) goto end;
1679 if(read == 0) break;
1680 overlap[read] = '\0';
1682 ptr = buf;
1683 do {
1684 ptr = strstr(ptr, nl_boundary);
1685 if(ptr)
1687 DWORD boundary_start = start + ptr - buf;
1688 char *end = ptr + boundary_len + 4;
1690 if(*end == '\0' || *(end + 1) == '\0')
1691 break;
1693 if(*end == '\r' && *(end + 1) == '\n')
1695 if(cur_body)
1697 cur_body->offsets.cbBodyEnd = boundary_start;
1698 list_add_tail(body_offsets, &cur_body->entry);
1700 cur_body = HeapAlloc(GetProcessHeap(), 0, sizeof(*cur_body));
1701 cur_body->offsets.cbBoundaryStart = boundary_start + 2; /* doesn't including the leading \r\n */
1702 cur_body->offsets.cbHeaderStart = boundary_start + boundary_len + 6;
1704 else if(*end == '-' && *(end + 1) == '-')
1706 if(cur_body)
1708 cur_body->offsets.cbBodyEnd = boundary_start;
1709 list_add_tail(body_offsets, &cur_body->entry);
1710 goto end;
1713 ptr = end + 2;
1715 } while(ptr);
1717 if(overlap == buf) /* 1st iteration */
1719 memmove(buf, buf + PARSER_BUF_SIZE - overlap_no, overlap_no);
1720 overlap = buf + overlap_no;
1721 start += read - overlap_no;
1723 else
1725 memmove(buf, buf + PARSER_BUF_SIZE, overlap_no);
1726 start += read;
1728 } while(1);
1730 end:
1731 HeapFree(GetProcessHeap(), 0, nl_boundary);
1732 HeapFree(GetProcessHeap(), 0, buf);
1733 return hr;
1736 static body_t *create_sub_body(MimeMessage *msg, IStream *pStm, BODYOFFSETS *offset, body_t *parent)
1738 MimeBody *mime_body;
1739 HRESULT hr;
1740 body_t *body;
1741 ULARGE_INTEGER cur;
1742 LARGE_INTEGER zero;
1744 mime_body = mimebody_create();
1745 IMimeBody_Load(&mime_body->IMimeBody_iface, pStm);
1746 zero.QuadPart = 0;
1747 hr = IStream_Seek(pStm, zero, STREAM_SEEK_CUR, &cur);
1748 offset->cbBodyStart = cur.u.LowPart + offset->cbHeaderStart;
1749 if (parent) MimeBody_set_offsets(mime_body, offset);
1750 IMimeBody_SetData(&mime_body->IMimeBody_iface, IET_BINARY, NULL, NULL, &IID_IStream, pStm);
1751 body = new_body_entry(mime_body, msg->next_index++, parent);
1753 if(IMimeBody_IsContentType(&mime_body->IMimeBody_iface, "multipart", NULL) == S_OK)
1755 MIMEPARAMINFO *param_info;
1756 ULONG count, i;
1757 IMimeAllocator *alloc;
1759 hr = IMimeBody_GetParameters(&mime_body->IMimeBody_iface, "Content-Type", &count,
1760 &param_info);
1761 if(hr != S_OK || count == 0) return body;
1763 MimeOleGetAllocator(&alloc);
1765 for(i = 0; i < count; i++)
1767 if(!lstrcmpiA(param_info[i].pszName, "boundary"))
1769 struct list offset_list;
1770 offset_entry_t *cur, *cursor2;
1771 hr = create_body_offset_list(pStm, param_info[i].pszData, &offset_list);
1772 LIST_FOR_EACH_ENTRY_SAFE(cur, cursor2, &offset_list, offset_entry_t, entry)
1774 body_t *sub_body;
1775 IStream *sub_stream;
1776 ULARGE_INTEGER start, length;
1778 start.QuadPart = cur->offsets.cbHeaderStart;
1779 length.QuadPart = cur->offsets.cbBodyEnd - cur->offsets.cbHeaderStart;
1780 create_sub_stream(pStm, start, length, &sub_stream);
1781 sub_body = create_sub_body(msg, sub_stream, &cur->offsets, body);
1782 IStream_Release(sub_stream);
1783 list_add_tail(&body->children, &sub_body->entry);
1784 list_remove(&cur->entry);
1785 HeapFree(GetProcessHeap(), 0, cur);
1787 break;
1790 IMimeAllocator_FreeParamInfoArray(alloc, count, param_info, TRUE);
1791 IMimeAllocator_Release(alloc);
1793 return body;
1796 static HRESULT WINAPI MimeMessage_Load(IMimeMessage *iface, IStream *pStm)
1798 MimeMessage *This = impl_from_IMimeMessage(iface);
1799 body_t *root_body;
1800 BODYOFFSETS offsets;
1801 ULARGE_INTEGER cur;
1802 LARGE_INTEGER zero;
1804 TRACE("(%p)->(%p)\n", iface, pStm);
1806 if(This->stream)
1808 FIXME("already loaded a message\n");
1809 return E_FAIL;
1812 empty_body_list(&This->body_tree);
1814 IStream_AddRef(pStm);
1815 This->stream = pStm;
1816 offsets.cbBoundaryStart = offsets.cbHeaderStart = 0;
1817 offsets.cbBodyStart = offsets.cbBodyEnd = 0;
1819 root_body = create_sub_body(This, pStm, &offsets, NULL);
1821 zero.QuadPart = 0;
1822 IStream_Seek(pStm, zero, STREAM_SEEK_END, &cur);
1823 offsets.cbBodyEnd = cur.u.LowPart;
1824 MimeBody_set_offsets(root_body->mime_body, &offsets);
1826 list_add_head(&This->body_tree, &root_body->entry);
1828 return S_OK;
1831 static HRESULT WINAPI MimeMessage_Save(IMimeMessage *iface, IStream *pStm, BOOL fClearDirty)
1833 FIXME("(%p)->(%p, %s)\n", iface, pStm, fClearDirty ? "TRUE" : "FALSE");
1834 return E_NOTIMPL;
1837 static HRESULT WINAPI MimeMessage_GetSizeMax(
1838 IMimeMessage *iface,
1839 ULARGE_INTEGER *pcbSize)
1841 FIXME("(%p)->(%p)\n", iface, pcbSize);
1842 return E_NOTIMPL;
1845 static HRESULT WINAPI MimeMessage_InitNew(
1846 IMimeMessage *iface)
1848 FIXME("(%p)->()\n", iface);
1849 return E_NOTIMPL;
1852 /*** IMimeMessageTree methods ***/
1853 static HRESULT WINAPI MimeMessage_GetMessageSource(IMimeMessage *iface, IStream **ppStream,
1854 DWORD dwFlags)
1856 MimeMessage *This = impl_from_IMimeMessage(iface);
1858 FIXME("(%p)->(%p, 0x%x)\n", iface, ppStream, dwFlags);
1860 IStream_AddRef(This->stream);
1861 *ppStream = This->stream;
1862 return S_OK;
1865 static HRESULT WINAPI MimeMessage_GetMessageSize(
1866 IMimeMessage *iface,
1867 ULONG *pcbSize,
1868 DWORD dwFlags)
1870 FIXME("(%p)->(%p, 0x%x)\n", iface, pcbSize, dwFlags);
1871 return E_NOTIMPL;
1874 static HRESULT WINAPI MimeMessage_LoadOffsetTable(
1875 IMimeMessage *iface,
1876 IStream *pStream)
1878 FIXME("(%p)->(%p)\n", iface, pStream);
1879 return E_NOTIMPL;
1882 static HRESULT WINAPI MimeMessage_SaveOffsetTable(
1883 IMimeMessage *iface,
1884 IStream *pStream,
1885 DWORD dwFlags)
1887 FIXME("(%p)->(%p, 0x%x)\n", iface, pStream, dwFlags);
1888 return E_NOTIMPL;
1892 static HRESULT WINAPI MimeMessage_GetFlags(
1893 IMimeMessage *iface,
1894 DWORD *pdwFlags)
1896 FIXME("(%p)->(%p)\n", iface, pdwFlags);
1897 return E_NOTIMPL;
1900 static HRESULT WINAPI MimeMessage_Commit(
1901 IMimeMessage *iface,
1902 DWORD dwFlags)
1904 FIXME("(%p)->(0x%x)\n", iface, dwFlags);
1905 return E_NOTIMPL;
1909 static HRESULT WINAPI MimeMessage_HandsOffStorage(
1910 IMimeMessage *iface)
1912 FIXME("(%p)->()\n", iface);
1913 return E_NOTIMPL;
1916 static HRESULT find_body(struct list *list, HBODY hbody, body_t **body)
1918 body_t *cur;
1919 HRESULT hr;
1921 if(hbody == HBODY_ROOT)
1923 *body = LIST_ENTRY(list_head(list), body_t, entry);
1924 return S_OK;
1927 LIST_FOR_EACH_ENTRY(cur, list, body_t, entry)
1929 if(cur->index == HandleToUlong(hbody))
1931 *body = cur;
1932 return S_OK;
1934 hr = find_body(&cur->children, hbody, body);
1935 if(hr == S_OK) return S_OK;
1937 return S_FALSE;
1940 static HRESULT WINAPI MimeMessage_BindToObject(IMimeMessage *iface, const HBODY hBody, REFIID riid,
1941 void **ppvObject)
1943 MimeMessage *This = impl_from_IMimeMessage(iface);
1944 HRESULT hr;
1945 body_t *body;
1947 TRACE("(%p)->(%p, %s, %p)\n", iface, hBody, debugstr_guid(riid), ppvObject);
1949 hr = find_body(&This->body_tree, hBody, &body);
1951 if(hr != S_OK) return hr;
1953 if(IsEqualIID(riid, &IID_IMimeBody))
1955 IMimeBody_AddRef(&body->mime_body->IMimeBody_iface);
1956 *ppvObject = &body->mime_body->IMimeBody_iface;
1957 return S_OK;
1960 return E_NOINTERFACE;
1963 static HRESULT WINAPI MimeMessage_SaveBody(
1964 IMimeMessage *iface,
1965 HBODY hBody,
1966 DWORD dwFlags,
1967 IStream *pStream)
1969 FIXME("(%p)->(%p, 0x%x, %p)\n", iface, hBody, dwFlags, pStream);
1970 return E_NOTIMPL;
1973 static HRESULT get_body(MimeMessage *msg, BODYLOCATION location, HBODY pivot, body_t **out)
1975 body_t *root = LIST_ENTRY(list_head(&msg->body_tree), body_t, entry);
1976 body_t *body;
1977 HRESULT hr;
1978 struct list *list;
1980 if(location == IBL_ROOT)
1982 *out = root;
1983 return S_OK;
1986 hr = find_body(&msg->body_tree, pivot, &body);
1988 if(hr == S_OK)
1990 switch(location)
1992 case IBL_PARENT:
1993 *out = body->parent;
1994 break;
1996 case IBL_FIRST:
1997 list = list_head(&body->children);
1998 if(list)
1999 *out = LIST_ENTRY(list, body_t, entry);
2000 else
2001 hr = MIME_E_NOT_FOUND;
2002 break;
2004 case IBL_LAST:
2005 list = list_tail(&body->children);
2006 if(list)
2007 *out = LIST_ENTRY(list, body_t, entry);
2008 else
2009 hr = MIME_E_NOT_FOUND;
2010 break;
2012 case IBL_NEXT:
2013 list = list_next(&body->parent->children, &body->entry);
2014 if(list)
2015 *out = LIST_ENTRY(list, body_t, entry);
2016 else
2017 hr = MIME_E_NOT_FOUND;
2018 break;
2020 case IBL_PREVIOUS:
2021 list = list_prev(&body->parent->children, &body->entry);
2022 if(list)
2023 *out = LIST_ENTRY(list, body_t, entry);
2024 else
2025 hr = MIME_E_NOT_FOUND;
2026 break;
2028 default:
2029 hr = E_FAIL;
2030 break;
2034 return hr;
2038 static HRESULT WINAPI MimeMessage_InsertBody(
2039 IMimeMessage *iface,
2040 BODYLOCATION location,
2041 HBODY hPivot,
2042 LPHBODY phBody)
2044 FIXME("(%p)->(%d, %p, %p)\n", iface, location, hPivot, phBody);
2045 return E_NOTIMPL;
2048 static HRESULT WINAPI MimeMessage_GetBody(IMimeMessage *iface, BODYLOCATION location, HBODY hPivot,
2049 HBODY *phBody)
2051 MimeMessage *This = impl_from_IMimeMessage(iface);
2052 body_t *body;
2053 HRESULT hr;
2055 TRACE("(%p)->(%d, %p, %p)\n", iface, location, hPivot, phBody);
2057 hr = get_body(This, location, hPivot, &body);
2059 if(hr == S_OK) *phBody = UlongToHandle(body->index);
2061 return hr;
2064 static HRESULT WINAPI MimeMessage_DeleteBody(
2065 IMimeMessage *iface,
2066 HBODY hBody,
2067 DWORD dwFlags)
2069 FIXME("(%p)->(%p, %08x)\n", iface, hBody, dwFlags);
2070 return E_NOTIMPL;
2073 static HRESULT WINAPI MimeMessage_MoveBody(
2074 IMimeMessage *iface,
2075 HBODY hBody,
2076 BODYLOCATION location)
2078 FIXME("(%p)->(%d)\n", iface, location);
2079 return E_NOTIMPL;
2082 static void count_children(body_t *body, boolean recurse, ULONG *count)
2084 body_t *child;
2086 LIST_FOR_EACH_ENTRY(child, &body->children, body_t, entry)
2088 (*count)++;
2089 if(recurse) count_children(child, recurse, count);
2093 static HRESULT WINAPI MimeMessage_CountBodies(IMimeMessage *iface, HBODY hParent, boolean fRecurse,
2094 ULONG *pcBodies)
2096 HRESULT hr;
2097 MimeMessage *This = impl_from_IMimeMessage(iface);
2098 body_t *body;
2100 TRACE("(%p)->(%p, %s, %p)\n", iface, hParent, fRecurse ? "TRUE" : "FALSE", pcBodies);
2102 hr = find_body(&This->body_tree, hParent, &body);
2103 if(hr != S_OK) return hr;
2105 *pcBodies = 1;
2106 count_children(body, fRecurse, pcBodies);
2108 return S_OK;
2111 static HRESULT find_next(MimeMessage *This, body_t *body, FINDBODY *find, HBODY *out)
2113 struct list *ptr;
2114 HBODY next;
2116 for (;;)
2118 if (!body) ptr = list_head( &This->body_tree );
2119 else
2121 ptr = list_head( &body->children );
2122 while (!ptr)
2124 if (!body->parent) return MIME_E_NOT_FOUND;
2125 if (!(ptr = list_next( &body->parent->children, &body->entry ))) body = body->parent;
2129 body = LIST_ENTRY( ptr, body_t, entry );
2130 next = UlongToHandle( body->index );
2131 find->dwReserved = body->index;
2132 if (IMimeBody_IsContentType(&body->mime_body->IMimeBody_iface, find->pszPriType,
2133 find->pszSubType) == S_OK)
2135 *out = next;
2136 return S_OK;
2139 return MIME_E_NOT_FOUND;
2142 static HRESULT WINAPI MimeMessage_FindFirst(IMimeMessage *iface, FINDBODY *pFindBody, HBODY *phBody)
2144 MimeMessage *This = impl_from_IMimeMessage(iface);
2146 TRACE("(%p)->(%p, %p)\n", iface, pFindBody, phBody);
2148 pFindBody->dwReserved = 0;
2149 return find_next(This, NULL, pFindBody, phBody);
2152 static HRESULT WINAPI MimeMessage_FindNext(IMimeMessage *iface, FINDBODY *pFindBody, HBODY *phBody)
2154 MimeMessage *This = impl_from_IMimeMessage(iface);
2155 body_t *body;
2156 HRESULT hr;
2158 TRACE("(%p)->(%p, %p)\n", iface, pFindBody, phBody);
2160 hr = find_body( &This->body_tree, UlongToHandle( pFindBody->dwReserved ), &body );
2161 if (hr != S_OK) return MIME_E_NOT_FOUND;
2162 return find_next(This, body, pFindBody, phBody);
2165 static HRESULT WINAPI MimeMessage_ResolveURL(
2166 IMimeMessage *iface,
2167 HBODY hRelated,
2168 LPCSTR pszBase,
2169 LPCSTR pszURL,
2170 DWORD dwFlags,
2171 LPHBODY phBody)
2173 FIXME("(%p)->(%p, %s, %s, 0x%x, %p)\n", iface, hRelated, pszBase, pszURL, dwFlags, phBody);
2174 return E_NOTIMPL;
2177 static HRESULT WINAPI MimeMessage_ToMultipart(
2178 IMimeMessage *iface,
2179 HBODY hBody,
2180 LPCSTR pszSubType,
2181 LPHBODY phMultipart)
2183 FIXME("(%p)->(%p, %s, %p)\n", iface, hBody, pszSubType, phMultipart);
2184 return E_NOTIMPL;
2187 static HRESULT WINAPI MimeMessage_GetBodyOffsets(
2188 IMimeMessage *iface,
2189 HBODY hBody,
2190 LPBODYOFFSETS pOffsets)
2192 FIXME("(%p)->(%p, %p)\n", iface, hBody, pOffsets);
2193 return E_NOTIMPL;
2196 static HRESULT WINAPI MimeMessage_GetCharset(
2197 IMimeMessage *iface,
2198 LPHCHARSET phCharset)
2200 FIXME("(%p)->(%p)\n", iface, phCharset);
2201 *phCharset = NULL;
2202 return S_OK;
2205 static HRESULT WINAPI MimeMessage_SetCharset(
2206 IMimeMessage *iface,
2207 HCHARSET hCharset,
2208 CSETAPPLYTYPE applytype)
2210 FIXME("(%p)->(%p, %d)\n", iface, hCharset, applytype);
2211 return E_NOTIMPL;
2214 static HRESULT WINAPI MimeMessage_IsBodyType(
2215 IMimeMessage *iface,
2216 HBODY hBody,
2217 IMSGBODYTYPE bodytype)
2219 HRESULT hr;
2220 IMimeBody *mime_body;
2221 TRACE("(%p)->(%p, %d)\n", iface, hBody, bodytype);
2223 hr = IMimeMessage_BindToObject(iface, hBody, &IID_IMimeBody, (void**)&mime_body);
2224 if(hr != S_OK) return hr;
2226 hr = IMimeBody_IsType(mime_body, bodytype);
2227 MimeBody_Release(mime_body);
2228 return hr;
2231 static HRESULT WINAPI MimeMessage_IsContentType(
2232 IMimeMessage *iface,
2233 HBODY hBody,
2234 LPCSTR pszPriType,
2235 LPCSTR pszSubType)
2237 HRESULT hr;
2238 IMimeBody *mime_body;
2239 TRACE("(%p)->(%p, %s, %s)\n", iface, hBody, debugstr_a(pszPriType),
2240 debugstr_a(pszSubType));
2242 hr = IMimeMessage_BindToObject(iface, hBody, &IID_IMimeBody, (void**)&mime_body);
2243 if(FAILED(hr)) return hr;
2245 hr = IMimeBody_IsContentType(mime_body, pszPriType, pszSubType);
2246 IMimeBody_Release(mime_body);
2247 return hr;
2250 static HRESULT WINAPI MimeMessage_QueryBodyProp(
2251 IMimeMessage *iface,
2252 HBODY hBody,
2253 LPCSTR pszName,
2254 LPCSTR pszCriteria,
2255 boolean fSubString,
2256 boolean fCaseSensitive)
2258 FIXME("(%p)->(%p, %s, %s, %s, %s)\n", iface, hBody, pszName, pszCriteria, fSubString ? "TRUE" : "FALSE", fCaseSensitive ? "TRUE" : "FALSE");
2259 return E_NOTIMPL;
2262 static HRESULT WINAPI MimeMessage_GetBodyProp(
2263 IMimeMessage *iface,
2264 HBODY hBody,
2265 LPCSTR pszName,
2266 DWORD dwFlags,
2267 LPPROPVARIANT pValue)
2269 HRESULT hr;
2270 IMimeBody *mime_body;
2272 TRACE("(%p)->(%p, %s, 0x%x, %p)\n", iface, hBody, pszName, dwFlags, pValue);
2274 hr = IMimeMessage_BindToObject(iface, hBody, &IID_IMimeBody, (void**)&mime_body);
2275 if(hr != S_OK) return hr;
2277 hr = IMimeBody_GetProp(mime_body, pszName, dwFlags, pValue);
2278 IMimeBody_Release(mime_body);
2280 return hr;
2283 static HRESULT WINAPI MimeMessage_SetBodyProp(
2284 IMimeMessage *iface,
2285 HBODY hBody,
2286 LPCSTR pszName,
2287 DWORD dwFlags,
2288 LPCPROPVARIANT pValue)
2290 FIXME("(%p)->(%p, %s, 0x%x, %p)\n", iface, hBody, pszName, dwFlags, pValue);
2291 return E_NOTIMPL;
2294 static HRESULT WINAPI MimeMessage_DeleteBodyProp(
2295 IMimeMessage *iface,
2296 HBODY hBody,
2297 LPCSTR pszName)
2299 FIXME("(%p)->(%p, %s)\n", iface, hBody, pszName);
2300 return E_NOTIMPL;
2303 static HRESULT WINAPI MimeMessage_SetOption(
2304 IMimeMessage *iface,
2305 const TYPEDID oid,
2306 LPCPROPVARIANT pValue)
2308 HRESULT hr = S_OK;
2309 TRACE("(%p)->(%08x, %p)\n", iface, oid, pValue);
2311 /* Message ID is checked before type.
2312 * OID 0x4D -> 0x56 and 0x58 aren't defined but will filtered out later.
2314 if(TYPEDID_ID(oid) < TYPEDID_ID(OID_ALLOW_8BIT_HEADER) || TYPEDID_ID(oid) > TYPEDID_ID(OID_SECURITY_2KEY_CERT_BAG_64))
2316 WARN("oid (%08x) out of range\n", oid);
2317 return MIME_E_INVALID_OPTION_ID;
2320 if(pValue->vt != TYPEDID_TYPE(oid))
2322 WARN("Called with vartype %04x and oid %08x\n", pValue->vt, oid);
2323 return S_OK;
2326 switch(oid)
2328 case OID_HIDE_TNEF_ATTACHMENTS:
2329 FIXME("OID_HIDE_TNEF_ATTACHMENTS (value %d): ignoring\n", pValue->u.boolVal);
2330 break;
2331 case OID_SHOW_MACBINARY:
2332 FIXME("OID_SHOW_MACBINARY (value %d): ignoring\n", pValue->u.boolVal);
2333 break;
2334 case OID_SAVEBODY_KEEPBOUNDARY:
2335 FIXME("OID_SAVEBODY_KEEPBOUNDARY (value %d): ignoring\n", pValue->u.boolVal);
2336 break;
2337 default:
2338 FIXME("Unhandled oid %08x\n", oid);
2339 hr = MIME_E_INVALID_OPTION_ID;
2342 return hr;
2345 static HRESULT WINAPI MimeMessage_GetOption(
2346 IMimeMessage *iface,
2347 const TYPEDID oid,
2348 LPPROPVARIANT pValue)
2350 FIXME("(%p)->(%08x, %p)\n", iface, oid, pValue);
2351 return E_NOTIMPL;
2354 /*** IMimeMessage methods ***/
2355 static HRESULT WINAPI MimeMessage_CreateWebPage(
2356 IMimeMessage *iface,
2357 IStream *pRootStm,
2358 LPWEBPAGEOPTIONS pOptions,
2359 IMimeMessageCallback *pCallback,
2360 IMoniker **ppMoniker)
2362 FIXME("(%p)->(%p, %p, %p, %p)\n", iface, pRootStm, pOptions, pCallback, ppMoniker);
2363 *ppMoniker = NULL;
2364 return E_NOTIMPL;
2367 static HRESULT WINAPI MimeMessage_GetProp(
2368 IMimeMessage *iface,
2369 LPCSTR pszName,
2370 DWORD dwFlags,
2371 LPPROPVARIANT pValue)
2373 FIXME("(%p)->(%s, 0x%x, %p)\n", iface, pszName, dwFlags, pValue);
2374 return E_NOTIMPL;
2377 static HRESULT WINAPI MimeMessage_SetProp(
2378 IMimeMessage *iface,
2379 LPCSTR pszName,
2380 DWORD dwFlags,
2381 LPCPROPVARIANT pValue)
2383 FIXME("(%p)->(%s, 0x%x, %p)\n", iface, pszName, dwFlags, pValue);
2384 return E_NOTIMPL;
2387 static HRESULT WINAPI MimeMessage_DeleteProp(
2388 IMimeMessage *iface,
2389 LPCSTR pszName)
2391 FIXME("(%p)->(%s)\n", iface, pszName);
2392 return E_NOTIMPL;
2395 static HRESULT WINAPI MimeMessage_QueryProp(
2396 IMimeMessage *iface,
2397 LPCSTR pszName,
2398 LPCSTR pszCriteria,
2399 boolean fSubString,
2400 boolean fCaseSensitive)
2402 FIXME("(%p)->(%s, %s, %s, %s)\n", iface, pszName, pszCriteria, fSubString ? "TRUE" : "FALSE", fCaseSensitive ? "TRUE" : "FALSE");
2403 return E_NOTIMPL;
2406 static HRESULT WINAPI MimeMessage_GetTextBody(
2407 IMimeMessage *iface,
2408 DWORD dwTxtType,
2409 ENCODINGTYPE ietEncoding,
2410 IStream **pStream,
2411 LPHBODY phBody)
2413 HRESULT hr;
2414 HBODY hbody;
2415 FINDBODY find_struct;
2416 IMimeBody *mime_body;
2417 static char text[] = "text";
2418 static char plain[] = "plain";
2419 static char html[] = "html";
2421 TRACE("(%p)->(%d, %d, %p, %p)\n", iface, dwTxtType, ietEncoding, pStream, phBody);
2423 find_struct.pszPriType = text;
2425 switch(dwTxtType)
2427 case TXT_PLAIN:
2428 find_struct.pszSubType = plain;
2429 break;
2430 case TXT_HTML:
2431 find_struct.pszSubType = html;
2432 break;
2433 default:
2434 return MIME_E_INVALID_TEXT_TYPE;
2437 hr = IMimeMessage_FindFirst(iface, &find_struct, &hbody);
2438 if(hr != S_OK)
2440 TRACE("not found hr %08x\n", hr);
2441 *phBody = NULL;
2442 return hr;
2445 IMimeMessage_BindToObject(iface, hbody, &IID_IMimeBody, (void**)&mime_body);
2447 IMimeBody_GetData(mime_body, ietEncoding, pStream);
2448 *phBody = hbody;
2449 IMimeBody_Release(mime_body);
2450 return hr;
2453 static HRESULT WINAPI MimeMessage_SetTextBody(
2454 IMimeMessage *iface,
2455 DWORD dwTxtType,
2456 ENCODINGTYPE ietEncoding,
2457 HBODY hAlternative,
2458 IStream *pStream,
2459 LPHBODY phBody)
2461 FIXME("(%p)->(%d, %d, %p, %p, %p)\n", iface, dwTxtType, ietEncoding, hAlternative, pStream, phBody);
2462 return E_NOTIMPL;
2465 static HRESULT WINAPI MimeMessage_AttachObject(
2466 IMimeMessage *iface,
2467 REFIID riid,
2468 void *pvObject,
2469 LPHBODY phBody)
2471 FIXME("(%p)->(%s, %p, %p)\n", iface, debugstr_guid(riid), pvObject, phBody);
2472 return E_NOTIMPL;
2475 static HRESULT WINAPI MimeMessage_AttachFile(
2476 IMimeMessage *iface,
2477 LPCSTR pszFilePath,
2478 IStream *pstmFile,
2479 LPHBODY phBody)
2481 FIXME("(%p)->(%s, %p, %p)\n", iface, pszFilePath, pstmFile, phBody);
2482 return E_NOTIMPL;
2485 static HRESULT WINAPI MimeMessage_AttachURL(
2486 IMimeMessage *iface,
2487 LPCSTR pszBase,
2488 LPCSTR pszURL,
2489 DWORD dwFlags,
2490 IStream *pstmURL,
2491 LPSTR *ppszCIDURL,
2492 LPHBODY phBody)
2494 FIXME("(%p)->(%s, %s, 0x%x, %p, %p, %p)\n", iface, pszBase, pszURL, dwFlags, pstmURL, ppszCIDURL, phBody);
2495 return E_NOTIMPL;
2498 static HRESULT WINAPI MimeMessage_GetAttachments(
2499 IMimeMessage *iface,
2500 ULONG *pcAttach,
2501 LPHBODY *pprghAttach)
2503 HRESULT hr;
2504 FINDBODY find_struct;
2505 HBODY hbody;
2506 LPHBODY array;
2507 ULONG size = 10;
2509 TRACE("(%p)->(%p, %p)\n", iface, pcAttach, pprghAttach);
2511 *pcAttach = 0;
2512 array = CoTaskMemAlloc(size * sizeof(HBODY));
2514 find_struct.pszPriType = find_struct.pszSubType = NULL;
2515 hr = IMimeMessage_FindFirst(iface, &find_struct, &hbody);
2516 while(hr == S_OK)
2518 hr = IMimeMessage_IsContentType(iface, hbody, "multipart", NULL);
2519 TRACE("IsCT rets %08x %d\n", hr, *pcAttach);
2520 if(hr != S_OK)
2522 if(*pcAttach + 1 > size)
2524 size *= 2;
2525 array = CoTaskMemRealloc(array, size * sizeof(HBODY));
2527 array[*pcAttach] = hbody;
2528 (*pcAttach)++;
2530 hr = IMimeMessage_FindNext(iface, &find_struct, &hbody);
2533 *pprghAttach = array;
2534 return S_OK;
2537 static HRESULT WINAPI MimeMessage_GetAddressTable(
2538 IMimeMessage *iface,
2539 IMimeAddressTable **ppTable)
2541 FIXME("(%p)->(%p)\n", iface, ppTable);
2542 return E_NOTIMPL;
2545 static HRESULT WINAPI MimeMessage_GetSender(
2546 IMimeMessage *iface,
2547 LPADDRESSPROPS pAddress)
2549 FIXME("(%p)->(%p)\n", iface, pAddress);
2550 return E_NOTIMPL;
2553 static HRESULT WINAPI MimeMessage_GetAddressTypes(
2554 IMimeMessage *iface,
2555 DWORD dwAdrTypes,
2556 DWORD dwProps,
2557 LPADDRESSLIST pList)
2559 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, dwProps, pList);
2560 return E_NOTIMPL;
2563 static HRESULT WINAPI MimeMessage_GetAddressFormat(
2564 IMimeMessage *iface,
2565 DWORD dwAdrTypes,
2566 ADDRESSFORMAT format,
2567 LPSTR *ppszFormat)
2569 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, format, ppszFormat);
2570 return E_NOTIMPL;
2573 static HRESULT WINAPI MimeMessage_EnumAddressTypes(
2574 IMimeMessage *iface,
2575 DWORD dwAdrTypes,
2576 DWORD dwProps,
2577 IMimeEnumAddressTypes **ppEnum)
2579 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, dwProps, ppEnum);
2580 return E_NOTIMPL;
2583 static HRESULT WINAPI MimeMessage_SplitMessage(
2584 IMimeMessage *iface,
2585 ULONG cbMaxPart,
2586 IMimeMessageParts **ppParts)
2588 FIXME("(%p)->(%d, %p)\n", iface, cbMaxPart, ppParts);
2589 return E_NOTIMPL;
2592 static HRESULT WINAPI MimeMessage_GetRootMoniker(
2593 IMimeMessage *iface,
2594 IMoniker **ppMoniker)
2596 FIXME("(%p)->(%p)\n", iface, ppMoniker);
2597 return E_NOTIMPL;
2600 static const IMimeMessageVtbl MimeMessageVtbl =
2602 MimeMessage_QueryInterface,
2603 MimeMessage_AddRef,
2604 MimeMessage_Release,
2605 MimeMessage_GetClassID,
2606 MimeMessage_IsDirty,
2607 MimeMessage_Load,
2608 MimeMessage_Save,
2609 MimeMessage_GetSizeMax,
2610 MimeMessage_InitNew,
2611 MimeMessage_GetMessageSource,
2612 MimeMessage_GetMessageSize,
2613 MimeMessage_LoadOffsetTable,
2614 MimeMessage_SaveOffsetTable,
2615 MimeMessage_GetFlags,
2616 MimeMessage_Commit,
2617 MimeMessage_HandsOffStorage,
2618 MimeMessage_BindToObject,
2619 MimeMessage_SaveBody,
2620 MimeMessage_InsertBody,
2621 MimeMessage_GetBody,
2622 MimeMessage_DeleteBody,
2623 MimeMessage_MoveBody,
2624 MimeMessage_CountBodies,
2625 MimeMessage_FindFirst,
2626 MimeMessage_FindNext,
2627 MimeMessage_ResolveURL,
2628 MimeMessage_ToMultipart,
2629 MimeMessage_GetBodyOffsets,
2630 MimeMessage_GetCharset,
2631 MimeMessage_SetCharset,
2632 MimeMessage_IsBodyType,
2633 MimeMessage_IsContentType,
2634 MimeMessage_QueryBodyProp,
2635 MimeMessage_GetBodyProp,
2636 MimeMessage_SetBodyProp,
2637 MimeMessage_DeleteBodyProp,
2638 MimeMessage_SetOption,
2639 MimeMessage_GetOption,
2640 MimeMessage_CreateWebPage,
2641 MimeMessage_GetProp,
2642 MimeMessage_SetProp,
2643 MimeMessage_DeleteProp,
2644 MimeMessage_QueryProp,
2645 MimeMessage_GetTextBody,
2646 MimeMessage_SetTextBody,
2647 MimeMessage_AttachObject,
2648 MimeMessage_AttachFile,
2649 MimeMessage_AttachURL,
2650 MimeMessage_GetAttachments,
2651 MimeMessage_GetAddressTable,
2652 MimeMessage_GetSender,
2653 MimeMessage_GetAddressTypes,
2654 MimeMessage_GetAddressFormat,
2655 MimeMessage_EnumAddressTypes,
2656 MimeMessage_SplitMessage,
2657 MimeMessage_GetRootMoniker,
2660 HRESULT MimeMessage_create(IUnknown *outer, void **obj)
2662 MimeMessage *This;
2663 MimeBody *mime_body;
2664 body_t *root_body;
2666 TRACE("(%p, %p)\n", outer, obj);
2668 if (outer)
2670 FIXME("outer unknown not supported yet\n");
2671 return E_NOTIMPL;
2674 *obj = NULL;
2676 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2677 if (!This) return E_OUTOFMEMORY;
2679 This->IMimeMessage_iface.lpVtbl = &MimeMessageVtbl;
2680 This->ref = 1;
2681 This->stream = NULL;
2682 list_init(&This->body_tree);
2683 This->next_index = 1;
2685 mime_body = mimebody_create();
2686 root_body = new_body_entry(mime_body, This->next_index++, NULL);
2687 list_add_head(&This->body_tree, &root_body->entry);
2689 *obj = &This->IMimeMessage_iface;
2690 return S_OK;
2693 /***********************************************************************
2694 * MimeOleCreateMessage (INETCOMM.@)
2696 HRESULT WINAPI MimeOleCreateMessage(IUnknown *pUnkOuter, IMimeMessage **ppMessage)
2698 TRACE("(%p, %p)\n", pUnkOuter, ppMessage);
2699 return MimeMessage_create(NULL, (void **)ppMessage);
2702 /***********************************************************************
2703 * MimeOleSetCompatMode (INETCOMM.@)
2705 HRESULT WINAPI MimeOleSetCompatMode(DWORD dwMode)
2707 FIXME("(0x%x)\n", dwMode);
2708 return S_OK;
2711 /***********************************************************************
2712 * MimeOleCreateVirtualStream (INETCOMM.@)
2714 HRESULT WINAPI MimeOleCreateVirtualStream(IStream **ppStream)
2716 HRESULT hr;
2717 FIXME("(%p)\n", ppStream);
2719 hr = CreateStreamOnHGlobal(NULL, TRUE, ppStream);
2720 return hr;
2723 typedef struct MimeSecurity
2725 IMimeSecurity IMimeSecurity_iface;
2726 LONG ref;
2727 } MimeSecurity;
2729 static inline MimeSecurity *impl_from_IMimeSecurity(IMimeSecurity *iface)
2731 return CONTAINING_RECORD(iface, MimeSecurity, IMimeSecurity_iface);
2734 static HRESULT WINAPI MimeSecurity_QueryInterface(IMimeSecurity *iface, REFIID riid, void **ppv)
2736 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2738 if (IsEqualIID(riid, &IID_IUnknown) ||
2739 IsEqualIID(riid, &IID_IMimeSecurity))
2741 *ppv = iface;
2742 IMimeSecurity_AddRef(iface);
2743 return S_OK;
2746 FIXME("no interface for %s\n", debugstr_guid(riid));
2747 *ppv = NULL;
2748 return E_NOINTERFACE;
2751 static ULONG WINAPI MimeSecurity_AddRef(IMimeSecurity *iface)
2753 MimeSecurity *This = impl_from_IMimeSecurity(iface);
2754 LONG ref = InterlockedIncrement(&This->ref);
2756 TRACE("(%p) ref=%d\n", This, ref);
2758 return ref;
2761 static ULONG WINAPI MimeSecurity_Release(IMimeSecurity *iface)
2763 MimeSecurity *This = impl_from_IMimeSecurity(iface);
2764 LONG ref = InterlockedDecrement(&This->ref);
2766 TRACE("(%p) ref=%d\n", This, ref);
2768 if (!ref)
2769 HeapFree(GetProcessHeap(), 0, This);
2771 return ref;
2774 static HRESULT WINAPI MimeSecurity_InitNew(
2775 IMimeSecurity* iface)
2777 FIXME("(%p)->(): stub\n", iface);
2778 return S_OK;
2781 static HRESULT WINAPI MimeSecurity_CheckInit(
2782 IMimeSecurity* iface)
2784 FIXME("(%p)->(): stub\n", iface);
2785 return E_NOTIMPL;
2788 static HRESULT WINAPI MimeSecurity_EncodeMessage(
2789 IMimeSecurity* iface,
2790 IMimeMessageTree* pTree,
2791 DWORD dwFlags)
2793 FIXME("(%p)->(%p, %08x): stub\n", iface, pTree, dwFlags);
2794 return E_NOTIMPL;
2797 static HRESULT WINAPI MimeSecurity_EncodeBody(
2798 IMimeSecurity* iface,
2799 IMimeMessageTree* pTree,
2800 HBODY hEncodeRoot,
2801 DWORD dwFlags)
2803 FIXME("(%p)->(%p, %p, %08x): stub\n", iface, pTree, hEncodeRoot, dwFlags);
2804 return E_NOTIMPL;
2807 static HRESULT WINAPI MimeSecurity_DecodeMessage(
2808 IMimeSecurity* iface,
2809 IMimeMessageTree* pTree,
2810 DWORD dwFlags)
2812 FIXME("(%p)->(%p, %08x): stub\n", iface, pTree, dwFlags);
2813 return E_NOTIMPL;
2816 static HRESULT WINAPI MimeSecurity_DecodeBody(
2817 IMimeSecurity* iface,
2818 IMimeMessageTree* pTree,
2819 HBODY hDecodeRoot,
2820 DWORD dwFlags)
2822 FIXME("(%p)->(%p, %p, %08x): stub\n", iface, pTree, hDecodeRoot, dwFlags);
2823 return E_NOTIMPL;
2826 static HRESULT WINAPI MimeSecurity_EnumCertificates(
2827 IMimeSecurity* iface,
2828 HCAPICERTSTORE hc,
2829 DWORD dwUsage,
2830 PCX509CERT pPrev,
2831 PCX509CERT* ppCert)
2833 FIXME("(%p)->(%p, %08x, %p, %p): stub\n", iface, hc, dwUsage, pPrev, ppCert);
2834 return E_NOTIMPL;
2837 static HRESULT WINAPI MimeSecurity_GetCertificateName(
2838 IMimeSecurity* iface,
2839 const PCX509CERT pX509Cert,
2840 const CERTNAMETYPE cn,
2841 LPSTR* ppszName)
2843 FIXME("(%p)->(%p, %08x, %p): stub\n", iface, pX509Cert, cn, ppszName);
2844 return E_NOTIMPL;
2847 static HRESULT WINAPI MimeSecurity_GetMessageType(
2848 IMimeSecurity* iface,
2849 const HWND hwndParent,
2850 IMimeBody* pBody,
2851 DWORD* pdwSecType)
2853 FIXME("(%p)->(%p, %p, %p): stub\n", iface, hwndParent, pBody, pdwSecType);
2854 return E_NOTIMPL;
2857 static HRESULT WINAPI MimeSecurity_GetCertData(
2858 IMimeSecurity* iface,
2859 const PCX509CERT pX509Cert,
2860 const CERTDATAID dataid,
2861 LPPROPVARIANT pValue)
2863 FIXME("(%p)->(%p, %x, %p): stub\n", iface, pX509Cert, dataid, pValue);
2864 return E_NOTIMPL;
2868 static const IMimeSecurityVtbl MimeSecurityVtbl =
2870 MimeSecurity_QueryInterface,
2871 MimeSecurity_AddRef,
2872 MimeSecurity_Release,
2873 MimeSecurity_InitNew,
2874 MimeSecurity_CheckInit,
2875 MimeSecurity_EncodeMessage,
2876 MimeSecurity_EncodeBody,
2877 MimeSecurity_DecodeMessage,
2878 MimeSecurity_DecodeBody,
2879 MimeSecurity_EnumCertificates,
2880 MimeSecurity_GetCertificateName,
2881 MimeSecurity_GetMessageType,
2882 MimeSecurity_GetCertData
2885 HRESULT MimeSecurity_create(IUnknown *outer, void **obj)
2887 MimeSecurity *This;
2889 *obj = NULL;
2891 if (outer) return CLASS_E_NOAGGREGATION;
2893 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2894 if (!This) return E_OUTOFMEMORY;
2896 This->IMimeSecurity_iface.lpVtbl = &MimeSecurityVtbl;
2897 This->ref = 1;
2899 *obj = &This->IMimeSecurity_iface;
2900 return S_OK;
2903 /***********************************************************************
2904 * MimeOleCreateSecurity (INETCOMM.@)
2906 HRESULT WINAPI MimeOleCreateSecurity(IMimeSecurity **ppSecurity)
2908 return MimeSecurity_create(NULL, (void **)ppSecurity);
2911 static HRESULT WINAPI MimeAlloc_QueryInterface(
2912 IMimeAllocator* iface,
2913 REFIID riid,
2914 void **obj)
2916 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), obj);
2918 if (IsEqualIID(riid, &IID_IUnknown) ||
2919 IsEqualIID(riid, &IID_IMalloc) ||
2920 IsEqualIID(riid, &IID_IMimeAllocator))
2922 *obj = iface;
2923 IMimeAllocator_AddRef(iface);
2924 return S_OK;
2927 FIXME("no interface for %s\n", debugstr_guid(riid));
2928 *obj = NULL;
2929 return E_NOINTERFACE;
2932 static ULONG WINAPI MimeAlloc_AddRef(
2933 IMimeAllocator* iface)
2935 return 2;
2938 static ULONG WINAPI MimeAlloc_Release(
2939 IMimeAllocator* iface)
2941 return 1;
2944 static LPVOID WINAPI MimeAlloc_Alloc(
2945 IMimeAllocator* iface,
2946 SIZE_T cb)
2948 return CoTaskMemAlloc(cb);
2951 static LPVOID WINAPI MimeAlloc_Realloc(
2952 IMimeAllocator* iface,
2953 LPVOID pv,
2954 SIZE_T cb)
2956 return CoTaskMemRealloc(pv, cb);
2959 static void WINAPI MimeAlloc_Free(
2960 IMimeAllocator* iface,
2961 LPVOID pv)
2963 CoTaskMemFree(pv);
2966 static SIZE_T WINAPI MimeAlloc_GetSize(
2967 IMimeAllocator* iface,
2968 LPVOID pv)
2970 FIXME("stub\n");
2971 return 0;
2974 static int WINAPI MimeAlloc_DidAlloc(
2975 IMimeAllocator* iface,
2976 LPVOID pv)
2978 FIXME("stub\n");
2979 return 0;
2982 static void WINAPI MimeAlloc_HeapMinimize(
2983 IMimeAllocator* iface)
2985 FIXME("stub\n");
2986 return;
2989 static HRESULT WINAPI MimeAlloc_FreeParamInfoArray(
2990 IMimeAllocator* iface,
2991 ULONG cParams,
2992 LPMIMEPARAMINFO prgParam,
2993 boolean fFreeArray)
2995 ULONG i;
2996 TRACE("(%p)->(%d, %p, %d)\n", iface, cParams, prgParam, fFreeArray);
2998 for(i = 0; i < cParams; i++)
3000 IMimeAllocator_Free(iface, prgParam[i].pszName);
3001 IMimeAllocator_Free(iface, prgParam[i].pszData);
3003 if(fFreeArray) IMimeAllocator_Free(iface, prgParam);
3004 return S_OK;
3007 static HRESULT WINAPI MimeAlloc_FreeAddressList(
3008 IMimeAllocator* iface,
3009 LPADDRESSLIST pList)
3011 FIXME("stub\n");
3012 return E_NOTIMPL;
3015 static HRESULT WINAPI MimeAlloc_FreeAddressProps(
3016 IMimeAllocator* iface,
3017 LPADDRESSPROPS pAddress)
3019 FIXME("stub\n");
3020 return E_NOTIMPL;
3023 static HRESULT WINAPI MimeAlloc_ReleaseObjects(
3024 IMimeAllocator* iface,
3025 ULONG cObjects,
3026 IUnknown **prgpUnknown,
3027 boolean fFreeArray)
3029 FIXME("stub\n");
3030 return E_NOTIMPL;
3034 static HRESULT WINAPI MimeAlloc_FreeEnumHeaderRowArray(
3035 IMimeAllocator* iface,
3036 ULONG cRows,
3037 LPENUMHEADERROW prgRow,
3038 boolean fFreeArray)
3040 FIXME("stub\n");
3041 return E_NOTIMPL;
3044 static HRESULT WINAPI MimeAlloc_FreeEnumPropertyArray(
3045 IMimeAllocator* iface,
3046 ULONG cProps,
3047 LPENUMPROPERTY prgProp,
3048 boolean fFreeArray)
3050 FIXME("stub\n");
3051 return E_NOTIMPL;
3054 static HRESULT WINAPI MimeAlloc_FreeThumbprint(
3055 IMimeAllocator* iface,
3056 THUMBBLOB *pthumbprint)
3058 FIXME("stub\n");
3059 return E_NOTIMPL;
3063 static HRESULT WINAPI MimeAlloc_PropVariantClear(
3064 IMimeAllocator* iface,
3065 LPPROPVARIANT pProp)
3067 FIXME("stub\n");
3068 return E_NOTIMPL;
3071 static IMimeAllocatorVtbl mime_alloc_vtbl =
3073 MimeAlloc_QueryInterface,
3074 MimeAlloc_AddRef,
3075 MimeAlloc_Release,
3076 MimeAlloc_Alloc,
3077 MimeAlloc_Realloc,
3078 MimeAlloc_Free,
3079 MimeAlloc_GetSize,
3080 MimeAlloc_DidAlloc,
3081 MimeAlloc_HeapMinimize,
3082 MimeAlloc_FreeParamInfoArray,
3083 MimeAlloc_FreeAddressList,
3084 MimeAlloc_FreeAddressProps,
3085 MimeAlloc_ReleaseObjects,
3086 MimeAlloc_FreeEnumHeaderRowArray,
3087 MimeAlloc_FreeEnumPropertyArray,
3088 MimeAlloc_FreeThumbprint,
3089 MimeAlloc_PropVariantClear
3092 static IMimeAllocator mime_allocator =
3094 &mime_alloc_vtbl
3097 HRESULT MimeAllocator_create(IUnknown *outer, void **obj)
3099 if(outer) return CLASS_E_NOAGGREGATION;
3101 *obj = &mime_allocator;
3102 return S_OK;
3105 HRESULT WINAPI MimeOleGetAllocator(IMimeAllocator **alloc)
3107 return MimeAllocator_create(NULL, (void**)alloc);
3110 HRESULT VirtualStream_create(IUnknown *outer, void **obj)
3112 FIXME("(%p, %p)\n", outer, obj);
3114 *obj = NULL;
3115 if (outer) return CLASS_E_NOAGGREGATION;
3117 return MimeOleCreateVirtualStream((IStream **)obj);
3120 /* IMimePropertySchema Interface */
3121 static HRESULT WINAPI propschema_QueryInterface(IMimePropertySchema *iface, REFIID riid, void **out)
3123 propschema *This = impl_from_IMimePropertySchema(iface);
3124 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), out);
3126 *out = NULL;
3128 if (IsEqualIID(riid, &IID_IUnknown) ||
3129 IsEqualIID(riid, &IID_IMimePropertySchema))
3131 *out = iface;
3133 else
3135 FIXME("no interface for %s\n", debugstr_guid(riid));
3136 return E_NOINTERFACE;
3139 IMimePropertySchema_AddRef(iface);
3140 return S_OK;
3143 static ULONG WINAPI propschema_AddRef(IMimePropertySchema *iface)
3145 propschema *This = impl_from_IMimePropertySchema(iface);
3146 LONG ref = InterlockedIncrement(&This->ref);
3148 TRACE("(%p) ref=%d\n", This, ref);
3150 return ref;
3153 static ULONG WINAPI propschema_Release(IMimePropertySchema *iface)
3155 propschema *This = impl_from_IMimePropertySchema(iface);
3156 LONG ref = InterlockedDecrement(&This->ref);
3158 TRACE("(%p) ref=%d\n", This, ref);
3160 if (!ref)
3162 HeapFree(GetProcessHeap(), 0, This);
3165 return ref;
3168 static HRESULT WINAPI propschema_RegisterProperty(IMimePropertySchema *iface, const char *name, DWORD flags,
3169 DWORD rownumber, VARTYPE vtdefault, DWORD *propid)
3171 propschema *This = impl_from_IMimePropertySchema(iface);
3172 FIXME("(%p)->(%s, %x, %d, %d, %p) stub\n", This, debugstr_a(name), flags, rownumber, vtdefault, propid);
3173 return E_NOTIMPL;
3176 static HRESULT WINAPI propschema_ModifyProperty(IMimePropertySchema *iface, const char *name, DWORD flags,
3177 DWORD rownumber, VARTYPE vtdefault)
3179 propschema *This = impl_from_IMimePropertySchema(iface);
3180 FIXME("(%p)->(%s, %x, %d, %d) stub\n", This, debugstr_a(name), flags, rownumber, vtdefault);
3181 return E_NOTIMPL;
3184 static HRESULT WINAPI propschema_GetPropertyId(IMimePropertySchema *iface, const char *name, DWORD *propid)
3186 propschema *This = impl_from_IMimePropertySchema(iface);
3187 FIXME("(%p)->(%s, %p) stub\n", This, debugstr_a(name), propid);
3188 return E_NOTIMPL;
3191 static HRESULT WINAPI propschema_GetPropertyName(IMimePropertySchema *iface, DWORD propid, char **name)
3193 propschema *This = impl_from_IMimePropertySchema(iface);
3194 FIXME("(%p)->(%d, %p) stub\n", This, propid, name);
3195 return E_NOTIMPL;
3198 static HRESULT WINAPI propschema_RegisterAddressType(IMimePropertySchema *iface, const char *name, DWORD *adrtype)
3200 propschema *This = impl_from_IMimePropertySchema(iface);
3201 FIXME("(%p)->(%s, %p) stub\n", This, debugstr_a(name), adrtype);
3202 return E_NOTIMPL;
3205 static IMimePropertySchemaVtbl prop_schema_vtbl =
3207 propschema_QueryInterface,
3208 propschema_AddRef,
3209 propschema_Release,
3210 propschema_RegisterProperty,
3211 propschema_ModifyProperty,
3212 propschema_GetPropertyId,
3213 propschema_GetPropertyName,
3214 propschema_RegisterAddressType
3218 HRESULT WINAPI MimeOleGetPropertySchema(IMimePropertySchema **schema)
3220 propschema *This;
3222 TRACE("(%p) stub\n", schema);
3224 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
3225 if (!This)
3226 return E_OUTOFMEMORY;
3228 This->IMimePropertySchema_iface.lpVtbl = &prop_schema_vtbl;
3229 This->ref = 1;
3231 *schema = &This->IMimePropertySchema_iface;
3233 return S_OK;
3236 HRESULT WINAPI MimeGetAddressFormatW(REFIID riid, void *object, DWORD addr_type,
3237 ADDRESSFORMAT addr_format, WCHAR **address)
3239 FIXME("(%s, %p, %d, %d, %p) stub\n", debugstr_guid(riid), object, addr_type, addr_format, address);
3241 return E_NOTIMPL;