winmm: Restrict some MCI actions to the creating thread.
[wine.git] / dlls / inetcomm / mimeole.c
blob96eab81c8bda2386361e761d1cee804473f22a4b
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 = E_NOTIMPL;
2309 TRACE("(%p)->(%08x, %p)\n", iface, oid, pValue);
2311 if(pValue->vt != TYPEDID_TYPE(oid))
2313 WARN("Called with vartype %04x and oid %08x\n", pValue->vt, oid);
2314 return E_INVALIDARG;
2317 switch(oid)
2319 case OID_HIDE_TNEF_ATTACHMENTS:
2320 FIXME("OID_HIDE_TNEF_ATTACHMENTS (value %d): ignoring\n", pValue->u.boolVal);
2321 hr = S_OK;
2322 break;
2323 case OID_SHOW_MACBINARY:
2324 FIXME("OID_SHOW_MACBINARY (value %d): ignoring\n", pValue->u.boolVal);
2325 hr = S_OK;
2326 break;
2327 default:
2328 FIXME("Unhandled oid %08x\n", oid);
2331 return hr;
2334 static HRESULT WINAPI MimeMessage_GetOption(
2335 IMimeMessage *iface,
2336 const TYPEDID oid,
2337 LPPROPVARIANT pValue)
2339 FIXME("(%p)->(%08x, %p)\n", iface, oid, pValue);
2340 return E_NOTIMPL;
2343 /*** IMimeMessage methods ***/
2344 static HRESULT WINAPI MimeMessage_CreateWebPage(
2345 IMimeMessage *iface,
2346 IStream *pRootStm,
2347 LPWEBPAGEOPTIONS pOptions,
2348 IMimeMessageCallback *pCallback,
2349 IMoniker **ppMoniker)
2351 FIXME("(%p)->(%p, %p, %p, %p)\n", iface, pRootStm, pOptions, pCallback, ppMoniker);
2352 *ppMoniker = NULL;
2353 return E_NOTIMPL;
2356 static HRESULT WINAPI MimeMessage_GetProp(
2357 IMimeMessage *iface,
2358 LPCSTR pszName,
2359 DWORD dwFlags,
2360 LPPROPVARIANT pValue)
2362 FIXME("(%p)->(%s, 0x%x, %p)\n", iface, pszName, dwFlags, pValue);
2363 return E_NOTIMPL;
2366 static HRESULT WINAPI MimeMessage_SetProp(
2367 IMimeMessage *iface,
2368 LPCSTR pszName,
2369 DWORD dwFlags,
2370 LPCPROPVARIANT pValue)
2372 FIXME("(%p)->(%s, 0x%x, %p)\n", iface, pszName, dwFlags, pValue);
2373 return E_NOTIMPL;
2376 static HRESULT WINAPI MimeMessage_DeleteProp(
2377 IMimeMessage *iface,
2378 LPCSTR pszName)
2380 FIXME("(%p)->(%s)\n", iface, pszName);
2381 return E_NOTIMPL;
2384 static HRESULT WINAPI MimeMessage_QueryProp(
2385 IMimeMessage *iface,
2386 LPCSTR pszName,
2387 LPCSTR pszCriteria,
2388 boolean fSubString,
2389 boolean fCaseSensitive)
2391 FIXME("(%p)->(%s, %s, %s, %s)\n", iface, pszName, pszCriteria, fSubString ? "TRUE" : "FALSE", fCaseSensitive ? "TRUE" : "FALSE");
2392 return E_NOTIMPL;
2395 static HRESULT WINAPI MimeMessage_GetTextBody(
2396 IMimeMessage *iface,
2397 DWORD dwTxtType,
2398 ENCODINGTYPE ietEncoding,
2399 IStream **pStream,
2400 LPHBODY phBody)
2402 HRESULT hr;
2403 HBODY hbody;
2404 FINDBODY find_struct;
2405 IMimeBody *mime_body;
2406 static char text[] = "text";
2407 static char plain[] = "plain";
2408 static char html[] = "html";
2410 TRACE("(%p)->(%d, %d, %p, %p)\n", iface, dwTxtType, ietEncoding, pStream, phBody);
2412 find_struct.pszPriType = text;
2414 switch(dwTxtType)
2416 case TXT_PLAIN:
2417 find_struct.pszSubType = plain;
2418 break;
2419 case TXT_HTML:
2420 find_struct.pszSubType = html;
2421 break;
2422 default:
2423 return MIME_E_INVALID_TEXT_TYPE;
2426 hr = IMimeMessage_FindFirst(iface, &find_struct, &hbody);
2427 if(hr != S_OK)
2429 TRACE("not found hr %08x\n", hr);
2430 *phBody = NULL;
2431 return hr;
2434 IMimeMessage_BindToObject(iface, hbody, &IID_IMimeBody, (void**)&mime_body);
2436 IMimeBody_GetData(mime_body, ietEncoding, pStream);
2437 *phBody = hbody;
2438 IMimeBody_Release(mime_body);
2439 return hr;
2442 static HRESULT WINAPI MimeMessage_SetTextBody(
2443 IMimeMessage *iface,
2444 DWORD dwTxtType,
2445 ENCODINGTYPE ietEncoding,
2446 HBODY hAlternative,
2447 IStream *pStream,
2448 LPHBODY phBody)
2450 FIXME("(%p)->(%d, %d, %p, %p, %p)\n", iface, dwTxtType, ietEncoding, hAlternative, pStream, phBody);
2451 return E_NOTIMPL;
2454 static HRESULT WINAPI MimeMessage_AttachObject(
2455 IMimeMessage *iface,
2456 REFIID riid,
2457 void *pvObject,
2458 LPHBODY phBody)
2460 FIXME("(%p)->(%s, %p, %p)\n", iface, debugstr_guid(riid), pvObject, phBody);
2461 return E_NOTIMPL;
2464 static HRESULT WINAPI MimeMessage_AttachFile(
2465 IMimeMessage *iface,
2466 LPCSTR pszFilePath,
2467 IStream *pstmFile,
2468 LPHBODY phBody)
2470 FIXME("(%p)->(%s, %p, %p)\n", iface, pszFilePath, pstmFile, phBody);
2471 return E_NOTIMPL;
2474 static HRESULT WINAPI MimeMessage_AttachURL(
2475 IMimeMessage *iface,
2476 LPCSTR pszBase,
2477 LPCSTR pszURL,
2478 DWORD dwFlags,
2479 IStream *pstmURL,
2480 LPSTR *ppszCIDURL,
2481 LPHBODY phBody)
2483 FIXME("(%p)->(%s, %s, 0x%x, %p, %p, %p)\n", iface, pszBase, pszURL, dwFlags, pstmURL, ppszCIDURL, phBody);
2484 return E_NOTIMPL;
2487 static HRESULT WINAPI MimeMessage_GetAttachments(
2488 IMimeMessage *iface,
2489 ULONG *pcAttach,
2490 LPHBODY *pprghAttach)
2492 HRESULT hr;
2493 FINDBODY find_struct;
2494 HBODY hbody;
2495 LPHBODY array;
2496 ULONG size = 10;
2498 TRACE("(%p)->(%p, %p)\n", iface, pcAttach, pprghAttach);
2500 *pcAttach = 0;
2501 array = CoTaskMemAlloc(size * sizeof(HBODY));
2503 find_struct.pszPriType = find_struct.pszSubType = NULL;
2504 hr = IMimeMessage_FindFirst(iface, &find_struct, &hbody);
2505 while(hr == S_OK)
2507 hr = IMimeMessage_IsContentType(iface, hbody, "multipart", NULL);
2508 TRACE("IsCT rets %08x %d\n", hr, *pcAttach);
2509 if(hr != S_OK)
2511 if(*pcAttach + 1 > size)
2513 size *= 2;
2514 array = CoTaskMemRealloc(array, size * sizeof(HBODY));
2516 array[*pcAttach] = hbody;
2517 (*pcAttach)++;
2519 hr = IMimeMessage_FindNext(iface, &find_struct, &hbody);
2522 *pprghAttach = array;
2523 return S_OK;
2526 static HRESULT WINAPI MimeMessage_GetAddressTable(
2527 IMimeMessage *iface,
2528 IMimeAddressTable **ppTable)
2530 FIXME("(%p)->(%p)\n", iface, ppTable);
2531 return E_NOTIMPL;
2534 static HRESULT WINAPI MimeMessage_GetSender(
2535 IMimeMessage *iface,
2536 LPADDRESSPROPS pAddress)
2538 FIXME("(%p)->(%p)\n", iface, pAddress);
2539 return E_NOTIMPL;
2542 static HRESULT WINAPI MimeMessage_GetAddressTypes(
2543 IMimeMessage *iface,
2544 DWORD dwAdrTypes,
2545 DWORD dwProps,
2546 LPADDRESSLIST pList)
2548 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, dwProps, pList);
2549 return E_NOTIMPL;
2552 static HRESULT WINAPI MimeMessage_GetAddressFormat(
2553 IMimeMessage *iface,
2554 DWORD dwAdrTypes,
2555 ADDRESSFORMAT format,
2556 LPSTR *ppszFormat)
2558 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, format, ppszFormat);
2559 return E_NOTIMPL;
2562 static HRESULT WINAPI MimeMessage_EnumAddressTypes(
2563 IMimeMessage *iface,
2564 DWORD dwAdrTypes,
2565 DWORD dwProps,
2566 IMimeEnumAddressTypes **ppEnum)
2568 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, dwProps, ppEnum);
2569 return E_NOTIMPL;
2572 static HRESULT WINAPI MimeMessage_SplitMessage(
2573 IMimeMessage *iface,
2574 ULONG cbMaxPart,
2575 IMimeMessageParts **ppParts)
2577 FIXME("(%p)->(%d, %p)\n", iface, cbMaxPart, ppParts);
2578 return E_NOTIMPL;
2581 static HRESULT WINAPI MimeMessage_GetRootMoniker(
2582 IMimeMessage *iface,
2583 IMoniker **ppMoniker)
2585 FIXME("(%p)->(%p)\n", iface, ppMoniker);
2586 return E_NOTIMPL;
2589 static const IMimeMessageVtbl MimeMessageVtbl =
2591 MimeMessage_QueryInterface,
2592 MimeMessage_AddRef,
2593 MimeMessage_Release,
2594 MimeMessage_GetClassID,
2595 MimeMessage_IsDirty,
2596 MimeMessage_Load,
2597 MimeMessage_Save,
2598 MimeMessage_GetSizeMax,
2599 MimeMessage_InitNew,
2600 MimeMessage_GetMessageSource,
2601 MimeMessage_GetMessageSize,
2602 MimeMessage_LoadOffsetTable,
2603 MimeMessage_SaveOffsetTable,
2604 MimeMessage_GetFlags,
2605 MimeMessage_Commit,
2606 MimeMessage_HandsOffStorage,
2607 MimeMessage_BindToObject,
2608 MimeMessage_SaveBody,
2609 MimeMessage_InsertBody,
2610 MimeMessage_GetBody,
2611 MimeMessage_DeleteBody,
2612 MimeMessage_MoveBody,
2613 MimeMessage_CountBodies,
2614 MimeMessage_FindFirst,
2615 MimeMessage_FindNext,
2616 MimeMessage_ResolveURL,
2617 MimeMessage_ToMultipart,
2618 MimeMessage_GetBodyOffsets,
2619 MimeMessage_GetCharset,
2620 MimeMessage_SetCharset,
2621 MimeMessage_IsBodyType,
2622 MimeMessage_IsContentType,
2623 MimeMessage_QueryBodyProp,
2624 MimeMessage_GetBodyProp,
2625 MimeMessage_SetBodyProp,
2626 MimeMessage_DeleteBodyProp,
2627 MimeMessage_SetOption,
2628 MimeMessage_GetOption,
2629 MimeMessage_CreateWebPage,
2630 MimeMessage_GetProp,
2631 MimeMessage_SetProp,
2632 MimeMessage_DeleteProp,
2633 MimeMessage_QueryProp,
2634 MimeMessage_GetTextBody,
2635 MimeMessage_SetTextBody,
2636 MimeMessage_AttachObject,
2637 MimeMessage_AttachFile,
2638 MimeMessage_AttachURL,
2639 MimeMessage_GetAttachments,
2640 MimeMessage_GetAddressTable,
2641 MimeMessage_GetSender,
2642 MimeMessage_GetAddressTypes,
2643 MimeMessage_GetAddressFormat,
2644 MimeMessage_EnumAddressTypes,
2645 MimeMessage_SplitMessage,
2646 MimeMessage_GetRootMoniker,
2649 HRESULT MimeMessage_create(IUnknown *outer, void **obj)
2651 MimeMessage *This;
2652 MimeBody *mime_body;
2653 body_t *root_body;
2655 TRACE("(%p, %p)\n", outer, obj);
2657 if (outer)
2659 FIXME("outer unknown not supported yet\n");
2660 return E_NOTIMPL;
2663 *obj = NULL;
2665 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2666 if (!This) return E_OUTOFMEMORY;
2668 This->IMimeMessage_iface.lpVtbl = &MimeMessageVtbl;
2669 This->ref = 1;
2670 This->stream = NULL;
2671 list_init(&This->body_tree);
2672 This->next_index = 1;
2674 mime_body = mimebody_create();
2675 root_body = new_body_entry(mime_body, This->next_index++, NULL);
2676 list_add_head(&This->body_tree, &root_body->entry);
2678 *obj = &This->IMimeMessage_iface;
2679 return S_OK;
2682 /***********************************************************************
2683 * MimeOleCreateMessage (INETCOMM.@)
2685 HRESULT WINAPI MimeOleCreateMessage(IUnknown *pUnkOuter, IMimeMessage **ppMessage)
2687 TRACE("(%p, %p)\n", pUnkOuter, ppMessage);
2688 return MimeMessage_create(NULL, (void **)ppMessage);
2691 /***********************************************************************
2692 * MimeOleSetCompatMode (INETCOMM.@)
2694 HRESULT WINAPI MimeOleSetCompatMode(DWORD dwMode)
2696 FIXME("(0x%x)\n", dwMode);
2697 return S_OK;
2700 /***********************************************************************
2701 * MimeOleCreateVirtualStream (INETCOMM.@)
2703 HRESULT WINAPI MimeOleCreateVirtualStream(IStream **ppStream)
2705 HRESULT hr;
2706 FIXME("(%p)\n", ppStream);
2708 hr = CreateStreamOnHGlobal(NULL, TRUE, ppStream);
2709 return hr;
2712 typedef struct MimeSecurity
2714 IMimeSecurity IMimeSecurity_iface;
2715 LONG ref;
2716 } MimeSecurity;
2718 static inline MimeSecurity *impl_from_IMimeSecurity(IMimeSecurity *iface)
2720 return CONTAINING_RECORD(iface, MimeSecurity, IMimeSecurity_iface);
2723 static HRESULT WINAPI MimeSecurity_QueryInterface(IMimeSecurity *iface, REFIID riid, void **ppv)
2725 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2727 if (IsEqualIID(riid, &IID_IUnknown) ||
2728 IsEqualIID(riid, &IID_IMimeSecurity))
2730 *ppv = iface;
2731 IMimeSecurity_AddRef(iface);
2732 return S_OK;
2735 FIXME("no interface for %s\n", debugstr_guid(riid));
2736 *ppv = NULL;
2737 return E_NOINTERFACE;
2740 static ULONG WINAPI MimeSecurity_AddRef(IMimeSecurity *iface)
2742 MimeSecurity *This = impl_from_IMimeSecurity(iface);
2743 LONG ref = InterlockedIncrement(&This->ref);
2745 TRACE("(%p) ref=%d\n", This, ref);
2747 return ref;
2750 static ULONG WINAPI MimeSecurity_Release(IMimeSecurity *iface)
2752 MimeSecurity *This = impl_from_IMimeSecurity(iface);
2753 LONG ref = InterlockedDecrement(&This->ref);
2755 TRACE("(%p) ref=%d\n", This, ref);
2757 if (!ref)
2758 HeapFree(GetProcessHeap(), 0, This);
2760 return ref;
2763 static HRESULT WINAPI MimeSecurity_InitNew(
2764 IMimeSecurity* iface)
2766 FIXME("(%p)->(): stub\n", iface);
2767 return S_OK;
2770 static HRESULT WINAPI MimeSecurity_CheckInit(
2771 IMimeSecurity* iface)
2773 FIXME("(%p)->(): stub\n", iface);
2774 return E_NOTIMPL;
2777 static HRESULT WINAPI MimeSecurity_EncodeMessage(
2778 IMimeSecurity* iface,
2779 IMimeMessageTree* pTree,
2780 DWORD dwFlags)
2782 FIXME("(%p)->(%p, %08x): stub\n", iface, pTree, dwFlags);
2783 return E_NOTIMPL;
2786 static HRESULT WINAPI MimeSecurity_EncodeBody(
2787 IMimeSecurity* iface,
2788 IMimeMessageTree* pTree,
2789 HBODY hEncodeRoot,
2790 DWORD dwFlags)
2792 FIXME("(%p)->(%p, %p, %08x): stub\n", iface, pTree, hEncodeRoot, dwFlags);
2793 return E_NOTIMPL;
2796 static HRESULT WINAPI MimeSecurity_DecodeMessage(
2797 IMimeSecurity* iface,
2798 IMimeMessageTree* pTree,
2799 DWORD dwFlags)
2801 FIXME("(%p)->(%p, %08x): stub\n", iface, pTree, dwFlags);
2802 return E_NOTIMPL;
2805 static HRESULT WINAPI MimeSecurity_DecodeBody(
2806 IMimeSecurity* iface,
2807 IMimeMessageTree* pTree,
2808 HBODY hDecodeRoot,
2809 DWORD dwFlags)
2811 FIXME("(%p)->(%p, %p, %08x): stub\n", iface, pTree, hDecodeRoot, dwFlags);
2812 return E_NOTIMPL;
2815 static HRESULT WINAPI MimeSecurity_EnumCertificates(
2816 IMimeSecurity* iface,
2817 HCAPICERTSTORE hc,
2818 DWORD dwUsage,
2819 PCX509CERT pPrev,
2820 PCX509CERT* ppCert)
2822 FIXME("(%p)->(%p, %08x, %p, %p): stub\n", iface, hc, dwUsage, pPrev, ppCert);
2823 return E_NOTIMPL;
2826 static HRESULT WINAPI MimeSecurity_GetCertificateName(
2827 IMimeSecurity* iface,
2828 const PCX509CERT pX509Cert,
2829 const CERTNAMETYPE cn,
2830 LPSTR* ppszName)
2832 FIXME("(%p)->(%p, %08x, %p): stub\n", iface, pX509Cert, cn, ppszName);
2833 return E_NOTIMPL;
2836 static HRESULT WINAPI MimeSecurity_GetMessageType(
2837 IMimeSecurity* iface,
2838 const HWND hwndParent,
2839 IMimeBody* pBody,
2840 DWORD* pdwSecType)
2842 FIXME("(%p)->(%p, %p, %p): stub\n", iface, hwndParent, pBody, pdwSecType);
2843 return E_NOTIMPL;
2846 static HRESULT WINAPI MimeSecurity_GetCertData(
2847 IMimeSecurity* iface,
2848 const PCX509CERT pX509Cert,
2849 const CERTDATAID dataid,
2850 LPPROPVARIANT pValue)
2852 FIXME("(%p)->(%p, %x, %p): stub\n", iface, pX509Cert, dataid, pValue);
2853 return E_NOTIMPL;
2857 static const IMimeSecurityVtbl MimeSecurityVtbl =
2859 MimeSecurity_QueryInterface,
2860 MimeSecurity_AddRef,
2861 MimeSecurity_Release,
2862 MimeSecurity_InitNew,
2863 MimeSecurity_CheckInit,
2864 MimeSecurity_EncodeMessage,
2865 MimeSecurity_EncodeBody,
2866 MimeSecurity_DecodeMessage,
2867 MimeSecurity_DecodeBody,
2868 MimeSecurity_EnumCertificates,
2869 MimeSecurity_GetCertificateName,
2870 MimeSecurity_GetMessageType,
2871 MimeSecurity_GetCertData
2874 HRESULT MimeSecurity_create(IUnknown *outer, void **obj)
2876 MimeSecurity *This;
2878 *obj = NULL;
2880 if (outer) return CLASS_E_NOAGGREGATION;
2882 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2883 if (!This) return E_OUTOFMEMORY;
2885 This->IMimeSecurity_iface.lpVtbl = &MimeSecurityVtbl;
2886 This->ref = 1;
2888 *obj = &This->IMimeSecurity_iface;
2889 return S_OK;
2892 /***********************************************************************
2893 * MimeOleCreateSecurity (INETCOMM.@)
2895 HRESULT WINAPI MimeOleCreateSecurity(IMimeSecurity **ppSecurity)
2897 return MimeSecurity_create(NULL, (void **)ppSecurity);
2900 static HRESULT WINAPI MimeAlloc_QueryInterface(
2901 IMimeAllocator* iface,
2902 REFIID riid,
2903 void **obj)
2905 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), obj);
2907 if (IsEqualIID(riid, &IID_IUnknown) ||
2908 IsEqualIID(riid, &IID_IMalloc) ||
2909 IsEqualIID(riid, &IID_IMimeAllocator))
2911 *obj = iface;
2912 IMimeAllocator_AddRef(iface);
2913 return S_OK;
2916 FIXME("no interface for %s\n", debugstr_guid(riid));
2917 *obj = NULL;
2918 return E_NOINTERFACE;
2921 static ULONG WINAPI MimeAlloc_AddRef(
2922 IMimeAllocator* iface)
2924 return 2;
2927 static ULONG WINAPI MimeAlloc_Release(
2928 IMimeAllocator* iface)
2930 return 1;
2933 static LPVOID WINAPI MimeAlloc_Alloc(
2934 IMimeAllocator* iface,
2935 SIZE_T cb)
2937 return CoTaskMemAlloc(cb);
2940 static LPVOID WINAPI MimeAlloc_Realloc(
2941 IMimeAllocator* iface,
2942 LPVOID pv,
2943 SIZE_T cb)
2945 return CoTaskMemRealloc(pv, cb);
2948 static void WINAPI MimeAlloc_Free(
2949 IMimeAllocator* iface,
2950 LPVOID pv)
2952 CoTaskMemFree(pv);
2955 static SIZE_T WINAPI MimeAlloc_GetSize(
2956 IMimeAllocator* iface,
2957 LPVOID pv)
2959 FIXME("stub\n");
2960 return 0;
2963 static int WINAPI MimeAlloc_DidAlloc(
2964 IMimeAllocator* iface,
2965 LPVOID pv)
2967 FIXME("stub\n");
2968 return 0;
2971 static void WINAPI MimeAlloc_HeapMinimize(
2972 IMimeAllocator* iface)
2974 FIXME("stub\n");
2975 return;
2978 static HRESULT WINAPI MimeAlloc_FreeParamInfoArray(
2979 IMimeAllocator* iface,
2980 ULONG cParams,
2981 LPMIMEPARAMINFO prgParam,
2982 boolean fFreeArray)
2984 ULONG i;
2985 TRACE("(%p)->(%d, %p, %d)\n", iface, cParams, prgParam, fFreeArray);
2987 for(i = 0; i < cParams; i++)
2989 IMimeAllocator_Free(iface, prgParam[i].pszName);
2990 IMimeAllocator_Free(iface, prgParam[i].pszData);
2992 if(fFreeArray) IMimeAllocator_Free(iface, prgParam);
2993 return S_OK;
2996 static HRESULT WINAPI MimeAlloc_FreeAddressList(
2997 IMimeAllocator* iface,
2998 LPADDRESSLIST pList)
3000 FIXME("stub\n");
3001 return E_NOTIMPL;
3004 static HRESULT WINAPI MimeAlloc_FreeAddressProps(
3005 IMimeAllocator* iface,
3006 LPADDRESSPROPS pAddress)
3008 FIXME("stub\n");
3009 return E_NOTIMPL;
3012 static HRESULT WINAPI MimeAlloc_ReleaseObjects(
3013 IMimeAllocator* iface,
3014 ULONG cObjects,
3015 IUnknown **prgpUnknown,
3016 boolean fFreeArray)
3018 FIXME("stub\n");
3019 return E_NOTIMPL;
3023 static HRESULT WINAPI MimeAlloc_FreeEnumHeaderRowArray(
3024 IMimeAllocator* iface,
3025 ULONG cRows,
3026 LPENUMHEADERROW prgRow,
3027 boolean fFreeArray)
3029 FIXME("stub\n");
3030 return E_NOTIMPL;
3033 static HRESULT WINAPI MimeAlloc_FreeEnumPropertyArray(
3034 IMimeAllocator* iface,
3035 ULONG cProps,
3036 LPENUMPROPERTY prgProp,
3037 boolean fFreeArray)
3039 FIXME("stub\n");
3040 return E_NOTIMPL;
3043 static HRESULT WINAPI MimeAlloc_FreeThumbprint(
3044 IMimeAllocator* iface,
3045 THUMBBLOB *pthumbprint)
3047 FIXME("stub\n");
3048 return E_NOTIMPL;
3052 static HRESULT WINAPI MimeAlloc_PropVariantClear(
3053 IMimeAllocator* iface,
3054 LPPROPVARIANT pProp)
3056 FIXME("stub\n");
3057 return E_NOTIMPL;
3060 static IMimeAllocatorVtbl mime_alloc_vtbl =
3062 MimeAlloc_QueryInterface,
3063 MimeAlloc_AddRef,
3064 MimeAlloc_Release,
3065 MimeAlloc_Alloc,
3066 MimeAlloc_Realloc,
3067 MimeAlloc_Free,
3068 MimeAlloc_GetSize,
3069 MimeAlloc_DidAlloc,
3070 MimeAlloc_HeapMinimize,
3071 MimeAlloc_FreeParamInfoArray,
3072 MimeAlloc_FreeAddressList,
3073 MimeAlloc_FreeAddressProps,
3074 MimeAlloc_ReleaseObjects,
3075 MimeAlloc_FreeEnumHeaderRowArray,
3076 MimeAlloc_FreeEnumPropertyArray,
3077 MimeAlloc_FreeThumbprint,
3078 MimeAlloc_PropVariantClear
3081 static IMimeAllocator mime_allocator =
3083 &mime_alloc_vtbl
3086 HRESULT MimeAllocator_create(IUnknown *outer, void **obj)
3088 if(outer) return CLASS_E_NOAGGREGATION;
3090 *obj = &mime_allocator;
3091 return S_OK;
3094 HRESULT WINAPI MimeOleGetAllocator(IMimeAllocator **alloc)
3096 return MimeAllocator_create(NULL, (void**)alloc);
3099 HRESULT VirtualStream_create(IUnknown *outer, void **obj)
3101 FIXME("(%p, %p)\n", outer, obj);
3103 *obj = NULL;
3104 if (outer) return CLASS_E_NOAGGREGATION;
3106 return MimeOleCreateVirtualStream((IStream **)obj);
3109 /* IMimePropertySchema Interface */
3110 static HRESULT WINAPI propschema_QueryInterface(IMimePropertySchema *iface, REFIID riid, void **out)
3112 propschema *This = impl_from_IMimePropertySchema(iface);
3113 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), out);
3115 *out = NULL;
3117 if (IsEqualIID(riid, &IID_IUnknown) ||
3118 IsEqualIID(riid, &IID_IMimePropertySchema))
3120 *out = iface;
3122 else
3124 FIXME("no interface for %s\n", debugstr_guid(riid));
3125 return E_NOINTERFACE;
3128 IMimePropertySchema_AddRef(iface);
3129 return S_OK;
3132 static ULONG WINAPI propschema_AddRef(IMimePropertySchema *iface)
3134 propschema *This = impl_from_IMimePropertySchema(iface);
3135 LONG ref = InterlockedIncrement(&This->ref);
3137 TRACE("(%p) ref=%d\n", This, ref);
3139 return ref;
3142 static ULONG WINAPI propschema_Release(IMimePropertySchema *iface)
3144 propschema *This = impl_from_IMimePropertySchema(iface);
3145 LONG ref = InterlockedDecrement(&This->ref);
3147 TRACE("(%p) ref=%d\n", This, ref);
3149 if (!ref)
3151 HeapFree(GetProcessHeap(), 0, This);
3154 return ref;
3157 static HRESULT WINAPI propschema_RegisterProperty(IMimePropertySchema *iface, const char *name, DWORD flags,
3158 DWORD rownumber, VARTYPE vtdefault, DWORD *propid)
3160 propschema *This = impl_from_IMimePropertySchema(iface);
3161 FIXME("(%p)->(%s, %x, %d, %d, %p) stub\n", This, debugstr_a(name), flags, rownumber, vtdefault, propid);
3162 return E_NOTIMPL;
3165 static HRESULT WINAPI propschema_ModifyProperty(IMimePropertySchema *iface, const char *name, DWORD flags,
3166 DWORD rownumber, VARTYPE vtdefault)
3168 propschema *This = impl_from_IMimePropertySchema(iface);
3169 FIXME("(%p)->(%s, %x, %d, %d) stub\n", This, debugstr_a(name), flags, rownumber, vtdefault);
3170 return E_NOTIMPL;
3173 static HRESULT WINAPI propschema_GetPropertyId(IMimePropertySchema *iface, const char *name, DWORD *propid)
3175 propschema *This = impl_from_IMimePropertySchema(iface);
3176 FIXME("(%p)->(%s, %p) stub\n", This, debugstr_a(name), propid);
3177 return E_NOTIMPL;
3180 static HRESULT WINAPI propschema_GetPropertyName(IMimePropertySchema *iface, DWORD propid, char **name)
3182 propschema *This = impl_from_IMimePropertySchema(iface);
3183 FIXME("(%p)->(%d, %p) stub\n", This, propid, name);
3184 return E_NOTIMPL;
3187 static HRESULT WINAPI propschema_RegisterAddressType(IMimePropertySchema *iface, const char *name, DWORD *adrtype)
3189 propschema *This = impl_from_IMimePropertySchema(iface);
3190 FIXME("(%p)->(%s, %p) stub\n", This, debugstr_a(name), adrtype);
3191 return E_NOTIMPL;
3194 static IMimePropertySchemaVtbl prop_schema_vtbl =
3196 propschema_QueryInterface,
3197 propschema_AddRef,
3198 propschema_Release,
3199 propschema_RegisterProperty,
3200 propschema_ModifyProperty,
3201 propschema_GetPropertyId,
3202 propschema_GetPropertyName,
3203 propschema_RegisterAddressType
3207 HRESULT WINAPI MimeOleGetPropertySchema(IMimePropertySchema **schema)
3209 propschema *This;
3211 TRACE("(%p) stub\n", schema);
3213 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
3214 if (!This)
3215 return E_OUTOFMEMORY;
3217 This->IMimePropertySchema_iface.lpVtbl = &prop_schema_vtbl;
3218 This->ref = 1;
3220 *schema = &This->IMimePropertySchema_iface;
3222 return S_OK;
3225 HRESULT WINAPI MimeGetAddressFormatW(REFIID riid, void *object, DWORD addr_type,
3226 ADDRESSFORMAT addr_format, WCHAR **address)
3228 FIXME("(%s, %p, %d, %d, %p) stub\n", debugstr_guid(riid), object, addr_type, addr_format, address);
3230 return E_NOTIMPL;