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
23 #define NONAMELESSUNION
35 #include "wine/list.h"
36 #include "wine/debug.h"
38 #include "inetcomm_private.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(inetcomm
);
46 DWORD flags
; /* MIMEPROPFLAGS */
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
},
90 const property_t
*prop
;
95 typedef struct MimeBody
97 IMimeBody IMimeBody_iface
;
103 struct list new_props
; /* FIXME: This should be in a PropertySchema */
105 char *content_pri_type
;
106 char *content_sub_type
;
107 ENCODINGTYPE encoding
;
110 BODYOFFSETS body_offsets
;
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
;
124 static inline propschema
*impl_from_IMimePropertySchema(IMimePropertySchema
*iface
)
126 return CONTAINING_RECORD(iface
, propschema
, IMimePropertySchema_iface
);
129 static LPSTR
strdupA(LPCSTR str
)
132 int len
= strlen(str
);
133 ret
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
134 memcpy(ret
, str
, len
+ 1);
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
)
149 DWORD size
= PARSER_BUF_SIZE
, offset
= 0, last_end
= 0;
161 buf
= HeapAlloc(GetProcessHeap(), 0, size
+ 1);
165 buf
= HeapReAlloc(GetProcessHeap(), 0, buf
, size
+ 1);
173 hr
= IStream_Read(stm
, buf
+ offset
, size
- offset
, &read
);
174 if(FAILED(hr
)) goto fail
;
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)
187 off
.QuadPart
= new_end
;
188 IStream_Seek(stm
, off
, STREAM_SEEK_SET
, NULL
);
201 HeapFree(GetProcessHeap(), 0, buf
);
205 static header_t
*read_prop(MimeBody
*body
, char **ptr
)
207 char *colon
= strchr(*ptr
, ':');
208 const property_t
*prop
;
211 if(!colon
) return NULL
;
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
);
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
;
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
));
251 PropVariantInit(&ret
->value
);
252 list_init(&ret
->params
);
258 static void unfold_header(char *header
, int len
)
260 char *start
= header
, *cp
= header
;
263 while(*cp
== ' ' || *cp
== '\t')
269 memmove(start
, cp
, len
+ 1);
271 cp
= strstr(start
, "\r\n");
278 } while(*cp
== ' ' || *cp
== '\t');
283 static char *unquote_string(const char *str
)
288 while(*str
== ' ' || *str
== '\t') str
++;
296 for(cp
= ret
; *cp
; cp
++)
299 memmove(cp
, cp
+ 1, strlen(cp
+ 1) + 1);
304 WARN("quote in unquoted string\n");
316 static void add_param(header_t
*header
, const char *p
)
318 const char *key
= p
, *value
, *cp
= p
;
322 TRACE("got param %s\n", p
);
324 while (*key
== ' ' || *key
== '\t' ) key
++;
326 cp
= strchr(key
, '=');
329 WARN("malformed parameter - skipping\n");
333 name
= HeapAlloc(GetProcessHeap(), 0, cp
- key
+ 1);
334 memcpy(name
, key
, cp
- key
);
335 name
[cp
- key
] = '\0';
339 param
= HeapAlloc(GetProcessHeap(), 0, sizeof(*param
));
341 param
->value
= unquote_string(value
);
342 list_add_tail(&header
->params
, ¶m
->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
;
352 if(!in_quotes
&& *cp
== ';')
355 if(done_value
) add_param(header
, start
);
360 in_quotes
= !in_quotes
;
363 if(done_value
) add_param(header
, start
);
366 static void read_value(header_t
*header
, char **cur
)
368 char *end
= *cur
, *value
;
372 end
= strstr(end
, "\r\n");
374 } while(*end
== ' ' || *end
== '\t');
377 value
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
378 memcpy(value
, *cur
, len
);
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
;
396 static void init_content_type(MimeBody
*body
, header_t
*header
)
401 if(header
->prop
->id
!= PID_HDR_CNTTYPE
)
403 ERR("called with header %s\n", header
->prop
->name
);
407 slash
= strchr(header
->value
.u
.pszVal
, '/');
410 WARN("malformed context type value\n");
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
;
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
);
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(¶m
->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
)
485 if(IsEqualIID(riid
, &IID_IStream
))
486 IStream_Release((IStream
*)data
);
488 FIXME("Unhandled data format %s\n", debugstr_guid(riid
));
491 static HRESULT
find_prop(MimeBody
*body
, const char *name
, header_t
**prop
)
497 LIST_FOR_EACH_ENTRY(header
, &body
->headers
, header_t
, entry
)
499 if(!lstrcmpiA(name
, header
->prop
->name
))
506 return MIME_E_NOT_FOUND
;
509 static HRESULT WINAPI
MimeBody_QueryInterface(IMimeBody
* iface
,
513 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppvObject
);
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
))
528 IUnknown_AddRef((IUnknown
*)*ppvObject
);
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
);
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
);
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
);
569 static HRESULT WINAPI
MimeBody_GetClassID(
573 MimeBody
*This
= impl_from_IMimeBody(iface
);
574 FIXME("(%p)->(%p) stub\n", This
, pClassID
);
579 static HRESULT WINAPI
MimeBody_IsDirty(
582 MimeBody
*This
= impl_from_IMimeBody(iface
);
583 FIXME("(%p)->() stub\n", This
);
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
);
601 static HRESULT WINAPI
MimeBody_GetSizeMax(
603 ULARGE_INTEGER
* pcbSize
)
605 MimeBody
*This
= impl_from_IMimeBody(iface
);
606 FIXME("(%p)->(%p) stub\n", This
, pcbSize
);
610 static HRESULT WINAPI
MimeBody_InitNew(
613 MimeBody
*This
= impl_from_IMimeBody(iface
);
614 TRACE("(%p)->()\n", This
);
618 static HRESULT WINAPI
MimeBody_GetPropInfo(
621 LPMIMEPROPINFO pInfo
)
623 MimeBody
*This
= impl_from_IMimeBody(iface
);
624 FIXME("(%p)->(%s, %p) stub\n", This
, debugstr_a(pszName
), pInfo
);
628 static HRESULT WINAPI
MimeBody_SetPropInfo(
631 LPCMIMEPROPINFO pInfo
)
633 MimeBody
*This
= impl_from_IMimeBody(iface
);
634 FIXME("(%p)->(%s, %p) stub\n", This
, debugstr_a(pszName
), pInfo
);
638 static HRESULT WINAPI
MimeBody_GetProp(
642 LPPROPVARIANT pValue
)
644 MimeBody
*This
= impl_from_IMimeBody(iface
);
648 TRACE("(%p)->(%s, 0x%x, %p)\n", This
, debugstr_a(pszName
), dwFlags
, pValue
);
650 if(!pszName
|| !pValue
)
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
);
661 hr
= find_prop(This
, pszName
, &header
);
664 PropVariantCopy(pValue
, &header
->value
);
670 static HRESULT WINAPI
MimeBody_SetProp(
674 LPCPROPVARIANT pValue
)
676 MimeBody
*This
= impl_from_IMimeBody(iface
);
680 TRACE("(%p)->(%s, 0x%x, %p)\n", This
, debugstr_a(pszName
), dwFlags
, pValue
);
682 if(!pszName
|| !pValue
)
685 hr
= find_prop(This
, pszName
, &header
);
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
;
701 header
= HeapAlloc(GetProcessHeap(), 0, sizeof(*header
));
703 return E_OUTOFMEMORY
;
707 prop_entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(*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
);
723 PropVariantInit(&header
->value
);
724 list_init(&header
->params
);
725 list_add_tail(&This
->headers
, &header
->entry
);
728 PropVariantCopy(&header
->value
, pValue
);
733 static HRESULT WINAPI
MimeBody_AppendProp(
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
);
744 static HRESULT WINAPI
MimeBody_DeleteProp(
748 MimeBody
*This
= impl_from_IMimeBody(iface
);
749 FIXME("(%p)->(%s) stub\n", This
, debugstr_a(pszName
));
753 static HRESULT WINAPI
MimeBody_CopyProps(
757 IMimePropertySet
* pPropertySet
)
759 MimeBody
*This
= impl_from_IMimeBody(iface
);
760 FIXME("(%p)->(%d, %p, %p) stub\n", This
, cNames
, prgszName
, pPropertySet
);
764 static HRESULT WINAPI
MimeBody_MoveProps(
768 IMimePropertySet
* pPropertySet
)
770 MimeBody
*This
= impl_from_IMimeBody(iface
);
771 FIXME("(%p)->(%d, %p, %p) stub\n", This
, cNames
, prgszName
, pPropertySet
);
775 static HRESULT WINAPI
MimeBody_DeleteExcept(
780 MimeBody
*This
= impl_from_IMimeBody(iface
);
781 FIXME("(%p)->(%d, %p) stub\n", This
, cNames
, prgszName
);
785 static HRESULT WINAPI
MimeBody_QueryProp(
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
);
797 static HRESULT WINAPI
MimeBody_GetCharset(
799 LPHCHARSET phCharset
)
801 MimeBody
*This
= impl_from_IMimeBody(iface
);
802 FIXME("(%p)->(%p) stub\n", This
, phCharset
);
807 static HRESULT WINAPI
MimeBody_SetCharset(
810 CSETAPPLYTYPE applytype
)
812 MimeBody
*This
= impl_from_IMimeBody(iface
);
813 FIXME("(%p)->(%p, %d) stub\n", This
, hCharset
, applytype
);
817 static HRESULT WINAPI
MimeBody_GetParameters(
821 LPMIMEPARAMINFO
* pprgParam
)
823 MimeBody
*This
= impl_from_IMimeBody(iface
);
827 TRACE("(%p)->(%s, %p, %p)\n", iface
, debugstr_a(pszName
), pcParams
, pprgParam
);
832 hr
= find_prop(This
, pszName
, &header
);
833 if(hr
!= S_OK
) return hr
;
835 *pcParams
= list_count(&header
->params
);
838 IMimeAllocator
*alloc
;
842 MimeOleGetAllocator(&alloc
);
844 *pprgParam
= info
= IMimeAllocator_Alloc(alloc
, *pcParams
* sizeof(**pprgParam
));
845 LIST_FOR_EACH_ENTRY(param
, &header
->params
, param_t
, entry
)
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
);
857 IMimeAllocator_Release(alloc
);
862 static HRESULT WINAPI
MimeBody_IsContentType(
867 MimeBody
*This
= impl_from_IMimeBody(iface
);
869 TRACE("(%p)->(%s, %s)\n", This
, debugstr_a(pszPriType
), debugstr_a(pszSubType
));
872 const char *pri
= This
->content_pri_type
;
873 if(!pri
) pri
= "text";
874 if(lstrcmpiA(pri
, pszPriType
)) return S_FALSE
;
879 const char *sub
= This
->content_sub_type
;
880 if(!sub
) sub
= "plain";
881 if(lstrcmpiA(sub
, pszSubType
)) return S_FALSE
;
887 static HRESULT WINAPI
MimeBody_BindToObject(
892 MimeBody
*This
= impl_from_IMimeBody(iface
);
893 FIXME("(%p)->(%s, %p) stub\n", This
, debugstr_guid(riid
), ppvObject
);
897 static HRESULT WINAPI
MimeBody_Clone(
899 IMimePropertySet
** ppPropertySet
)
901 MimeBody
*This
= impl_from_IMimeBody(iface
);
902 FIXME("(%p)->(%p) stub\n", This
, ppPropertySet
);
906 static HRESULT WINAPI
MimeBody_SetOption(
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
);
923 case OID_SECURITY_HWND_OWNER
:
924 FIXME("OID_SECURITY_HWND_OWNER (value %08x): ignoring\n", pValue
->u
.ulVal
);
928 FIXME("Unhandled oid %08x\n", oid
);
934 static HRESULT WINAPI
MimeBody_GetOption(
937 LPPROPVARIANT pValue
)
939 MimeBody
*This
= impl_from_IMimeBody(iface
);
940 FIXME("(%p)->(%08x, %p): stub\n", This
, oid
, pValue
);
944 static HRESULT WINAPI
MimeBody_EnumProps(
947 IMimeEnumProperties
** ppEnum
)
949 MimeBody
*This
= impl_from_IMimeBody(iface
);
950 FIXME("(%p)->(0x%x, %p) stub\n", This
, dwFlags
, ppEnum
);
954 static HRESULT WINAPI
MimeBody_IsType(
956 IMSGBODYTYPE bodytype
)
958 MimeBody
*This
= impl_from_IMimeBody(iface
);
960 TRACE("(%p)->(%d)\n", This
, bodytype
);
964 return This
->data
? S_FALSE
: S_OK
;
966 FIXME("Unimplemented bodytype %d - returning S_OK\n", bodytype
);
971 static HRESULT WINAPI
MimeBody_SetDisplayName(
975 MimeBody
*This
= impl_from_IMimeBody(iface
);
976 FIXME("(%p)->(%s) stub\n", This
, debugstr_a(pszDisplay
));
980 static HRESULT WINAPI
MimeBody_GetDisplayName(
984 MimeBody
*This
= impl_from_IMimeBody(iface
);
985 FIXME("(%p)->(%p) stub\n", This
, ppszDisplay
);
989 static HRESULT WINAPI
MimeBody_GetOffsets(
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
;
1002 static HRESULT WINAPI
MimeBody_GetCurrentEncoding(
1004 ENCODINGTYPE
* pietEncoding
)
1006 MimeBody
*This
= impl_from_IMimeBody(iface
);
1008 TRACE("(%p)->(%p)\n", This
, pietEncoding
);
1010 *pietEncoding
= This
->encoding
;
1014 static HRESULT WINAPI
MimeBody_SetCurrentEncoding(
1016 ENCODINGTYPE ietEncoding
)
1018 MimeBody
*This
= impl_from_IMimeBody(iface
);
1020 TRACE("(%p)->(%d)\n", This
, ietEncoding
);
1022 This
->encoding
= ietEncoding
;
1026 static HRESULT WINAPI
MimeBody_GetEstimatedSize(
1028 ENCODINGTYPE ietEncoding
,
1031 MimeBody
*This
= impl_from_IMimeBody(iface
);
1032 FIXME("(%p)->(%d, %p) stub\n", This
, ietEncoding
, pcbSize
);
1036 static HRESULT WINAPI
MimeBody_GetDataHere(
1038 ENCODINGTYPE ietEncoding
,
1041 MimeBody
*This
= impl_from_IMimeBody(iface
);
1042 FIXME("(%p)->(%d, %p) stub\n", This
, ietEncoding
, pStream
);
1046 static HRESULT WINAPI
MimeBody_GetData(
1048 ENCODINGTYPE ietEncoding
,
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
);
1059 static HRESULT WINAPI
MimeBody_SetData(
1061 ENCODINGTYPE ietEncoding
,
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
);
1075 FIXME("Unhandled object type %s\n", debugstr_guid(riid
));
1076 return E_INVALIDARG
;
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' */
1094 static HRESULT WINAPI
MimeBody_EmptyData(
1097 MimeBody
*This
= impl_from_IMimeBody(iface
);
1098 FIXME("(%p)->() stub\n", This
);
1102 static HRESULT WINAPI
MimeBody_CopyTo(
1106 MimeBody
*This
= impl_from_IMimeBody(iface
);
1107 FIXME("(%p)->(%p) stub\n", This
, pBody
);
1111 static HRESULT WINAPI
MimeBody_GetTransmitInfo(
1113 LPTRANSMITINFO pTransmitInfo
)
1115 MimeBody
*This
= impl_from_IMimeBody(iface
);
1116 FIXME("(%p)->(%p) stub\n", This
, pTransmitInfo
);
1120 static HRESULT WINAPI
MimeBody_SaveToFile(
1122 ENCODINGTYPE ietEncoding
,
1125 MimeBody
*This
= impl_from_IMimeBody(iface
);
1126 FIXME("(%p)->(%d, %s) stub\n", This
, ietEncoding
, debugstr_a(pszFilePath
));
1130 static HRESULT WINAPI
MimeBody_GetHandle(
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
,
1146 MimeBody_GetClassID
,
1150 MimeBody_GetSizeMax
,
1152 MimeBody_GetPropInfo
,
1153 MimeBody_SetPropInfo
,
1156 MimeBody_AppendProp
,
1157 MimeBody_DeleteProp
,
1160 MimeBody_DeleteExcept
,
1162 MimeBody_GetCharset
,
1163 MimeBody_SetCharset
,
1164 MimeBody_GetParameters
,
1165 MimeBody_IsContentType
,
1166 MimeBody_BindToObject
,
1172 MimeBody_SetDisplayName
,
1173 MimeBody_GetDisplayName
,
1174 MimeBody_GetOffsets
,
1175 MimeBody_GetCurrentEncoding
,
1176 MimeBody_SetCurrentEncoding
,
1177 MimeBody_GetEstimatedSize
,
1178 MimeBody_GetDataHere
,
1183 MimeBody_GetTransmitInfo
,
1184 MimeBody_SaveToFile
,
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
;
1197 #define FIRST_CUSTOM_PROP_ID 0x100
1199 static MimeBody
*mimebody_create(void)
1202 BODYOFFSETS body_offsets
;
1204 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1208 This
->IMimeBody_iface
.lpVtbl
= &body_vtbl
;
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
;
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
);
1227 HRESULT
MimeBody_create(IUnknown
*outer
, void **ppv
)
1232 return CLASS_E_NOAGGREGATION
;
1234 if ((mb
= mimebody_create()))
1236 *ppv
= &mb
->IMimeBody_iface
;
1242 return E_OUTOFMEMORY
;
1250 IStream IStream_iface
;
1253 ULARGE_INTEGER pos
, start
, length
;
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
);
1268 if(IsEqualIID(riid
, &IID_IUnknown
) ||
1269 IsEqualIID(riid
, &IID_ISequentialStream
) ||
1270 IsEqualIID(riid
, &IID_IStream
))
1272 IStream_AddRef(iface
);
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
);
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
);
1298 IStream_Release(This
->base
);
1299 HeapFree(GetProcessHeap(), 0, This
);
1304 static HRESULT WINAPI
sub_stream_Read(
1310 sub_stream_t
*This
= impl_from_IStream(iface
);
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
);
1335 static HRESULT WINAPI
sub_stream_Write(
1345 static HRESULT WINAPI
sub_stream_Seek(
1347 LARGE_INTEGER dlibMove
,
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
);
1358 case STREAM_SEEK_SET
:
1361 case STREAM_SEEK_CUR
:
1362 new_pos
.QuadPart
= This
->pos
.QuadPart
+ dlibMove
.QuadPart
;
1364 case STREAM_SEEK_END
:
1365 new_pos
.QuadPart
= This
->length
.QuadPart
+ dlibMove
.QuadPart
;
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
;
1380 static HRESULT WINAPI
sub_stream_SetSize(
1382 ULARGE_INTEGER libNewSize
)
1388 static HRESULT WINAPI
sub_stream_CopyTo(
1392 ULARGE_INTEGER
*pcbRead
,
1393 ULARGE_INTEGER
*pcbWritten
)
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
);
1411 copySize
= cb
.u
.LowPart
;
1413 hr
= IStream_Read(iface
, tmpBuffer
, copySize
, &bytesRead
);
1414 if (FAILED(hr
)) break;
1416 totalBytesRead
.QuadPart
+= bytesRead
;
1420 hr
= IStream_Write(pstm
, tmpBuffer
, bytesRead
, &bytesWritten
);
1421 if (FAILED(hr
)) break;
1422 totalBytesWritten
.QuadPart
+= bytesWritten
;
1425 if (bytesRead
!= copySize
)
1428 cb
.QuadPart
-= bytesRead
;
1431 if (pcbRead
) pcbRead
->QuadPart
= totalBytesRead
.QuadPart
;
1432 if (pcbWritten
) pcbWritten
->QuadPart
= totalBytesWritten
.QuadPart
;
1437 static HRESULT WINAPI
sub_stream_Commit(
1439 DWORD grfCommitFlags
)
1445 static HRESULT WINAPI
sub_stream_Revert(
1452 static HRESULT WINAPI
sub_stream_LockRegion(
1454 ULARGE_INTEGER libOffset
,
1462 static HRESULT WINAPI
sub_stream_UnlockRegion(
1464 ULARGE_INTEGER libOffset
,
1472 static HRESULT WINAPI
sub_stream_Stat(
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
;
1484 static HRESULT WINAPI
sub_stream_Clone(
1492 static struct IStreamVtbl sub_stream_vtbl
=
1494 sub_stream_QueryInterface
,
1504 sub_stream_LockRegion
,
1505 sub_stream_UnlockRegion
,
1510 static HRESULT
create_sub_stream(IStream
*stream
, ULARGE_INTEGER start
, ULARGE_INTEGER length
, IStream
**out
)
1515 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1516 if(!This
) return E_OUTOFMEMORY
;
1518 This
->IStream_iface
.lpVtbl
= &sub_stream_vtbl
;
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
;
1531 typedef struct body_t
1535 MimeBody
*mime_body
;
1537 struct body_t
*parent
;
1538 struct list children
;
1541 typedef struct MimeMessage
1543 IMimeMessage IMimeMessage_iface
;
1547 struct list body_tree
;
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
))
1567 IMimeMessage_AddRef(iface
);
1571 FIXME("no interface for %s\n", debugstr_guid(riid
));
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
);
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
);
1607 empty_body_list(&This
->body_tree
);
1609 if(This
->stream
) IStream_Release(This
->stream
);
1610 HeapFree(GetProcessHeap(), 0, This
);
1616 /*** IPersist methods ***/
1617 static HRESULT WINAPI
MimeMessage_GetClassID(
1618 IMimeMessage
*iface
,
1621 FIXME("(%p)->(%p)\n", iface
, pClassID
);
1625 /*** IPersistStreamInit methods ***/
1626 static HRESULT WINAPI
MimeMessage_IsDirty(
1627 IMimeMessage
*iface
)
1629 FIXME("(%p)->()\n", iface
);
1633 static body_t
*new_body_entry(MimeBody
*mime_body
, DWORD index
, body_t
*parent
)
1635 body_t
*body
= HeapAlloc(GetProcessHeap(), 0, sizeof(*body
));
1638 body
->mime_body
= mime_body
;
1639 body
->index
= index
;
1640 list_init(&body
->children
);
1641 body
->parent
= parent
;
1649 BODYOFFSETS offsets
;
1652 static HRESULT
create_body_offset_list(IStream
*stm
, const char *boundary
, struct list
*body_offsets
)
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
;
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);
1673 hr
= IStream_Seek(stm
, zero
, STREAM_SEEK_CUR
, &cur
);
1674 start
= cur
.u
.LowPart
;
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';
1684 ptr
= strstr(ptr
, nl_boundary
);
1687 DWORD boundary_start
= start
+ ptr
- buf
;
1688 char *end
= ptr
+ boundary_len
+ 4;
1690 if(*end
== '\0' || *(end
+ 1) == '\0')
1693 if(*end
== '\r' && *(end
+ 1) == '\n')
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) == '-')
1708 cur_body
->offsets
.cbBodyEnd
= boundary_start
;
1709 list_add_tail(body_offsets
, &cur_body
->entry
);
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
;
1725 memmove(buf
, buf
+ PARSER_BUF_SIZE
, overlap_no
);
1731 HeapFree(GetProcessHeap(), 0, nl_boundary
);
1732 HeapFree(GetProcessHeap(), 0, buf
);
1736 static body_t
*create_sub_body(MimeMessage
*msg
, IStream
*pStm
, BODYOFFSETS
*offset
, body_t
*parent
)
1738 MimeBody
*mime_body
;
1744 mime_body
= mimebody_create();
1745 IMimeBody_Load(&mime_body
->IMimeBody_iface
, pStm
);
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
;
1757 IMimeAllocator
*alloc
;
1759 hr
= IMimeBody_GetParameters(&mime_body
->IMimeBody_iface
, "Content-Type", &count
,
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
)
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
);
1790 IMimeAllocator_FreeParamInfoArray(alloc
, count
, param_info
, TRUE
);
1791 IMimeAllocator_Release(alloc
);
1796 static HRESULT WINAPI
MimeMessage_Load(IMimeMessage
*iface
, IStream
*pStm
)
1798 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
1800 BODYOFFSETS offsets
;
1804 TRACE("(%p)->(%p)\n", iface
, pStm
);
1808 FIXME("already loaded a message\n");
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
);
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
);
1831 static HRESULT WINAPI
MimeMessage_Save(IMimeMessage
*iface
, IStream
*pStm
, BOOL fClearDirty
)
1833 FIXME("(%p)->(%p, %s)\n", iface
, pStm
, fClearDirty
? "TRUE" : "FALSE");
1837 static HRESULT WINAPI
MimeMessage_GetSizeMax(
1838 IMimeMessage
*iface
,
1839 ULARGE_INTEGER
*pcbSize
)
1841 FIXME("(%p)->(%p)\n", iface
, pcbSize
);
1845 static HRESULT WINAPI
MimeMessage_InitNew(
1846 IMimeMessage
*iface
)
1848 FIXME("(%p)->()\n", iface
);
1852 /*** IMimeMessageTree methods ***/
1853 static HRESULT WINAPI
MimeMessage_GetMessageSource(IMimeMessage
*iface
, IStream
**ppStream
,
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
;
1865 static HRESULT WINAPI
MimeMessage_GetMessageSize(
1866 IMimeMessage
*iface
,
1870 FIXME("(%p)->(%p, 0x%x)\n", iface
, pcbSize
, dwFlags
);
1874 static HRESULT WINAPI
MimeMessage_LoadOffsetTable(
1875 IMimeMessage
*iface
,
1878 FIXME("(%p)->(%p)\n", iface
, pStream
);
1882 static HRESULT WINAPI
MimeMessage_SaveOffsetTable(
1883 IMimeMessage
*iface
,
1887 FIXME("(%p)->(%p, 0x%x)\n", iface
, pStream
, dwFlags
);
1892 static HRESULT WINAPI
MimeMessage_GetFlags(
1893 IMimeMessage
*iface
,
1896 FIXME("(%p)->(%p)\n", iface
, pdwFlags
);
1900 static HRESULT WINAPI
MimeMessage_Commit(
1901 IMimeMessage
*iface
,
1904 FIXME("(%p)->(0x%x)\n", iface
, dwFlags
);
1909 static HRESULT WINAPI
MimeMessage_HandsOffStorage(
1910 IMimeMessage
*iface
)
1912 FIXME("(%p)->()\n", iface
);
1916 static HRESULT
find_body(struct list
*list
, HBODY hbody
, body_t
**body
)
1921 if(hbody
== HBODY_ROOT
)
1923 *body
= LIST_ENTRY(list_head(list
), body_t
, entry
);
1927 LIST_FOR_EACH_ENTRY(cur
, list
, body_t
, entry
)
1929 if(cur
->index
== HandleToUlong(hbody
))
1934 hr
= find_body(&cur
->children
, hbody
, body
);
1935 if(hr
== S_OK
) return S_OK
;
1940 static HRESULT WINAPI
MimeMessage_BindToObject(IMimeMessage
*iface
, const HBODY hBody
, REFIID riid
,
1943 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
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
;
1960 return E_NOINTERFACE
;
1963 static HRESULT WINAPI
MimeMessage_SaveBody(
1964 IMimeMessage
*iface
,
1969 FIXME("(%p)->(%p, 0x%x, %p)\n", iface
, hBody
, dwFlags
, pStream
);
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
);
1980 if(location
== IBL_ROOT
)
1986 hr
= find_body(&msg
->body_tree
, pivot
, &body
);
1993 *out
= body
->parent
;
1997 list
= list_head(&body
->children
);
1999 *out
= LIST_ENTRY(list
, body_t
, entry
);
2001 hr
= MIME_E_NOT_FOUND
;
2005 list
= list_tail(&body
->children
);
2007 *out
= LIST_ENTRY(list
, body_t
, entry
);
2009 hr
= MIME_E_NOT_FOUND
;
2013 list
= list_next(&body
->parent
->children
, &body
->entry
);
2015 *out
= LIST_ENTRY(list
, body_t
, entry
);
2017 hr
= MIME_E_NOT_FOUND
;
2021 list
= list_prev(&body
->parent
->children
, &body
->entry
);
2023 *out
= LIST_ENTRY(list
, body_t
, entry
);
2025 hr
= MIME_E_NOT_FOUND
;
2038 static HRESULT WINAPI
MimeMessage_InsertBody(
2039 IMimeMessage
*iface
,
2040 BODYLOCATION location
,
2044 FIXME("(%p)->(%d, %p, %p)\n", iface
, location
, hPivot
, phBody
);
2048 static HRESULT WINAPI
MimeMessage_GetBody(IMimeMessage
*iface
, BODYLOCATION location
, HBODY hPivot
,
2051 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
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
);
2064 static HRESULT WINAPI
MimeMessage_DeleteBody(
2065 IMimeMessage
*iface
,
2069 FIXME("(%p)->(%p, %08x)\n", iface
, hBody
, dwFlags
);
2073 static HRESULT WINAPI
MimeMessage_MoveBody(
2074 IMimeMessage
*iface
,
2076 BODYLOCATION location
)
2078 FIXME("(%p)->(%d)\n", iface
, location
);
2082 static void count_children(body_t
*body
, boolean recurse
, ULONG
*count
)
2086 LIST_FOR_EACH_ENTRY(child
, &body
->children
, body_t
, entry
)
2089 if(recurse
) count_children(child
, recurse
, count
);
2093 static HRESULT WINAPI
MimeMessage_CountBodies(IMimeMessage
*iface
, HBODY hParent
, boolean fRecurse
,
2097 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
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
;
2106 count_children(body
, fRecurse
, pcBodies
);
2111 static HRESULT
find_next(MimeMessage
*This
, body_t
*body
, FINDBODY
*find
, HBODY
*out
)
2118 if (!body
) ptr
= list_head( &This
->body_tree
);
2121 ptr
= list_head( &body
->children
);
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
)
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
);
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
,
2173 FIXME("(%p)->(%p, %s, %s, 0x%x, %p)\n", iface
, hRelated
, pszBase
, pszURL
, dwFlags
, phBody
);
2177 static HRESULT WINAPI
MimeMessage_ToMultipart(
2178 IMimeMessage
*iface
,
2181 LPHBODY phMultipart
)
2183 FIXME("(%p)->(%p, %s, %p)\n", iface
, hBody
, pszSubType
, phMultipart
);
2187 static HRESULT WINAPI
MimeMessage_GetBodyOffsets(
2188 IMimeMessage
*iface
,
2190 LPBODYOFFSETS pOffsets
)
2192 FIXME("(%p)->(%p, %p)\n", iface
, hBody
, pOffsets
);
2196 static HRESULT WINAPI
MimeMessage_GetCharset(
2197 IMimeMessage
*iface
,
2198 LPHCHARSET phCharset
)
2200 FIXME("(%p)->(%p)\n", iface
, phCharset
);
2205 static HRESULT WINAPI
MimeMessage_SetCharset(
2206 IMimeMessage
*iface
,
2208 CSETAPPLYTYPE applytype
)
2210 FIXME("(%p)->(%p, %d)\n", iface
, hCharset
, applytype
);
2214 static HRESULT WINAPI
MimeMessage_IsBodyType(
2215 IMimeMessage
*iface
,
2217 IMSGBODYTYPE bodytype
)
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
);
2231 static HRESULT WINAPI
MimeMessage_IsContentType(
2232 IMimeMessage
*iface
,
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
);
2250 static HRESULT WINAPI
MimeMessage_QueryBodyProp(
2251 IMimeMessage
*iface
,
2256 boolean fCaseSensitive
)
2258 FIXME("(%p)->(%p, %s, %s, %s, %s)\n", iface
, hBody
, pszName
, pszCriteria
, fSubString
? "TRUE" : "FALSE", fCaseSensitive
? "TRUE" : "FALSE");
2262 static HRESULT WINAPI
MimeMessage_GetBodyProp(
2263 IMimeMessage
*iface
,
2267 LPPROPVARIANT pValue
)
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
);
2283 static HRESULT WINAPI
MimeMessage_SetBodyProp(
2284 IMimeMessage
*iface
,
2288 LPCPROPVARIANT pValue
)
2290 FIXME("(%p)->(%p, %s, 0x%x, %p)\n", iface
, hBody
, pszName
, dwFlags
, pValue
);
2294 static HRESULT WINAPI
MimeMessage_DeleteBodyProp(
2295 IMimeMessage
*iface
,
2299 FIXME("(%p)->(%p, %s)\n", iface
, hBody
, pszName
);
2303 static HRESULT WINAPI
MimeMessage_SetOption(
2304 IMimeMessage
*iface
,
2306 LPCPROPVARIANT pValue
)
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
);
2328 case OID_HIDE_TNEF_ATTACHMENTS
:
2329 FIXME("OID_HIDE_TNEF_ATTACHMENTS (value %d): ignoring\n", pValue
->u
.boolVal
);
2331 case OID_SHOW_MACBINARY
:
2332 FIXME("OID_SHOW_MACBINARY (value %d): ignoring\n", pValue
->u
.boolVal
);
2334 case OID_SAVEBODY_KEEPBOUNDARY
:
2335 FIXME("OID_SAVEBODY_KEEPBOUNDARY (value %d): ignoring\n", pValue
->u
.boolVal
);
2338 FIXME("Unhandled oid %08x\n", oid
);
2339 hr
= MIME_E_INVALID_OPTION_ID
;
2345 static HRESULT WINAPI
MimeMessage_GetOption(
2346 IMimeMessage
*iface
,
2348 LPPROPVARIANT pValue
)
2350 FIXME("(%p)->(%08x, %p)\n", iface
, oid
, pValue
);
2354 /*** IMimeMessage methods ***/
2355 static HRESULT WINAPI
MimeMessage_CreateWebPage(
2356 IMimeMessage
*iface
,
2358 LPWEBPAGEOPTIONS pOptions
,
2359 IMimeMessageCallback
*pCallback
,
2360 IMoniker
**ppMoniker
)
2362 FIXME("(%p)->(%p, %p, %p, %p)\n", iface
, pRootStm
, pOptions
, pCallback
, ppMoniker
);
2367 static HRESULT WINAPI
MimeMessage_GetProp(
2368 IMimeMessage
*iface
,
2371 LPPROPVARIANT pValue
)
2373 FIXME("(%p)->(%s, 0x%x, %p)\n", iface
, pszName
, dwFlags
, pValue
);
2377 static HRESULT WINAPI
MimeMessage_SetProp(
2378 IMimeMessage
*iface
,
2381 LPCPROPVARIANT pValue
)
2383 FIXME("(%p)->(%s, 0x%x, %p)\n", iface
, pszName
, dwFlags
, pValue
);
2387 static HRESULT WINAPI
MimeMessage_DeleteProp(
2388 IMimeMessage
*iface
,
2391 FIXME("(%p)->(%s)\n", iface
, pszName
);
2395 static HRESULT WINAPI
MimeMessage_QueryProp(
2396 IMimeMessage
*iface
,
2400 boolean fCaseSensitive
)
2402 FIXME("(%p)->(%s, %s, %s, %s)\n", iface
, pszName
, pszCriteria
, fSubString
? "TRUE" : "FALSE", fCaseSensitive
? "TRUE" : "FALSE");
2406 static HRESULT WINAPI
MimeMessage_GetTextBody(
2407 IMimeMessage
*iface
,
2409 ENCODINGTYPE ietEncoding
,
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
;
2428 find_struct
.pszSubType
= plain
;
2431 find_struct
.pszSubType
= html
;
2434 return MIME_E_INVALID_TEXT_TYPE
;
2437 hr
= IMimeMessage_FindFirst(iface
, &find_struct
, &hbody
);
2440 TRACE("not found hr %08x\n", hr
);
2445 IMimeMessage_BindToObject(iface
, hbody
, &IID_IMimeBody
, (void**)&mime_body
);
2447 IMimeBody_GetData(mime_body
, ietEncoding
, pStream
);
2449 IMimeBody_Release(mime_body
);
2453 static HRESULT WINAPI
MimeMessage_SetTextBody(
2454 IMimeMessage
*iface
,
2456 ENCODINGTYPE ietEncoding
,
2461 FIXME("(%p)->(%d, %d, %p, %p, %p)\n", iface
, dwTxtType
, ietEncoding
, hAlternative
, pStream
, phBody
);
2465 static HRESULT WINAPI
MimeMessage_AttachObject(
2466 IMimeMessage
*iface
,
2471 FIXME("(%p)->(%s, %p, %p)\n", iface
, debugstr_guid(riid
), pvObject
, phBody
);
2475 static HRESULT WINAPI
MimeMessage_AttachFile(
2476 IMimeMessage
*iface
,
2481 FIXME("(%p)->(%s, %p, %p)\n", iface
, pszFilePath
, pstmFile
, phBody
);
2485 static HRESULT WINAPI
MimeMessage_AttachURL(
2486 IMimeMessage
*iface
,
2494 FIXME("(%p)->(%s, %s, 0x%x, %p, %p, %p)\n", iface
, pszBase
, pszURL
, dwFlags
, pstmURL
, ppszCIDURL
, phBody
);
2498 static HRESULT WINAPI
MimeMessage_GetAttachments(
2499 IMimeMessage
*iface
,
2501 LPHBODY
*pprghAttach
)
2504 FINDBODY find_struct
;
2509 TRACE("(%p)->(%p, %p)\n", iface
, pcAttach
, pprghAttach
);
2512 array
= CoTaskMemAlloc(size
* sizeof(HBODY
));
2514 find_struct
.pszPriType
= find_struct
.pszSubType
= NULL
;
2515 hr
= IMimeMessage_FindFirst(iface
, &find_struct
, &hbody
);
2518 hr
= IMimeMessage_IsContentType(iface
, hbody
, "multipart", NULL
);
2519 TRACE("IsCT rets %08x %d\n", hr
, *pcAttach
);
2522 if(*pcAttach
+ 1 > size
)
2525 array
= CoTaskMemRealloc(array
, size
* sizeof(HBODY
));
2527 array
[*pcAttach
] = hbody
;
2530 hr
= IMimeMessage_FindNext(iface
, &find_struct
, &hbody
);
2533 *pprghAttach
= array
;
2537 static HRESULT WINAPI
MimeMessage_GetAddressTable(
2538 IMimeMessage
*iface
,
2539 IMimeAddressTable
**ppTable
)
2541 FIXME("(%p)->(%p)\n", iface
, ppTable
);
2545 static HRESULT WINAPI
MimeMessage_GetSender(
2546 IMimeMessage
*iface
,
2547 LPADDRESSPROPS pAddress
)
2549 FIXME("(%p)->(%p)\n", iface
, pAddress
);
2553 static HRESULT WINAPI
MimeMessage_GetAddressTypes(
2554 IMimeMessage
*iface
,
2557 LPADDRESSLIST pList
)
2559 FIXME("(%p)->(%d, %d, %p)\n", iface
, dwAdrTypes
, dwProps
, pList
);
2563 static HRESULT WINAPI
MimeMessage_GetAddressFormat(
2564 IMimeMessage
*iface
,
2566 ADDRESSFORMAT format
,
2569 FIXME("(%p)->(%d, %d, %p)\n", iface
, dwAdrTypes
, format
, ppszFormat
);
2573 static HRESULT WINAPI
MimeMessage_EnumAddressTypes(
2574 IMimeMessage
*iface
,
2577 IMimeEnumAddressTypes
**ppEnum
)
2579 FIXME("(%p)->(%d, %d, %p)\n", iface
, dwAdrTypes
, dwProps
, ppEnum
);
2583 static HRESULT WINAPI
MimeMessage_SplitMessage(
2584 IMimeMessage
*iface
,
2586 IMimeMessageParts
**ppParts
)
2588 FIXME("(%p)->(%d, %p)\n", iface
, cbMaxPart
, ppParts
);
2592 static HRESULT WINAPI
MimeMessage_GetRootMoniker(
2593 IMimeMessage
*iface
,
2594 IMoniker
**ppMoniker
)
2596 FIXME("(%p)->(%p)\n", iface
, ppMoniker
);
2600 static const IMimeMessageVtbl MimeMessageVtbl
=
2602 MimeMessage_QueryInterface
,
2604 MimeMessage_Release
,
2605 MimeMessage_GetClassID
,
2606 MimeMessage_IsDirty
,
2609 MimeMessage_GetSizeMax
,
2610 MimeMessage_InitNew
,
2611 MimeMessage_GetMessageSource
,
2612 MimeMessage_GetMessageSize
,
2613 MimeMessage_LoadOffsetTable
,
2614 MimeMessage_SaveOffsetTable
,
2615 MimeMessage_GetFlags
,
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
)
2663 MimeBody
*mime_body
;
2666 TRACE("(%p, %p)\n", outer
, obj
);
2670 FIXME("outer unknown not supported yet\n");
2676 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
2677 if (!This
) return E_OUTOFMEMORY
;
2679 This
->IMimeMessage_iface
.lpVtbl
= &MimeMessageVtbl
;
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
;
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
);
2711 /***********************************************************************
2712 * MimeOleCreateVirtualStream (INETCOMM.@)
2714 HRESULT WINAPI
MimeOleCreateVirtualStream(IStream
**ppStream
)
2717 FIXME("(%p)\n", ppStream
);
2719 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, ppStream
);
2723 typedef struct MimeSecurity
2725 IMimeSecurity IMimeSecurity_iface
;
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
))
2742 IMimeSecurity_AddRef(iface
);
2746 FIXME("no interface for %s\n", debugstr_guid(riid
));
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
);
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
);
2769 HeapFree(GetProcessHeap(), 0, This
);
2774 static HRESULT WINAPI
MimeSecurity_InitNew(
2775 IMimeSecurity
* iface
)
2777 FIXME("(%p)->(): stub\n", iface
);
2781 static HRESULT WINAPI
MimeSecurity_CheckInit(
2782 IMimeSecurity
* iface
)
2784 FIXME("(%p)->(): stub\n", iface
);
2788 static HRESULT WINAPI
MimeSecurity_EncodeMessage(
2789 IMimeSecurity
* iface
,
2790 IMimeMessageTree
* pTree
,
2793 FIXME("(%p)->(%p, %08x): stub\n", iface
, pTree
, dwFlags
);
2797 static HRESULT WINAPI
MimeSecurity_EncodeBody(
2798 IMimeSecurity
* iface
,
2799 IMimeMessageTree
* pTree
,
2803 FIXME("(%p)->(%p, %p, %08x): stub\n", iface
, pTree
, hEncodeRoot
, dwFlags
);
2807 static HRESULT WINAPI
MimeSecurity_DecodeMessage(
2808 IMimeSecurity
* iface
,
2809 IMimeMessageTree
* pTree
,
2812 FIXME("(%p)->(%p, %08x): stub\n", iface
, pTree
, dwFlags
);
2816 static HRESULT WINAPI
MimeSecurity_DecodeBody(
2817 IMimeSecurity
* iface
,
2818 IMimeMessageTree
* pTree
,
2822 FIXME("(%p)->(%p, %p, %08x): stub\n", iface
, pTree
, hDecodeRoot
, dwFlags
);
2826 static HRESULT WINAPI
MimeSecurity_EnumCertificates(
2827 IMimeSecurity
* iface
,
2833 FIXME("(%p)->(%p, %08x, %p, %p): stub\n", iface
, hc
, dwUsage
, pPrev
, ppCert
);
2837 static HRESULT WINAPI
MimeSecurity_GetCertificateName(
2838 IMimeSecurity
* iface
,
2839 const PCX509CERT pX509Cert
,
2840 const CERTNAMETYPE cn
,
2843 FIXME("(%p)->(%p, %08x, %p): stub\n", iface
, pX509Cert
, cn
, ppszName
);
2847 static HRESULT WINAPI
MimeSecurity_GetMessageType(
2848 IMimeSecurity
* iface
,
2849 const HWND hwndParent
,
2853 FIXME("(%p)->(%p, %p, %p): stub\n", iface
, hwndParent
, pBody
, pdwSecType
);
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
);
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
)
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
;
2899 *obj
= &This
->IMimeSecurity_iface
;
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
,
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
))
2923 IMimeAllocator_AddRef(iface
);
2927 FIXME("no interface for %s\n", debugstr_guid(riid
));
2929 return E_NOINTERFACE
;
2932 static ULONG WINAPI
MimeAlloc_AddRef(
2933 IMimeAllocator
* iface
)
2938 static ULONG WINAPI
MimeAlloc_Release(
2939 IMimeAllocator
* iface
)
2944 static LPVOID WINAPI
MimeAlloc_Alloc(
2945 IMimeAllocator
* iface
,
2948 return CoTaskMemAlloc(cb
);
2951 static LPVOID WINAPI
MimeAlloc_Realloc(
2952 IMimeAllocator
* iface
,
2956 return CoTaskMemRealloc(pv
, cb
);
2959 static void WINAPI
MimeAlloc_Free(
2960 IMimeAllocator
* iface
,
2966 static SIZE_T WINAPI
MimeAlloc_GetSize(
2967 IMimeAllocator
* iface
,
2974 static int WINAPI
MimeAlloc_DidAlloc(
2975 IMimeAllocator
* iface
,
2982 static void WINAPI
MimeAlloc_HeapMinimize(
2983 IMimeAllocator
* iface
)
2989 static HRESULT WINAPI
MimeAlloc_FreeParamInfoArray(
2990 IMimeAllocator
* iface
,
2992 LPMIMEPARAMINFO prgParam
,
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
);
3007 static HRESULT WINAPI
MimeAlloc_FreeAddressList(
3008 IMimeAllocator
* iface
,
3009 LPADDRESSLIST pList
)
3015 static HRESULT WINAPI
MimeAlloc_FreeAddressProps(
3016 IMimeAllocator
* iface
,
3017 LPADDRESSPROPS pAddress
)
3023 static HRESULT WINAPI
MimeAlloc_ReleaseObjects(
3024 IMimeAllocator
* iface
,
3026 IUnknown
**prgpUnknown
,
3034 static HRESULT WINAPI
MimeAlloc_FreeEnumHeaderRowArray(
3035 IMimeAllocator
* iface
,
3037 LPENUMHEADERROW prgRow
,
3044 static HRESULT WINAPI
MimeAlloc_FreeEnumPropertyArray(
3045 IMimeAllocator
* iface
,
3047 LPENUMPROPERTY prgProp
,
3054 static HRESULT WINAPI
MimeAlloc_FreeThumbprint(
3055 IMimeAllocator
* iface
,
3056 THUMBBLOB
*pthumbprint
)
3063 static HRESULT WINAPI
MimeAlloc_PropVariantClear(
3064 IMimeAllocator
* iface
,
3065 LPPROPVARIANT pProp
)
3071 static IMimeAllocatorVtbl mime_alloc_vtbl
=
3073 MimeAlloc_QueryInterface
,
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
=
3097 HRESULT
MimeAllocator_create(IUnknown
*outer
, void **obj
)
3099 if(outer
) return CLASS_E_NOAGGREGATION
;
3101 *obj
= &mime_allocator
;
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
);
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
);
3128 if (IsEqualIID(riid
, &IID_IUnknown
) ||
3129 IsEqualIID(riid
, &IID_IMimePropertySchema
))
3135 FIXME("no interface for %s\n", debugstr_guid(riid
));
3136 return E_NOINTERFACE
;
3139 IMimePropertySchema_AddRef(iface
);
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
);
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
);
3162 HeapFree(GetProcessHeap(), 0, This
);
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
);
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
);
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
);
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
);
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
);
3205 static IMimePropertySchemaVtbl prop_schema_vtbl
=
3207 propschema_QueryInterface
,
3210 propschema_RegisterProperty
,
3211 propschema_ModifyProperty
,
3212 propschema_GetPropertyId
,
3213 propschema_GetPropertyName
,
3214 propschema_RegisterAddressType
3218 HRESULT WINAPI
MimeOleGetPropertySchema(IMimePropertySchema
**schema
)
3222 TRACE("(%p) stub\n", schema
);
3224 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
3226 return E_OUTOFMEMORY
;
3228 This
->IMimePropertySchema_iface
.lpVtbl
= &prop_schema_vtbl
;
3231 *schema
= &This
->IMimePropertySchema_iface
;
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
);