4 * Copyright 2006 Robert Shearman for CodeWeavers
5 * Copyright 2007 Huw Davies for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "inetcomm_private.h"
28 DWORD flags
; /* MIMEPROPFLAGS */
36 } property_list_entry_t
;
38 static const property_t default_props
[] =
40 {"References", PID_HDR_REFS
, 0, VT_LPSTR
},
41 {"Subject", PID_HDR_SUBJECT
, 0, VT_LPSTR
},
42 {"From", PID_HDR_FROM
, MPF_ADDRESS
, VT_LPSTR
},
43 {"Message-ID", PID_HDR_MESSAGEID
, 0, VT_LPSTR
},
44 {"Return-Path", PID_HDR_RETURNPATH
, MPF_ADDRESS
, VT_LPSTR
},
45 {"Date", PID_HDR_DATE
, 0, VT_LPSTR
},
46 {"Received", PID_HDR_RECEIVED
, 0, VT_LPSTR
},
47 {"Reply-To", PID_HDR_REPLYTO
, MPF_ADDRESS
, VT_LPSTR
},
48 {"X-Mailer", PID_HDR_XMAILER
, 0, VT_LPSTR
},
49 {"Bcc", PID_HDR_BCC
, MPF_ADDRESS
, VT_LPSTR
},
50 {"MIME-Version", PID_HDR_MIMEVER
, MPF_MIME
, VT_LPSTR
},
51 {"Content-Type", PID_HDR_CNTTYPE
, MPF_MIME
| MPF_HASPARAMS
, VT_LPSTR
},
52 {"Content-Transfer-Encoding", PID_HDR_CNTXFER
, MPF_MIME
, VT_LPSTR
},
53 {"Content-ID", PID_HDR_CNTID
, MPF_MIME
, VT_LPSTR
},
54 {"Content-Disposition", PID_HDR_CNTDISP
, MPF_MIME
| MPF_HASPARAMS
, VT_LPSTR
},
55 {"To", PID_HDR_TO
, MPF_ADDRESS
, VT_LPSTR
},
56 {"Cc", PID_HDR_CC
, MPF_ADDRESS
, VT_LPSTR
},
57 {"Sender", PID_HDR_SENDER
, MPF_ADDRESS
, VT_LPSTR
},
58 {"In-Reply-To", PID_HDR_INREPLYTO
, 0, VT_LPSTR
},
72 const property_t
*prop
;
77 typedef struct MimeBody
79 IMimeBody IMimeBody_iface
;
85 struct list new_props
; /* FIXME: This should be in a PropertySchema */
87 char *content_pri_type
;
88 char *content_sub_type
;
89 ENCODINGTYPE encoding
;
92 BODYOFFSETS body_offsets
;
95 static inline MimeBody
*impl_from_IMimeBody(IMimeBody
*iface
)
97 return CONTAINING_RECORD(iface
, MimeBody
, IMimeBody_iface
);
100 static LPSTR
strdupA(LPCSTR str
)
103 int len
= strlen(str
);
104 ret
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
105 memcpy(ret
, str
, len
+ 1);
109 #define PARSER_BUF_SIZE 1024
111 /*****************************************************
112 * copy_headers_to_buf [internal]
114 * Copies the headers into a '\0' terminated memory block and leave
115 * the stream's current position set to after the blank line.
117 static HRESULT
copy_headers_to_buf(IStream
*stm
, char **ptr
)
120 DWORD size
= PARSER_BUF_SIZE
, offset
= 0, last_end
= 0;
132 buf
= HeapAlloc(GetProcessHeap(), 0, size
+ 1);
136 buf
= HeapReAlloc(GetProcessHeap(), 0, buf
, size
+ 1);
144 hr
= IStream_Read(stm
, buf
+ offset
, size
- offset
, &read
);
145 if(FAILED(hr
)) goto fail
;
150 if(read
== 0) done
= TRUE
;
152 while(!done
&& (end
= strstr(buf
+ last_end
, "\r\n")))
154 DWORD new_end
= end
- buf
+ 2;
155 if(new_end
- last_end
== 2)
158 off
.QuadPart
= new_end
;
159 IStream_Seek(stm
, off
, STREAM_SEEK_SET
, NULL
);
172 HeapFree(GetProcessHeap(), 0, buf
);
176 static header_t
*read_prop(MimeBody
*body
, char **ptr
)
178 char *colon
= strchr(*ptr
, ':');
179 const property_t
*prop
;
182 if(!colon
) return NULL
;
186 for(prop
= default_props
; prop
->name
; prop
++)
188 if(!strcasecmp(*ptr
, prop
->name
))
190 TRACE("%s: found match with default property id %d\n", *ptr
, prop
->id
);
197 property_list_entry_t
*prop_entry
;
198 LIST_FOR_EACH_ENTRY(prop_entry
, &body
->new_props
, property_list_entry_t
, entry
)
200 if(!strcasecmp(*ptr
, prop_entry
->prop
.name
))
202 TRACE("%s: found match with already added new property id %d\n", *ptr
, prop_entry
->prop
.id
);
203 prop
= &prop_entry
->prop
;
209 prop_entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(*prop_entry
));
210 prop_entry
->prop
.name
= strdupA(*ptr
);
211 prop_entry
->prop
.id
= body
->next_prop_id
++;
212 prop_entry
->prop
.flags
= 0;
213 prop_entry
->prop
.default_vt
= VT_LPSTR
;
214 list_add_tail(&body
->new_props
, &prop_entry
->entry
);
215 prop
= &prop_entry
->prop
;
216 TRACE("%s: allocating new prop id %d\n", *ptr
, prop_entry
->prop
.id
);
220 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ret
));
222 PropVariantInit(&ret
->value
);
223 list_init(&ret
->params
);
229 static void unfold_header(char *header
, int len
)
231 char *start
= header
, *cp
= header
;
234 while(*cp
== ' ' || *cp
== '\t')
240 memmove(start
, cp
, len
+ 1);
242 cp
= strstr(start
, "\r\n");
249 } while(*cp
== ' ' || *cp
== '\t');
254 static char *unquote_string(const char *str
)
259 while(*str
== ' ' || *str
== '\t') str
++;
267 for(cp
= ret
; *cp
; cp
++)
270 memmove(cp
, cp
+ 1, strlen(cp
+ 1) + 1);
275 WARN("quote in unquoted string\n");
287 static void add_param(header_t
*header
, const char *p
)
289 const char *key
= p
, *value
, *cp
= p
;
293 TRACE("got param %s\n", p
);
295 while (*key
== ' ' || *key
== '\t' ) key
++;
297 cp
= strchr(key
, '=');
300 WARN("malformed parameter - skipping\n");
304 name
= HeapAlloc(GetProcessHeap(), 0, cp
- key
+ 1);
305 memcpy(name
, key
, cp
- key
);
306 name
[cp
- key
] = '\0';
310 param
= HeapAlloc(GetProcessHeap(), 0, sizeof(*param
));
312 param
->value
= unquote_string(value
);
313 list_add_tail(&header
->params
, ¶m
->entry
);
316 static void split_params(header_t
*header
, char *value
)
318 char *cp
= value
, *start
= value
;
319 BOOL in_quotes
= FALSE
, done_value
= FALSE
;
323 if(!in_quotes
&& *cp
== ';')
326 if(done_value
) add_param(header
, start
);
331 in_quotes
= !in_quotes
;
334 if(done_value
) add_param(header
, start
);
337 static void read_value(header_t
*header
, char **cur
)
339 char *end
= *cur
, *value
;
343 end
= strstr(end
, "\r\n");
345 } while(*end
== ' ' || *end
== '\t');
348 value
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
349 memcpy(value
, *cur
, len
);
352 unfold_header(value
, len
);
353 TRACE("value %s\n", debugstr_a(value
));
355 if(header
->prop
->flags
& MPF_HASPARAMS
)
357 split_params(header
, value
);
358 TRACE("value w/o params %s\n", debugstr_a(value
));
361 header
->value
.vt
= VT_LPSTR
;
362 header
->value
.u
.pszVal
= value
;
367 static void init_content_type(MimeBody
*body
, header_t
*header
)
372 if(header
->prop
->id
!= PID_HDR_CNTTYPE
)
374 ERR("called with header %s\n", header
->prop
->name
);
378 slash
= strchr(header
->value
.u
.pszVal
, '/');
381 WARN("malformed context type value\n");
384 len
= slash
- header
->value
.u
.pszVal
;
385 body
->content_pri_type
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
386 memcpy(body
->content_pri_type
, header
->value
.u
.pszVal
, len
);
387 body
->content_pri_type
[len
] = '\0';
388 body
->content_sub_type
= strdupA(slash
+ 1);
391 static HRESULT
parse_headers(MimeBody
*body
, IStream
*stm
)
393 char *header_buf
, *cur_header_ptr
;
397 hr
= copy_headers_to_buf(stm
, &header_buf
);
398 if(FAILED(hr
)) return hr
;
400 cur_header_ptr
= header_buf
;
401 while((header
= read_prop(body
, &cur_header_ptr
)))
403 read_value(header
, &cur_header_ptr
);
404 list_add_tail(&body
->headers
, &header
->entry
);
406 if(header
->prop
->id
== PID_HDR_CNTTYPE
)
407 init_content_type(body
, header
);
410 HeapFree(GetProcessHeap(), 0, header_buf
);
414 static void empty_param_list(struct list
*list
)
416 param_t
*param
, *cursor2
;
418 LIST_FOR_EACH_ENTRY_SAFE(param
, cursor2
, list
, param_t
, entry
)
420 list_remove(¶m
->entry
);
421 HeapFree(GetProcessHeap(), 0, param
->name
);
422 HeapFree(GetProcessHeap(), 0, param
->value
);
423 HeapFree(GetProcessHeap(), 0, param
);
427 static void empty_header_list(struct list
*list
)
429 header_t
*header
, *cursor2
;
431 LIST_FOR_EACH_ENTRY_SAFE(header
, cursor2
, list
, header_t
, entry
)
433 list_remove(&header
->entry
);
434 PropVariantClear(&header
->value
);
435 empty_param_list(&header
->params
);
436 HeapFree(GetProcessHeap(), 0, header
);
440 static void empty_new_prop_list(struct list
*list
)
442 property_list_entry_t
*prop
, *cursor2
;
444 LIST_FOR_EACH_ENTRY_SAFE(prop
, cursor2
, list
, property_list_entry_t
, entry
)
446 list_remove(&prop
->entry
);
447 HeapFree(GetProcessHeap(), 0, (char *)prop
->prop
.name
);
448 HeapFree(GetProcessHeap(), 0, prop
);
452 static void release_data(REFIID riid
, void *data
)
456 if(IsEqualIID(riid
, &IID_IStream
))
457 IStream_Release((IStream
*)data
);
459 FIXME("Unhandled data format %s\n", debugstr_guid(riid
));
462 static HRESULT
find_prop(MimeBody
*body
, const char *name
, header_t
**prop
)
468 LIST_FOR_EACH_ENTRY(header
, &body
->headers
, header_t
, entry
)
470 if(!strcasecmp(name
, header
->prop
->name
))
477 return MIME_E_NOT_FOUND
;
480 static HRESULT WINAPI
MimeBody_QueryInterface(IMimeBody
* iface
,
484 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppvObject
);
488 if (IsEqualIID(riid
, &IID_IUnknown
) ||
489 IsEqualIID(riid
, &IID_IPersist
) ||
490 IsEqualIID(riid
, &IID_IPersistStreamInit
) ||
491 IsEqualIID(riid
, &IID_IMimePropertySet
) ||
492 IsEqualIID(riid
, &IID_IMimeBody
))
499 IUnknown_AddRef((IUnknown
*)*ppvObject
);
503 FIXME("no interface for %s\n", debugstr_guid(riid
));
504 return E_NOINTERFACE
;
507 static ULONG WINAPI
MimeBody_AddRef(IMimeBody
*iface
)
509 MimeBody
*This
= impl_from_IMimeBody(iface
);
510 LONG ref
= InterlockedIncrement(&This
->ref
);
512 TRACE("(%p) ref=%d\n", This
, ref
);
517 static ULONG WINAPI
MimeBody_Release(IMimeBody
*iface
)
519 MimeBody
*This
= impl_from_IMimeBody(iface
);
520 LONG ref
= InterlockedDecrement(&This
->ref
);
522 TRACE("(%p) ref=%d\n", This
, ref
);
526 empty_header_list(&This
->headers
);
527 empty_new_prop_list(&This
->new_props
);
529 HeapFree(GetProcessHeap(), 0, This
->content_pri_type
);
530 HeapFree(GetProcessHeap(), 0, This
->content_sub_type
);
532 release_data(&This
->data_iid
, This
->data
);
534 HeapFree(GetProcessHeap(), 0, This
);
540 static HRESULT WINAPI
MimeBody_GetClassID(
549 static HRESULT WINAPI
MimeBody_IsDirty(
556 static HRESULT WINAPI
MimeBody_Load(IMimeBody
*iface
, IStream
*pStm
)
558 MimeBody
*This
= impl_from_IMimeBody(iface
);
559 TRACE("(%p)->(%p)\n", iface
, pStm
);
560 return parse_headers(This
, pStm
);
563 static HRESULT WINAPI
MimeBody_Save(IMimeBody
*iface
, IStream
*pStm
, BOOL fClearDirty
)
569 static HRESULT WINAPI
MimeBody_GetSizeMax(
571 ULARGE_INTEGER
* pcbSize
)
577 static HRESULT WINAPI
MimeBody_InitNew(
580 TRACE("%p->()\n", iface
);
584 static HRESULT WINAPI
MimeBody_GetPropInfo(
587 LPMIMEPROPINFO pInfo
)
593 static HRESULT WINAPI
MimeBody_SetPropInfo(
596 LPCMIMEPROPINFO pInfo
)
602 static HRESULT WINAPI
MimeBody_GetProp(
606 LPPROPVARIANT pValue
)
608 MimeBody
*This
= impl_from_IMimeBody(iface
);
609 TRACE("(%p)->(%s, %d, %p)\n", This
, pszName
, dwFlags
, pValue
);
611 if(!strcasecmp(pszName
, "att:pri-content-type"))
613 PropVariantClear(pValue
);
614 pValue
->vt
= VT_LPSTR
;
615 pValue
->u
.pszVal
= strdupA(This
->content_pri_type
);
623 static HRESULT WINAPI
MimeBody_SetProp(
627 LPCPROPVARIANT pValue
)
633 static HRESULT WINAPI
MimeBody_AppendProp(
637 LPPROPVARIANT pValue
)
643 static HRESULT WINAPI
MimeBody_DeleteProp(
651 static HRESULT WINAPI
MimeBody_CopyProps(
655 IMimePropertySet
* pPropertySet
)
661 static HRESULT WINAPI
MimeBody_MoveProps(
665 IMimePropertySet
* pPropertySet
)
671 static HRESULT WINAPI
MimeBody_DeleteExcept(
680 static HRESULT WINAPI
MimeBody_QueryProp(
685 boolean fCaseSensitive
)
691 static HRESULT WINAPI
MimeBody_GetCharset(
693 LPHCHARSET phCharset
)
700 static HRESULT WINAPI
MimeBody_SetCharset(
703 CSETAPPLYTYPE applytype
)
709 static HRESULT WINAPI
MimeBody_GetParameters(
713 LPMIMEPARAMINFO
* pprgParam
)
715 MimeBody
*This
= impl_from_IMimeBody(iface
);
719 TRACE("(%p)->(%s, %p, %p)\n", iface
, debugstr_a(pszName
), pcParams
, pprgParam
);
724 hr
= find_prop(This
, pszName
, &header
);
725 if(hr
!= S_OK
) return hr
;
727 *pcParams
= list_count(&header
->params
);
730 IMimeAllocator
*alloc
;
734 MimeOleGetAllocator(&alloc
);
736 *pprgParam
= info
= IMimeAllocator_Alloc(alloc
, *pcParams
* sizeof(**pprgParam
));
737 LIST_FOR_EACH_ENTRY(param
, &header
->params
, param_t
, entry
)
741 len
= strlen(param
->name
) + 1;
742 info
->pszName
= IMimeAllocator_Alloc(alloc
, len
);
743 memcpy(info
->pszName
, param
->name
, len
);
744 len
= strlen(param
->value
) + 1;
745 info
->pszData
= IMimeAllocator_Alloc(alloc
, len
);
746 memcpy(info
->pszData
, param
->value
, len
);
749 IMimeAllocator_Release(alloc
);
754 static HRESULT WINAPI
MimeBody_IsContentType(
759 MimeBody
*This
= impl_from_IMimeBody(iface
);
761 TRACE("(%p)->(%s, %s)\n", This
, debugstr_a(pszPriType
), debugstr_a(pszSubType
));
764 const char *pri
= This
->content_pri_type
;
765 if(!pri
) pri
= "text";
766 if(strcasecmp(pri
, pszPriType
)) return S_FALSE
;
771 const char *sub
= This
->content_sub_type
;
772 if(!sub
) sub
= "plain";
773 if(strcasecmp(sub
, pszSubType
)) return S_FALSE
;
779 static HRESULT WINAPI
MimeBody_BindToObject(
788 static HRESULT WINAPI
MimeBody_Clone(
790 IMimePropertySet
** ppPropertySet
)
796 static HRESULT WINAPI
MimeBody_SetOption(
799 LPCPROPVARIANT pValue
)
801 HRESULT hr
= E_NOTIMPL
;
802 TRACE("(%p)->(%08x, %p)\n", iface
, oid
, pValue
);
804 if(pValue
->vt
!= TYPEDID_TYPE(oid
))
806 WARN("Called with vartype %04x and oid %08x\n", pValue
->vt
, oid
);
812 case OID_SECURITY_HWND_OWNER
:
813 FIXME("OID_SECURITY_HWND_OWNER (value %08x): ignoring\n", pValue
->u
.ulVal
);
817 FIXME("Unhandled oid %08x\n", oid
);
823 static HRESULT WINAPI
MimeBody_GetOption(
826 LPPROPVARIANT pValue
)
828 FIXME("(%p)->(%08x, %p): stub\n", iface
, oid
, pValue
);
832 static HRESULT WINAPI
MimeBody_EnumProps(
835 IMimeEnumProperties
** ppEnum
)
841 static HRESULT WINAPI
MimeBody_IsType(
843 IMSGBODYTYPE bodytype
)
845 MimeBody
*This
= impl_from_IMimeBody(iface
);
847 TRACE("(%p)->(%d)\n", iface
, bodytype
);
851 return This
->data
? S_FALSE
: S_OK
;
853 FIXME("Unimplemented bodytype %d - returning S_OK\n", bodytype
);
858 static HRESULT WINAPI
MimeBody_SetDisplayName(
866 static HRESULT WINAPI
MimeBody_GetDisplayName(
874 static HRESULT WINAPI
MimeBody_GetOffsets(
876 LPBODYOFFSETS pOffsets
)
878 MimeBody
*This
= impl_from_IMimeBody(iface
);
879 TRACE("(%p)->(%p)\n", This
, pOffsets
);
881 *pOffsets
= This
->body_offsets
;
883 if(This
->body_offsets
.cbBodyEnd
== 0) return MIME_E_NO_DATA
;
887 static HRESULT WINAPI
MimeBody_GetCurrentEncoding(
889 ENCODINGTYPE
* pietEncoding
)
891 MimeBody
*This
= impl_from_IMimeBody(iface
);
893 TRACE("(%p)->(%p)\n", This
, pietEncoding
);
895 *pietEncoding
= This
->encoding
;
899 static HRESULT WINAPI
MimeBody_SetCurrentEncoding(
901 ENCODINGTYPE ietEncoding
)
903 MimeBody
*This
= impl_from_IMimeBody(iface
);
905 TRACE("(%p)->(%d)\n", This
, ietEncoding
);
907 This
->encoding
= ietEncoding
;
911 static HRESULT WINAPI
MimeBody_GetEstimatedSize(
913 ENCODINGTYPE ietEncoding
,
920 static HRESULT WINAPI
MimeBody_GetDataHere(
922 ENCODINGTYPE ietEncoding
,
929 static HRESULT WINAPI
MimeBody_GetData(
931 ENCODINGTYPE ietEncoding
,
934 MimeBody
*This
= impl_from_IMimeBody(iface
);
935 FIXME("(%p)->(%d, %p). Ignoring encoding type.\n", This
, ietEncoding
, ppStream
);
937 *ppStream
= This
->data
;
938 IStream_AddRef(*ppStream
);
942 static HRESULT WINAPI
MimeBody_SetData(
944 ENCODINGTYPE ietEncoding
,
950 MimeBody
*This
= impl_from_IMimeBody(iface
);
951 TRACE("(%p)->(%d, %s, %s, %s %p)\n", This
, ietEncoding
, debugstr_a(pszPriType
), debugstr_a(pszSubType
),
952 debugstr_guid(riid
), pvObject
);
954 if(IsEqualIID(riid
, &IID_IStream
))
955 IStream_AddRef((IStream
*)pvObject
);
958 FIXME("Unhandled object type %s\n", debugstr_guid(riid
));
963 FIXME("release old data\n");
965 This
->data_iid
= *riid
;
966 This
->data
= pvObject
;
968 IMimeBody_SetCurrentEncoding(iface
, ietEncoding
);
970 /* FIXME: Update the content type.
971 If pszPriType == NULL use 'application'
972 If pszSubType == NULL use 'octet-stream' */
977 static HRESULT WINAPI
MimeBody_EmptyData(
984 static HRESULT WINAPI
MimeBody_CopyTo(
992 static HRESULT WINAPI
MimeBody_GetTransmitInfo(
994 LPTRANSMITINFO pTransmitInfo
)
1000 static HRESULT WINAPI
MimeBody_SaveToFile(
1002 ENCODINGTYPE ietEncoding
,
1009 static HRESULT WINAPI
MimeBody_GetHandle(
1013 MimeBody
*This
= impl_from_IMimeBody(iface
);
1014 TRACE("(%p)->(%p)\n", iface
, phBody
);
1016 *phBody
= This
->handle
;
1017 return This
->handle
? S_OK
: MIME_E_NO_DATA
;
1020 static IMimeBodyVtbl body_vtbl
=
1022 MimeBody_QueryInterface
,
1025 MimeBody_GetClassID
,
1029 MimeBody_GetSizeMax
,
1031 MimeBody_GetPropInfo
,
1032 MimeBody_SetPropInfo
,
1035 MimeBody_AppendProp
,
1036 MimeBody_DeleteProp
,
1039 MimeBody_DeleteExcept
,
1041 MimeBody_GetCharset
,
1042 MimeBody_SetCharset
,
1043 MimeBody_GetParameters
,
1044 MimeBody_IsContentType
,
1045 MimeBody_BindToObject
,
1051 MimeBody_SetDisplayName
,
1052 MimeBody_GetDisplayName
,
1053 MimeBody_GetOffsets
,
1054 MimeBody_GetCurrentEncoding
,
1055 MimeBody_SetCurrentEncoding
,
1056 MimeBody_GetEstimatedSize
,
1057 MimeBody_GetDataHere
,
1062 MimeBody_GetTransmitInfo
,
1063 MimeBody_SaveToFile
,
1067 static HRESULT
MimeBody_set_offsets(MimeBody
*body
, const BODYOFFSETS
*offsets
)
1069 TRACE("setting offsets to %d, %d, %d, %d\n", offsets
->cbBoundaryStart
,
1070 offsets
->cbHeaderStart
, offsets
->cbBodyStart
, offsets
->cbBodyEnd
);
1072 body
->body_offsets
= *offsets
;
1076 #define FIRST_CUSTOM_PROP_ID 0x100
1078 static MimeBody
*mimebody_create(void)
1081 BODYOFFSETS body_offsets
;
1083 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1087 This
->IMimeBody_iface
.lpVtbl
= &body_vtbl
;
1089 This
->handle
= NULL
;
1090 list_init(&This
->headers
);
1091 list_init(&This
->new_props
);
1092 This
->next_prop_id
= FIRST_CUSTOM_PROP_ID
;
1093 This
->content_pri_type
= NULL
;
1094 This
->content_sub_type
= NULL
;
1095 This
->encoding
= IET_7BIT
;
1097 This
->data_iid
= IID_NULL
;
1099 body_offsets
.cbBoundaryStart
= body_offsets
.cbHeaderStart
= 0;
1100 body_offsets
.cbBodyStart
= body_offsets
.cbBodyEnd
= 0;
1101 MimeBody_set_offsets(This
, &body_offsets
);
1106 HRESULT
MimeBody_create(IUnknown
*outer
, void **ppv
)
1111 return CLASS_E_NOAGGREGATION
;
1113 if ((mb
= mimebody_create()))
1115 *ppv
= &mb
->IMimeBody_iface
;
1121 return E_OUTOFMEMORY
;
1129 IStream IStream_iface
;
1132 ULARGE_INTEGER pos
, start
, length
;
1135 static inline sub_stream_t
*impl_from_IStream(IStream
*iface
)
1137 return CONTAINING_RECORD(iface
, sub_stream_t
, IStream_iface
);
1140 static HRESULT WINAPI
sub_stream_QueryInterface(IStream
*iface
, REFIID riid
, void **ppv
)
1142 sub_stream_t
*This
= impl_from_IStream(iface
);
1144 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
1147 if(IsEqualIID(riid
, &IID_IUnknown
) ||
1148 IsEqualIID(riid
, &IID_ISequentialStream
) ||
1149 IsEqualIID(riid
, &IID_IStream
))
1151 IStream_AddRef(iface
);
1155 return E_NOINTERFACE
;
1158 static ULONG WINAPI
sub_stream_AddRef(IStream
*iface
)
1160 sub_stream_t
*This
= impl_from_IStream(iface
);
1161 LONG ref
= InterlockedIncrement(&This
->ref
);
1163 TRACE("(%p) ref=%d\n", This
, ref
);
1168 static ULONG WINAPI
sub_stream_Release(IStream
*iface
)
1170 sub_stream_t
*This
= impl_from_IStream(iface
);
1171 LONG ref
= InterlockedDecrement(&This
->ref
);
1173 TRACE("(%p) ref=%d\n", This
, ref
);
1177 IStream_Release(This
->base
);
1178 HeapFree(GetProcessHeap(), 0, This
);
1183 static HRESULT WINAPI
sub_stream_Read(
1189 sub_stream_t
*This
= impl_from_IStream(iface
);
1191 ULARGE_INTEGER base_pos
;
1192 LARGE_INTEGER tmp_pos
;
1194 TRACE("(%p, %d, %p)\n", pv
, cb
, pcbRead
);
1196 tmp_pos
.QuadPart
= 0;
1197 IStream_Seek(This
->base
, tmp_pos
, STREAM_SEEK_CUR
, &base_pos
);
1198 tmp_pos
.QuadPart
= This
->pos
.QuadPart
+ This
->start
.QuadPart
;
1199 IStream_Seek(This
->base
, tmp_pos
, STREAM_SEEK_SET
, NULL
);
1201 if(This
->pos
.QuadPart
+ cb
> This
->length
.QuadPart
)
1202 cb
= This
->length
.QuadPart
- This
->pos
.QuadPart
;
1204 hr
= IStream_Read(This
->base
, pv
, cb
, pcbRead
);
1206 This
->pos
.QuadPart
+= *pcbRead
;
1208 tmp_pos
.QuadPart
= base_pos
.QuadPart
;
1209 IStream_Seek(This
->base
, tmp_pos
, STREAM_SEEK_SET
, NULL
);
1214 static HRESULT WINAPI
sub_stream_Write(
1224 static HRESULT WINAPI
sub_stream_Seek(
1226 LARGE_INTEGER dlibMove
,
1228 ULARGE_INTEGER
*plibNewPosition
)
1230 sub_stream_t
*This
= impl_from_IStream(iface
);
1231 LARGE_INTEGER new_pos
;
1233 TRACE("(%08x.%08x, %x, %p)\n", dlibMove
.u
.HighPart
, dlibMove
.u
.LowPart
, dwOrigin
, plibNewPosition
);
1237 case STREAM_SEEK_SET
:
1240 case STREAM_SEEK_CUR
:
1241 new_pos
.QuadPart
= This
->pos
.QuadPart
+ dlibMove
.QuadPart
;
1243 case STREAM_SEEK_END
:
1244 new_pos
.QuadPart
= This
->length
.QuadPart
+ dlibMove
.QuadPart
;
1247 return STG_E_INVALIDFUNCTION
;
1250 if(new_pos
.QuadPart
< 0) new_pos
.QuadPart
= 0;
1251 else if(new_pos
.QuadPart
> This
->length
.QuadPart
) new_pos
.QuadPart
= This
->length
.QuadPart
;
1253 This
->pos
.QuadPart
= new_pos
.QuadPart
;
1255 if(plibNewPosition
) *plibNewPosition
= This
->pos
;
1259 static HRESULT WINAPI
sub_stream_SetSize(
1261 ULARGE_INTEGER libNewSize
)
1267 static HRESULT WINAPI
sub_stream_CopyTo(
1271 ULARGE_INTEGER
*pcbRead
,
1272 ULARGE_INTEGER
*pcbWritten
)
1275 BYTE tmpBuffer
[128];
1276 ULONG bytesRead
, bytesWritten
, copySize
;
1277 ULARGE_INTEGER totalBytesRead
;
1278 ULARGE_INTEGER totalBytesWritten
;
1280 TRACE("(%p)->(%p, %d, %p, %p)\n", iface
, pstm
, cb
.u
.LowPart
, pcbRead
, pcbWritten
);
1282 totalBytesRead
.QuadPart
= 0;
1283 totalBytesWritten
.QuadPart
= 0;
1285 while ( cb
.QuadPart
> 0 )
1287 if ( cb
.QuadPart
>= sizeof(tmpBuffer
) )
1288 copySize
= sizeof(tmpBuffer
);
1290 copySize
= cb
.u
.LowPart
;
1292 hr
= IStream_Read(iface
, tmpBuffer
, copySize
, &bytesRead
);
1293 if (FAILED(hr
)) break;
1295 totalBytesRead
.QuadPart
+= bytesRead
;
1299 hr
= IStream_Write(pstm
, tmpBuffer
, bytesRead
, &bytesWritten
);
1300 if (FAILED(hr
)) break;
1301 totalBytesWritten
.QuadPart
+= bytesWritten
;
1304 if (bytesRead
!= copySize
)
1307 cb
.QuadPart
-= bytesRead
;
1310 if (pcbRead
) pcbRead
->QuadPart
= totalBytesRead
.QuadPart
;
1311 if (pcbWritten
) pcbWritten
->QuadPart
= totalBytesWritten
.QuadPart
;
1316 static HRESULT WINAPI
sub_stream_Commit(
1318 DWORD grfCommitFlags
)
1324 static HRESULT WINAPI
sub_stream_Revert(
1331 static HRESULT WINAPI
sub_stream_LockRegion(
1333 ULARGE_INTEGER libOffset
,
1341 static HRESULT WINAPI
sub_stream_UnlockRegion(
1343 ULARGE_INTEGER libOffset
,
1351 static HRESULT WINAPI
sub_stream_Stat(
1356 sub_stream_t
*This
= impl_from_IStream(iface
);
1357 FIXME("(%p)->(%p, %08x)\n", This
, pstatstg
, grfStatFlag
);
1358 memset(pstatstg
, 0, sizeof(*pstatstg
));
1359 pstatstg
->cbSize
= This
->length
;
1363 static HRESULT WINAPI
sub_stream_Clone(
1371 static struct IStreamVtbl sub_stream_vtbl
=
1373 sub_stream_QueryInterface
,
1383 sub_stream_LockRegion
,
1384 sub_stream_UnlockRegion
,
1389 static HRESULT
create_sub_stream(IStream
*stream
, ULARGE_INTEGER start
, ULARGE_INTEGER length
, IStream
**out
)
1394 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1395 if(!This
) return E_OUTOFMEMORY
;
1397 This
->IStream_iface
.lpVtbl
= &sub_stream_vtbl
;
1399 This
->start
= start
;
1400 This
->length
= length
;
1401 This
->pos
.QuadPart
= 0;
1402 IStream_AddRef(stream
);
1403 This
->base
= stream
;
1405 *out
= &This
->IStream_iface
;
1410 typedef struct body_t
1414 MimeBody
*mime_body
;
1416 struct body_t
*parent
;
1417 struct list children
;
1420 typedef struct MimeMessage
1422 IMimeMessage IMimeMessage_iface
;
1426 struct list body_tree
;
1430 static inline MimeMessage
*impl_from_IMimeMessage(IMimeMessage
*iface
)
1432 return CONTAINING_RECORD(iface
, MimeMessage
, IMimeMessage_iface
);
1435 static HRESULT WINAPI
MimeMessage_QueryInterface(IMimeMessage
*iface
, REFIID riid
, void **ppv
)
1437 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
1439 if (IsEqualIID(riid
, &IID_IUnknown
) ||
1440 IsEqualIID(riid
, &IID_IPersist
) ||
1441 IsEqualIID(riid
, &IID_IPersistStreamInit
) ||
1442 IsEqualIID(riid
, &IID_IMimeMessageTree
) ||
1443 IsEqualIID(riid
, &IID_IMimeMessage
))
1446 IMimeMessage_AddRef(iface
);
1450 FIXME("no interface for %s\n", debugstr_guid(riid
));
1452 return E_NOINTERFACE
;
1455 static ULONG WINAPI
MimeMessage_AddRef(IMimeMessage
*iface
)
1457 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
1458 ULONG ref
= InterlockedIncrement(&This
->ref
);
1460 TRACE("(%p) ref=%d\n", This
, ref
);
1465 static void empty_body_list(struct list
*list
)
1467 body_t
*body
, *cursor2
;
1468 LIST_FOR_EACH_ENTRY_SAFE(body
, cursor2
, list
, body_t
, entry
)
1470 empty_body_list(&body
->children
);
1471 list_remove(&body
->entry
);
1472 IMimeBody_Release(&body
->mime_body
->IMimeBody_iface
);
1473 HeapFree(GetProcessHeap(), 0, body
);
1477 static ULONG WINAPI
MimeMessage_Release(IMimeMessage
*iface
)
1479 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
1480 ULONG ref
= InterlockedDecrement(&This
->ref
);
1482 TRACE("(%p) ref=%d\n", This
, ref
);
1486 empty_body_list(&This
->body_tree
);
1488 if(This
->stream
) IStream_Release(This
->stream
);
1489 HeapFree(GetProcessHeap(), 0, This
);
1495 /*** IPersist methods ***/
1496 static HRESULT WINAPI
MimeMessage_GetClassID(
1497 IMimeMessage
*iface
,
1500 FIXME("(%p)->(%p)\n", iface
, pClassID
);
1504 /*** IPersistStreamInit methods ***/
1505 static HRESULT WINAPI
MimeMessage_IsDirty(
1506 IMimeMessage
*iface
)
1508 FIXME("(%p)->()\n", iface
);
1512 static body_t
*new_body_entry(MimeBody
*mime_body
, DWORD index
, body_t
*parent
)
1514 body_t
*body
= HeapAlloc(GetProcessHeap(), 0, sizeof(*body
));
1517 body
->mime_body
= mime_body
;
1518 body
->index
= index
;
1519 list_init(&body
->children
);
1520 body
->parent
= parent
;
1528 BODYOFFSETS offsets
;
1531 static HRESULT
create_body_offset_list(IStream
*stm
, const char *boundary
, struct list
*body_offsets
)
1535 int boundary_len
= strlen(boundary
);
1536 char *buf
, *nl_boundary
, *ptr
, *overlap
;
1537 DWORD start
= 0, overlap_no
;
1538 offset_entry_t
*cur_body
= NULL
;
1542 list_init(body_offsets
);
1543 nl_boundary
= HeapAlloc(GetProcessHeap(), 0, 4 + boundary_len
+ 1);
1544 memcpy(nl_boundary
, "\r\n--", 4);
1545 memcpy(nl_boundary
+ 4, boundary
, boundary_len
+ 1);
1547 overlap_no
= boundary_len
+ 5;
1549 overlap
= buf
= HeapAlloc(GetProcessHeap(), 0, overlap_no
+ PARSER_BUF_SIZE
+ 1);
1552 hr
= IStream_Seek(stm
, zero
, STREAM_SEEK_CUR
, &cur
);
1553 start
= cur
.u
.LowPart
;
1556 hr
= IStream_Read(stm
, overlap
, PARSER_BUF_SIZE
, &read
);
1557 if(FAILED(hr
)) goto end
;
1558 if(read
== 0) break;
1559 overlap
[read
] = '\0';
1563 ptr
= strstr(ptr
, nl_boundary
);
1566 DWORD boundary_start
= start
+ ptr
- buf
;
1567 char *end
= ptr
+ boundary_len
+ 4;
1569 if(*end
== '\0' || *(end
+ 1) == '\0')
1572 if(*end
== '\r' && *(end
+ 1) == '\n')
1576 cur_body
->offsets
.cbBodyEnd
= boundary_start
;
1577 list_add_tail(body_offsets
, &cur_body
->entry
);
1579 cur_body
= HeapAlloc(GetProcessHeap(), 0, sizeof(*cur_body
));
1580 cur_body
->offsets
.cbBoundaryStart
= boundary_start
+ 2; /* doesn't including the leading \r\n */
1581 cur_body
->offsets
.cbHeaderStart
= boundary_start
+ boundary_len
+ 6;
1583 else if(*end
== '-' && *(end
+ 1) == '-')
1587 cur_body
->offsets
.cbBodyEnd
= boundary_start
;
1588 list_add_tail(body_offsets
, &cur_body
->entry
);
1596 if(overlap
== buf
) /* 1st iteration */
1598 memcpy(buf
, buf
+ PARSER_BUF_SIZE
- overlap_no
, overlap_no
);
1599 overlap
= buf
+ overlap_no
;
1600 start
+= read
- overlap_no
;
1604 memcpy(buf
, buf
+ PARSER_BUF_SIZE
, overlap_no
);
1610 HeapFree(GetProcessHeap(), 0, nl_boundary
);
1611 HeapFree(GetProcessHeap(), 0, buf
);
1615 static body_t
*create_sub_body(MimeMessage
*msg
, IStream
*pStm
, BODYOFFSETS
*offset
, body_t
*parent
)
1617 MimeBody
*mime_body
;
1623 mime_body
= mimebody_create();
1624 IMimeBody_Load(&mime_body
->IMimeBody_iface
, pStm
);
1626 hr
= IStream_Seek(pStm
, zero
, STREAM_SEEK_CUR
, &cur
);
1627 offset
->cbBodyStart
= cur
.u
.LowPart
+ offset
->cbHeaderStart
;
1628 if (parent
) MimeBody_set_offsets(mime_body
, offset
);
1629 IMimeBody_SetData(&mime_body
->IMimeBody_iface
, IET_BINARY
, NULL
, NULL
, &IID_IStream
, pStm
);
1630 body
= new_body_entry(mime_body
, msg
->next_index
++, parent
);
1632 if(IMimeBody_IsContentType(&mime_body
->IMimeBody_iface
, "multipart", NULL
) == S_OK
)
1634 MIMEPARAMINFO
*param_info
;
1636 IMimeAllocator
*alloc
;
1638 hr
= IMimeBody_GetParameters(&mime_body
->IMimeBody_iface
, "Content-Type", &count
,
1640 if(hr
!= S_OK
|| count
== 0) return body
;
1642 MimeOleGetAllocator(&alloc
);
1644 for(i
= 0; i
< count
; i
++)
1646 if(!strcasecmp(param_info
[i
].pszName
, "boundary"))
1648 struct list offset_list
;
1649 offset_entry_t
*cur
, *cursor2
;
1650 hr
= create_body_offset_list(pStm
, param_info
[i
].pszData
, &offset_list
);
1651 LIST_FOR_EACH_ENTRY_SAFE(cur
, cursor2
, &offset_list
, offset_entry_t
, entry
)
1654 IStream
*sub_stream
;
1655 ULARGE_INTEGER start
, length
;
1657 start
.QuadPart
= cur
->offsets
.cbHeaderStart
;
1658 length
.QuadPart
= cur
->offsets
.cbBodyEnd
- cur
->offsets
.cbHeaderStart
;
1659 create_sub_stream(pStm
, start
, length
, &sub_stream
);
1660 sub_body
= create_sub_body(msg
, sub_stream
, &cur
->offsets
, body
);
1661 IStream_Release(sub_stream
);
1662 list_add_tail(&body
->children
, &sub_body
->entry
);
1663 list_remove(&cur
->entry
);
1664 HeapFree(GetProcessHeap(), 0, cur
);
1669 IMimeAllocator_FreeParamInfoArray(alloc
, count
, param_info
, TRUE
);
1670 IMimeAllocator_Release(alloc
);
1675 static HRESULT WINAPI
MimeMessage_Load(IMimeMessage
*iface
, IStream
*pStm
)
1677 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
1679 BODYOFFSETS offsets
;
1683 TRACE("(%p)->(%p)\n", iface
, pStm
);
1687 FIXME("already loaded a message\n");
1691 IStream_AddRef(pStm
);
1692 This
->stream
= pStm
;
1693 offsets
.cbBoundaryStart
= offsets
.cbHeaderStart
= 0;
1694 offsets
.cbBodyStart
= offsets
.cbBodyEnd
= 0;
1696 root_body
= create_sub_body(This
, pStm
, &offsets
, NULL
);
1699 IStream_Seek(pStm
, zero
, STREAM_SEEK_END
, &cur
);
1700 offsets
.cbBodyEnd
= cur
.u
.LowPart
;
1701 MimeBody_set_offsets(root_body
->mime_body
, &offsets
);
1703 list_add_head(&This
->body_tree
, &root_body
->entry
);
1708 static HRESULT WINAPI
MimeMessage_Save(IMimeMessage
*iface
, IStream
*pStm
, BOOL fClearDirty
)
1710 FIXME("(%p)->(%p, %s)\n", iface
, pStm
, fClearDirty
? "TRUE" : "FALSE");
1714 static HRESULT WINAPI
MimeMessage_GetSizeMax(
1715 IMimeMessage
*iface
,
1716 ULARGE_INTEGER
*pcbSize
)
1718 FIXME("(%p)->(%p)\n", iface
, pcbSize
);
1722 static HRESULT WINAPI
MimeMessage_InitNew(
1723 IMimeMessage
*iface
)
1725 FIXME("(%p)->()\n", iface
);
1729 /*** IMimeMessageTree methods ***/
1730 static HRESULT WINAPI
MimeMessage_GetMessageSource(IMimeMessage
*iface
, IStream
**ppStream
,
1733 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
1735 FIXME("(%p)->(%p, 0x%x)\n", iface
, ppStream
, dwFlags
);
1737 IStream_AddRef(This
->stream
);
1738 *ppStream
= This
->stream
;
1742 static HRESULT WINAPI
MimeMessage_GetMessageSize(
1743 IMimeMessage
*iface
,
1747 FIXME("(%p)->(%p, 0x%x)\n", iface
, pcbSize
, dwFlags
);
1751 static HRESULT WINAPI
MimeMessage_LoadOffsetTable(
1752 IMimeMessage
*iface
,
1755 FIXME("(%p)->(%p)\n", iface
, pStream
);
1759 static HRESULT WINAPI
MimeMessage_SaveOffsetTable(
1760 IMimeMessage
*iface
,
1764 FIXME("(%p)->(%p, 0x%x)\n", iface
, pStream
, dwFlags
);
1769 static HRESULT WINAPI
MimeMessage_GetFlags(
1770 IMimeMessage
*iface
,
1773 FIXME("(%p)->(%p)\n", iface
, pdwFlags
);
1777 static HRESULT WINAPI
MimeMessage_Commit(
1778 IMimeMessage
*iface
,
1781 FIXME("(%p)->(0x%x)\n", iface
, dwFlags
);
1786 static HRESULT WINAPI
MimeMessage_HandsOffStorage(
1787 IMimeMessage
*iface
)
1789 FIXME("(%p)->()\n", iface
);
1793 static HRESULT
find_body(struct list
*list
, HBODY hbody
, body_t
**body
)
1798 if(hbody
== HBODY_ROOT
)
1800 *body
= LIST_ENTRY(list_head(list
), body_t
, entry
);
1804 LIST_FOR_EACH_ENTRY(cur
, list
, body_t
, entry
)
1806 if(cur
->index
== HandleToUlong(hbody
))
1811 hr
= find_body(&cur
->children
, hbody
, body
);
1812 if(hr
== S_OK
) return S_OK
;
1817 static HRESULT WINAPI
MimeMessage_BindToObject(IMimeMessage
*iface
, const HBODY hBody
, REFIID riid
,
1820 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
1824 TRACE("(%p)->(%p, %s, %p)\n", iface
, hBody
, debugstr_guid(riid
), ppvObject
);
1826 hr
= find_body(&This
->body_tree
, hBody
, &body
);
1828 if(hr
!= S_OK
) return hr
;
1830 if(IsEqualIID(riid
, &IID_IMimeBody
))
1832 IMimeBody_AddRef(&body
->mime_body
->IMimeBody_iface
);
1833 *ppvObject
= &body
->mime_body
->IMimeBody_iface
;
1837 return E_NOINTERFACE
;
1840 static HRESULT WINAPI
MimeMessage_SaveBody(
1841 IMimeMessage
*iface
,
1846 FIXME("(%p)->(%p, 0x%x, %p)\n", iface
, hBody
, dwFlags
, pStream
);
1850 static HRESULT
get_body(MimeMessage
*msg
, BODYLOCATION location
, HBODY pivot
, body_t
**out
)
1852 body_t
*root
= LIST_ENTRY(list_head(&msg
->body_tree
), body_t
, entry
);
1857 if(location
== IBL_ROOT
)
1863 hr
= find_body(&msg
->body_tree
, pivot
, &body
);
1870 *out
= body
->parent
;
1874 list
= list_head(&body
->children
);
1876 *out
= LIST_ENTRY(list
, body_t
, entry
);
1878 hr
= MIME_E_NOT_FOUND
;
1882 list
= list_tail(&body
->children
);
1884 *out
= LIST_ENTRY(list
, body_t
, entry
);
1886 hr
= MIME_E_NOT_FOUND
;
1890 list
= list_next(&body
->parent
->children
, &body
->entry
);
1892 *out
= LIST_ENTRY(list
, body_t
, entry
);
1894 hr
= MIME_E_NOT_FOUND
;
1898 list
= list_prev(&body
->parent
->children
, &body
->entry
);
1900 *out
= LIST_ENTRY(list
, body_t
, entry
);
1902 hr
= MIME_E_NOT_FOUND
;
1915 static HRESULT WINAPI
MimeMessage_InsertBody(
1916 IMimeMessage
*iface
,
1917 BODYLOCATION location
,
1921 FIXME("(%p)->(%d, %p, %p)\n", iface
, location
, hPivot
, phBody
);
1925 static HRESULT WINAPI
MimeMessage_GetBody(IMimeMessage
*iface
, BODYLOCATION location
, HBODY hPivot
,
1928 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
1932 TRACE("(%p)->(%d, %p, %p)\n", iface
, location
, hPivot
, phBody
);
1934 hr
= get_body(This
, location
, hPivot
, &body
);
1936 if(hr
== S_OK
) *phBody
= UlongToHandle(body
->index
);
1941 static HRESULT WINAPI
MimeMessage_DeleteBody(
1942 IMimeMessage
*iface
,
1946 FIXME("(%p)->(%p, %08x)\n", iface
, hBody
, dwFlags
);
1950 static HRESULT WINAPI
MimeMessage_MoveBody(
1951 IMimeMessage
*iface
,
1953 BODYLOCATION location
)
1955 FIXME("(%p)->(%d)\n", iface
, location
);
1959 static void count_children(body_t
*body
, boolean recurse
, ULONG
*count
)
1963 LIST_FOR_EACH_ENTRY(child
, &body
->children
, body_t
, entry
)
1966 if(recurse
) count_children(child
, recurse
, count
);
1970 static HRESULT WINAPI
MimeMessage_CountBodies(IMimeMessage
*iface
, HBODY hParent
, boolean fRecurse
,
1974 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
1977 TRACE("(%p)->(%p, %s, %p)\n", iface
, hParent
, fRecurse
? "TRUE" : "FALSE", pcBodies
);
1979 hr
= find_body(&This
->body_tree
, hParent
, &body
);
1980 if(hr
!= S_OK
) return hr
;
1983 count_children(body
, fRecurse
, pcBodies
);
1988 static HRESULT
find_next(MimeMessage
*This
, body_t
*body
, FINDBODY
*find
, HBODY
*out
)
1995 if (!body
) ptr
= list_head( &This
->body_tree
);
1998 ptr
= list_head( &body
->children
);
2001 if (!body
->parent
) return MIME_E_NOT_FOUND
;
2002 if (!(ptr
= list_next( &body
->parent
->children
, &body
->entry
))) body
= body
->parent
;
2006 body
= LIST_ENTRY( ptr
, body_t
, entry
);
2007 next
= UlongToHandle( body
->index
);
2008 find
->dwReserved
= body
->index
;
2009 if (IMimeBody_IsContentType(&body
->mime_body
->IMimeBody_iface
, find
->pszPriType
,
2010 find
->pszSubType
) == S_OK
)
2016 return MIME_E_NOT_FOUND
;
2019 static HRESULT WINAPI
MimeMessage_FindFirst(IMimeMessage
*iface
, FINDBODY
*pFindBody
, HBODY
*phBody
)
2021 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2023 TRACE("(%p)->(%p, %p)\n", iface
, pFindBody
, phBody
);
2025 pFindBody
->dwReserved
= 0;
2026 return find_next(This
, NULL
, pFindBody
, phBody
);
2029 static HRESULT WINAPI
MimeMessage_FindNext(IMimeMessage
*iface
, FINDBODY
*pFindBody
, HBODY
*phBody
)
2031 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2035 TRACE("(%p)->(%p, %p)\n", iface
, pFindBody
, phBody
);
2037 hr
= find_body( &This
->body_tree
, UlongToHandle( pFindBody
->dwReserved
), &body
);
2038 if (hr
!= S_OK
) return MIME_E_NOT_FOUND
;
2039 return find_next(This
, body
, pFindBody
, phBody
);
2042 static HRESULT WINAPI
MimeMessage_ResolveURL(
2043 IMimeMessage
*iface
,
2050 FIXME("(%p)->(%p, %s, %s, 0x%x, %p)\n", iface
, hRelated
, pszBase
, pszURL
, dwFlags
, phBody
);
2054 static HRESULT WINAPI
MimeMessage_ToMultipart(
2055 IMimeMessage
*iface
,
2058 LPHBODY phMultipart
)
2060 FIXME("(%p)->(%p, %s, %p)\n", iface
, hBody
, pszSubType
, phMultipart
);
2064 static HRESULT WINAPI
MimeMessage_GetBodyOffsets(
2065 IMimeMessage
*iface
,
2067 LPBODYOFFSETS pOffsets
)
2069 FIXME("(%p)->(%p, %p)\n", iface
, hBody
, pOffsets
);
2073 static HRESULT WINAPI
MimeMessage_GetCharset(
2074 IMimeMessage
*iface
,
2075 LPHCHARSET phCharset
)
2077 FIXME("(%p)->(%p)\n", iface
, phCharset
);
2082 static HRESULT WINAPI
MimeMessage_SetCharset(
2083 IMimeMessage
*iface
,
2085 CSETAPPLYTYPE applytype
)
2087 FIXME("(%p)->(%p, %d)\n", iface
, hCharset
, applytype
);
2091 static HRESULT WINAPI
MimeMessage_IsBodyType(
2092 IMimeMessage
*iface
,
2094 IMSGBODYTYPE bodytype
)
2097 IMimeBody
*mime_body
;
2098 TRACE("(%p)->(%p, %d)\n", iface
, hBody
, bodytype
);
2100 hr
= IMimeMessage_BindToObject(iface
, hBody
, &IID_IMimeBody
, (void**)&mime_body
);
2101 if(hr
!= S_OK
) return hr
;
2103 hr
= IMimeBody_IsType(mime_body
, bodytype
);
2104 MimeBody_Release(mime_body
);
2108 static HRESULT WINAPI
MimeMessage_IsContentType(
2109 IMimeMessage
*iface
,
2115 IMimeBody
*mime_body
;
2116 TRACE("(%p)->(%p, %s, %s)\n", iface
, hBody
, debugstr_a(pszPriType
),
2117 debugstr_a(pszSubType
));
2119 hr
= IMimeMessage_BindToObject(iface
, hBody
, &IID_IMimeBody
, (void**)&mime_body
);
2120 if(FAILED(hr
)) return hr
;
2122 hr
= IMimeBody_IsContentType(mime_body
, pszPriType
, pszSubType
);
2123 IMimeBody_Release(mime_body
);
2127 static HRESULT WINAPI
MimeMessage_QueryBodyProp(
2128 IMimeMessage
*iface
,
2133 boolean fCaseSensitive
)
2135 FIXME("(%p)->(%p, %s, %s, %s, %s)\n", iface
, hBody
, pszName
, pszCriteria
, fSubString
? "TRUE" : "FALSE", fCaseSensitive
? "TRUE" : "FALSE");
2139 static HRESULT WINAPI
MimeMessage_GetBodyProp(
2140 IMimeMessage
*iface
,
2144 LPPROPVARIANT pValue
)
2147 IMimeBody
*mime_body
;
2149 TRACE("(%p)->(%p, %s, 0x%x, %p)\n", iface
, hBody
, pszName
, dwFlags
, pValue
);
2151 hr
= IMimeMessage_BindToObject(iface
, hBody
, &IID_IMimeBody
, (void**)&mime_body
);
2152 if(hr
!= S_OK
) return hr
;
2154 hr
= IMimeBody_GetProp(mime_body
, pszName
, dwFlags
, pValue
);
2155 IMimeBody_Release(mime_body
);
2160 static HRESULT WINAPI
MimeMessage_SetBodyProp(
2161 IMimeMessage
*iface
,
2165 LPCPROPVARIANT pValue
)
2167 FIXME("(%p)->(%p, %s, 0x%x, %p)\n", iface
, hBody
, pszName
, dwFlags
, pValue
);
2171 static HRESULT WINAPI
MimeMessage_DeleteBodyProp(
2172 IMimeMessage
*iface
,
2176 FIXME("(%p)->(%p, %s)\n", iface
, hBody
, pszName
);
2180 static HRESULT WINAPI
MimeMessage_SetOption(
2181 IMimeMessage
*iface
,
2183 LPCPROPVARIANT pValue
)
2185 HRESULT hr
= E_NOTIMPL
;
2186 TRACE("(%p)->(%08x, %p)\n", iface
, oid
, pValue
);
2188 if(pValue
->vt
!= TYPEDID_TYPE(oid
))
2190 WARN("Called with vartype %04x and oid %08x\n", pValue
->vt
, oid
);
2191 return E_INVALIDARG
;
2196 case OID_HIDE_TNEF_ATTACHMENTS
:
2197 FIXME("OID_HIDE_TNEF_ATTACHMENTS (value %d): ignoring\n", pValue
->u
.boolVal
);
2200 case OID_SHOW_MACBINARY
:
2201 FIXME("OID_SHOW_MACBINARY (value %d): ignoring\n", pValue
->u
.boolVal
);
2205 FIXME("Unhandled oid %08x\n", oid
);
2211 static HRESULT WINAPI
MimeMessage_GetOption(
2212 IMimeMessage
*iface
,
2214 LPPROPVARIANT pValue
)
2216 FIXME("(%p)->(%08x, %p)\n", iface
, oid
, pValue
);
2220 /*** IMimeMessage methods ***/
2221 static HRESULT WINAPI
MimeMessage_CreateWebPage(
2222 IMimeMessage
*iface
,
2224 LPWEBPAGEOPTIONS pOptions
,
2225 IMimeMessageCallback
*pCallback
,
2226 IMoniker
**ppMoniker
)
2228 FIXME("(%p)->(%p, %p, %p, %p)\n", iface
, pRootStm
, pOptions
, pCallback
, ppMoniker
);
2233 static HRESULT WINAPI
MimeMessage_GetProp(
2234 IMimeMessage
*iface
,
2237 LPPROPVARIANT pValue
)
2239 FIXME("(%p)->(%s, 0x%x, %p)\n", iface
, pszName
, dwFlags
, pValue
);
2243 static HRESULT WINAPI
MimeMessage_SetProp(
2244 IMimeMessage
*iface
,
2247 LPCPROPVARIANT pValue
)
2249 FIXME("(%p)->(%s, 0x%x, %p)\n", iface
, pszName
, dwFlags
, pValue
);
2253 static HRESULT WINAPI
MimeMessage_DeleteProp(
2254 IMimeMessage
*iface
,
2257 FIXME("(%p)->(%s)\n", iface
, pszName
);
2261 static HRESULT WINAPI
MimeMessage_QueryProp(
2262 IMimeMessage
*iface
,
2266 boolean fCaseSensitive
)
2268 FIXME("(%p)->(%s, %s, %s, %s)\n", iface
, pszName
, pszCriteria
, fSubString
? "TRUE" : "FALSE", fCaseSensitive
? "TRUE" : "FALSE");
2272 static HRESULT WINAPI
MimeMessage_GetTextBody(
2273 IMimeMessage
*iface
,
2275 ENCODINGTYPE ietEncoding
,
2281 FINDBODY find_struct
;
2282 IMimeBody
*mime_body
;
2283 static char text
[] = "text";
2284 static char plain
[] = "plain";
2285 static char html
[] = "html";
2287 TRACE("(%p)->(%d, %d, %p, %p)\n", iface
, dwTxtType
, ietEncoding
, pStream
, phBody
);
2289 find_struct
.pszPriType
= text
;
2294 find_struct
.pszSubType
= plain
;
2297 find_struct
.pszSubType
= html
;
2300 return MIME_E_INVALID_TEXT_TYPE
;
2303 hr
= IMimeMessage_FindFirst(iface
, &find_struct
, &hbody
);
2306 TRACE("not found hr %08x\n", hr
);
2311 IMimeMessage_BindToObject(iface
, hbody
, &IID_IMimeBody
, (void**)&mime_body
);
2313 IMimeBody_GetData(mime_body
, ietEncoding
, pStream
);
2315 IMimeBody_Release(mime_body
);
2319 static HRESULT WINAPI
MimeMessage_SetTextBody(
2320 IMimeMessage
*iface
,
2322 ENCODINGTYPE ietEncoding
,
2327 FIXME("(%p)->(%d, %d, %p, %p, %p)\n", iface
, dwTxtType
, ietEncoding
, hAlternative
, pStream
, phBody
);
2331 static HRESULT WINAPI
MimeMessage_AttachObject(
2332 IMimeMessage
*iface
,
2337 FIXME("(%p)->(%s, %p, %p)\n", iface
, debugstr_guid(riid
), pvObject
, phBody
);
2341 static HRESULT WINAPI
MimeMessage_AttachFile(
2342 IMimeMessage
*iface
,
2347 FIXME("(%p)->(%s, %p, %p)\n", iface
, pszFilePath
, pstmFile
, phBody
);
2351 static HRESULT WINAPI
MimeMessage_AttachURL(
2352 IMimeMessage
*iface
,
2360 FIXME("(%p)->(%s, %s, 0x%x, %p, %p, %p)\n", iface
, pszBase
, pszURL
, dwFlags
, pstmURL
, ppszCIDURL
, phBody
);
2364 static HRESULT WINAPI
MimeMessage_GetAttachments(
2365 IMimeMessage
*iface
,
2367 LPHBODY
*pprghAttach
)
2370 FINDBODY find_struct
;
2375 TRACE("(%p)->(%p, %p)\n", iface
, pcAttach
, pprghAttach
);
2378 array
= CoTaskMemAlloc(size
* sizeof(HBODY
));
2380 find_struct
.pszPriType
= find_struct
.pszSubType
= NULL
;
2381 hr
= IMimeMessage_FindFirst(iface
, &find_struct
, &hbody
);
2384 hr
= IMimeMessage_IsContentType(iface
, hbody
, "multipart", NULL
);
2385 TRACE("IsCT rets %08x %d\n", hr
, *pcAttach
);
2388 if(*pcAttach
+ 1 > size
)
2391 array
= CoTaskMemRealloc(array
, size
* sizeof(HBODY
));
2393 array
[*pcAttach
] = hbody
;
2396 hr
= IMimeMessage_FindNext(iface
, &find_struct
, &hbody
);
2399 *pprghAttach
= array
;
2403 static HRESULT WINAPI
MimeMessage_GetAddressTable(
2404 IMimeMessage
*iface
,
2405 IMimeAddressTable
**ppTable
)
2407 FIXME("(%p)->(%p)\n", iface
, ppTable
);
2411 static HRESULT WINAPI
MimeMessage_GetSender(
2412 IMimeMessage
*iface
,
2413 LPADDRESSPROPS pAddress
)
2415 FIXME("(%p)->(%p)\n", iface
, pAddress
);
2419 static HRESULT WINAPI
MimeMessage_GetAddressTypes(
2420 IMimeMessage
*iface
,
2423 LPADDRESSLIST pList
)
2425 FIXME("(%p)->(%d, %d, %p)\n", iface
, dwAdrTypes
, dwProps
, pList
);
2429 static HRESULT WINAPI
MimeMessage_GetAddressFormat(
2430 IMimeMessage
*iface
,
2432 ADDRESSFORMAT format
,
2435 FIXME("(%p)->(%d, %d, %p)\n", iface
, dwAdrTypes
, format
, ppszFormat
);
2439 static HRESULT WINAPI
MimeMessage_EnumAddressTypes(
2440 IMimeMessage
*iface
,
2443 IMimeEnumAddressTypes
**ppEnum
)
2445 FIXME("(%p)->(%d, %d, %p)\n", iface
, dwAdrTypes
, dwProps
, ppEnum
);
2449 static HRESULT WINAPI
MimeMessage_SplitMessage(
2450 IMimeMessage
*iface
,
2452 IMimeMessageParts
**ppParts
)
2454 FIXME("(%p)->(%d, %p)\n", iface
, cbMaxPart
, ppParts
);
2458 static HRESULT WINAPI
MimeMessage_GetRootMoniker(
2459 IMimeMessage
*iface
,
2460 IMoniker
**ppMoniker
)
2462 FIXME("(%p)->(%p)\n", iface
, ppMoniker
);
2466 static const IMimeMessageVtbl MimeMessageVtbl
=
2468 MimeMessage_QueryInterface
,
2470 MimeMessage_Release
,
2471 MimeMessage_GetClassID
,
2472 MimeMessage_IsDirty
,
2475 MimeMessage_GetSizeMax
,
2476 MimeMessage_InitNew
,
2477 MimeMessage_GetMessageSource
,
2478 MimeMessage_GetMessageSize
,
2479 MimeMessage_LoadOffsetTable
,
2480 MimeMessage_SaveOffsetTable
,
2481 MimeMessage_GetFlags
,
2483 MimeMessage_HandsOffStorage
,
2484 MimeMessage_BindToObject
,
2485 MimeMessage_SaveBody
,
2486 MimeMessage_InsertBody
,
2487 MimeMessage_GetBody
,
2488 MimeMessage_DeleteBody
,
2489 MimeMessage_MoveBody
,
2490 MimeMessage_CountBodies
,
2491 MimeMessage_FindFirst
,
2492 MimeMessage_FindNext
,
2493 MimeMessage_ResolveURL
,
2494 MimeMessage_ToMultipart
,
2495 MimeMessage_GetBodyOffsets
,
2496 MimeMessage_GetCharset
,
2497 MimeMessage_SetCharset
,
2498 MimeMessage_IsBodyType
,
2499 MimeMessage_IsContentType
,
2500 MimeMessage_QueryBodyProp
,
2501 MimeMessage_GetBodyProp
,
2502 MimeMessage_SetBodyProp
,
2503 MimeMessage_DeleteBodyProp
,
2504 MimeMessage_SetOption
,
2505 MimeMessage_GetOption
,
2506 MimeMessage_CreateWebPage
,
2507 MimeMessage_GetProp
,
2508 MimeMessage_SetProp
,
2509 MimeMessage_DeleteProp
,
2510 MimeMessage_QueryProp
,
2511 MimeMessage_GetTextBody
,
2512 MimeMessage_SetTextBody
,
2513 MimeMessage_AttachObject
,
2514 MimeMessage_AttachFile
,
2515 MimeMessage_AttachURL
,
2516 MimeMessage_GetAttachments
,
2517 MimeMessage_GetAddressTable
,
2518 MimeMessage_GetSender
,
2519 MimeMessage_GetAddressTypes
,
2520 MimeMessage_GetAddressFormat
,
2521 MimeMessage_EnumAddressTypes
,
2522 MimeMessage_SplitMessage
,
2523 MimeMessage_GetRootMoniker
,
2526 HRESULT
MimeMessage_create(IUnknown
*outer
, void **obj
)
2530 TRACE("(%p, %p)\n", outer
, obj
);
2534 FIXME("outer unknown not supported yet\n");
2540 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
2541 if (!This
) return E_OUTOFMEMORY
;
2543 This
->IMimeMessage_iface
.lpVtbl
= &MimeMessageVtbl
;
2545 This
->stream
= NULL
;
2546 list_init(&This
->body_tree
);
2547 This
->next_index
= 1;
2549 *obj
= &This
->IMimeMessage_iface
;
2553 /***********************************************************************
2554 * MimeOleCreateMessage (INETCOMM.@)
2556 HRESULT WINAPI
MimeOleCreateMessage(IUnknown
*pUnkOuter
, IMimeMessage
**ppMessage
)
2558 TRACE("(%p, %p)\n", pUnkOuter
, ppMessage
);
2559 return MimeMessage_create(NULL
, (void **)ppMessage
);
2562 /***********************************************************************
2563 * MimeOleSetCompatMode (INETCOMM.@)
2565 HRESULT WINAPI
MimeOleSetCompatMode(DWORD dwMode
)
2567 FIXME("(0x%x)\n", dwMode
);
2571 /***********************************************************************
2572 * MimeOleCreateVirtualStream (INETCOMM.@)
2574 HRESULT WINAPI
MimeOleCreateVirtualStream(IStream
**ppStream
)
2577 FIXME("(%p)\n", ppStream
);
2579 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, ppStream
);
2583 typedef struct MimeSecurity
2585 IMimeSecurity IMimeSecurity_iface
;
2589 static inline MimeSecurity
*impl_from_IMimeSecurity(IMimeSecurity
*iface
)
2591 return CONTAINING_RECORD(iface
, MimeSecurity
, IMimeSecurity_iface
);
2594 static HRESULT WINAPI
MimeSecurity_QueryInterface(IMimeSecurity
*iface
, REFIID riid
, void **ppv
)
2596 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
2598 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2599 IsEqualIID(riid
, &IID_IMimeSecurity
))
2602 IMimeSecurity_AddRef(iface
);
2606 FIXME("no interface for %s\n", debugstr_guid(riid
));
2608 return E_NOINTERFACE
;
2611 static ULONG WINAPI
MimeSecurity_AddRef(IMimeSecurity
*iface
)
2613 MimeSecurity
*This
= impl_from_IMimeSecurity(iface
);
2614 LONG ref
= InterlockedIncrement(&This
->ref
);
2616 TRACE("(%p) ref=%d\n", This
, ref
);
2621 static ULONG WINAPI
MimeSecurity_Release(IMimeSecurity
*iface
)
2623 MimeSecurity
*This
= impl_from_IMimeSecurity(iface
);
2624 LONG ref
= InterlockedDecrement(&This
->ref
);
2626 TRACE("(%p) ref=%d\n", This
, ref
);
2629 HeapFree(GetProcessHeap(), 0, This
);
2634 static HRESULT WINAPI
MimeSecurity_InitNew(
2635 IMimeSecurity
* iface
)
2637 FIXME("(%p)->(): stub\n", iface
);
2641 static HRESULT WINAPI
MimeSecurity_CheckInit(
2642 IMimeSecurity
* iface
)
2644 FIXME("(%p)->(): stub\n", iface
);
2648 static HRESULT WINAPI
MimeSecurity_EncodeMessage(
2649 IMimeSecurity
* iface
,
2650 IMimeMessageTree
* pTree
,
2653 FIXME("(%p)->(%p, %08x): stub\n", iface
, pTree
, dwFlags
);
2657 static HRESULT WINAPI
MimeSecurity_EncodeBody(
2658 IMimeSecurity
* iface
,
2659 IMimeMessageTree
* pTree
,
2663 FIXME("(%p)->(%p, %p, %08x): stub\n", iface
, pTree
, hEncodeRoot
, dwFlags
);
2667 static HRESULT WINAPI
MimeSecurity_DecodeMessage(
2668 IMimeSecurity
* iface
,
2669 IMimeMessageTree
* pTree
,
2672 FIXME("(%p)->(%p, %08x): stub\n", iface
, pTree
, dwFlags
);
2676 static HRESULT WINAPI
MimeSecurity_DecodeBody(
2677 IMimeSecurity
* iface
,
2678 IMimeMessageTree
* pTree
,
2682 FIXME("(%p)->(%p, %p, %08x): stub\n", iface
, pTree
, hDecodeRoot
, dwFlags
);
2686 static HRESULT WINAPI
MimeSecurity_EnumCertificates(
2687 IMimeSecurity
* iface
,
2693 FIXME("(%p)->(%p, %08x, %p, %p): stub\n", iface
, hc
, dwUsage
, pPrev
, ppCert
);
2697 static HRESULT WINAPI
MimeSecurity_GetCertificateName(
2698 IMimeSecurity
* iface
,
2699 const PCX509CERT pX509Cert
,
2700 const CERTNAMETYPE cn
,
2703 FIXME("(%p)->(%p, %08x, %p): stub\n", iface
, pX509Cert
, cn
, ppszName
);
2707 static HRESULT WINAPI
MimeSecurity_GetMessageType(
2708 IMimeSecurity
* iface
,
2709 const HWND hwndParent
,
2713 FIXME("(%p)->(%p, %p, %p): stub\n", iface
, hwndParent
, pBody
, pdwSecType
);
2717 static HRESULT WINAPI
MimeSecurity_GetCertData(
2718 IMimeSecurity
* iface
,
2719 const PCX509CERT pX509Cert
,
2720 const CERTDATAID dataid
,
2721 LPPROPVARIANT pValue
)
2723 FIXME("(%p)->(%p, %x, %p): stub\n", iface
, pX509Cert
, dataid
, pValue
);
2728 static const IMimeSecurityVtbl MimeSecurityVtbl
=
2730 MimeSecurity_QueryInterface
,
2731 MimeSecurity_AddRef
,
2732 MimeSecurity_Release
,
2733 MimeSecurity_InitNew
,
2734 MimeSecurity_CheckInit
,
2735 MimeSecurity_EncodeMessage
,
2736 MimeSecurity_EncodeBody
,
2737 MimeSecurity_DecodeMessage
,
2738 MimeSecurity_DecodeBody
,
2739 MimeSecurity_EnumCertificates
,
2740 MimeSecurity_GetCertificateName
,
2741 MimeSecurity_GetMessageType
,
2742 MimeSecurity_GetCertData
2745 HRESULT
MimeSecurity_create(IUnknown
*outer
, void **obj
)
2751 if (outer
) return CLASS_E_NOAGGREGATION
;
2753 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
2754 if (!This
) return E_OUTOFMEMORY
;
2756 This
->IMimeSecurity_iface
.lpVtbl
= &MimeSecurityVtbl
;
2759 *obj
= &This
->IMimeSecurity_iface
;
2763 /***********************************************************************
2764 * MimeOleCreateSecurity (INETCOMM.@)
2766 HRESULT WINAPI
MimeOleCreateSecurity(IMimeSecurity
**ppSecurity
)
2768 return MimeSecurity_create(NULL
, (void **)ppSecurity
);
2771 static HRESULT WINAPI
MimeAlloc_QueryInterface(
2772 IMimeAllocator
* iface
,
2776 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), obj
);
2778 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2779 IsEqualIID(riid
, &IID_IMalloc
) ||
2780 IsEqualIID(riid
, &IID_IMimeAllocator
))
2783 IMimeAllocator_AddRef(iface
);
2787 FIXME("no interface for %s\n", debugstr_guid(riid
));
2789 return E_NOINTERFACE
;
2792 static ULONG WINAPI
MimeAlloc_AddRef(
2793 IMimeAllocator
* iface
)
2798 static ULONG WINAPI
MimeAlloc_Release(
2799 IMimeAllocator
* iface
)
2804 static LPVOID WINAPI
MimeAlloc_Alloc(
2805 IMimeAllocator
* iface
,
2808 return CoTaskMemAlloc(cb
);
2811 static LPVOID WINAPI
MimeAlloc_Realloc(
2812 IMimeAllocator
* iface
,
2816 return CoTaskMemRealloc(pv
, cb
);
2819 static void WINAPI
MimeAlloc_Free(
2820 IMimeAllocator
* iface
,
2826 static ULONG WINAPI
MimeAlloc_GetSize(
2827 IMimeAllocator
* iface
,
2834 static int WINAPI
MimeAlloc_DidAlloc(
2835 IMimeAllocator
* iface
,
2842 static void WINAPI
MimeAlloc_HeapMinimize(
2843 IMimeAllocator
* iface
)
2849 static HRESULT WINAPI
MimeAlloc_FreeParamInfoArray(
2850 IMimeAllocator
* iface
,
2852 LPMIMEPARAMINFO prgParam
,
2856 TRACE("(%p)->(%d, %p, %d)\n", iface
, cParams
, prgParam
, fFreeArray
);
2858 for(i
= 0; i
< cParams
; i
++)
2860 IMimeAllocator_Free(iface
, prgParam
[i
].pszName
);
2861 IMimeAllocator_Free(iface
, prgParam
[i
].pszData
);
2863 if(fFreeArray
) IMimeAllocator_Free(iface
, prgParam
);
2867 static HRESULT WINAPI
MimeAlloc_FreeAddressList(
2868 IMimeAllocator
* iface
,
2869 LPADDRESSLIST pList
)
2875 static HRESULT WINAPI
MimeAlloc_FreeAddressProps(
2876 IMimeAllocator
* iface
,
2877 LPADDRESSPROPS pAddress
)
2883 static HRESULT WINAPI
MimeAlloc_ReleaseObjects(
2884 IMimeAllocator
* iface
,
2886 IUnknown
**prgpUnknown
,
2894 static HRESULT WINAPI
MimeAlloc_FreeEnumHeaderRowArray(
2895 IMimeAllocator
* iface
,
2897 LPENUMHEADERROW prgRow
,
2904 static HRESULT WINAPI
MimeAlloc_FreeEnumPropertyArray(
2905 IMimeAllocator
* iface
,
2907 LPENUMPROPERTY prgProp
,
2914 static HRESULT WINAPI
MimeAlloc_FreeThumbprint(
2915 IMimeAllocator
* iface
,
2916 THUMBBLOB
*pthumbprint
)
2923 static HRESULT WINAPI
MimeAlloc_PropVariantClear(
2924 IMimeAllocator
* iface
,
2925 LPPROPVARIANT pProp
)
2931 static IMimeAllocatorVtbl mime_alloc_vtbl
=
2933 MimeAlloc_QueryInterface
,
2941 MimeAlloc_HeapMinimize
,
2942 MimeAlloc_FreeParamInfoArray
,
2943 MimeAlloc_FreeAddressList
,
2944 MimeAlloc_FreeAddressProps
,
2945 MimeAlloc_ReleaseObjects
,
2946 MimeAlloc_FreeEnumHeaderRowArray
,
2947 MimeAlloc_FreeEnumPropertyArray
,
2948 MimeAlloc_FreeThumbprint
,
2949 MimeAlloc_PropVariantClear
2952 static IMimeAllocator mime_allocator
=
2957 HRESULT
MimeAllocator_create(IUnknown
*outer
, void **obj
)
2959 if(outer
) return CLASS_E_NOAGGREGATION
;
2961 *obj
= &mime_allocator
;
2965 HRESULT WINAPI
MimeOleGetAllocator(IMimeAllocator
**alloc
)
2967 return MimeAllocator_create(NULL
, (void**)alloc
);
2970 HRESULT
VirtualStream_create(IUnknown
*outer
, void **obj
)
2972 FIXME("(%p, %p)\n", outer
, obj
);
2975 if (outer
) return CLASS_E_NOAGGREGATION
;
2977 return MimeOleCreateVirtualStream((IStream
**)obj
);