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
, 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 const IMimeBodyVtbl
*lpVtbl
;
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 (MimeBody
*)((char*)iface
- FIELD_OFFSET(MimeBody
, lpVtbl
));
118 static LPSTR
strdupA(LPCSTR str
)
121 int len
= strlen(str
);
122 ret
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
123 memcpy(ret
, str
, len
+ 1);
127 #define PARSER_BUF_SIZE 1024
129 /*****************************************************
130 * copy_headers_to_buf [internal]
132 * Copies the headers into a '\0' terminated memory block and leave
133 * the stream's current position set to after the blank line.
135 static HRESULT
copy_headers_to_buf(IStream
*stm
, char **ptr
)
138 DWORD size
= PARSER_BUF_SIZE
, offset
= 0, last_end
= 0;
150 buf
= HeapAlloc(GetProcessHeap(), 0, size
+ 1);
154 buf
= HeapReAlloc(GetProcessHeap(), 0, buf
, size
+ 1);
162 hr
= IStream_Read(stm
, buf
+ offset
, size
- offset
, &read
);
163 if(FAILED(hr
)) goto fail
;
168 if(read
== 0) done
= 1;
170 while(!done
&& (end
= strstr(buf
+ last_end
, "\r\n")))
172 DWORD new_end
= end
- buf
+ 2;
173 if(new_end
- last_end
== 2)
176 off
.QuadPart
= new_end
;
177 IStream_Seek(stm
, off
, STREAM_SEEK_SET
, NULL
);
190 HeapFree(GetProcessHeap(), 0, buf
);
194 static header_t
*read_prop(MimeBody
*body
, char **ptr
)
196 char *colon
= strchr(*ptr
, ':');
197 const property_t
*prop
;
200 if(!colon
) return NULL
;
204 for(prop
= default_props
; prop
->name
; prop
++)
206 if(!strcasecmp(*ptr
, prop
->name
))
208 TRACE("%s: found match with default property id %d\n", *ptr
, prop
->id
);
215 property_list_entry_t
*prop_entry
;
216 LIST_FOR_EACH_ENTRY(prop_entry
, &body
->new_props
, property_list_entry_t
, entry
)
218 if(!strcasecmp(*ptr
, prop_entry
->prop
.name
))
220 TRACE("%s: found match with already added new property id %d\n", *ptr
, prop_entry
->prop
.id
);
221 prop
= &prop_entry
->prop
;
227 prop_entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(*prop_entry
));
228 prop_entry
->prop
.name
= strdupA(*ptr
);
229 prop_entry
->prop
.id
= body
->next_prop_id
++;
230 prop_entry
->prop
.flags
= 0;
231 prop_entry
->prop
.default_vt
= VT_LPSTR
;
232 list_add_tail(&body
->new_props
, &prop_entry
->entry
);
233 prop
= &prop_entry
->prop
;
234 TRACE("%s: allocating new prop id %d\n", *ptr
, prop_entry
->prop
.id
);
238 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ret
));
240 PropVariantInit(&ret
->value
);
241 list_init(&ret
->params
);
247 static void unfold_header(char *header
, int len
)
249 char *start
= header
, *cp
= header
;
252 while(*cp
== ' ' || *cp
== '\t')
258 memmove(start
, cp
, len
+ 1);
260 cp
= strstr(start
, "\r\n");
267 } while(*cp
== ' ' || *cp
== '\t');
272 static char *unquote_string(const char *str
)
277 while(*str
== ' ' || *str
== '\t') str
++;
285 for(cp
= ret
; *cp
; cp
++)
288 memmove(cp
, cp
+ 1, strlen(cp
+ 1) + 1);
293 WARN("quote in unquoted string\n");
305 static void add_param(header_t
*header
, const char *p
)
307 const char *key
= p
, *value
, *cp
= p
;
311 TRACE("got param %s\n", p
);
313 while (*key
== ' ' || *key
== '\t' ) key
++;
315 cp
= strchr(key
, '=');
318 WARN("malformed parameter - skipping\n");
322 name
= HeapAlloc(GetProcessHeap(), 0, cp
- key
+ 1);
323 memcpy(name
, key
, cp
- key
);
324 name
[cp
- key
] = '\0';
328 param
= HeapAlloc(GetProcessHeap(), 0, sizeof(*param
));
330 param
->value
= unquote_string(value
);
331 list_add_tail(&header
->params
, ¶m
->entry
);
334 static void split_params(header_t
*header
, char *value
)
336 char *cp
= value
, *start
= value
;
342 if(!in_quote
&& *cp
== ';')
345 if(done_value
) add_param(header
, start
);
350 in_quote
= !in_quote
;
353 if(done_value
) add_param(header
, start
);
356 static void read_value(header_t
*header
, char **cur
)
358 char *end
= *cur
, *value
;
362 end
= strstr(end
, "\r\n");
364 } while(*end
== ' ' || *end
== '\t');
367 value
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
368 memcpy(value
, *cur
, len
);
371 unfold_header(value
, len
);
372 TRACE("value %s\n", debugstr_a(value
));
374 if(header
->prop
->flags
& MPF_HASPARAMS
)
376 split_params(header
, value
);
377 TRACE("value w/o params %s\n", debugstr_a(value
));
380 header
->value
.vt
= VT_LPSTR
;
381 header
->value
.u
.pszVal
= value
;
386 static void init_content_type(MimeBody
*body
, header_t
*header
)
391 if(header
->prop
->id
!= PID_HDR_CNTTYPE
)
393 ERR("called with header %s\n", header
->prop
->name
);
397 slash
= strchr(header
->value
.u
.pszVal
, '/');
400 WARN("malformed context type value\n");
403 len
= slash
- header
->value
.u
.pszVal
;
404 body
->content_pri_type
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
405 memcpy(body
->content_pri_type
, header
->value
.u
.pszVal
, len
);
406 body
->content_pri_type
[len
] = '\0';
407 body
->content_sub_type
= strdupA(slash
+ 1);
410 static HRESULT
parse_headers(MimeBody
*body
, IStream
*stm
)
412 char *header_buf
, *cur_header_ptr
;
416 hr
= copy_headers_to_buf(stm
, &header_buf
);
417 if(FAILED(hr
)) return hr
;
419 cur_header_ptr
= header_buf
;
420 while((header
= read_prop(body
, &cur_header_ptr
)))
422 read_value(header
, &cur_header_ptr
);
423 list_add_tail(&body
->headers
, &header
->entry
);
425 if(header
->prop
->id
== PID_HDR_CNTTYPE
)
426 init_content_type(body
, header
);
429 HeapFree(GetProcessHeap(), 0, header_buf
);
433 static void empty_param_list(struct list
*list
)
435 param_t
*param
, *cursor2
;
437 LIST_FOR_EACH_ENTRY_SAFE(param
, cursor2
, list
, param_t
, entry
)
439 list_remove(¶m
->entry
);
440 HeapFree(GetProcessHeap(), 0, param
->name
);
441 HeapFree(GetProcessHeap(), 0, param
->value
);
442 HeapFree(GetProcessHeap(), 0, param
);
446 static void empty_header_list(struct list
*list
)
448 header_t
*header
, *cursor2
;
450 LIST_FOR_EACH_ENTRY_SAFE(header
, cursor2
, list
, header_t
, entry
)
452 list_remove(&header
->entry
);
453 PropVariantClear(&header
->value
);
454 empty_param_list(&header
->params
);
455 HeapFree(GetProcessHeap(), 0, header
);
459 static void empty_new_prop_list(struct list
*list
)
461 property_list_entry_t
*prop
, *cursor2
;
463 LIST_FOR_EACH_ENTRY_SAFE(prop
, cursor2
, list
, property_list_entry_t
, entry
)
465 list_remove(&prop
->entry
);
466 HeapFree(GetProcessHeap(), 0, (char *)prop
->prop
.name
);
467 HeapFree(GetProcessHeap(), 0, prop
);
471 static void release_data(REFIID riid
, void *data
)
475 if(IsEqualIID(riid
, &IID_IStream
))
476 IStream_Release((IStream
*)data
);
478 FIXME("Unhandled data format %s\n", debugstr_guid(riid
));
481 static HRESULT
find_prop(MimeBody
*body
, const char *name
, header_t
**prop
)
487 LIST_FOR_EACH_ENTRY(header
, &body
->headers
, header_t
, entry
)
489 if(!strcasecmp(name
, header
->prop
->name
))
496 return MIME_E_NOT_FOUND
;
499 static HRESULT WINAPI
MimeBody_QueryInterface(IMimeBody
* iface
,
503 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppvObject
);
507 if (IsEqualIID(riid
, &IID_IUnknown
) ||
508 IsEqualIID(riid
, &IID_IPersist
) ||
509 IsEqualIID(riid
, &IID_IPersistStreamInit
) ||
510 IsEqualIID(riid
, &IID_IMimePropertySet
) ||
511 IsEqualIID(riid
, &IID_IMimeBody
))
518 IUnknown_AddRef((IUnknown
*)*ppvObject
);
522 FIXME("no interface for %s\n", debugstr_guid(riid
));
523 return E_NOINTERFACE
;
526 static ULONG WINAPI
MimeBody_AddRef(IMimeBody
* iface
)
528 MimeBody
*This
= impl_from_IMimeBody(iface
);
529 TRACE("(%p)->()\n", iface
);
530 return InterlockedIncrement(&This
->refs
);
533 static ULONG WINAPI
MimeBody_Release(IMimeBody
* iface
)
535 MimeBody
*This
= impl_from_IMimeBody(iface
);
538 TRACE("(%p)->()\n", iface
);
540 refs
= InterlockedDecrement(&This
->refs
);
543 empty_header_list(&This
->headers
);
544 empty_new_prop_list(&This
->new_props
);
546 HeapFree(GetProcessHeap(), 0, This
->content_pri_type
);
547 HeapFree(GetProcessHeap(), 0, This
->content_sub_type
);
549 release_data(&This
->data_iid
, This
->data
);
551 HeapFree(GetProcessHeap(), 0, This
);
557 static HRESULT WINAPI
MimeBody_GetClassID(
566 static HRESULT WINAPI
MimeBody_IsDirty(
573 static HRESULT WINAPI
MimeBody_Load(
577 MimeBody
*This
= impl_from_IMimeBody(iface
);
578 TRACE("(%p)->(%p)\n", iface
, pStm
);
579 return parse_headers(This
, pStm
);
582 static HRESULT WINAPI
MimeBody_Save(
591 static HRESULT WINAPI
MimeBody_GetSizeMax(
593 ULARGE_INTEGER
* pcbSize
)
599 static HRESULT WINAPI
MimeBody_InitNew(
602 TRACE("%p->()\n", iface
);
606 static HRESULT WINAPI
MimeBody_GetPropInfo(
609 LPMIMEPROPINFO pInfo
)
615 static HRESULT WINAPI
MimeBody_SetPropInfo(
618 LPCMIMEPROPINFO pInfo
)
624 static HRESULT WINAPI
MimeBody_GetProp(
628 LPPROPVARIANT pValue
)
630 MimeBody
*This
= impl_from_IMimeBody(iface
);
631 TRACE("(%p)->(%s, %d, %p)\n", This
, pszName
, dwFlags
, pValue
);
633 if(!strcasecmp(pszName
, "att:pri-content-type"))
635 PropVariantClear(pValue
);
636 pValue
->vt
= VT_LPSTR
;
637 pValue
->u
.pszVal
= strdupA(This
->content_pri_type
);
645 static HRESULT WINAPI
MimeBody_SetProp(
649 LPCPROPVARIANT pValue
)
655 static HRESULT WINAPI
MimeBody_AppendProp(
659 LPPROPVARIANT pValue
)
665 static HRESULT WINAPI
MimeBody_DeleteProp(
673 static HRESULT WINAPI
MimeBody_CopyProps(
677 IMimePropertySet
* pPropertySet
)
683 static HRESULT WINAPI
MimeBody_MoveProps(
687 IMimePropertySet
* pPropertySet
)
693 static HRESULT WINAPI
MimeBody_DeleteExcept(
702 static HRESULT WINAPI
MimeBody_QueryProp(
707 boolean fCaseSensitive
)
713 static HRESULT WINAPI
MimeBody_GetCharset(
715 LPHCHARSET phCharset
)
722 static HRESULT WINAPI
MimeBody_SetCharset(
725 CSETAPPLYTYPE applytype
)
731 static HRESULT WINAPI
MimeBody_GetParameters(
735 LPMIMEPARAMINFO
* pprgParam
)
737 MimeBody
*This
= impl_from_IMimeBody(iface
);
741 TRACE("(%p)->(%s, %p, %p)\n", iface
, debugstr_a(pszName
), pcParams
, pprgParam
);
746 hr
= find_prop(This
, pszName
, &header
);
747 if(hr
!= S_OK
) return hr
;
749 *pcParams
= list_count(&header
->params
);
752 IMimeAllocator
*alloc
;
756 MimeOleGetAllocator(&alloc
);
758 *pprgParam
= info
= IMimeAllocator_Alloc(alloc
, *pcParams
* sizeof(**pprgParam
));
759 LIST_FOR_EACH_ENTRY(param
, &header
->params
, param_t
, entry
)
763 len
= strlen(param
->name
) + 1;
764 info
->pszName
= IMimeAllocator_Alloc(alloc
, len
);
765 memcpy(info
->pszName
, param
->name
, len
);
766 len
= strlen(param
->value
) + 1;
767 info
->pszData
= IMimeAllocator_Alloc(alloc
, len
);
768 memcpy(info
->pszData
, param
->value
, len
);
771 IMimeAllocator_Release(alloc
);
776 static HRESULT WINAPI
MimeBody_IsContentType(
781 MimeBody
*This
= impl_from_IMimeBody(iface
);
783 TRACE("(%p)->(%s, %s)\n", This
, debugstr_a(pszPriType
), debugstr_a(pszSubType
));
786 const char *pri
= This
->content_pri_type
;
787 if(!pri
) pri
= "text";
788 if(strcasecmp(pri
, pszPriType
)) return S_FALSE
;
793 const char *sub
= This
->content_sub_type
;
794 if(!sub
) sub
= "plain";
795 if(strcasecmp(sub
, pszSubType
)) return S_FALSE
;
801 static HRESULT WINAPI
MimeBody_BindToObject(
810 static HRESULT WINAPI
MimeBody_Clone(
812 IMimePropertySet
** ppPropertySet
)
818 static HRESULT WINAPI
MimeBody_SetOption(
821 LPCPROPVARIANT pValue
)
823 FIXME("(%p)->(%08x, %p): stub\n", iface
, oid
, pValue
);
827 static HRESULT WINAPI
MimeBody_GetOption(
830 LPPROPVARIANT pValue
)
832 FIXME("(%p)->(%08x, %p): stub\n", iface
, oid
, pValue
);
836 static HRESULT WINAPI
MimeBody_EnumProps(
839 IMimeEnumProperties
** ppEnum
)
845 static HRESULT WINAPI
MimeBody_IsType(
847 IMSGBODYTYPE bodytype
)
849 FIXME("(%p)->(%d): stub\n", iface
, bodytype
);
853 static HRESULT WINAPI
MimeBody_SetDisplayName(
861 static HRESULT WINAPI
MimeBody_GetDisplayName(
869 static HRESULT WINAPI
MimeBody_GetOffsets(
871 LPBODYOFFSETS pOffsets
)
873 MimeBody
*This
= impl_from_IMimeBody(iface
);
874 TRACE("(%p)->(%p)\n", This
, pOffsets
);
876 *pOffsets
= This
->body_offsets
;
878 if(This
->body_offsets
.cbBodyEnd
== 0) return MIME_E_NO_DATA
;
882 static HRESULT WINAPI
MimeBody_GetCurrentEncoding(
884 ENCODINGTYPE
* pietEncoding
)
886 MimeBody
*This
= impl_from_IMimeBody(iface
);
888 TRACE("(%p)->(%p)\n", This
, pietEncoding
);
890 *pietEncoding
= This
->encoding
;
894 static HRESULT WINAPI
MimeBody_SetCurrentEncoding(
896 ENCODINGTYPE ietEncoding
)
898 MimeBody
*This
= impl_from_IMimeBody(iface
);
900 TRACE("(%p)->(%d)\n", This
, ietEncoding
);
902 This
->encoding
= ietEncoding
;
906 static HRESULT WINAPI
MimeBody_GetEstimatedSize(
908 ENCODINGTYPE ietEncoding
,
915 static HRESULT WINAPI
MimeBody_GetDataHere(
917 ENCODINGTYPE ietEncoding
,
924 static HRESULT WINAPI
MimeBody_GetData(
926 ENCODINGTYPE ietEncoding
,
929 MimeBody
*This
= impl_from_IMimeBody(iface
);
930 FIXME("(%p)->(%d, %p). Ignoring encoding type.\n", This
, ietEncoding
, ppStream
);
932 *ppStream
= This
->data
;
933 IStream_AddRef(*ppStream
);
937 static HRESULT WINAPI
MimeBody_SetData(
939 ENCODINGTYPE ietEncoding
,
945 MimeBody
*This
= impl_from_IMimeBody(iface
);
946 TRACE("(%p)->(%d, %s, %s, %s %p)\n", This
, ietEncoding
, debugstr_a(pszPriType
), debugstr_a(pszSubType
),
947 debugstr_guid(riid
), pvObject
);
949 if(IsEqualIID(riid
, &IID_IStream
))
950 IStream_AddRef((IStream
*)pvObject
);
953 FIXME("Unhandled object type %s\n", debugstr_guid(riid
));
958 FIXME("release old data\n");
960 This
->data_iid
= *riid
;
961 This
->data
= pvObject
;
963 IMimeBody_SetCurrentEncoding(iface
, ietEncoding
);
965 /* FIXME: Update the content type.
966 If pszPriType == NULL use 'application'
967 If pszSubType == NULL use 'octet-stream' */
972 static HRESULT WINAPI
MimeBody_EmptyData(
979 static HRESULT WINAPI
MimeBody_CopyTo(
987 static HRESULT WINAPI
MimeBody_GetTransmitInfo(
989 LPTRANSMITINFO pTransmitInfo
)
995 static HRESULT WINAPI
MimeBody_SaveToFile(
997 ENCODINGTYPE ietEncoding
,
1004 static HRESULT WINAPI
MimeBody_GetHandle(
1008 MimeBody
*This
= impl_from_IMimeBody(iface
);
1009 TRACE("(%p)->(%p)\n", iface
, phBody
);
1011 *phBody
= This
->handle
;
1012 return This
->handle
? S_OK
: MIME_E_NO_DATA
;
1015 static IMimeBodyVtbl body_vtbl
=
1017 MimeBody_QueryInterface
,
1020 MimeBody_GetClassID
,
1024 MimeBody_GetSizeMax
,
1026 MimeBody_GetPropInfo
,
1027 MimeBody_SetPropInfo
,
1030 MimeBody_AppendProp
,
1031 MimeBody_DeleteProp
,
1034 MimeBody_DeleteExcept
,
1036 MimeBody_GetCharset
,
1037 MimeBody_SetCharset
,
1038 MimeBody_GetParameters
,
1039 MimeBody_IsContentType
,
1040 MimeBody_BindToObject
,
1046 MimeBody_SetDisplayName
,
1047 MimeBody_GetDisplayName
,
1048 MimeBody_GetOffsets
,
1049 MimeBody_GetCurrentEncoding
,
1050 MimeBody_SetCurrentEncoding
,
1051 MimeBody_GetEstimatedSize
,
1052 MimeBody_GetDataHere
,
1057 MimeBody_GetTransmitInfo
,
1058 MimeBody_SaveToFile
,
1062 static HRESULT
MimeBody_set_offsets(MimeBody
*body
, const BODYOFFSETS
*offsets
)
1064 TRACE("setting offsets to %d, %d, %d, %d\n", offsets
->cbBoundaryStart
,
1065 offsets
->cbHeaderStart
, offsets
->cbBodyStart
, offsets
->cbBodyEnd
);
1067 body
->body_offsets
= *offsets
;
1071 #define FIRST_CUSTOM_PROP_ID 0x100
1073 HRESULT
MimeBody_create(IUnknown
*outer
, void **obj
)
1076 BODYOFFSETS body_offsets
;
1080 if(outer
) return CLASS_E_NOAGGREGATION
;
1082 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1083 if (!This
) return E_OUTOFMEMORY
;
1085 This
->lpVtbl
= &body_vtbl
;
1087 This
->handle
= NULL
;
1088 list_init(&This
->headers
);
1089 list_init(&This
->new_props
);
1090 This
->next_prop_id
= FIRST_CUSTOM_PROP_ID
;
1091 This
->content_pri_type
= NULL
;
1092 This
->content_sub_type
= NULL
;
1093 This
->encoding
= IET_7BIT
;
1095 This
->data_iid
= IID_NULL
;
1097 body_offsets
.cbBoundaryStart
= body_offsets
.cbHeaderStart
= 0;
1098 body_offsets
.cbBodyStart
= body_offsets
.cbBodyEnd
= 0;
1099 MimeBody_set_offsets(This
, &body_offsets
);
1101 *obj
= (IMimeBody
*)&This
->lpVtbl
;
1107 IStreamVtbl
*lpVtbl
;
1111 ULARGE_INTEGER pos
, start
, length
;
1114 static inline sub_stream_t
*impl_from_IStream( IStream
*iface
)
1116 return (sub_stream_t
*)((char*)iface
- FIELD_OFFSET(sub_stream_t
, lpVtbl
));
1119 static HRESULT WINAPI
sub_stream_QueryInterface(
1124 sub_stream_t
*This
= impl_from_IStream(iface
);
1126 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
1129 if(IsEqualIID(riid
, &IID_IUnknown
) ||
1130 IsEqualIID(riid
, &IID_ISequentialStream
) ||
1131 IsEqualIID(riid
, &IID_IStream
))
1133 IStream_AddRef(iface
);
1137 return E_NOINTERFACE
;
1140 static ULONG WINAPI
sub_stream_AddRef(
1143 sub_stream_t
*This
= impl_from_IStream(iface
);
1145 TRACE("(%p)\n", This
);
1146 return InterlockedIncrement(&This
->refs
);
1149 static ULONG WINAPI
sub_stream_Release(
1152 sub_stream_t
*This
= impl_from_IStream(iface
);
1155 TRACE("(%p)\n", This
);
1156 refs
= InterlockedDecrement(&This
->refs
);
1159 IStream_Release(This
->base
);
1160 HeapFree(GetProcessHeap(), 0, This
);
1165 static HRESULT WINAPI
sub_stream_Read(
1171 sub_stream_t
*This
= impl_from_IStream(iface
);
1173 ULARGE_INTEGER base_pos
;
1174 LARGE_INTEGER tmp_pos
;
1176 TRACE("(%p, %d, %p)\n", pv
, cb
, pcbRead
);
1178 tmp_pos
.QuadPart
= 0;
1179 IStream_Seek(This
->base
, tmp_pos
, STREAM_SEEK_CUR
, &base_pos
);
1180 tmp_pos
.QuadPart
= This
->pos
.QuadPart
+ This
->start
.QuadPart
;
1181 IStream_Seek(This
->base
, tmp_pos
, STREAM_SEEK_SET
, NULL
);
1183 if(This
->pos
.QuadPart
+ cb
> This
->length
.QuadPart
)
1184 cb
= This
->length
.QuadPart
- This
->pos
.QuadPart
;
1186 hr
= IStream_Read(This
->base
, pv
, cb
, pcbRead
);
1188 This
->pos
.QuadPart
+= *pcbRead
;
1190 tmp_pos
.QuadPart
= base_pos
.QuadPart
;
1191 IStream_Seek(This
->base
, tmp_pos
, STREAM_SEEK_SET
, NULL
);
1196 static HRESULT WINAPI
sub_stream_Write(
1206 static HRESULT WINAPI
sub_stream_Seek(
1208 LARGE_INTEGER dlibMove
,
1210 ULARGE_INTEGER
*plibNewPosition
)
1212 sub_stream_t
*This
= impl_from_IStream(iface
);
1213 LARGE_INTEGER new_pos
;
1215 TRACE("(%08x.%08x, %x, %p)\n", dlibMove
.u
.HighPart
, dlibMove
.u
.LowPart
, dwOrigin
, plibNewPosition
);
1219 case STREAM_SEEK_SET
:
1222 case STREAM_SEEK_CUR
:
1223 new_pos
.QuadPart
= This
->pos
.QuadPart
+ dlibMove
.QuadPart
;
1225 case STREAM_SEEK_END
:
1226 new_pos
.QuadPart
= This
->length
.QuadPart
+ dlibMove
.QuadPart
;
1229 return STG_E_INVALIDFUNCTION
;
1232 if(new_pos
.QuadPart
< 0) new_pos
.QuadPart
= 0;
1233 else if(new_pos
.QuadPart
> This
->length
.QuadPart
) new_pos
.QuadPart
= This
->length
.QuadPart
;
1235 This
->pos
.QuadPart
= new_pos
.QuadPart
;
1237 if(plibNewPosition
) *plibNewPosition
= This
->pos
;
1241 static HRESULT WINAPI
sub_stream_SetSize(
1243 ULARGE_INTEGER libNewSize
)
1249 static HRESULT WINAPI
sub_stream_CopyTo(
1253 ULARGE_INTEGER
*pcbRead
,
1254 ULARGE_INTEGER
*pcbWritten
)
1257 BYTE tmpBuffer
[128];
1258 ULONG bytesRead
, bytesWritten
, copySize
;
1259 ULARGE_INTEGER totalBytesRead
;
1260 ULARGE_INTEGER totalBytesWritten
;
1262 TRACE("(%p)->(%p, %d, %p, %p)\n", iface
, pstm
, cb
.u
.LowPart
, pcbRead
, pcbWritten
);
1264 totalBytesRead
.QuadPart
= 0;
1265 totalBytesWritten
.QuadPart
= 0;
1267 while ( cb
.QuadPart
> 0 )
1269 if ( cb
.QuadPart
>= sizeof(tmpBuffer
) )
1270 copySize
= sizeof(tmpBuffer
);
1272 copySize
= cb
.u
.LowPart
;
1274 hr
= IStream_Read(iface
, tmpBuffer
, copySize
, &bytesRead
);
1275 if (FAILED(hr
)) break;
1277 totalBytesRead
.QuadPart
+= bytesRead
;
1281 hr
= IStream_Write(pstm
, tmpBuffer
, bytesRead
, &bytesWritten
);
1282 if (FAILED(hr
)) break;
1283 totalBytesWritten
.QuadPart
+= bytesWritten
;
1286 if (bytesRead
!= copySize
)
1289 cb
.QuadPart
-= bytesRead
;
1292 if (pcbRead
) pcbRead
->QuadPart
= totalBytesRead
.QuadPart
;
1293 if (pcbWritten
) pcbWritten
->QuadPart
= totalBytesWritten
.QuadPart
;
1298 static HRESULT WINAPI
sub_stream_Commit(
1300 DWORD grfCommitFlags
)
1306 static HRESULT WINAPI
sub_stream_Revert(
1313 static HRESULT WINAPI
sub_stream_LockRegion(
1315 ULARGE_INTEGER libOffset
,
1323 static HRESULT WINAPI
sub_stream_UnlockRegion(
1325 ULARGE_INTEGER libOffset
,
1333 static HRESULT WINAPI
sub_stream_Stat(
1338 sub_stream_t
*This
= impl_from_IStream(iface
);
1339 FIXME("(%p)->(%p, %08x)\n", This
, pstatstg
, grfStatFlag
);
1340 memset(pstatstg
, 0, sizeof(*pstatstg
));
1341 pstatstg
->cbSize
= This
->length
;
1345 static HRESULT WINAPI
sub_stream_Clone(
1353 static struct IStreamVtbl sub_stream_vtbl
=
1355 sub_stream_QueryInterface
,
1365 sub_stream_LockRegion
,
1366 sub_stream_UnlockRegion
,
1371 static HRESULT
create_sub_stream(IStream
*stream
, ULARGE_INTEGER start
, ULARGE_INTEGER length
, IStream
**out
)
1376 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1377 if(!This
) return E_OUTOFMEMORY
;
1379 This
->lpVtbl
= &sub_stream_vtbl
;
1381 This
->start
= start
;
1382 This
->length
= length
;
1383 This
->pos
.QuadPart
= 0;
1384 IStream_AddRef(stream
);
1385 This
->base
= stream
;
1387 *out
= (IStream
*)&This
->lpVtbl
;
1392 typedef struct body_t
1396 IMimeBody
*mime_body
;
1398 struct body_t
*parent
;
1399 struct list children
;
1402 typedef struct MimeMessage
1404 const IMimeMessageVtbl
*lpVtbl
;
1409 struct list body_tree
;
1413 static HRESULT WINAPI
MimeMessage_QueryInterface(IMimeMessage
*iface
, REFIID riid
, void **ppv
)
1415 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
1417 if (IsEqualIID(riid
, &IID_IUnknown
) ||
1418 IsEqualIID(riid
, &IID_IPersist
) ||
1419 IsEqualIID(riid
, &IID_IPersistStreamInit
) ||
1420 IsEqualIID(riid
, &IID_IMimeMessageTree
) ||
1421 IsEqualIID(riid
, &IID_IMimeMessage
))
1424 IUnknown_AddRef(iface
);
1428 FIXME("no interface for %s\n", debugstr_guid(riid
));
1430 return E_NOINTERFACE
;
1433 static ULONG WINAPI
MimeMessage_AddRef(IMimeMessage
*iface
)
1435 MimeMessage
*This
= (MimeMessage
*)iface
;
1436 TRACE("(%p)->()\n", iface
);
1437 return InterlockedIncrement(&This
->refs
);
1440 static void empty_body_list(struct list
*list
)
1442 body_t
*body
, *cursor2
;
1443 LIST_FOR_EACH_ENTRY_SAFE(body
, cursor2
, list
, body_t
, entry
)
1445 empty_body_list(&body
->children
);
1446 list_remove(&body
->entry
);
1447 IMimeBody_Release(body
->mime_body
);
1448 HeapFree(GetProcessHeap(), 0, body
);
1452 static ULONG WINAPI
MimeMessage_Release(IMimeMessage
*iface
)
1454 MimeMessage
*This
= (MimeMessage
*)iface
;
1457 TRACE("(%p)->()\n", iface
);
1459 refs
= InterlockedDecrement(&This
->refs
);
1462 empty_body_list(&This
->body_tree
);
1464 if(This
->stream
) IStream_Release(This
->stream
);
1465 HeapFree(GetProcessHeap(), 0, This
);
1471 /*** IPersist methods ***/
1472 static HRESULT WINAPI
MimeMessage_GetClassID(
1473 IMimeMessage
*iface
,
1476 FIXME("(%p)->(%p)\n", iface
, pClassID
);
1480 /*** IPersistStreamInit methods ***/
1481 static HRESULT WINAPI
MimeMessage_IsDirty(
1482 IMimeMessage
*iface
)
1484 FIXME("(%p)->()\n", iface
);
1488 static body_t
*new_body_entry(IMimeBody
*mime_body
, HBODY hbody
, body_t
*parent
)
1490 body_t
*body
= HeapAlloc(GetProcessHeap(), 0, sizeof(*body
));
1493 body
->mime_body
= mime_body
;
1494 body
->hbody
= hbody
;
1495 list_init(&body
->children
);
1496 body
->parent
= parent
;
1504 BODYOFFSETS offsets
;
1507 static HRESULT
create_body_offset_list(IStream
*stm
, const char *boundary
, struct list
*body_offsets
)
1511 int boundary_len
= strlen(boundary
);
1512 char *buf
, *nl_boundary
, *ptr
, *overlap
;
1513 DWORD total_read
= 0;
1514 DWORD start
= 0, overlap_no
;
1515 offset_entry_t
*cur_body
= NULL
;
1519 list_init(body_offsets
);
1520 nl_boundary
= HeapAlloc(GetProcessHeap(), 0, 4 + boundary_len
+ 1);
1521 memcpy(nl_boundary
, "\r\n--", 4);
1522 memcpy(nl_boundary
+ 4, boundary
, boundary_len
+ 1);
1524 overlap_no
= boundary_len
+ 5;
1526 overlap
= buf
= HeapAlloc(GetProcessHeap(), 0, overlap_no
+ PARSER_BUF_SIZE
+ 1);
1529 hr
= IStream_Seek(stm
, zero
, STREAM_SEEK_CUR
, &cur
);
1530 start
= cur
.u
.LowPart
;
1533 hr
= IStream_Read(stm
, overlap
, PARSER_BUF_SIZE
, &read
);
1534 if(FAILED(hr
)) goto end
;
1535 if(read
== 0) break;
1537 overlap
[read
] = '\0';
1541 ptr
= strstr(ptr
, nl_boundary
);
1544 DWORD boundary_start
= start
+ ptr
- buf
;
1545 char *end
= ptr
+ boundary_len
+ 4;
1547 if(*end
== '\0' || *(end
+ 1) == '\0')
1550 if(*end
== '\r' && *(end
+ 1) == '\n')
1554 cur_body
->offsets
.cbBodyEnd
= boundary_start
;
1555 list_add_tail(body_offsets
, &cur_body
->entry
);
1557 cur_body
= HeapAlloc(GetProcessHeap(), 0, sizeof(*cur_body
));
1558 cur_body
->offsets
.cbBoundaryStart
= boundary_start
+ 2; /* doesn't including the leading \r\n */
1559 cur_body
->offsets
.cbHeaderStart
= boundary_start
+ boundary_len
+ 6;
1561 else if(*end
== '-' && *(end
+ 1) == '-')
1565 cur_body
->offsets
.cbBodyEnd
= boundary_start
;
1566 list_add_tail(body_offsets
, &cur_body
->entry
);
1574 if(overlap
== buf
) /* 1st iteration */
1576 memcpy(buf
, buf
+ PARSER_BUF_SIZE
- overlap_no
, overlap_no
);
1577 overlap
= buf
+ overlap_no
;
1578 start
+= read
- overlap_no
;
1582 memcpy(buf
, buf
+ PARSER_BUF_SIZE
, overlap_no
);
1588 HeapFree(GetProcessHeap(), 0, buf
);
1592 static body_t
*create_sub_body(MimeMessage
*msg
, IStream
*pStm
, BODYOFFSETS
*offset
, body_t
*parent
)
1594 IMimeBody
*mime_body
;
1600 MimeBody_create(NULL
, (void**)&mime_body
);
1601 IMimeBody_Load(mime_body
, pStm
);
1603 hr
= IStream_Seek(pStm
, zero
, STREAM_SEEK_CUR
, &cur
);
1604 offset
->cbBodyStart
= cur
.u
.LowPart
+ offset
->cbHeaderStart
;
1605 if(parent
) MimeBody_set_offsets(impl_from_IMimeBody(mime_body
), offset
);
1606 IMimeBody_SetData(mime_body
, IET_BINARY
, NULL
, NULL
, &IID_IStream
, pStm
);
1607 body
= new_body_entry(mime_body
, msg
->next_hbody
, parent
);
1608 msg
->next_hbody
= (HBODY
)((DWORD
)msg
->next_hbody
+ 1);
1610 if(IMimeBody_IsContentType(mime_body
, "multipart", NULL
) == S_OK
)
1612 MIMEPARAMINFO
*param_info
;
1614 IMimeAllocator
*alloc
;
1616 hr
= IMimeBody_GetParameters(mime_body
, "Content-Type", &count
, ¶m_info
);
1617 if(hr
!= S_OK
|| count
== 0) return body
;
1619 MimeOleGetAllocator(&alloc
);
1621 for(i
= 0; i
< count
; i
++)
1623 if(!strcasecmp(param_info
[i
].pszName
, "boundary"))
1625 struct list offset_list
;
1626 offset_entry_t
*cur
, *cursor2
;
1627 hr
= create_body_offset_list(pStm
, param_info
[i
].pszData
, &offset_list
);
1628 LIST_FOR_EACH_ENTRY_SAFE(cur
, cursor2
, &offset_list
, offset_entry_t
, entry
)
1631 IStream
*sub_stream
;
1632 ULARGE_INTEGER start
, length
;
1634 start
.u
.LowPart
= cur
->offsets
.cbHeaderStart
;
1635 length
.u
.LowPart
= cur
->offsets
.cbBodyEnd
- cur
->offsets
.cbHeaderStart
;
1636 create_sub_stream(pStm
, start
, length
, &sub_stream
);
1637 sub_body
= create_sub_body(msg
, sub_stream
, &cur
->offsets
, body
);
1638 IStream_Release(sub_stream
);
1639 list_add_tail(&body
->children
, &sub_body
->entry
);
1640 list_remove(&cur
->entry
);
1641 HeapFree(GetProcessHeap(), 0, cur
);
1646 IMimeAllocator_FreeParamInfoArray(alloc
, count
, param_info
, TRUE
);
1647 IMimeAllocator_Release(alloc
);
1652 static HRESULT WINAPI
MimeMessage_Load(
1653 IMimeMessage
*iface
,
1656 MimeMessage
*This
= (MimeMessage
*)iface
;
1658 BODYOFFSETS offsets
;
1662 TRACE("(%p)->(%p)\n", iface
, pStm
);
1666 FIXME("already loaded a message\n");
1670 IStream_AddRef(pStm
);
1671 This
->stream
= pStm
;
1672 offsets
.cbBoundaryStart
= offsets
.cbHeaderStart
= 0;
1673 offsets
.cbBodyStart
= offsets
.cbBodyEnd
= 0;
1675 root_body
= create_sub_body(This
, pStm
, &offsets
, NULL
);
1678 IStream_Seek(pStm
, zero
, STREAM_SEEK_END
, &cur
);
1679 offsets
.cbBodyEnd
= cur
.u
.LowPart
;
1680 MimeBody_set_offsets(impl_from_IMimeBody(root_body
->mime_body
), &offsets
);
1682 list_add_head(&This
->body_tree
, &root_body
->entry
);
1687 static HRESULT WINAPI
MimeMessage_Save(
1688 IMimeMessage
*iface
,
1692 FIXME("(%p)->(%p, %s)\n", iface
, pStm
, fClearDirty
? "TRUE" : "FALSE");
1696 static HRESULT WINAPI
MimeMessage_GetSizeMax(
1697 IMimeMessage
*iface
,
1698 ULARGE_INTEGER
*pcbSize
)
1700 FIXME("(%p)->(%p)\n", iface
, pcbSize
);
1704 static HRESULT WINAPI
MimeMessage_InitNew(
1705 IMimeMessage
*iface
)
1707 FIXME("(%p)->()\n", iface
);
1711 /*** IMimeMessageTree methods ***/
1712 static HRESULT WINAPI
MimeMessage_GetMessageSource(
1713 IMimeMessage
*iface
,
1717 MimeMessage
*This
= (MimeMessage
*)iface
;
1718 FIXME("(%p)->(%p, 0x%x)\n", iface
, ppStream
, dwFlags
);
1720 IStream_AddRef(This
->stream
);
1721 *ppStream
= This
->stream
;
1725 static HRESULT WINAPI
MimeMessage_GetMessageSize(
1726 IMimeMessage
*iface
,
1730 FIXME("(%p)->(%p, 0x%x)\n", iface
, pcbSize
, dwFlags
);
1734 static HRESULT WINAPI
MimeMessage_LoadOffsetTable(
1735 IMimeMessage
*iface
,
1738 FIXME("(%p)->(%p)\n", iface
, pStream
);
1742 static HRESULT WINAPI
MimeMessage_SaveOffsetTable(
1743 IMimeMessage
*iface
,
1747 FIXME("(%p)->(%p, 0x%x)\n", iface
, pStream
, dwFlags
);
1752 static HRESULT WINAPI
MimeMessage_GetFlags(
1753 IMimeMessage
*iface
,
1756 FIXME("(%p)->(%p)\n", iface
, pdwFlags
);
1760 static HRESULT WINAPI
MimeMessage_Commit(
1761 IMimeMessage
*iface
,
1764 FIXME("(%p)->(0x%x)\n", iface
, dwFlags
);
1769 static HRESULT WINAPI
MimeMessage_HandsOffStorage(
1770 IMimeMessage
*iface
)
1772 FIXME("(%p)->()\n", iface
);
1776 static HRESULT
find_body(struct list
*list
, HBODY hbody
, body_t
**body
)
1781 if(hbody
== HBODY_ROOT
)
1783 *body
= LIST_ENTRY(list_head(list
), body_t
, entry
);
1787 LIST_FOR_EACH_ENTRY(cur
, list
, body_t
, entry
)
1789 if(cur
->hbody
== hbody
)
1794 hr
= find_body(&cur
->children
, hbody
, body
);
1795 if(hr
== S_OK
) return S_OK
;
1800 static HRESULT WINAPI
MimeMessage_BindToObject(
1801 IMimeMessage
*iface
,
1806 MimeMessage
*This
= (MimeMessage
*)iface
;
1810 TRACE("(%p)->(%p, %s, %p)\n", iface
, hBody
, debugstr_guid(riid
), ppvObject
);
1812 hr
= find_body(&This
->body_tree
, hBody
, &body
);
1814 if(hr
!= S_OK
) return hr
;
1816 if(IsEqualIID(riid
, &IID_IMimeBody
))
1818 IMimeBody_AddRef(body
->mime_body
);
1819 *ppvObject
= body
->mime_body
;
1823 return E_NOINTERFACE
;
1826 static HRESULT WINAPI
MimeMessage_SaveBody(
1827 IMimeMessage
*iface
,
1832 FIXME("(%p)->(%p, 0x%x, %p)\n", iface
, hBody
, dwFlags
, pStream
);
1836 static HRESULT
get_body(MimeMessage
*msg
, BODYLOCATION location
, HBODY pivot
, body_t
**out
)
1838 body_t
*root
= LIST_ENTRY(list_head(&msg
->body_tree
), body_t
, entry
);
1843 if(location
== IBL_ROOT
)
1849 hr
= find_body(&msg
->body_tree
, pivot
, &body
);
1856 *out
= body
->parent
;
1860 list
= list_head(&body
->children
);
1862 *out
= LIST_ENTRY(list
, body_t
, entry
);
1864 hr
= MIME_E_NOT_FOUND
;
1868 list
= list_tail(&body
->children
);
1870 *out
= LIST_ENTRY(list
, body_t
, entry
);
1872 hr
= MIME_E_NOT_FOUND
;
1876 list
= list_next(&body
->parent
->children
, &body
->entry
);
1878 *out
= LIST_ENTRY(list
, body_t
, entry
);
1880 hr
= MIME_E_NOT_FOUND
;
1884 list
= list_prev(&body
->parent
->children
, &body
->entry
);
1886 *out
= LIST_ENTRY(list
, body_t
, entry
);
1888 hr
= MIME_E_NOT_FOUND
;
1901 static HRESULT WINAPI
MimeMessage_InsertBody(
1902 IMimeMessage
*iface
,
1903 BODYLOCATION location
,
1907 FIXME("(%p)->(%d, %p, %p)\n", iface
, location
, hPivot
, phBody
);
1911 static HRESULT WINAPI
MimeMessage_GetBody(
1912 IMimeMessage
*iface
,
1913 BODYLOCATION location
,
1917 MimeMessage
*This
= (MimeMessage
*)iface
;
1921 TRACE("(%p)->(%d, %p, %p)\n", iface
, location
, hPivot
, phBody
);
1923 hr
= get_body(This
, location
, hPivot
, &body
);
1925 if(hr
== S_OK
) *phBody
= body
->hbody
;
1930 static HRESULT WINAPI
MimeMessage_DeleteBody(
1931 IMimeMessage
*iface
,
1935 FIXME("(%p)->(%p, %08x)\n", iface
, hBody
, dwFlags
);
1939 static HRESULT WINAPI
MimeMessage_MoveBody(
1940 IMimeMessage
*iface
,
1942 BODYLOCATION location
)
1944 FIXME("(%p)->(%d)\n", iface
, location
);
1948 static void count_children(body_t
*body
, boolean recurse
, ULONG
*count
)
1952 LIST_FOR_EACH_ENTRY(child
, &body
->children
, body_t
, entry
)
1955 if(recurse
) count_children(child
, recurse
, count
);
1959 static HRESULT WINAPI
MimeMessage_CountBodies(
1960 IMimeMessage
*iface
,
1966 MimeMessage
*This
= (MimeMessage
*)iface
;
1969 TRACE("(%p)->(%p, %s, %p)\n", iface
, hParent
, fRecurse
? "TRUE" : "FALSE", pcBodies
);
1971 hr
= find_body(&This
->body_tree
, hParent
, &body
);
1972 if(hr
!= S_OK
) return hr
;
1975 count_children(body
, fRecurse
, pcBodies
);
1980 static HRESULT
find_next(IMimeMessage
*msg
, LPFINDBODY find_body
, HBODY
*out
)
1983 IMimeBody
*mime_body
;
1986 if(find_body
->dwReserved
== 0)
1987 find_body
->dwReserved
= (DWORD
)HBODY_ROOT
;
1990 hr
= IMimeMessage_GetBody(msg
, IBL_FIRST
, (HBODY
)find_body
->dwReserved
, &next
);
1992 find_body
->dwReserved
= (DWORD
)next
;
1995 hr
= IMimeMessage_GetBody(msg
, IBL_NEXT
, (HBODY
)find_body
->dwReserved
, &next
);
1997 find_body
->dwReserved
= (DWORD
)next
;
1999 return MIME_E_NOT_FOUND
;
2003 hr
= IMimeMessage_BindToObject(msg
, (HBODY
)find_body
->dwReserved
, &IID_IMimeBody
, (void**)&mime_body
);
2004 if(IMimeBody_IsContentType(mime_body
, find_body
->pszPriType
, find_body
->pszSubType
) == S_OK
)
2006 IMimeBody_Release(mime_body
);
2007 *out
= (HBODY
)find_body
->dwReserved
;
2010 IMimeBody_Release(mime_body
);
2011 return find_next(msg
, find_body
, out
);
2014 static HRESULT WINAPI
MimeMessage_FindFirst(
2015 IMimeMessage
*iface
,
2016 LPFINDBODY pFindBody
,
2019 TRACE("(%p)->(%p, %p)\n", iface
, pFindBody
, phBody
);
2021 pFindBody
->dwReserved
= 0;
2022 return find_next(iface
, pFindBody
, phBody
);
2025 static HRESULT WINAPI
MimeMessage_FindNext(
2026 IMimeMessage
*iface
,
2027 LPFINDBODY pFindBody
,
2030 TRACE("(%p)->(%p, %p)\n", iface
, pFindBody
, phBody
);
2032 return find_next(iface
, pFindBody
, phBody
);
2035 static HRESULT WINAPI
MimeMessage_ResolveURL(
2036 IMimeMessage
*iface
,
2043 FIXME("(%p)->(%p, %s, %s, 0x%x, %p)\n", iface
, hRelated
, pszBase
, pszURL
, dwFlags
, phBody
);
2047 static HRESULT WINAPI
MimeMessage_ToMultipart(
2048 IMimeMessage
*iface
,
2051 LPHBODY phMultipart
)
2053 FIXME("(%p)->(%p, %s, %p)\n", iface
, hBody
, pszSubType
, phMultipart
);
2057 static HRESULT WINAPI
MimeMessage_GetBodyOffsets(
2058 IMimeMessage
*iface
,
2060 LPBODYOFFSETS pOffsets
)
2062 FIXME("(%p)->(%p, %p)\n", iface
, hBody
, pOffsets
);
2066 static HRESULT WINAPI
MimeMessage_GetCharset(
2067 IMimeMessage
*iface
,
2068 LPHCHARSET phCharset
)
2070 FIXME("(%p)->(%p)\n", iface
, phCharset
);
2075 static HRESULT WINAPI
MimeMessage_SetCharset(
2076 IMimeMessage
*iface
,
2078 CSETAPPLYTYPE applytype
)
2080 FIXME("(%p)->(%p, %d)\n", iface
, hCharset
, applytype
);
2084 static HRESULT WINAPI
MimeMessage_IsBodyType(
2085 IMimeMessage
*iface
,
2087 IMSGBODYTYPE bodytype
)
2090 IMimeBody
*mime_body
;
2091 TRACE("(%p)->(%p, %d)\n", iface
, hBody
, bodytype
);
2093 hr
= IMimeMessage_BindToObject(iface
, hBody
, &IID_IMimeBody
, (void**)&mime_body
);
2094 if(hr
!= S_OK
) return hr
;
2096 hr
= IMimeBody_IsType(mime_body
, bodytype
);
2097 MimeBody_Release(mime_body
);
2101 static HRESULT WINAPI
MimeMessage_IsContentType(
2102 IMimeMessage
*iface
,
2108 IMimeBody
*mime_body
;
2109 TRACE("(%p)->(%p, %s, %s)\n", iface
, hBody
, pszPriType
, pszSubType
);
2111 hr
= IMimeMessage_BindToObject(iface
, hBody
, &IID_IMimeBody
, (void**)&mime_body
);
2112 if(FAILED(hr
)) return hr
;
2114 hr
= IMimeBody_IsContentType(mime_body
, pszPriType
, pszSubType
);
2115 IMimeBody_Release(mime_body
);
2119 static HRESULT WINAPI
MimeMessage_QueryBodyProp(
2120 IMimeMessage
*iface
,
2125 boolean fCaseSensitive
)
2127 FIXME("(%p)->(%p, %s, %s, %s, %s)\n", iface
, hBody
, pszName
, pszCriteria
, fSubString
? "TRUE" : "FALSE", fCaseSensitive
? "TRUE" : "FALSE");
2131 static HRESULT WINAPI
MimeMessage_GetBodyProp(
2132 IMimeMessage
*iface
,
2136 LPPROPVARIANT pValue
)
2139 IMimeBody
*mime_body
;
2141 TRACE("(%p)->(%p, %s, 0x%x, %p)\n", iface
, hBody
, pszName
, dwFlags
, pValue
);
2143 hr
= IMimeMessage_BindToObject(iface
, hBody
, &IID_IMimeBody
, (void**)&mime_body
);
2144 if(hr
!= S_OK
) return hr
;
2146 hr
= IMimeBody_GetProp(mime_body
, pszName
, dwFlags
, pValue
);
2147 IMimeBody_Release(mime_body
);
2152 static HRESULT WINAPI
MimeMessage_SetBodyProp(
2153 IMimeMessage
*iface
,
2157 LPCPROPVARIANT pValue
)
2159 FIXME("(%p)->(%p, %s, 0x%x, %p)\n", iface
, hBody
, pszName
, dwFlags
, pValue
);
2163 static HRESULT WINAPI
MimeMessage_DeleteBodyProp(
2164 IMimeMessage
*iface
,
2168 FIXME("(%p)->(%p, %s)\n", iface
, hBody
, pszName
);
2172 static HRESULT WINAPI
MimeMessage_SetOption(
2173 IMimeMessage
*iface
,
2175 LPCPROPVARIANT pValue
)
2177 FIXME("(%p)->(%08x, %p)\n", iface
, oid
, pValue
);
2181 static HRESULT WINAPI
MimeMessage_GetOption(
2182 IMimeMessage
*iface
,
2184 LPPROPVARIANT pValue
)
2186 FIXME("(%p)->(%08x, %p)\n", iface
, oid
, pValue
);
2190 /*** IMimeMessage methods ***/
2191 static HRESULT WINAPI
MimeMessage_CreateWebPage(
2192 IMimeMessage
*iface
,
2194 LPWEBPAGEOPTIONS pOptions
,
2195 IMimeMessageCallback
*pCallback
,
2196 IMoniker
**ppMoniker
)
2198 FIXME("(%p)->(%p, %p, %p, %p)\n", iface
, pRootStm
, pOptions
, pCallback
, ppMoniker
);
2203 static HRESULT WINAPI
MimeMessage_GetProp(
2204 IMimeMessage
*iface
,
2207 LPPROPVARIANT pValue
)
2209 FIXME("(%p)->(%s, 0x%x, %p)\n", iface
, pszName
, dwFlags
, pValue
);
2213 static HRESULT WINAPI
MimeMessage_SetProp(
2214 IMimeMessage
*iface
,
2217 LPCPROPVARIANT pValue
)
2219 FIXME("(%p)->(%s, 0x%x, %p)\n", iface
, pszName
, dwFlags
, pValue
);
2223 static HRESULT WINAPI
MimeMessage_DeleteProp(
2224 IMimeMessage
*iface
,
2227 FIXME("(%p)->(%s)\n", iface
, pszName
);
2231 static HRESULT WINAPI
MimeMessage_QueryProp(
2232 IMimeMessage
*iface
,
2236 boolean fCaseSensitive
)
2238 FIXME("(%p)->(%s, %s, %s, %s)\n", iface
, pszName
, pszCriteria
, fSubString
? "TRUE" : "FALSE", fCaseSensitive
? "TRUE" : "FALSE");
2242 static HRESULT WINAPI
MimeMessage_GetTextBody(
2243 IMimeMessage
*iface
,
2245 ENCODINGTYPE ietEncoding
,
2251 FINDBODY find_struct
;
2252 IMimeBody
*mime_body
;
2253 static char text
[] = "text";
2254 static char plain
[] = "plain";
2255 static char html
[] = "html";
2257 TRACE("(%p)->(%d, %d, %p, %p)\n", iface
, dwTxtType
, ietEncoding
, pStream
, phBody
);
2259 find_struct
.pszPriType
= text
;
2264 find_struct
.pszSubType
= plain
;
2267 find_struct
.pszSubType
= html
;
2270 return MIME_E_INVALID_TEXT_TYPE
;
2273 hr
= IMimeMessage_FindFirst(iface
, &find_struct
, &hbody
);
2276 TRACE("not found hr %08x\n", hr
);
2281 IMimeMessage_BindToObject(iface
, hbody
, &IID_IMimeBody
, (void**)&mime_body
);
2283 IMimeBody_GetData(mime_body
, ietEncoding
, pStream
);
2285 IMimeBody_Release(mime_body
);
2289 static HRESULT WINAPI
MimeMessage_SetTextBody(
2290 IMimeMessage
*iface
,
2292 ENCODINGTYPE ietEncoding
,
2297 FIXME("(%p)->(%d, %d, %p, %p, %p)\n", iface
, dwTxtType
, ietEncoding
, hAlternative
, pStream
, phBody
);
2301 static HRESULT WINAPI
MimeMessage_AttachObject(
2302 IMimeMessage
*iface
,
2307 FIXME("(%p)->(%s, %p, %p)\n", iface
, debugstr_guid(riid
), pvObject
, phBody
);
2311 static HRESULT WINAPI
MimeMessage_AttachFile(
2312 IMimeMessage
*iface
,
2317 FIXME("(%p)->(%s, %p, %p)\n", iface
, pszFilePath
, pstmFile
, phBody
);
2321 static HRESULT WINAPI
MimeMessage_AttachURL(
2322 IMimeMessage
*iface
,
2330 FIXME("(%p)->(%s, %s, 0x%x, %p, %p, %p)\n", iface
, pszBase
, pszURL
, dwFlags
, pstmURL
, ppszCIDURL
, phBody
);
2334 static HRESULT WINAPI
MimeMessage_GetAttachments(
2335 IMimeMessage
*iface
,
2337 LPHBODY
*pprghAttach
)
2340 FINDBODY find_struct
;
2345 TRACE("(%p)->(%p, %p)\n", iface
, pcAttach
, pprghAttach
);
2348 array
= CoTaskMemAlloc(size
* sizeof(HBODY
));
2350 find_struct
.pszPriType
= find_struct
.pszSubType
= NULL
;
2351 hr
= IMimeMessage_FindFirst(iface
, &find_struct
, &hbody
);
2354 hr
= IMimeMessage_IsContentType(iface
, hbody
, "multipart", NULL
);
2355 TRACE("IsCT rets %08x %d\n", hr
, *pcAttach
);
2358 if(*pcAttach
+ 1 > size
)
2361 array
= CoTaskMemRealloc(array
, size
* sizeof(HBODY
));
2363 array
[*pcAttach
] = hbody
;
2366 hr
= IMimeMessage_FindNext(iface
, &find_struct
, &hbody
);
2369 *pprghAttach
= array
;
2373 static HRESULT WINAPI
MimeMessage_GetAddressTable(
2374 IMimeMessage
*iface
,
2375 IMimeAddressTable
**ppTable
)
2377 FIXME("(%p)->(%p)\n", iface
, ppTable
);
2381 static HRESULT WINAPI
MimeMessage_GetSender(
2382 IMimeMessage
*iface
,
2383 LPADDRESSPROPS pAddress
)
2385 FIXME("(%p)->(%p)\n", iface
, pAddress
);
2389 static HRESULT WINAPI
MimeMessage_GetAddressTypes(
2390 IMimeMessage
*iface
,
2393 LPADDRESSLIST pList
)
2395 FIXME("(%p)->(%d, %d, %p)\n", iface
, dwAdrTypes
, dwProps
, pList
);
2399 static HRESULT WINAPI
MimeMessage_GetAddressFormat(
2400 IMimeMessage
*iface
,
2402 ADDRESSFORMAT format
,
2405 FIXME("(%p)->(%d, %d, %p)\n", iface
, dwAdrTypes
, format
, ppszFormat
);
2409 static HRESULT WINAPI
MimeMessage_EnumAddressTypes(
2410 IMimeMessage
*iface
,
2413 IMimeEnumAddressTypes
**ppEnum
)
2415 FIXME("(%p)->(%d, %d, %p)\n", iface
, dwAdrTypes
, dwProps
, ppEnum
);
2419 static HRESULT WINAPI
MimeMessage_SplitMessage(
2420 IMimeMessage
*iface
,
2422 IMimeMessageParts
**ppParts
)
2424 FIXME("(%p)->(%d, %p)\n", iface
, cbMaxPart
, ppParts
);
2428 static HRESULT WINAPI
MimeMessage_GetRootMoniker(
2429 IMimeMessage
*iface
,
2430 IMoniker
**ppMoniker
)
2432 FIXME("(%p)->(%p)\n", iface
, ppMoniker
);
2436 static const IMimeMessageVtbl MimeMessageVtbl
=
2438 MimeMessage_QueryInterface
,
2440 MimeMessage_Release
,
2441 MimeMessage_GetClassID
,
2442 MimeMessage_IsDirty
,
2445 MimeMessage_GetSizeMax
,
2446 MimeMessage_InitNew
,
2447 MimeMessage_GetMessageSource
,
2448 MimeMessage_GetMessageSize
,
2449 MimeMessage_LoadOffsetTable
,
2450 MimeMessage_SaveOffsetTable
,
2451 MimeMessage_GetFlags
,
2453 MimeMessage_HandsOffStorage
,
2454 MimeMessage_BindToObject
,
2455 MimeMessage_SaveBody
,
2456 MimeMessage_InsertBody
,
2457 MimeMessage_GetBody
,
2458 MimeMessage_DeleteBody
,
2459 MimeMessage_MoveBody
,
2460 MimeMessage_CountBodies
,
2461 MimeMessage_FindFirst
,
2462 MimeMessage_FindNext
,
2463 MimeMessage_ResolveURL
,
2464 MimeMessage_ToMultipart
,
2465 MimeMessage_GetBodyOffsets
,
2466 MimeMessage_GetCharset
,
2467 MimeMessage_SetCharset
,
2468 MimeMessage_IsBodyType
,
2469 MimeMessage_IsContentType
,
2470 MimeMessage_QueryBodyProp
,
2471 MimeMessage_GetBodyProp
,
2472 MimeMessage_SetBodyProp
,
2473 MimeMessage_DeleteBodyProp
,
2474 MimeMessage_SetOption
,
2475 MimeMessage_GetOption
,
2476 MimeMessage_CreateWebPage
,
2477 MimeMessage_GetProp
,
2478 MimeMessage_SetProp
,
2479 MimeMessage_DeleteProp
,
2480 MimeMessage_QueryProp
,
2481 MimeMessage_GetTextBody
,
2482 MimeMessage_SetTextBody
,
2483 MimeMessage_AttachObject
,
2484 MimeMessage_AttachFile
,
2485 MimeMessage_AttachURL
,
2486 MimeMessage_GetAttachments
,
2487 MimeMessage_GetAddressTable
,
2488 MimeMessage_GetSender
,
2489 MimeMessage_GetAddressTypes
,
2490 MimeMessage_GetAddressFormat
,
2491 MimeMessage_EnumAddressTypes
,
2492 MimeMessage_SplitMessage
,
2493 MimeMessage_GetRootMoniker
,
2496 /***********************************************************************
2497 * MimeOleCreateMessage (INETCOMM.@)
2499 HRESULT WINAPI
MimeOleCreateMessage(IUnknown
*pUnkOuter
, IMimeMessage
**ppMessage
)
2503 TRACE("(%p, %p)\n", pUnkOuter
, ppMessage
);
2507 FIXME("outer unknown not supported yet\n");
2513 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
2514 if (!This
) return E_OUTOFMEMORY
;
2516 This
->lpVtbl
= &MimeMessageVtbl
;
2518 This
->stream
= NULL
;
2519 list_init(&This
->body_tree
);
2520 This
->next_hbody
= (HBODY
)1;
2522 *ppMessage
= (IMimeMessage
*)&This
->lpVtbl
;
2526 /***********************************************************************
2527 * MimeOleSetCompatMode (INETCOMM.@)
2529 HRESULT WINAPI
MimeOleSetCompatMode(DWORD dwMode
)
2531 FIXME("(0x%x)\n", dwMode
);
2535 /***********************************************************************
2536 * MimeOleCreateVirtualStream (INETCOMM.@)
2538 HRESULT WINAPI
MimeOleCreateVirtualStream(IStream
**ppStream
)
2541 FIXME("(%p)\n", ppStream
);
2543 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, ppStream
);
2547 typedef struct MimeSecurity
2549 const IMimeSecurityVtbl
*lpVtbl
;
2554 static HRESULT WINAPI
MimeSecurity_QueryInterface(
2555 IMimeSecurity
* iface
,
2559 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), obj
);
2561 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2562 IsEqualIID(riid
, &IID_IMimeSecurity
))
2565 IUnknown_AddRef(iface
);
2569 FIXME("no interface for %s\n", debugstr_guid(riid
));
2571 return E_NOINTERFACE
;
2574 static ULONG WINAPI
MimeSecurity_AddRef(
2575 IMimeSecurity
* iface
)
2577 MimeSecurity
*This
= (MimeSecurity
*)iface
;
2578 TRACE("(%p)->()\n", iface
);
2579 return InterlockedIncrement(&This
->refs
);
2582 static ULONG WINAPI
MimeSecurity_Release(
2583 IMimeSecurity
* iface
)
2585 MimeSecurity
*This
= (MimeSecurity
*)iface
;
2588 TRACE("(%p)->()\n", iface
);
2590 refs
= InterlockedDecrement(&This
->refs
);
2593 HeapFree(GetProcessHeap(), 0, This
);
2599 static HRESULT WINAPI
MimeSecurity_InitNew(
2600 IMimeSecurity
* iface
)
2602 FIXME("(%p)->(): stub\n", iface
);
2606 static HRESULT WINAPI
MimeSecurity_CheckInit(
2607 IMimeSecurity
* iface
)
2609 FIXME("(%p)->(): stub\n", iface
);
2613 static HRESULT WINAPI
MimeSecurity_EncodeMessage(
2614 IMimeSecurity
* iface
,
2615 IMimeMessageTree
* pTree
,
2618 FIXME("(%p)->(%p, %08x): stub\n", iface
, pTree
, dwFlags
);
2622 static HRESULT WINAPI
MimeSecurity_EncodeBody(
2623 IMimeSecurity
* iface
,
2624 IMimeMessageTree
* pTree
,
2628 FIXME("(%p)->(%p, %p, %08x): stub\n", iface
, pTree
, hEncodeRoot
, dwFlags
);
2632 static HRESULT WINAPI
MimeSecurity_DecodeMessage(
2633 IMimeSecurity
* iface
,
2634 IMimeMessageTree
* pTree
,
2637 FIXME("(%p)->(%p, %08x): stub\n", iface
, pTree
, dwFlags
);
2641 static HRESULT WINAPI
MimeSecurity_DecodeBody(
2642 IMimeSecurity
* iface
,
2643 IMimeMessageTree
* pTree
,
2647 FIXME("(%p)->(%p, %p, %08x): stub\n", iface
, pTree
, hDecodeRoot
, dwFlags
);
2651 static HRESULT WINAPI
MimeSecurity_EnumCertificates(
2652 IMimeSecurity
* iface
,
2658 FIXME("(%p)->(%p, %08x, %p, %p): stub\n", iface
, hc
, dwUsage
, pPrev
, ppCert
);
2662 static HRESULT WINAPI
MimeSecurity_GetCertificateName(
2663 IMimeSecurity
* iface
,
2664 const PCX509CERT pX509Cert
,
2665 const CERTNAMETYPE cn
,
2668 FIXME("(%p)->(%p, %08x, %p): stub\n", iface
, pX509Cert
, cn
, ppszName
);
2672 static HRESULT WINAPI
MimeSecurity_GetMessageType(
2673 IMimeSecurity
* iface
,
2674 const HWND hwndParent
,
2678 FIXME("(%p)->(%p, %p, %p): stub\n", iface
, hwndParent
, pBody
, pdwSecType
);
2682 static HRESULT WINAPI
MimeSecurity_GetCertData(
2683 IMimeSecurity
* iface
,
2684 const PCX509CERT pX509Cert
,
2685 const CERTDATAID dataid
,
2686 LPPROPVARIANT pValue
)
2688 FIXME("(%p)->(%p, %x, %p): stub\n", iface
, pX509Cert
, dataid
, pValue
);
2693 static const IMimeSecurityVtbl MimeSecurityVtbl
=
2695 MimeSecurity_QueryInterface
,
2696 MimeSecurity_AddRef
,
2697 MimeSecurity_Release
,
2698 MimeSecurity_InitNew
,
2699 MimeSecurity_CheckInit
,
2700 MimeSecurity_EncodeMessage
,
2701 MimeSecurity_EncodeBody
,
2702 MimeSecurity_DecodeMessage
,
2703 MimeSecurity_DecodeBody
,
2704 MimeSecurity_EnumCertificates
,
2705 MimeSecurity_GetCertificateName
,
2706 MimeSecurity_GetMessageType
,
2707 MimeSecurity_GetCertData
2710 /***********************************************************************
2711 * MimeOleCreateSecurity (INETCOMM.@)
2713 HRESULT WINAPI
MimeOleCreateSecurity(IMimeSecurity
**ppSecurity
)
2717 TRACE("(%p)\n", ppSecurity
);
2721 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
2722 if (!This
) return E_OUTOFMEMORY
;
2724 This
->lpVtbl
= &MimeSecurityVtbl
;
2727 *ppSecurity
= (IMimeSecurity
*)&This
->lpVtbl
;
2734 IMimeAllocatorVtbl
*lpVtbl
;
2737 static HRESULT WINAPI
MimeAlloc_QueryInterface(
2738 IMimeAllocator
* iface
,
2742 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), obj
);
2744 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2745 IsEqualIID(riid
, &IID_IMalloc
) ||
2746 IsEqualIID(riid
, &IID_IMimeAllocator
))
2749 IUnknown_AddRef(iface
);
2753 FIXME("no interface for %s\n", debugstr_guid(riid
));
2755 return E_NOINTERFACE
;
2758 static ULONG WINAPI
MimeAlloc_AddRef(
2759 IMimeAllocator
* iface
)
2764 static ULONG WINAPI
MimeAlloc_Release(
2765 IMimeAllocator
* iface
)
2770 static LPVOID WINAPI
MimeAlloc_Alloc(
2771 IMimeAllocator
* iface
,
2774 return CoTaskMemAlloc(cb
);
2777 static LPVOID WINAPI
MimeAlloc_Realloc(
2778 IMimeAllocator
* iface
,
2782 return CoTaskMemRealloc(pv
, cb
);
2785 static void WINAPI
MimeAlloc_Free(
2786 IMimeAllocator
* iface
,
2792 static ULONG WINAPI
MimeAlloc_GetSize(
2793 IMimeAllocator
* iface
,
2800 static int WINAPI
MimeAlloc_DidAlloc(
2801 IMimeAllocator
* iface
,
2808 static void WINAPI
MimeAlloc_HeapMinimize(
2809 IMimeAllocator
* iface
)
2815 static HRESULT WINAPI
MimeAlloc_FreeParamInfoArray(
2816 IMimeAllocator
* iface
,
2818 LPMIMEPARAMINFO prgParam
,
2822 TRACE("(%p)->(%d, %p, %d)\n", iface
, cParams
, prgParam
, fFreeArray
);
2824 for(i
= 0; i
< cParams
; i
++)
2826 IMimeAllocator_Free(iface
, prgParam
[i
].pszName
);
2827 IMimeAllocator_Free(iface
, prgParam
[i
].pszData
);
2829 if(fFreeArray
) IMimeAllocator_Free(iface
, prgParam
);
2833 static HRESULT WINAPI
MimeAlloc_FreeAddressList(
2834 IMimeAllocator
* iface
,
2835 LPADDRESSLIST pList
)
2841 static HRESULT WINAPI
MimeAlloc_FreeAddressProps(
2842 IMimeAllocator
* iface
,
2843 LPADDRESSPROPS pAddress
)
2849 static HRESULT WINAPI
MimeAlloc_ReleaseObjects(
2850 IMimeAllocator
* iface
,
2852 IUnknown
**prgpUnknown
,
2860 static HRESULT WINAPI
MimeAlloc_FreeEnumHeaderRowArray(
2861 IMimeAllocator
* iface
,
2863 LPENUMHEADERROW prgRow
,
2870 static HRESULT WINAPI
MimeAlloc_FreeEnumPropertyArray(
2871 IMimeAllocator
* iface
,
2873 LPENUMPROPERTY prgProp
,
2880 static HRESULT WINAPI
MimeAlloc_FreeThumbprint(
2881 IMimeAllocator
* iface
,
2882 THUMBBLOB
*pthumbprint
)
2889 static HRESULT WINAPI
MimeAlloc_PropVariantClear(
2890 IMimeAllocator
* iface
,
2891 LPPROPVARIANT pProp
)
2897 static IMimeAllocatorVtbl mime_alloc_vtbl
=
2899 MimeAlloc_QueryInterface
,
2907 MimeAlloc_HeapMinimize
,
2908 MimeAlloc_FreeParamInfoArray
,
2909 MimeAlloc_FreeAddressList
,
2910 MimeAlloc_FreeAddressProps
,
2911 MimeAlloc_ReleaseObjects
,
2912 MimeAlloc_FreeEnumHeaderRowArray
,
2913 MimeAlloc_FreeEnumPropertyArray
,
2914 MimeAlloc_FreeThumbprint
,
2915 MimeAlloc_PropVariantClear
2918 static MimeAllocator mime_allocator
=
2923 HRESULT
MimeAllocator_create(IUnknown
*outer
, void **obj
)
2925 if(outer
) return CLASS_E_NOAGGREGATION
;
2927 *obj
= &mime_allocator
;
2931 HRESULT WINAPI
MimeOleGetAllocator(IMimeAllocator
**alloc
)
2933 return MimeAllocator_create(NULL
, (void**)alloc
);
2936 HRESULT WINAPI
MimeOleGetCharsetInfo(HCHARSET hCharset
, LPINETCSETINFO pCsetInfo
)
2938 FIXME("(%p, %p)\n", hCharset
, pCsetInfo
);
2939 if(!hCharset
) return E_INVALIDARG
;