4 * Copyright 2006 Robert Shearman for CodeWeavers
5 * Copyright 2007 Huw Davies for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define WIN32_NO_STATUS
24 #define COM_NO_WINDOWS_H
27 #define NONAMELESSUNION
34 //#include "winuser.h"
35 //#include "objbase.h"
39 #include <wine/list.h>
40 #include <wine/debug.h>
42 #include "inetcomm_private.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(inetcomm
);
50 DWORD flags
; /* MIMEPROPFLAGS */
58 } property_list_entry_t
;
60 static const property_t default_props
[] =
62 {"References", PID_HDR_REFS
, 0, VT_LPSTR
},
63 {"Subject", PID_HDR_SUBJECT
, 0, VT_LPSTR
},
64 {"From", PID_HDR_FROM
, MPF_ADDRESS
, VT_LPSTR
},
65 {"Message-ID", PID_HDR_MESSAGEID
, 0, VT_LPSTR
},
66 {"Return-Path", PID_HDR_RETURNPATH
, MPF_ADDRESS
, VT_LPSTR
},
67 {"Date", PID_HDR_DATE
, 0, VT_LPSTR
},
68 {"Received", PID_HDR_RECEIVED
, 0, VT_LPSTR
},
69 {"Reply-To", PID_HDR_REPLYTO
, MPF_ADDRESS
, VT_LPSTR
},
70 {"X-Mailer", PID_HDR_XMAILER
, 0, VT_LPSTR
},
71 {"Bcc", PID_HDR_BCC
, MPF_ADDRESS
, VT_LPSTR
},
72 {"MIME-Version", PID_HDR_MIMEVER
, MPF_MIME
, VT_LPSTR
},
73 {"Content-Type", PID_HDR_CNTTYPE
, MPF_MIME
| MPF_HASPARAMS
, VT_LPSTR
},
74 {"Content-Transfer-Encoding", PID_HDR_CNTXFER
, MPF_MIME
, VT_LPSTR
},
75 {"Content-ID", PID_HDR_CNTID
, MPF_MIME
, VT_LPSTR
},
76 {"Content-Disposition", PID_HDR_CNTDISP
, MPF_MIME
| MPF_HASPARAMS
, VT_LPSTR
},
77 {"To", PID_HDR_TO
, MPF_ADDRESS
, VT_LPSTR
},
78 {"Cc", PID_HDR_CC
, MPF_ADDRESS
, VT_LPSTR
},
79 {"Sender", PID_HDR_SENDER
, MPF_ADDRESS
, VT_LPSTR
},
80 {"In-Reply-To", PID_HDR_INREPLYTO
, 0, VT_LPSTR
},
94 const property_t
*prop
;
99 typedef struct MimeBody
101 const IMimeBodyVtbl
*lpVtbl
;
107 struct list new_props
; /* FIXME: This should be in a PropertySchema */
109 char *content_pri_type
;
110 char *content_sub_type
;
111 ENCODINGTYPE encoding
;
114 BODYOFFSETS body_offsets
;
117 static inline MimeBody
*impl_from_IMimeBody( IMimeBody
*iface
)
119 return (MimeBody
*)((char*)iface
- FIELD_OFFSET(MimeBody
, lpVtbl
));
122 static LPSTR
strdupA(LPCSTR str
)
125 int len
= strlen(str
);
126 ret
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
127 memcpy(ret
, str
, len
+ 1);
131 #define PARSER_BUF_SIZE 1024
133 /*****************************************************
134 * copy_headers_to_buf [internal]
136 * Copies the headers into a '\0' terminated memory block and leave
137 * the stream's current position set to after the blank line.
139 static HRESULT
copy_headers_to_buf(IStream
*stm
, char **ptr
)
142 DWORD size
= PARSER_BUF_SIZE
, offset
= 0, last_end
= 0;
154 buf
= HeapAlloc(GetProcessHeap(), 0, size
+ 1);
158 buf
= HeapReAlloc(GetProcessHeap(), 0, buf
, size
+ 1);
166 hr
= IStream_Read(stm
, buf
+ offset
, size
- offset
, &read
);
167 if(FAILED(hr
)) goto fail
;
172 if(read
== 0) done
= 1;
174 while(!done
&& (end
= strstr(buf
+ last_end
, "\r\n")))
176 DWORD new_end
= end
- buf
+ 2;
177 if(new_end
- last_end
== 2)
180 off
.QuadPart
= new_end
;
181 IStream_Seek(stm
, off
, STREAM_SEEK_SET
, NULL
);
194 HeapFree(GetProcessHeap(), 0, buf
);
198 static header_t
*read_prop(MimeBody
*body
, char **ptr
)
200 char *colon
= strchr(*ptr
, ':');
201 const property_t
*prop
;
204 if(!colon
) return NULL
;
208 for(prop
= default_props
; prop
->name
; prop
++)
210 if(!strcasecmp(*ptr
, prop
->name
))
212 TRACE("%s: found match with default property id %d\n", *ptr
, prop
->id
);
219 property_list_entry_t
*prop_entry
;
220 LIST_FOR_EACH_ENTRY(prop_entry
, &body
->new_props
, property_list_entry_t
, entry
)
222 if(!strcasecmp(*ptr
, prop_entry
->prop
.name
))
224 TRACE("%s: found match with already added new property id %d\n", *ptr
, prop_entry
->prop
.id
);
225 prop
= &prop_entry
->prop
;
231 prop_entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(*prop_entry
));
232 prop_entry
->prop
.name
= strdupA(*ptr
);
233 prop_entry
->prop
.id
= body
->next_prop_id
++;
234 prop_entry
->prop
.flags
= 0;
235 prop_entry
->prop
.default_vt
= VT_LPSTR
;
236 list_add_tail(&body
->new_props
, &prop_entry
->entry
);
237 prop
= &prop_entry
->prop
;
238 TRACE("%s: allocating new prop id %d\n", *ptr
, prop_entry
->prop
.id
);
242 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ret
));
244 PropVariantInit(&ret
->value
);
245 list_init(&ret
->params
);
251 static void unfold_header(char *header
, int len
)
253 char *start
= header
, *cp
= header
;
256 while(*cp
== ' ' || *cp
== '\t')
262 memmove(start
, cp
, len
+ 1);
264 cp
= strstr(start
, "\r\n");
271 } while(*cp
== ' ' || *cp
== '\t');
276 static char *unquote_string(const char *str
)
281 while(*str
== ' ' || *str
== '\t') str
++;
289 for(cp
= ret
; *cp
; cp
++)
292 memmove(cp
, cp
+ 1, strlen(cp
+ 1) + 1);
297 WARN("quote in unquoted string\n");
309 static void add_param(header_t
*header
, const char *p
)
311 const char *key
= p
, *value
, *cp
= p
;
315 TRACE("got param %s\n", p
);
317 while (*key
== ' ' || *key
== '\t' ) key
++;
319 cp
= strchr(key
, '=');
322 WARN("malformed parameter - skipping\n");
326 name
= HeapAlloc(GetProcessHeap(), 0, cp
- key
+ 1);
327 memcpy(name
, key
, cp
- key
);
328 name
[cp
- key
] = '\0';
332 param
= HeapAlloc(GetProcessHeap(), 0, sizeof(*param
));
334 param
->value
= unquote_string(value
);
335 list_add_tail(&header
->params
, ¶m
->entry
);
338 static void split_params(header_t
*header
, char *value
)
340 char *cp
= value
, *start
= value
;
346 if(!in_quote
&& *cp
== ';')
349 if(done_value
) add_param(header
, start
);
354 in_quote
= !in_quote
;
357 if(done_value
) add_param(header
, start
);
360 static void read_value(header_t
*header
, char **cur
)
362 char *end
= *cur
, *value
;
366 end
= strstr(end
, "\r\n");
368 } while(*end
== ' ' || *end
== '\t');
371 value
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
372 memcpy(value
, *cur
, len
);
375 unfold_header(value
, len
);
376 TRACE("value %s\n", debugstr_a(value
));
378 if(header
->prop
->flags
& MPF_HASPARAMS
)
380 split_params(header
, value
);
381 TRACE("value w/o params %s\n", debugstr_a(value
));
384 header
->value
.vt
= VT_LPSTR
;
385 header
->value
.u
.pszVal
= value
;
390 static void init_content_type(MimeBody
*body
, header_t
*header
)
395 if(header
->prop
->id
!= PID_HDR_CNTTYPE
)
397 ERR("called with header %s\n", header
->prop
->name
);
401 slash
= strchr(header
->value
.u
.pszVal
, '/');
404 WARN("malformed context type value\n");
407 len
= slash
- header
->value
.u
.pszVal
;
408 body
->content_pri_type
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
409 memcpy(body
->content_pri_type
, header
->value
.u
.pszVal
, len
);
410 body
->content_pri_type
[len
] = '\0';
411 body
->content_sub_type
= strdupA(slash
+ 1);
414 static HRESULT
parse_headers(MimeBody
*body
, IStream
*stm
)
416 char *header_buf
, *cur_header_ptr
;
420 hr
= copy_headers_to_buf(stm
, &header_buf
);
421 if(FAILED(hr
)) return hr
;
423 cur_header_ptr
= header_buf
;
424 while((header
= read_prop(body
, &cur_header_ptr
)))
426 read_value(header
, &cur_header_ptr
);
427 list_add_tail(&body
->headers
, &header
->entry
);
429 if(header
->prop
->id
== PID_HDR_CNTTYPE
)
430 init_content_type(body
, header
);
433 HeapFree(GetProcessHeap(), 0, header_buf
);
437 static void empty_param_list(struct list
*list
)
439 param_t
*param
, *cursor2
;
441 LIST_FOR_EACH_ENTRY_SAFE(param
, cursor2
, list
, param_t
, entry
)
443 list_remove(¶m
->entry
);
444 HeapFree(GetProcessHeap(), 0, param
->name
);
445 HeapFree(GetProcessHeap(), 0, param
->value
);
446 HeapFree(GetProcessHeap(), 0, param
);
450 static void empty_header_list(struct list
*list
)
452 header_t
*header
, *cursor2
;
454 LIST_FOR_EACH_ENTRY_SAFE(header
, cursor2
, list
, header_t
, entry
)
456 list_remove(&header
->entry
);
457 PropVariantClear(&header
->value
);
458 empty_param_list(&header
->params
);
459 HeapFree(GetProcessHeap(), 0, header
);
463 static void empty_new_prop_list(struct list
*list
)
465 property_list_entry_t
*prop
, *cursor2
;
467 LIST_FOR_EACH_ENTRY_SAFE(prop
, cursor2
, list
, property_list_entry_t
, entry
)
469 list_remove(&prop
->entry
);
470 HeapFree(GetProcessHeap(), 0, (char *)prop
->prop
.name
);
471 HeapFree(GetProcessHeap(), 0, prop
);
475 static void release_data(REFIID riid
, void *data
)
479 if(IsEqualIID(riid
, &IID_IStream
))
480 IStream_Release((IStream
*)data
);
482 FIXME("Unhandled data format %s\n", debugstr_guid(riid
));
485 static HRESULT
find_prop(MimeBody
*body
, const char *name
, header_t
**prop
)
491 LIST_FOR_EACH_ENTRY(header
, &body
->headers
, header_t
, entry
)
493 if(!strcasecmp(name
, header
->prop
->name
))
500 return MIME_E_NOT_FOUND
;
503 static HRESULT WINAPI
MimeBody_QueryInterface(IMimeBody
* iface
,
507 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppvObject
);
511 if (IsEqualIID(riid
, &IID_IUnknown
) ||
512 IsEqualIID(riid
, &IID_IPersist
) ||
513 IsEqualIID(riid
, &IID_IPersistStreamInit
) ||
514 IsEqualIID(riid
, &IID_IMimePropertySet
) ||
515 IsEqualIID(riid
, &IID_IMimeBody
))
522 IUnknown_AddRef((IUnknown
*)*ppvObject
);
526 FIXME("no interface for %s\n", debugstr_guid(riid
));
527 return E_NOINTERFACE
;
530 static ULONG WINAPI
MimeBody_AddRef(IMimeBody
* iface
)
532 MimeBody
*This
= impl_from_IMimeBody(iface
);
533 TRACE("(%p)->()\n", iface
);
534 return InterlockedIncrement(&This
->refs
);
537 static ULONG WINAPI
MimeBody_Release(IMimeBody
* iface
)
539 MimeBody
*This
= impl_from_IMimeBody(iface
);
542 TRACE("(%p)->()\n", iface
);
544 refs
= InterlockedDecrement(&This
->refs
);
547 empty_header_list(&This
->headers
);
548 empty_new_prop_list(&This
->new_props
);
550 HeapFree(GetProcessHeap(), 0, This
->content_pri_type
);
551 HeapFree(GetProcessHeap(), 0, This
->content_sub_type
);
553 release_data(&This
->data_iid
, This
->data
);
555 HeapFree(GetProcessHeap(), 0, This
);
561 static HRESULT WINAPI
MimeBody_GetClassID(
570 static HRESULT WINAPI
MimeBody_IsDirty(
577 static HRESULT WINAPI
MimeBody_Load(
581 MimeBody
*This
= impl_from_IMimeBody(iface
);
582 TRACE("(%p)->(%p)\n", iface
, pStm
);
583 return parse_headers(This
, pStm
);
586 static HRESULT WINAPI
MimeBody_Save(
595 static HRESULT WINAPI
MimeBody_GetSizeMax(
597 ULARGE_INTEGER
* pcbSize
)
603 static HRESULT WINAPI
MimeBody_InitNew(
606 TRACE("%p->()\n", iface
);
610 static HRESULT WINAPI
MimeBody_GetPropInfo(
613 LPMIMEPROPINFO pInfo
)
619 static HRESULT WINAPI
MimeBody_SetPropInfo(
622 LPCMIMEPROPINFO pInfo
)
628 static HRESULT WINAPI
MimeBody_GetProp(
632 LPPROPVARIANT pValue
)
634 MimeBody
*This
= impl_from_IMimeBody(iface
);
635 TRACE("(%p)->(%s, %d, %p)\n", This
, pszName
, dwFlags
, pValue
);
637 if(!strcasecmp(pszName
, "att:pri-content-type"))
639 PropVariantClear(pValue
);
640 pValue
->vt
= VT_LPSTR
;
641 pValue
->u
.pszVal
= strdupA(This
->content_pri_type
);
649 static HRESULT WINAPI
MimeBody_SetProp(
653 LPCPROPVARIANT pValue
)
659 static HRESULT WINAPI
MimeBody_AppendProp(
663 LPPROPVARIANT pValue
)
669 static HRESULT WINAPI
MimeBody_DeleteProp(
677 static HRESULT WINAPI
MimeBody_CopyProps(
681 IMimePropertySet
* pPropertySet
)
687 static HRESULT WINAPI
MimeBody_MoveProps(
691 IMimePropertySet
* pPropertySet
)
697 static HRESULT WINAPI
MimeBody_DeleteExcept(
706 static HRESULT WINAPI
MimeBody_QueryProp(
711 boolean fCaseSensitive
)
717 static HRESULT WINAPI
MimeBody_GetCharset(
719 LPHCHARSET phCharset
)
726 static HRESULT WINAPI
MimeBody_SetCharset(
729 CSETAPPLYTYPE applytype
)
735 static HRESULT WINAPI
MimeBody_GetParameters(
739 LPMIMEPARAMINFO
* pprgParam
)
741 MimeBody
*This
= impl_from_IMimeBody(iface
);
745 TRACE("(%p)->(%s, %p, %p)\n", iface
, debugstr_a(pszName
), pcParams
, pprgParam
);
750 hr
= find_prop(This
, pszName
, &header
);
751 if(hr
!= S_OK
) return hr
;
753 *pcParams
= list_count(&header
->params
);
756 IMimeAllocator
*alloc
;
760 MimeOleGetAllocator(&alloc
);
762 *pprgParam
= info
= IMimeAllocator_Alloc(alloc
, *pcParams
* sizeof(**pprgParam
));
763 LIST_FOR_EACH_ENTRY(param
, &header
->params
, param_t
, entry
)
767 len
= strlen(param
->name
) + 1;
768 info
->pszName
= IMimeAllocator_Alloc(alloc
, len
);
769 memcpy(info
->pszName
, param
->name
, len
);
770 len
= strlen(param
->value
) + 1;
771 info
->pszData
= IMimeAllocator_Alloc(alloc
, len
);
772 memcpy(info
->pszData
, param
->value
, len
);
775 IMimeAllocator_Release(alloc
);
780 static HRESULT WINAPI
MimeBody_IsContentType(
785 MimeBody
*This
= impl_from_IMimeBody(iface
);
787 TRACE("(%p)->(%s, %s)\n", This
, debugstr_a(pszPriType
), debugstr_a(pszSubType
));
790 const char *pri
= This
->content_pri_type
;
791 if(!pri
) pri
= "text";
792 if(strcasecmp(pri
, pszPriType
)) return S_FALSE
;
797 const char *sub
= This
->content_sub_type
;
798 if(!sub
) sub
= "plain";
799 if(strcasecmp(sub
, pszSubType
)) return S_FALSE
;
805 static HRESULT WINAPI
MimeBody_BindToObject(
814 static HRESULT WINAPI
MimeBody_Clone(
816 IMimePropertySet
** ppPropertySet
)
822 static HRESULT WINAPI
MimeBody_SetOption(
825 LPCPROPVARIANT pValue
)
827 HRESULT hr
= E_NOTIMPL
;
828 TRACE("(%p)->(%08x, %p)\n", iface
, oid
, pValue
);
830 if(pValue
->vt
!= TYPEDID_TYPE(oid
))
832 WARN("Called with vartype %04x and oid %08x\n", pValue
->vt
, oid
);
838 case OID_SECURITY_HWND_OWNER
:
839 FIXME("OID_SECURITY_HWND_OWNER (value %08x): ignoring\n", pValue
->u
.ulVal
);
843 FIXME("Unhandled oid %08x\n", oid
);
849 static HRESULT WINAPI
MimeBody_GetOption(
852 LPPROPVARIANT pValue
)
854 FIXME("(%p)->(%08x, %p): stub\n", iface
, oid
, pValue
);
858 static HRESULT WINAPI
MimeBody_EnumProps(
861 IMimeEnumProperties
** ppEnum
)
867 static HRESULT WINAPI
MimeBody_IsType(
869 IMSGBODYTYPE bodytype
)
871 MimeBody
*This
= impl_from_IMimeBody(iface
);
873 TRACE("(%p)->(%d)\n", iface
, bodytype
);
877 return This
->data
? S_FALSE
: S_OK
;
879 FIXME("Unimplemented bodytype %d - returning S_OK\n", bodytype
);
884 static HRESULT WINAPI
MimeBody_SetDisplayName(
892 static HRESULT WINAPI
MimeBody_GetDisplayName(
900 static HRESULT WINAPI
MimeBody_GetOffsets(
902 LPBODYOFFSETS pOffsets
)
904 MimeBody
*This
= impl_from_IMimeBody(iface
);
905 TRACE("(%p)->(%p)\n", This
, pOffsets
);
907 *pOffsets
= This
->body_offsets
;
909 if(This
->body_offsets
.cbBodyEnd
== 0) return MIME_E_NO_DATA
;
913 static HRESULT WINAPI
MimeBody_GetCurrentEncoding(
915 ENCODINGTYPE
* pietEncoding
)
917 MimeBody
*This
= impl_from_IMimeBody(iface
);
919 TRACE("(%p)->(%p)\n", This
, pietEncoding
);
921 *pietEncoding
= This
->encoding
;
925 static HRESULT WINAPI
MimeBody_SetCurrentEncoding(
927 ENCODINGTYPE ietEncoding
)
929 MimeBody
*This
= impl_from_IMimeBody(iface
);
931 TRACE("(%p)->(%d)\n", This
, ietEncoding
);
933 This
->encoding
= ietEncoding
;
937 static HRESULT WINAPI
MimeBody_GetEstimatedSize(
939 ENCODINGTYPE ietEncoding
,
946 static HRESULT WINAPI
MimeBody_GetDataHere(
948 ENCODINGTYPE ietEncoding
,
955 static HRESULT WINAPI
MimeBody_GetData(
957 ENCODINGTYPE ietEncoding
,
960 MimeBody
*This
= impl_from_IMimeBody(iface
);
961 FIXME("(%p)->(%d, %p). Ignoring encoding type.\n", This
, ietEncoding
, ppStream
);
963 *ppStream
= This
->data
;
964 IStream_AddRef(*ppStream
);
968 static HRESULT WINAPI
MimeBody_SetData(
970 ENCODINGTYPE ietEncoding
,
976 MimeBody
*This
= impl_from_IMimeBody(iface
);
977 TRACE("(%p)->(%d, %s, %s, %s %p)\n", This
, ietEncoding
, debugstr_a(pszPriType
), debugstr_a(pszSubType
),
978 debugstr_guid(riid
), pvObject
);
980 if(IsEqualIID(riid
, &IID_IStream
))
981 IStream_AddRef((IStream
*)pvObject
);
984 FIXME("Unhandled object type %s\n", debugstr_guid(riid
));
989 FIXME("release old data\n");
991 This
->data_iid
= *riid
;
992 This
->data
= pvObject
;
994 IMimeBody_SetCurrentEncoding(iface
, ietEncoding
);
996 /* FIXME: Update the content type.
997 If pszPriType == NULL use 'application'
998 If pszSubType == NULL use 'octet-stream' */
1003 static HRESULT WINAPI
MimeBody_EmptyData(
1010 static HRESULT WINAPI
MimeBody_CopyTo(
1018 static HRESULT WINAPI
MimeBody_GetTransmitInfo(
1020 LPTRANSMITINFO pTransmitInfo
)
1026 static HRESULT WINAPI
MimeBody_SaveToFile(
1028 ENCODINGTYPE ietEncoding
,
1035 static HRESULT WINAPI
MimeBody_GetHandle(
1039 MimeBody
*This
= impl_from_IMimeBody(iface
);
1040 TRACE("(%p)->(%p)\n", iface
, phBody
);
1042 *phBody
= This
->handle
;
1043 return This
->handle
? S_OK
: MIME_E_NO_DATA
;
1046 static IMimeBodyVtbl body_vtbl
=
1048 MimeBody_QueryInterface
,
1051 MimeBody_GetClassID
,
1055 MimeBody_GetSizeMax
,
1057 MimeBody_GetPropInfo
,
1058 MimeBody_SetPropInfo
,
1061 MimeBody_AppendProp
,
1062 MimeBody_DeleteProp
,
1065 MimeBody_DeleteExcept
,
1067 MimeBody_GetCharset
,
1068 MimeBody_SetCharset
,
1069 MimeBody_GetParameters
,
1070 MimeBody_IsContentType
,
1071 MimeBody_BindToObject
,
1077 MimeBody_SetDisplayName
,
1078 MimeBody_GetDisplayName
,
1079 MimeBody_GetOffsets
,
1080 MimeBody_GetCurrentEncoding
,
1081 MimeBody_SetCurrentEncoding
,
1082 MimeBody_GetEstimatedSize
,
1083 MimeBody_GetDataHere
,
1088 MimeBody_GetTransmitInfo
,
1089 MimeBody_SaveToFile
,
1093 static HRESULT
MimeBody_set_offsets(MimeBody
*body
, const BODYOFFSETS
*offsets
)
1095 TRACE("setting offsets to %d, %d, %d, %d\n", offsets
->cbBoundaryStart
,
1096 offsets
->cbHeaderStart
, offsets
->cbBodyStart
, offsets
->cbBodyEnd
);
1098 body
->body_offsets
= *offsets
;
1102 #define FIRST_CUSTOM_PROP_ID 0x100
1104 HRESULT
MimeBody_create(IUnknown
*outer
, void **obj
)
1107 BODYOFFSETS body_offsets
;
1111 if(outer
) return CLASS_E_NOAGGREGATION
;
1113 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1114 if (!This
) return E_OUTOFMEMORY
;
1116 This
->lpVtbl
= &body_vtbl
;
1118 This
->handle
= NULL
;
1119 list_init(&This
->headers
);
1120 list_init(&This
->new_props
);
1121 This
->next_prop_id
= FIRST_CUSTOM_PROP_ID
;
1122 This
->content_pri_type
= NULL
;
1123 This
->content_sub_type
= NULL
;
1124 This
->encoding
= IET_7BIT
;
1126 This
->data_iid
= IID_NULL
;
1128 body_offsets
.cbBoundaryStart
= body_offsets
.cbHeaderStart
= 0;
1129 body_offsets
.cbBodyStart
= body_offsets
.cbBodyEnd
= 0;
1130 MimeBody_set_offsets(This
, &body_offsets
);
1132 *obj
= &This
->lpVtbl
;
1138 IStreamVtbl
*lpVtbl
;
1142 ULARGE_INTEGER pos
, start
, length
;
1145 static inline sub_stream_t
*impl_from_IStream( IStream
*iface
)
1147 return (sub_stream_t
*)((char*)iface
- FIELD_OFFSET(sub_stream_t
, lpVtbl
));
1150 static HRESULT WINAPI
sub_stream_QueryInterface(
1155 sub_stream_t
*This
= impl_from_IStream(iface
);
1157 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
1160 if(IsEqualIID(riid
, &IID_IUnknown
) ||
1161 IsEqualIID(riid
, &IID_ISequentialStream
) ||
1162 IsEqualIID(riid
, &IID_IStream
))
1164 IStream_AddRef(iface
);
1168 return E_NOINTERFACE
;
1171 static ULONG WINAPI
sub_stream_AddRef(
1174 sub_stream_t
*This
= impl_from_IStream(iface
);
1176 TRACE("(%p)\n", This
);
1177 return InterlockedIncrement(&This
->refs
);
1180 static ULONG WINAPI
sub_stream_Release(
1183 sub_stream_t
*This
= impl_from_IStream(iface
);
1186 TRACE("(%p)\n", This
);
1187 refs
= InterlockedDecrement(&This
->refs
);
1190 IStream_Release(This
->base
);
1191 HeapFree(GetProcessHeap(), 0, This
);
1196 static HRESULT WINAPI
sub_stream_Read(
1202 sub_stream_t
*This
= impl_from_IStream(iface
);
1204 ULARGE_INTEGER base_pos
;
1205 LARGE_INTEGER tmp_pos
;
1207 TRACE("(%p, %d, %p)\n", pv
, cb
, pcbRead
);
1209 tmp_pos
.QuadPart
= 0;
1210 IStream_Seek(This
->base
, tmp_pos
, STREAM_SEEK_CUR
, &base_pos
);
1211 tmp_pos
.QuadPart
= This
->pos
.QuadPart
+ This
->start
.QuadPart
;
1212 IStream_Seek(This
->base
, tmp_pos
, STREAM_SEEK_SET
, NULL
);
1214 if(This
->pos
.QuadPart
+ cb
> This
->length
.QuadPart
)
1215 cb
= This
->length
.QuadPart
- This
->pos
.QuadPart
;
1217 hr
= IStream_Read(This
->base
, pv
, cb
, pcbRead
);
1219 This
->pos
.QuadPart
+= *pcbRead
;
1221 tmp_pos
.QuadPart
= base_pos
.QuadPart
;
1222 IStream_Seek(This
->base
, tmp_pos
, STREAM_SEEK_SET
, NULL
);
1227 static HRESULT WINAPI
sub_stream_Write(
1237 static HRESULT WINAPI
sub_stream_Seek(
1239 LARGE_INTEGER dlibMove
,
1241 ULARGE_INTEGER
*plibNewPosition
)
1243 sub_stream_t
*This
= impl_from_IStream(iface
);
1244 LARGE_INTEGER new_pos
;
1246 TRACE("(%08x.%08x, %x, %p)\n", dlibMove
.u
.HighPart
, dlibMove
.u
.LowPart
, dwOrigin
, plibNewPosition
);
1250 case STREAM_SEEK_SET
:
1253 case STREAM_SEEK_CUR
:
1254 new_pos
.QuadPart
= This
->pos
.QuadPart
+ dlibMove
.QuadPart
;
1256 case STREAM_SEEK_END
:
1257 new_pos
.QuadPart
= This
->length
.QuadPart
+ dlibMove
.QuadPart
;
1260 return STG_E_INVALIDFUNCTION
;
1263 if(new_pos
.QuadPart
< 0) new_pos
.QuadPart
= 0;
1264 else if(new_pos
.QuadPart
> This
->length
.QuadPart
) new_pos
.QuadPart
= This
->length
.QuadPart
;
1266 This
->pos
.QuadPart
= new_pos
.QuadPart
;
1268 if(plibNewPosition
) *plibNewPosition
= This
->pos
;
1272 static HRESULT WINAPI
sub_stream_SetSize(
1274 ULARGE_INTEGER libNewSize
)
1280 static HRESULT WINAPI
sub_stream_CopyTo(
1284 ULARGE_INTEGER
*pcbRead
,
1285 ULARGE_INTEGER
*pcbWritten
)
1288 BYTE tmpBuffer
[128];
1289 ULONG bytesRead
, bytesWritten
, copySize
;
1290 ULARGE_INTEGER totalBytesRead
;
1291 ULARGE_INTEGER totalBytesWritten
;
1293 TRACE("(%p)->(%p, %d, %p, %p)\n", iface
, pstm
, cb
.u
.LowPart
, pcbRead
, pcbWritten
);
1295 totalBytesRead
.QuadPart
= 0;
1296 totalBytesWritten
.QuadPart
= 0;
1298 while ( cb
.QuadPart
> 0 )
1300 if ( cb
.QuadPart
>= sizeof(tmpBuffer
) )
1301 copySize
= sizeof(tmpBuffer
);
1303 copySize
= cb
.u
.LowPart
;
1305 hr
= IStream_Read(iface
, tmpBuffer
, copySize
, &bytesRead
);
1306 if (FAILED(hr
)) break;
1308 totalBytesRead
.QuadPart
+= bytesRead
;
1312 hr
= IStream_Write(pstm
, tmpBuffer
, bytesRead
, &bytesWritten
);
1313 if (FAILED(hr
)) break;
1314 totalBytesWritten
.QuadPart
+= bytesWritten
;
1317 if (bytesRead
!= copySize
)
1320 cb
.QuadPart
-= bytesRead
;
1323 if (pcbRead
) pcbRead
->QuadPart
= totalBytesRead
.QuadPart
;
1324 if (pcbWritten
) pcbWritten
->QuadPart
= totalBytesWritten
.QuadPart
;
1329 static HRESULT WINAPI
sub_stream_Commit(
1331 DWORD grfCommitFlags
)
1337 static HRESULT WINAPI
sub_stream_Revert(
1344 static HRESULT WINAPI
sub_stream_LockRegion(
1346 ULARGE_INTEGER libOffset
,
1354 static HRESULT WINAPI
sub_stream_UnlockRegion(
1356 ULARGE_INTEGER libOffset
,
1364 static HRESULT WINAPI
sub_stream_Stat(
1369 sub_stream_t
*This
= impl_from_IStream(iface
);
1370 FIXME("(%p)->(%p, %08x)\n", This
, pstatstg
, grfStatFlag
);
1371 memset(pstatstg
, 0, sizeof(*pstatstg
));
1372 pstatstg
->cbSize
= This
->length
;
1376 static HRESULT WINAPI
sub_stream_Clone(
1384 static struct IStreamVtbl sub_stream_vtbl
=
1386 sub_stream_QueryInterface
,
1396 sub_stream_LockRegion
,
1397 sub_stream_UnlockRegion
,
1402 static HRESULT
create_sub_stream(IStream
*stream
, ULARGE_INTEGER start
, ULARGE_INTEGER length
, IStream
**out
)
1407 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1408 if(!This
) return E_OUTOFMEMORY
;
1410 This
->lpVtbl
= &sub_stream_vtbl
;
1412 This
->start
= start
;
1413 This
->length
= length
;
1414 This
->pos
.QuadPart
= 0;
1415 IStream_AddRef(stream
);
1416 This
->base
= stream
;
1418 *out
= (IStream
*)&This
->lpVtbl
;
1423 typedef struct body_t
1427 IMimeBody
*mime_body
;
1429 struct body_t
*parent
;
1430 struct list children
;
1433 typedef struct MimeMessage
1435 const IMimeMessageVtbl
*lpVtbl
;
1440 struct list body_tree
;
1444 static HRESULT WINAPI
MimeMessage_QueryInterface(IMimeMessage
*iface
, REFIID riid
, void **ppv
)
1446 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
1448 if (IsEqualIID(riid
, &IID_IUnknown
) ||
1449 IsEqualIID(riid
, &IID_IPersist
) ||
1450 IsEqualIID(riid
, &IID_IPersistStreamInit
) ||
1451 IsEqualIID(riid
, &IID_IMimeMessageTree
) ||
1452 IsEqualIID(riid
, &IID_IMimeMessage
))
1455 IUnknown_AddRef(iface
);
1459 FIXME("no interface for %s\n", debugstr_guid(riid
));
1461 return E_NOINTERFACE
;
1464 static ULONG WINAPI
MimeMessage_AddRef(IMimeMessage
*iface
)
1466 MimeMessage
*This
= (MimeMessage
*)iface
;
1467 TRACE("(%p)->()\n", iface
);
1468 return InterlockedIncrement(&This
->refs
);
1471 static void empty_body_list(struct list
*list
)
1473 body_t
*body
, *cursor2
;
1474 LIST_FOR_EACH_ENTRY_SAFE(body
, cursor2
, list
, body_t
, entry
)
1476 empty_body_list(&body
->children
);
1477 list_remove(&body
->entry
);
1478 IMimeBody_Release(body
->mime_body
);
1479 HeapFree(GetProcessHeap(), 0, body
);
1483 static ULONG WINAPI
MimeMessage_Release(IMimeMessage
*iface
)
1485 MimeMessage
*This
= (MimeMessage
*)iface
;
1488 TRACE("(%p)->()\n", iface
);
1490 refs
= InterlockedDecrement(&This
->refs
);
1493 empty_body_list(&This
->body_tree
);
1495 if(This
->stream
) IStream_Release(This
->stream
);
1496 HeapFree(GetProcessHeap(), 0, This
);
1502 /*** IPersist methods ***/
1503 static HRESULT WINAPI
MimeMessage_GetClassID(
1504 IMimeMessage
*iface
,
1507 FIXME("(%p)->(%p)\n", iface
, pClassID
);
1511 /*** IPersistStreamInit methods ***/
1512 static HRESULT WINAPI
MimeMessage_IsDirty(
1513 IMimeMessage
*iface
)
1515 FIXME("(%p)->()\n", iface
);
1519 static body_t
*new_body_entry(IMimeBody
*mime_body
, DWORD index
, body_t
*parent
)
1521 body_t
*body
= HeapAlloc(GetProcessHeap(), 0, sizeof(*body
));
1524 body
->mime_body
= mime_body
;
1525 body
->index
= index
;
1526 list_init(&body
->children
);
1527 body
->parent
= parent
;
1535 BODYOFFSETS offsets
;
1538 static HRESULT
create_body_offset_list(IStream
*stm
, const char *boundary
, struct list
*body_offsets
)
1542 int boundary_len
= strlen(boundary
);
1543 char *buf
, *nl_boundary
, *ptr
, *overlap
;
1544 DWORD start
= 0, overlap_no
;
1545 offset_entry_t
*cur_body
= NULL
;
1549 list_init(body_offsets
);
1550 nl_boundary
= HeapAlloc(GetProcessHeap(), 0, 4 + boundary_len
+ 1);
1551 memcpy(nl_boundary
, "\r\n--", 4);
1552 memcpy(nl_boundary
+ 4, boundary
, boundary_len
+ 1);
1554 overlap_no
= boundary_len
+ 5;
1556 overlap
= buf
= HeapAlloc(GetProcessHeap(), 0, overlap_no
+ PARSER_BUF_SIZE
+ 1);
1559 hr
= IStream_Seek(stm
, zero
, STREAM_SEEK_CUR
, &cur
);
1560 start
= cur
.u
.LowPart
;
1563 hr
= IStream_Read(stm
, overlap
, PARSER_BUF_SIZE
, &read
);
1564 if(FAILED(hr
)) goto end
;
1565 if(read
== 0) break;
1566 overlap
[read
] = '\0';
1570 ptr
= strstr(ptr
, nl_boundary
);
1573 DWORD boundary_start
= start
+ ptr
- buf
;
1574 char *end
= ptr
+ boundary_len
+ 4;
1576 if(*end
== '\0' || *(end
+ 1) == '\0')
1579 if(*end
== '\r' && *(end
+ 1) == '\n')
1583 cur_body
->offsets
.cbBodyEnd
= boundary_start
;
1584 list_add_tail(body_offsets
, &cur_body
->entry
);
1586 cur_body
= HeapAlloc(GetProcessHeap(), 0, sizeof(*cur_body
));
1587 cur_body
->offsets
.cbBoundaryStart
= boundary_start
+ 2; /* doesn't including the leading \r\n */
1588 cur_body
->offsets
.cbHeaderStart
= boundary_start
+ boundary_len
+ 6;
1590 else if(*end
== '-' && *(end
+ 1) == '-')
1594 cur_body
->offsets
.cbBodyEnd
= boundary_start
;
1595 list_add_tail(body_offsets
, &cur_body
->entry
);
1603 if(overlap
== buf
) /* 1st iteration */
1605 memcpy(buf
, buf
+ PARSER_BUF_SIZE
- overlap_no
, overlap_no
);
1606 overlap
= buf
+ overlap_no
;
1607 start
+= read
- overlap_no
;
1611 memcpy(buf
, buf
+ PARSER_BUF_SIZE
, overlap_no
);
1617 HeapFree(GetProcessHeap(), 0, nl_boundary
);
1618 HeapFree(GetProcessHeap(), 0, buf
);
1622 static body_t
*create_sub_body(MimeMessage
*msg
, IStream
*pStm
, BODYOFFSETS
*offset
, body_t
*parent
)
1624 IMimeBody
*mime_body
;
1630 MimeBody_create(NULL
, (void**)&mime_body
);
1631 IMimeBody_Load(mime_body
, pStm
);
1633 hr
= IStream_Seek(pStm
, zero
, STREAM_SEEK_CUR
, &cur
);
1634 offset
->cbBodyStart
= cur
.u
.LowPart
+ offset
->cbHeaderStart
;
1635 if(parent
) MimeBody_set_offsets(impl_from_IMimeBody(mime_body
), offset
);
1636 IMimeBody_SetData(mime_body
, IET_BINARY
, NULL
, NULL
, &IID_IStream
, pStm
);
1637 body
= new_body_entry(mime_body
, msg
->next_index
++, parent
);
1639 if(IMimeBody_IsContentType(mime_body
, "multipart", NULL
) == S_OK
)
1641 MIMEPARAMINFO
*param_info
;
1643 IMimeAllocator
*alloc
;
1645 hr
= IMimeBody_GetParameters(mime_body
, "Content-Type", &count
, ¶m_info
);
1646 if(hr
!= S_OK
|| count
== 0) return body
;
1648 MimeOleGetAllocator(&alloc
);
1650 for(i
= 0; i
< count
; i
++)
1652 if(!strcasecmp(param_info
[i
].pszName
, "boundary"))
1654 struct list offset_list
;
1655 offset_entry_t
*cur
, *cursor2
;
1656 hr
= create_body_offset_list(pStm
, param_info
[i
].pszData
, &offset_list
);
1657 LIST_FOR_EACH_ENTRY_SAFE(cur
, cursor2
, &offset_list
, offset_entry_t
, entry
)
1660 IStream
*sub_stream
;
1661 ULARGE_INTEGER start
, length
;
1663 start
.QuadPart
= cur
->offsets
.cbHeaderStart
;
1664 length
.QuadPart
= cur
->offsets
.cbBodyEnd
- cur
->offsets
.cbHeaderStart
;
1665 create_sub_stream(pStm
, start
, length
, &sub_stream
);
1666 sub_body
= create_sub_body(msg
, sub_stream
, &cur
->offsets
, body
);
1667 IStream_Release(sub_stream
);
1668 list_add_tail(&body
->children
, &sub_body
->entry
);
1669 list_remove(&cur
->entry
);
1670 HeapFree(GetProcessHeap(), 0, cur
);
1675 IMimeAllocator_FreeParamInfoArray(alloc
, count
, param_info
, TRUE
);
1676 IMimeAllocator_Release(alloc
);
1681 static HRESULT WINAPI
MimeMessage_Load(
1682 IMimeMessage
*iface
,
1685 MimeMessage
*This
= (MimeMessage
*)iface
;
1687 BODYOFFSETS offsets
;
1691 TRACE("(%p)->(%p)\n", iface
, pStm
);
1695 FIXME("already loaded a message\n");
1699 IStream_AddRef(pStm
);
1700 This
->stream
= pStm
;
1701 offsets
.cbBoundaryStart
= offsets
.cbHeaderStart
= 0;
1702 offsets
.cbBodyStart
= offsets
.cbBodyEnd
= 0;
1704 root_body
= create_sub_body(This
, pStm
, &offsets
, NULL
);
1707 IStream_Seek(pStm
, zero
, STREAM_SEEK_END
, &cur
);
1708 offsets
.cbBodyEnd
= cur
.u
.LowPart
;
1709 MimeBody_set_offsets(impl_from_IMimeBody(root_body
->mime_body
), &offsets
);
1711 list_add_head(&This
->body_tree
, &root_body
->entry
);
1716 static HRESULT WINAPI
MimeMessage_Save(
1717 IMimeMessage
*iface
,
1721 FIXME("(%p)->(%p, %s)\n", iface
, pStm
, fClearDirty
? "TRUE" : "FALSE");
1725 static HRESULT WINAPI
MimeMessage_GetSizeMax(
1726 IMimeMessage
*iface
,
1727 ULARGE_INTEGER
*pcbSize
)
1729 FIXME("(%p)->(%p)\n", iface
, pcbSize
);
1733 static HRESULT WINAPI
MimeMessage_InitNew(
1734 IMimeMessage
*iface
)
1736 FIXME("(%p)->()\n", iface
);
1740 /*** IMimeMessageTree methods ***/
1741 static HRESULT WINAPI
MimeMessage_GetMessageSource(
1742 IMimeMessage
*iface
,
1746 MimeMessage
*This
= (MimeMessage
*)iface
;
1747 FIXME("(%p)->(%p, 0x%x)\n", iface
, ppStream
, dwFlags
);
1749 IStream_AddRef(This
->stream
);
1750 *ppStream
= This
->stream
;
1754 static HRESULT WINAPI
MimeMessage_GetMessageSize(
1755 IMimeMessage
*iface
,
1759 FIXME("(%p)->(%p, 0x%x)\n", iface
, pcbSize
, dwFlags
);
1763 static HRESULT WINAPI
MimeMessage_LoadOffsetTable(
1764 IMimeMessage
*iface
,
1767 FIXME("(%p)->(%p)\n", iface
, pStream
);
1771 static HRESULT WINAPI
MimeMessage_SaveOffsetTable(
1772 IMimeMessage
*iface
,
1776 FIXME("(%p)->(%p, 0x%x)\n", iface
, pStream
, dwFlags
);
1781 static HRESULT WINAPI
MimeMessage_GetFlags(
1782 IMimeMessage
*iface
,
1785 FIXME("(%p)->(%p)\n", iface
, pdwFlags
);
1789 static HRESULT WINAPI
MimeMessage_Commit(
1790 IMimeMessage
*iface
,
1793 FIXME("(%p)->(0x%x)\n", iface
, dwFlags
);
1798 static HRESULT WINAPI
MimeMessage_HandsOffStorage(
1799 IMimeMessage
*iface
)
1801 FIXME("(%p)->()\n", iface
);
1805 static HRESULT
find_body(struct list
*list
, HBODY hbody
, body_t
**body
)
1810 if(hbody
== HBODY_ROOT
)
1812 *body
= LIST_ENTRY(list_head(list
), body_t
, entry
);
1816 LIST_FOR_EACH_ENTRY(cur
, list
, body_t
, entry
)
1818 if(cur
->index
== HandleToUlong(hbody
))
1823 hr
= find_body(&cur
->children
, hbody
, body
);
1824 if(hr
== S_OK
) return S_OK
;
1829 static HRESULT WINAPI
MimeMessage_BindToObject(
1830 IMimeMessage
*iface
,
1835 MimeMessage
*This
= (MimeMessage
*)iface
;
1839 TRACE("(%p)->(%p, %s, %p)\n", iface
, hBody
, debugstr_guid(riid
), ppvObject
);
1841 hr
= find_body(&This
->body_tree
, hBody
, &body
);
1843 if(hr
!= S_OK
) return hr
;
1845 if(IsEqualIID(riid
, &IID_IMimeBody
))
1847 IMimeBody_AddRef(body
->mime_body
);
1848 *ppvObject
= body
->mime_body
;
1852 return E_NOINTERFACE
;
1855 static HRESULT WINAPI
MimeMessage_SaveBody(
1856 IMimeMessage
*iface
,
1861 FIXME("(%p)->(%p, 0x%x, %p)\n", iface
, hBody
, dwFlags
, pStream
);
1865 static HRESULT
get_body(MimeMessage
*msg
, BODYLOCATION location
, HBODY pivot
, body_t
**out
)
1867 body_t
*root
= LIST_ENTRY(list_head(&msg
->body_tree
), body_t
, entry
);
1872 if(location
== IBL_ROOT
)
1878 hr
= find_body(&msg
->body_tree
, pivot
, &body
);
1885 *out
= body
->parent
;
1889 list
= list_head(&body
->children
);
1891 *out
= LIST_ENTRY(list
, body_t
, entry
);
1893 hr
= MIME_E_NOT_FOUND
;
1897 list
= list_tail(&body
->children
);
1899 *out
= LIST_ENTRY(list
, body_t
, entry
);
1901 hr
= MIME_E_NOT_FOUND
;
1905 list
= list_next(&body
->parent
->children
, &body
->entry
);
1907 *out
= LIST_ENTRY(list
, body_t
, entry
);
1909 hr
= MIME_E_NOT_FOUND
;
1913 list
= list_prev(&body
->parent
->children
, &body
->entry
);
1915 *out
= LIST_ENTRY(list
, body_t
, entry
);
1917 hr
= MIME_E_NOT_FOUND
;
1930 static HRESULT WINAPI
MimeMessage_InsertBody(
1931 IMimeMessage
*iface
,
1932 BODYLOCATION location
,
1936 FIXME("(%p)->(%d, %p, %p)\n", iface
, location
, hPivot
, phBody
);
1940 static HRESULT WINAPI
MimeMessage_GetBody(
1941 IMimeMessage
*iface
,
1942 BODYLOCATION location
,
1946 MimeMessage
*This
= (MimeMessage
*)iface
;
1950 TRACE("(%p)->(%d, %p, %p)\n", iface
, location
, hPivot
, phBody
);
1952 hr
= get_body(This
, location
, hPivot
, &body
);
1954 if(hr
== S_OK
) *phBody
= UlongToHandle(body
->index
);
1959 static HRESULT WINAPI
MimeMessage_DeleteBody(
1960 IMimeMessage
*iface
,
1964 FIXME("(%p)->(%p, %08x)\n", iface
, hBody
, dwFlags
);
1968 static HRESULT WINAPI
MimeMessage_MoveBody(
1969 IMimeMessage
*iface
,
1971 BODYLOCATION location
)
1973 FIXME("(%p)->(%d)\n", iface
, location
);
1977 static void count_children(body_t
*body
, boolean recurse
, ULONG
*count
)
1981 LIST_FOR_EACH_ENTRY(child
, &body
->children
, body_t
, entry
)
1984 if(recurse
) count_children(child
, recurse
, count
);
1988 static HRESULT WINAPI
MimeMessage_CountBodies(
1989 IMimeMessage
*iface
,
1995 MimeMessage
*This
= (MimeMessage
*)iface
;
1998 TRACE("(%p)->(%p, %s, %p)\n", iface
, hParent
, fRecurse
? "TRUE" : "FALSE", pcBodies
);
2000 hr
= find_body(&This
->body_tree
, hParent
, &body
);
2001 if(hr
!= S_OK
) return hr
;
2004 count_children(body
, fRecurse
, pcBodies
);
2009 static HRESULT
find_next(IMimeMessage
*msg
, body_t
*body
, LPFINDBODY find
, HBODY
*out
)
2011 MimeMessage
*This
= (MimeMessage
*)msg
;
2017 if (!body
) ptr
= list_head( &This
->body_tree
);
2020 ptr
= list_head( &body
->children
);
2023 if (!body
->parent
) return MIME_E_NOT_FOUND
;
2024 if (!(ptr
= list_next( &body
->parent
->children
, &body
->entry
))) body
= body
->parent
;
2028 body
= LIST_ENTRY( ptr
, body_t
, entry
);
2029 next
= UlongToHandle( body
->index
);
2030 find
->dwReserved
= body
->index
;
2031 if (IMimeBody_IsContentType(body
->mime_body
, find
->pszPriType
, find
->pszSubType
) == S_OK
)
2037 return MIME_E_NOT_FOUND
;
2040 static HRESULT WINAPI
MimeMessage_FindFirst(
2041 IMimeMessage
*iface
,
2042 LPFINDBODY pFindBody
,
2045 TRACE("(%p)->(%p, %p)\n", iface
, pFindBody
, phBody
);
2047 pFindBody
->dwReserved
= 0;
2048 return find_next( iface
, NULL
, pFindBody
, phBody
);
2051 static HRESULT WINAPI
MimeMessage_FindNext(
2052 IMimeMessage
*iface
,
2053 LPFINDBODY pFindBody
,
2056 MimeMessage
*This
= (MimeMessage
*)iface
;
2060 TRACE("(%p)->(%p, %p)\n", iface
, pFindBody
, phBody
);
2062 hr
= find_body( &This
->body_tree
, UlongToHandle( pFindBody
->dwReserved
), &body
);
2063 if (hr
!= S_OK
) return MIME_E_NOT_FOUND
;
2064 return find_next( iface
, body
, pFindBody
, phBody
);
2067 static HRESULT WINAPI
MimeMessage_ResolveURL(
2068 IMimeMessage
*iface
,
2075 FIXME("(%p)->(%p, %s, %s, 0x%x, %p)\n", iface
, hRelated
, pszBase
, pszURL
, dwFlags
, phBody
);
2079 static HRESULT WINAPI
MimeMessage_ToMultipart(
2080 IMimeMessage
*iface
,
2083 LPHBODY phMultipart
)
2085 FIXME("(%p)->(%p, %s, %p)\n", iface
, hBody
, pszSubType
, phMultipart
);
2089 static HRESULT WINAPI
MimeMessage_GetBodyOffsets(
2090 IMimeMessage
*iface
,
2092 LPBODYOFFSETS pOffsets
)
2094 FIXME("(%p)->(%p, %p)\n", iface
, hBody
, pOffsets
);
2098 static HRESULT WINAPI
MimeMessage_GetCharset(
2099 IMimeMessage
*iface
,
2100 LPHCHARSET phCharset
)
2102 FIXME("(%p)->(%p)\n", iface
, phCharset
);
2107 static HRESULT WINAPI
MimeMessage_SetCharset(
2108 IMimeMessage
*iface
,
2110 CSETAPPLYTYPE applytype
)
2112 FIXME("(%p)->(%p, %d)\n", iface
, hCharset
, applytype
);
2116 static HRESULT WINAPI
MimeMessage_IsBodyType(
2117 IMimeMessage
*iface
,
2119 IMSGBODYTYPE bodytype
)
2122 IMimeBody
*mime_body
;
2123 TRACE("(%p)->(%p, %d)\n", iface
, hBody
, bodytype
);
2125 hr
= IMimeMessage_BindToObject(iface
, hBody
, &IID_IMimeBody
, (void**)&mime_body
);
2126 if(hr
!= S_OK
) return hr
;
2128 hr
= IMimeBody_IsType(mime_body
, bodytype
);
2129 MimeBody_Release(mime_body
);
2133 static HRESULT WINAPI
MimeMessage_IsContentType(
2134 IMimeMessage
*iface
,
2140 IMimeBody
*mime_body
;
2141 TRACE("(%p)->(%p, %s, %s)\n", iface
, hBody
, debugstr_a(pszPriType
),
2142 debugstr_a(pszSubType
));
2144 hr
= IMimeMessage_BindToObject(iface
, hBody
, &IID_IMimeBody
, (void**)&mime_body
);
2145 if(FAILED(hr
)) return hr
;
2147 hr
= IMimeBody_IsContentType(mime_body
, pszPriType
, pszSubType
);
2148 IMimeBody_Release(mime_body
);
2152 static HRESULT WINAPI
MimeMessage_QueryBodyProp(
2153 IMimeMessage
*iface
,
2158 boolean fCaseSensitive
)
2160 FIXME("(%p)->(%p, %s, %s, %s, %s)\n", iface
, hBody
, pszName
, pszCriteria
, fSubString
? "TRUE" : "FALSE", fCaseSensitive
? "TRUE" : "FALSE");
2164 static HRESULT WINAPI
MimeMessage_GetBodyProp(
2165 IMimeMessage
*iface
,
2169 LPPROPVARIANT pValue
)
2172 IMimeBody
*mime_body
;
2174 TRACE("(%p)->(%p, %s, 0x%x, %p)\n", iface
, hBody
, pszName
, dwFlags
, pValue
);
2176 hr
= IMimeMessage_BindToObject(iface
, hBody
, &IID_IMimeBody
, (void**)&mime_body
);
2177 if(hr
!= S_OK
) return hr
;
2179 hr
= IMimeBody_GetProp(mime_body
, pszName
, dwFlags
, pValue
);
2180 IMimeBody_Release(mime_body
);
2185 static HRESULT WINAPI
MimeMessage_SetBodyProp(
2186 IMimeMessage
*iface
,
2190 LPCPROPVARIANT pValue
)
2192 FIXME("(%p)->(%p, %s, 0x%x, %p)\n", iface
, hBody
, pszName
, dwFlags
, pValue
);
2196 static HRESULT WINAPI
MimeMessage_DeleteBodyProp(
2197 IMimeMessage
*iface
,
2201 FIXME("(%p)->(%p, %s)\n", iface
, hBody
, pszName
);
2205 static HRESULT WINAPI
MimeMessage_SetOption(
2206 IMimeMessage
*iface
,
2208 LPCPROPVARIANT pValue
)
2210 HRESULT hr
= E_NOTIMPL
;
2211 TRACE("(%p)->(%08x, %p)\n", iface
, oid
, pValue
);
2213 if(pValue
->vt
!= TYPEDID_TYPE(oid
))
2215 WARN("Called with vartype %04x and oid %08x\n", pValue
->vt
, oid
);
2216 return E_INVALIDARG
;
2221 case OID_HIDE_TNEF_ATTACHMENTS
:
2222 FIXME("OID_HIDE_TNEF_ATTACHMENTS (value %d): ignoring\n", pValue
->u
.boolVal
);
2225 case OID_SHOW_MACBINARY
:
2226 FIXME("OID_SHOW_MACBINARY (value %d): ignoring\n", pValue
->u
.boolVal
);
2230 FIXME("Unhandled oid %08x\n", oid
);
2236 static HRESULT WINAPI
MimeMessage_GetOption(
2237 IMimeMessage
*iface
,
2239 LPPROPVARIANT pValue
)
2241 FIXME("(%p)->(%08x, %p)\n", iface
, oid
, pValue
);
2245 /*** IMimeMessage methods ***/
2246 static HRESULT WINAPI
MimeMessage_CreateWebPage(
2247 IMimeMessage
*iface
,
2249 LPWEBPAGEOPTIONS pOptions
,
2250 IMimeMessageCallback
*pCallback
,
2251 IMoniker
**ppMoniker
)
2253 FIXME("(%p)->(%p, %p, %p, %p)\n", iface
, pRootStm
, pOptions
, pCallback
, ppMoniker
);
2258 static HRESULT WINAPI
MimeMessage_GetProp(
2259 IMimeMessage
*iface
,
2262 LPPROPVARIANT pValue
)
2264 FIXME("(%p)->(%s, 0x%x, %p)\n", iface
, pszName
, dwFlags
, pValue
);
2268 static HRESULT WINAPI
MimeMessage_SetProp(
2269 IMimeMessage
*iface
,
2272 LPCPROPVARIANT pValue
)
2274 FIXME("(%p)->(%s, 0x%x, %p)\n", iface
, pszName
, dwFlags
, pValue
);
2278 static HRESULT WINAPI
MimeMessage_DeleteProp(
2279 IMimeMessage
*iface
,
2282 FIXME("(%p)->(%s)\n", iface
, pszName
);
2286 static HRESULT WINAPI
MimeMessage_QueryProp(
2287 IMimeMessage
*iface
,
2291 boolean fCaseSensitive
)
2293 FIXME("(%p)->(%s, %s, %s, %s)\n", iface
, pszName
, pszCriteria
, fSubString
? "TRUE" : "FALSE", fCaseSensitive
? "TRUE" : "FALSE");
2297 static HRESULT WINAPI
MimeMessage_GetTextBody(
2298 IMimeMessage
*iface
,
2300 ENCODINGTYPE ietEncoding
,
2306 FINDBODY find_struct
;
2307 IMimeBody
*mime_body
;
2308 static char text
[] = "text";
2309 static char plain
[] = "plain";
2310 static char html
[] = "html";
2312 TRACE("(%p)->(%d, %d, %p, %p)\n", iface
, dwTxtType
, ietEncoding
, pStream
, phBody
);
2314 find_struct
.pszPriType
= text
;
2319 find_struct
.pszSubType
= plain
;
2322 find_struct
.pszSubType
= html
;
2325 return MIME_E_INVALID_TEXT_TYPE
;
2328 hr
= IMimeMessage_FindFirst(iface
, &find_struct
, &hbody
);
2331 TRACE("not found hr %08x\n", hr
);
2336 IMimeMessage_BindToObject(iface
, hbody
, &IID_IMimeBody
, (void**)&mime_body
);
2338 IMimeBody_GetData(mime_body
, ietEncoding
, pStream
);
2340 IMimeBody_Release(mime_body
);
2344 static HRESULT WINAPI
MimeMessage_SetTextBody(
2345 IMimeMessage
*iface
,
2347 ENCODINGTYPE ietEncoding
,
2352 FIXME("(%p)->(%d, %d, %p, %p, %p)\n", iface
, dwTxtType
, ietEncoding
, hAlternative
, pStream
, phBody
);
2356 static HRESULT WINAPI
MimeMessage_AttachObject(
2357 IMimeMessage
*iface
,
2362 FIXME("(%p)->(%s, %p, %p)\n", iface
, debugstr_guid(riid
), pvObject
, phBody
);
2366 static HRESULT WINAPI
MimeMessage_AttachFile(
2367 IMimeMessage
*iface
,
2372 FIXME("(%p)->(%s, %p, %p)\n", iface
, pszFilePath
, pstmFile
, phBody
);
2376 static HRESULT WINAPI
MimeMessage_AttachURL(
2377 IMimeMessage
*iface
,
2385 FIXME("(%p)->(%s, %s, 0x%x, %p, %p, %p)\n", iface
, pszBase
, pszURL
, dwFlags
, pstmURL
, ppszCIDURL
, phBody
);
2389 static HRESULT WINAPI
MimeMessage_GetAttachments(
2390 IMimeMessage
*iface
,
2392 LPHBODY
*pprghAttach
)
2395 FINDBODY find_struct
;
2400 TRACE("(%p)->(%p, %p)\n", iface
, pcAttach
, pprghAttach
);
2403 array
= CoTaskMemAlloc(size
* sizeof(HBODY
));
2405 find_struct
.pszPriType
= find_struct
.pszSubType
= NULL
;
2406 hr
= IMimeMessage_FindFirst(iface
, &find_struct
, &hbody
);
2409 hr
= IMimeMessage_IsContentType(iface
, hbody
, "multipart", NULL
);
2410 TRACE("IsCT rets %08x %d\n", hr
, *pcAttach
);
2413 if(*pcAttach
+ 1 > size
)
2416 array
= CoTaskMemRealloc(array
, size
* sizeof(HBODY
));
2418 array
[*pcAttach
] = hbody
;
2421 hr
= IMimeMessage_FindNext(iface
, &find_struct
, &hbody
);
2424 *pprghAttach
= array
;
2428 static HRESULT WINAPI
MimeMessage_GetAddressTable(
2429 IMimeMessage
*iface
,
2430 IMimeAddressTable
**ppTable
)
2432 FIXME("(%p)->(%p)\n", iface
, ppTable
);
2436 static HRESULT WINAPI
MimeMessage_GetSender(
2437 IMimeMessage
*iface
,
2438 LPADDRESSPROPS pAddress
)
2440 FIXME("(%p)->(%p)\n", iface
, pAddress
);
2444 static HRESULT WINAPI
MimeMessage_GetAddressTypes(
2445 IMimeMessage
*iface
,
2448 LPADDRESSLIST pList
)
2450 FIXME("(%p)->(%d, %d, %p)\n", iface
, dwAdrTypes
, dwProps
, pList
);
2454 static HRESULT WINAPI
MimeMessage_GetAddressFormat(
2455 IMimeMessage
*iface
,
2457 ADDRESSFORMAT format
,
2460 FIXME("(%p)->(%d, %d, %p)\n", iface
, dwAdrTypes
, format
, ppszFormat
);
2464 static HRESULT WINAPI
MimeMessage_EnumAddressTypes(
2465 IMimeMessage
*iface
,
2468 IMimeEnumAddressTypes
**ppEnum
)
2470 FIXME("(%p)->(%d, %d, %p)\n", iface
, dwAdrTypes
, dwProps
, ppEnum
);
2474 static HRESULT WINAPI
MimeMessage_SplitMessage(
2475 IMimeMessage
*iface
,
2477 IMimeMessageParts
**ppParts
)
2479 FIXME("(%p)->(%d, %p)\n", iface
, cbMaxPart
, ppParts
);
2483 static HRESULT WINAPI
MimeMessage_GetRootMoniker(
2484 IMimeMessage
*iface
,
2485 IMoniker
**ppMoniker
)
2487 FIXME("(%p)->(%p)\n", iface
, ppMoniker
);
2491 static const IMimeMessageVtbl MimeMessageVtbl
=
2493 MimeMessage_QueryInterface
,
2495 MimeMessage_Release
,
2496 MimeMessage_GetClassID
,
2497 MimeMessage_IsDirty
,
2500 MimeMessage_GetSizeMax
,
2501 MimeMessage_InitNew
,
2502 MimeMessage_GetMessageSource
,
2503 MimeMessage_GetMessageSize
,
2504 MimeMessage_LoadOffsetTable
,
2505 MimeMessage_SaveOffsetTable
,
2506 MimeMessage_GetFlags
,
2508 MimeMessage_HandsOffStorage
,
2509 MimeMessage_BindToObject
,
2510 MimeMessage_SaveBody
,
2511 MimeMessage_InsertBody
,
2512 MimeMessage_GetBody
,
2513 MimeMessage_DeleteBody
,
2514 MimeMessage_MoveBody
,
2515 MimeMessage_CountBodies
,
2516 MimeMessage_FindFirst
,
2517 MimeMessage_FindNext
,
2518 MimeMessage_ResolveURL
,
2519 MimeMessage_ToMultipart
,
2520 MimeMessage_GetBodyOffsets
,
2521 MimeMessage_GetCharset
,
2522 MimeMessage_SetCharset
,
2523 MimeMessage_IsBodyType
,
2524 MimeMessage_IsContentType
,
2525 MimeMessage_QueryBodyProp
,
2526 MimeMessage_GetBodyProp
,
2527 MimeMessage_SetBodyProp
,
2528 MimeMessage_DeleteBodyProp
,
2529 MimeMessage_SetOption
,
2530 MimeMessage_GetOption
,
2531 MimeMessage_CreateWebPage
,
2532 MimeMessage_GetProp
,
2533 MimeMessage_SetProp
,
2534 MimeMessage_DeleteProp
,
2535 MimeMessage_QueryProp
,
2536 MimeMessage_GetTextBody
,
2537 MimeMessage_SetTextBody
,
2538 MimeMessage_AttachObject
,
2539 MimeMessage_AttachFile
,
2540 MimeMessage_AttachURL
,
2541 MimeMessage_GetAttachments
,
2542 MimeMessage_GetAddressTable
,
2543 MimeMessage_GetSender
,
2544 MimeMessage_GetAddressTypes
,
2545 MimeMessage_GetAddressFormat
,
2546 MimeMessage_EnumAddressTypes
,
2547 MimeMessage_SplitMessage
,
2548 MimeMessage_GetRootMoniker
,
2551 HRESULT
MimeMessage_create(IUnknown
*outer
, void **obj
)
2555 TRACE("(%p, %p)\n", outer
, obj
);
2559 FIXME("outer unknown not supported yet\n");
2565 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
2566 if (!This
) return E_OUTOFMEMORY
;
2568 This
->lpVtbl
= &MimeMessageVtbl
;
2570 This
->stream
= NULL
;
2571 list_init(&This
->body_tree
);
2572 This
->next_index
= 1;
2574 *obj
= &This
->lpVtbl
;
2578 /***********************************************************************
2579 * MimeOleCreateMessage (INETCOMM.@)
2581 HRESULT WINAPI
MimeOleCreateMessage(IUnknown
*pUnkOuter
, IMimeMessage
**ppMessage
)
2583 TRACE("(%p, %p)\n", pUnkOuter
, ppMessage
);
2584 return MimeMessage_create(NULL
, (void **)ppMessage
);
2587 /***********************************************************************
2588 * MimeOleSetCompatMode (INETCOMM.@)
2590 HRESULT WINAPI
MimeOleSetCompatMode(DWORD dwMode
)
2592 FIXME("(0x%x)\n", dwMode
);
2596 /***********************************************************************
2597 * MimeOleCreateVirtualStream (INETCOMM.@)
2599 HRESULT WINAPI
MimeOleCreateVirtualStream(IStream
**ppStream
)
2602 FIXME("(%p)\n", ppStream
);
2604 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, ppStream
);
2608 typedef struct MimeSecurity
2610 const IMimeSecurityVtbl
*lpVtbl
;
2615 static HRESULT WINAPI
MimeSecurity_QueryInterface(
2616 IMimeSecurity
* iface
,
2620 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), obj
);
2622 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2623 IsEqualIID(riid
, &IID_IMimeSecurity
))
2626 IUnknown_AddRef(iface
);
2630 FIXME("no interface for %s\n", debugstr_guid(riid
));
2632 return E_NOINTERFACE
;
2635 static ULONG WINAPI
MimeSecurity_AddRef(
2636 IMimeSecurity
* iface
)
2638 MimeSecurity
*This
= (MimeSecurity
*)iface
;
2639 TRACE("(%p)->()\n", iface
);
2640 return InterlockedIncrement(&This
->refs
);
2643 static ULONG WINAPI
MimeSecurity_Release(
2644 IMimeSecurity
* iface
)
2646 MimeSecurity
*This
= (MimeSecurity
*)iface
;
2649 TRACE("(%p)->()\n", iface
);
2651 refs
= InterlockedDecrement(&This
->refs
);
2654 HeapFree(GetProcessHeap(), 0, This
);
2660 static HRESULT WINAPI
MimeSecurity_InitNew(
2661 IMimeSecurity
* iface
)
2663 FIXME("(%p)->(): stub\n", iface
);
2667 static HRESULT WINAPI
MimeSecurity_CheckInit(
2668 IMimeSecurity
* iface
)
2670 FIXME("(%p)->(): stub\n", iface
);
2674 static HRESULT WINAPI
MimeSecurity_EncodeMessage(
2675 IMimeSecurity
* iface
,
2676 IMimeMessageTree
* pTree
,
2679 FIXME("(%p)->(%p, %08x): stub\n", iface
, pTree
, dwFlags
);
2683 static HRESULT WINAPI
MimeSecurity_EncodeBody(
2684 IMimeSecurity
* iface
,
2685 IMimeMessageTree
* pTree
,
2689 FIXME("(%p)->(%p, %p, %08x): stub\n", iface
, pTree
, hEncodeRoot
, dwFlags
);
2693 static HRESULT WINAPI
MimeSecurity_DecodeMessage(
2694 IMimeSecurity
* iface
,
2695 IMimeMessageTree
* pTree
,
2698 FIXME("(%p)->(%p, %08x): stub\n", iface
, pTree
, dwFlags
);
2702 static HRESULT WINAPI
MimeSecurity_DecodeBody(
2703 IMimeSecurity
* iface
,
2704 IMimeMessageTree
* pTree
,
2708 FIXME("(%p)->(%p, %p, %08x): stub\n", iface
, pTree
, hDecodeRoot
, dwFlags
);
2712 static HRESULT WINAPI
MimeSecurity_EnumCertificates(
2713 IMimeSecurity
* iface
,
2719 FIXME("(%p)->(%p, %08x, %p, %p): stub\n", iface
, hc
, dwUsage
, pPrev
, ppCert
);
2723 static HRESULT WINAPI
MimeSecurity_GetCertificateName(
2724 IMimeSecurity
* iface
,
2725 const PCX509CERT pX509Cert
,
2726 const CERTNAMETYPE cn
,
2729 FIXME("(%p)->(%p, %08x, %p): stub\n", iface
, pX509Cert
, cn
, ppszName
);
2733 static HRESULT WINAPI
MimeSecurity_GetMessageType(
2734 IMimeSecurity
* iface
,
2735 const HWND hwndParent
,
2739 FIXME("(%p)->(%p, %p, %p): stub\n", iface
, hwndParent
, pBody
, pdwSecType
);
2743 static HRESULT WINAPI
MimeSecurity_GetCertData(
2744 IMimeSecurity
* iface
,
2745 const PCX509CERT pX509Cert
,
2746 const CERTDATAID dataid
,
2747 LPPROPVARIANT pValue
)
2749 FIXME("(%p)->(%p, %x, %p): stub\n", iface
, pX509Cert
, dataid
, pValue
);
2754 static const IMimeSecurityVtbl MimeSecurityVtbl
=
2756 MimeSecurity_QueryInterface
,
2757 MimeSecurity_AddRef
,
2758 MimeSecurity_Release
,
2759 MimeSecurity_InitNew
,
2760 MimeSecurity_CheckInit
,
2761 MimeSecurity_EncodeMessage
,
2762 MimeSecurity_EncodeBody
,
2763 MimeSecurity_DecodeMessage
,
2764 MimeSecurity_DecodeBody
,
2765 MimeSecurity_EnumCertificates
,
2766 MimeSecurity_GetCertificateName
,
2767 MimeSecurity_GetMessageType
,
2768 MimeSecurity_GetCertData
2771 HRESULT
MimeSecurity_create(IUnknown
*outer
, void **obj
)
2777 if (outer
) return CLASS_E_NOAGGREGATION
;
2779 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
2780 if (!This
) return E_OUTOFMEMORY
;
2782 This
->lpVtbl
= &MimeSecurityVtbl
;
2785 *obj
= &This
->lpVtbl
;
2789 /***********************************************************************
2790 * MimeOleCreateSecurity (INETCOMM.@)
2792 HRESULT WINAPI
MimeOleCreateSecurity(IMimeSecurity
**ppSecurity
)
2794 return MimeSecurity_create(NULL
, (void **)ppSecurity
);
2799 IMimeAllocatorVtbl
*lpVtbl
;
2802 static HRESULT WINAPI
MimeAlloc_QueryInterface(
2803 IMimeAllocator
* iface
,
2807 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), obj
);
2809 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2810 IsEqualIID(riid
, &IID_IMalloc
) ||
2811 IsEqualIID(riid
, &IID_IMimeAllocator
))
2814 IUnknown_AddRef(iface
);
2818 FIXME("no interface for %s\n", debugstr_guid(riid
));
2820 return E_NOINTERFACE
;
2823 static ULONG WINAPI
MimeAlloc_AddRef(
2824 IMimeAllocator
* iface
)
2829 static ULONG WINAPI
MimeAlloc_Release(
2830 IMimeAllocator
* iface
)
2835 static LPVOID WINAPI
MimeAlloc_Alloc(
2836 IMimeAllocator
* iface
,
2839 return CoTaskMemAlloc(cb
);
2842 static LPVOID WINAPI
MimeAlloc_Realloc(
2843 IMimeAllocator
* iface
,
2847 return CoTaskMemRealloc(pv
, cb
);
2850 static void WINAPI
MimeAlloc_Free(
2851 IMimeAllocator
* iface
,
2857 static ULONG WINAPI
MimeAlloc_GetSize(
2858 IMimeAllocator
* iface
,
2865 static int WINAPI
MimeAlloc_DidAlloc(
2866 IMimeAllocator
* iface
,
2873 static void WINAPI
MimeAlloc_HeapMinimize(
2874 IMimeAllocator
* iface
)
2880 static HRESULT WINAPI
MimeAlloc_FreeParamInfoArray(
2881 IMimeAllocator
* iface
,
2883 LPMIMEPARAMINFO prgParam
,
2887 TRACE("(%p)->(%d, %p, %d)\n", iface
, cParams
, prgParam
, fFreeArray
);
2889 for(i
= 0; i
< cParams
; i
++)
2891 IMimeAllocator_Free(iface
, prgParam
[i
].pszName
);
2892 IMimeAllocator_Free(iface
, prgParam
[i
].pszData
);
2894 if(fFreeArray
) IMimeAllocator_Free(iface
, prgParam
);
2898 static HRESULT WINAPI
MimeAlloc_FreeAddressList(
2899 IMimeAllocator
* iface
,
2900 LPADDRESSLIST pList
)
2906 static HRESULT WINAPI
MimeAlloc_FreeAddressProps(
2907 IMimeAllocator
* iface
,
2908 LPADDRESSPROPS pAddress
)
2914 static HRESULT WINAPI
MimeAlloc_ReleaseObjects(
2915 IMimeAllocator
* iface
,
2917 IUnknown
**prgpUnknown
,
2925 static HRESULT WINAPI
MimeAlloc_FreeEnumHeaderRowArray(
2926 IMimeAllocator
* iface
,
2928 LPENUMHEADERROW prgRow
,
2935 static HRESULT WINAPI
MimeAlloc_FreeEnumPropertyArray(
2936 IMimeAllocator
* iface
,
2938 LPENUMPROPERTY prgProp
,
2945 static HRESULT WINAPI
MimeAlloc_FreeThumbprint(
2946 IMimeAllocator
* iface
,
2947 THUMBBLOB
*pthumbprint
)
2954 static HRESULT WINAPI
MimeAlloc_PropVariantClear(
2955 IMimeAllocator
* iface
,
2956 LPPROPVARIANT pProp
)
2962 static IMimeAllocatorVtbl mime_alloc_vtbl
=
2964 MimeAlloc_QueryInterface
,
2972 MimeAlloc_HeapMinimize
,
2973 MimeAlloc_FreeParamInfoArray
,
2974 MimeAlloc_FreeAddressList
,
2975 MimeAlloc_FreeAddressProps
,
2976 MimeAlloc_ReleaseObjects
,
2977 MimeAlloc_FreeEnumHeaderRowArray
,
2978 MimeAlloc_FreeEnumPropertyArray
,
2979 MimeAlloc_FreeThumbprint
,
2980 MimeAlloc_PropVariantClear
2983 static MimeAllocator mime_allocator
=
2988 HRESULT
MimeAllocator_create(IUnknown
*outer
, void **obj
)
2990 if(outer
) return CLASS_E_NOAGGREGATION
;
2992 *obj
= &mime_allocator
;
2996 HRESULT WINAPI
MimeOleGetAllocator(IMimeAllocator
**alloc
)
2998 return MimeAllocator_create(NULL
, (void**)alloc
);
3001 HRESULT
VirtualStream_create(IUnknown
*outer
, void **obj
)
3003 FIXME("(%p, %p)\n", outer
, obj
);
3006 if (outer
) return CLASS_E_NOAGGREGATION
;
3008 return MimeOleCreateVirtualStream((IStream
**)obj
);