4 * Copyright 2006 Robert Shearman for CodeWeavers
5 * Copyright 2007 Huw Davies for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define NONAMELESSUNION
34 #include "propvarutil.h"
36 #include "wine/list.h"
37 #include "wine/debug.h"
39 #include "inetcomm_private.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(inetcomm
);
47 DWORD flags
; /* MIMEPROPFLAGS */
55 } property_list_entry_t
;
57 static const property_t default_props
[] =
59 {"X-Newsgroup", PID_HDR_NEWSGROUP
, 0, VT_LPSTR
},
60 {"Newsgroups", PID_HDR_NEWSGROUPS
, 0, VT_LPSTR
},
61 {"References", PID_HDR_REFS
, 0, VT_LPSTR
},
62 {"Subject", PID_HDR_SUBJECT
, 0, VT_LPSTR
},
63 {"From", PID_HDR_FROM
, MPF_ADDRESS
, VT_LPSTR
},
64 {"Message-ID", PID_HDR_MESSAGEID
, 0, VT_LPSTR
},
65 {"Return-Path", PID_HDR_RETURNPATH
, MPF_ADDRESS
, VT_LPSTR
},
66 {"Rr", PID_HDR_RR
, 0, VT_LPSTR
},
67 {"Return-Receipt-To", PID_HDR_RETRCPTO
, MPF_ADDRESS
, VT_LPSTR
},
68 {"Apparently-To", PID_HDR_APPARTO
, MPF_ADDRESS
, VT_LPSTR
},
69 {"Date", PID_HDR_DATE
, 0, VT_LPSTR
},
70 {"Received", PID_HDR_RECEIVED
, 0, VT_LPSTR
},
71 {"Reply-To", PID_HDR_REPLYTO
, MPF_ADDRESS
, VT_LPSTR
},
72 {"X-Mailer", PID_HDR_XMAILER
, 0, VT_LPSTR
},
73 {"Bcc", PID_HDR_BCC
, MPF_ADDRESS
, VT_LPSTR
},
74 {"MIME-Version", PID_HDR_MIMEVER
, MPF_MIME
, VT_LPSTR
},
75 {"Content-Type", PID_HDR_CNTTYPE
, MPF_MIME
| MPF_HASPARAMS
, VT_LPSTR
},
76 {"Content-Transfer-Encoding", PID_HDR_CNTXFER
, MPF_MIME
, VT_LPSTR
},
77 {"Content-ID", PID_HDR_CNTID
, MPF_MIME
, VT_LPSTR
},
78 {"Content-Description", PID_HDR_CNTDESC
, MPF_MIME
, VT_LPSTR
},
79 {"Content-Disposition", PID_HDR_CNTDISP
, MPF_MIME
| MPF_HASPARAMS
, VT_LPSTR
},
80 {"Content-Base", PID_HDR_CNTBASE
, MPF_MIME
, VT_LPSTR
},
81 {"Content-Location", PID_HDR_CNTLOC
, MPF_MIME
, VT_LPSTR
},
82 {"To", PID_HDR_TO
, MPF_ADDRESS
, VT_LPSTR
},
83 {"Path", PID_HDR_PATH
, 0, VT_LPSTR
},
84 {"Followup-To", PID_HDR_FOLLOWUPTO
, 0, VT_LPSTR
},
85 {"Expires", PID_HDR_EXPIRES
, 0, VT_LPSTR
},
86 {"Cc", PID_HDR_CC
, MPF_ADDRESS
, VT_LPSTR
},
87 {"Control", PID_HDR_CONTROL
, 0, VT_LPSTR
},
88 {"Distribution", PID_HDR_DISTRIB
, 0, VT_LPSTR
},
89 {"Keywords", PID_HDR_KEYWORDS
, 0, VT_LPSTR
},
90 {"Summary", PID_HDR_SUMMARY
, 0, VT_LPSTR
},
91 {"Approved", PID_HDR_APPROVED
, 0, VT_LPSTR
},
92 {"Lines", PID_HDR_LINES
, 0, VT_LPSTR
},
93 {"Xref", PID_HDR_XREF
, 0, VT_LPSTR
},
94 {"Organization", PID_HDR_ORG
, 0, VT_LPSTR
},
95 {"X-Newsreader", PID_HDR_XNEWSRDR
, 0, VT_LPSTR
},
96 {"X-Priority", PID_HDR_XPRI
, 0, VT_LPSTR
},
97 {"X-MSMail-Priority", PID_HDR_XMSPRI
, 0, VT_LPSTR
},
98 {"par:content-disposition:filename", PID_PAR_FILENAME
, 0, VT_LPSTR
},
99 {"par:content-type:boundary", PID_PAR_BOUNDARY
, 0, VT_LPSTR
},
100 {"par:content-type:charset", PID_PAR_CHARSET
, 0, VT_LPSTR
},
101 {"par:content-type:name", PID_PAR_NAME
, 0, VT_LPSTR
},
102 {"att:filename", PID_ATT_FILENAME
, 0, VT_LPSTR
},
103 {"att:pri-content-type", PID_ATT_PRITYPE
, 0, VT_LPSTR
},
104 {"att:sub-content-type", PID_ATT_SUBTYPE
, 0, VT_LPSTR
},
105 {"att:illegal-lines", PID_ATT_ILLEGAL
, 0, VT_LPSTR
},
106 {"att:rendered", PID_ATT_RENDERED
, 0, VT_LPSTR
},
107 {"att:sent-time", PID_ATT_SENTTIME
, 0, VT_LPSTR
},
108 {"att:priority", PID_ATT_PRIORITY
, 0, VT_LPSTR
},
109 {"Comment", PID_HDR_COMMENT
, 0, VT_LPSTR
},
110 {"Encoding", PID_HDR_ENCODING
, 0, VT_LPSTR
},
111 {"Encrypted", PID_HDR_ENCRYPTED
, 0, VT_LPSTR
},
112 {"X-Offsets", PID_HDR_OFFSETS
, 0, VT_LPSTR
},
113 {"X-Unsent", PID_HDR_XUNSENT
, 0, VT_LPSTR
},
114 {"X-ArticleId", PID_HDR_ARTICLEID
, 0, VT_LPSTR
},
115 {"Sender", PID_HDR_SENDER
, MPF_ADDRESS
, VT_LPSTR
},
116 {"att:athena-server", PID_ATT_SERVER
, 0, VT_LPSTR
},
117 {"att:athena-account-id", PID_ATT_ACCOUNT
, 0, VT_LPSTR
},
118 {"att:athena-pop3-uidl", PID_ATT_UIDL
, 0, VT_LPSTR
},
119 {"att:athena-store-msgid", PID_ATT_STOREMSGID
, 0, VT_LPSTR
},
120 {"att:athena-user-name", PID_ATT_USERNAME
, 0, VT_LPSTR
},
121 {"att:athena-forward-to", PID_ATT_FORWARDTO
, 0, VT_LPSTR
},
122 {"att:athena-store-fdrid", PID_ATT_STOREFOLDERID
,0, VT_LPSTR
},
123 {"att:athena-ghosted", PID_ATT_GHOSTED
, 0, VT_LPSTR
},
124 {"att:athena-uncachedsize", PID_ATT_UNCACHEDSIZE
, 0, VT_LPSTR
},
125 {"att:athena-combined", PID_ATT_COMBINED
, 0, VT_LPSTR
},
126 {"att:auto-inlined", PID_ATT_AUTOINLINED
, 0, VT_LPSTR
},
127 {"Disposition-Notification-To", PID_HDR_DISP_NOTIFICATION_TO
, 0, VT_LPSTR
},
128 {"par:Content-Type:reply-type", PID_PAR_REPLYTYPE
, 0, VT_LPSTR
},
129 {"par:Content-Type:format", PID_PAR_FORMAT
, 0, VT_LPSTR
},
130 {"att:format", PID_ATT_FORMAT
, 0, VT_LPSTR
},
131 {"In-Reply-To", PID_HDR_INREPLYTO
, 0, VT_LPSTR
},
132 {"att:athena-account-name", PID_ATT_ACCOUNTNAME
, 0, VT_LPSTR
},
146 const property_t
*prop
;
151 typedef struct MimeBody
153 IMimeBody IMimeBody_iface
;
159 struct list new_props
; /* FIXME: This should be in a PropertySchema */
161 char *content_pri_type
;
162 char *content_sub_type
;
163 ENCODINGTYPE encoding
;
166 BODYOFFSETS body_offsets
;
169 static inline MimeBody
*impl_from_IMimeBody(IMimeBody
*iface
)
171 return CONTAINING_RECORD(iface
, MimeBody
, IMimeBody_iface
);
174 typedef struct propschema
176 IMimePropertySchema IMimePropertySchema_iface
;
180 static inline propschema
*impl_from_IMimePropertySchema(IMimePropertySchema
*iface
)
182 return CONTAINING_RECORD(iface
, propschema
, IMimePropertySchema_iface
);
185 static LPSTR
strdupA(LPCSTR str
)
188 int len
= strlen(str
);
189 ret
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
190 memcpy(ret
, str
, len
+ 1);
194 #define PARSER_BUF_SIZE 1024
196 /*****************************************************
197 * copy_headers_to_buf [internal]
199 * Copies the headers into a '\0' terminated memory block and leave
200 * the stream's current position set to after the blank line.
202 static HRESULT
copy_headers_to_buf(IStream
*stm
, char **ptr
)
205 DWORD size
= PARSER_BUF_SIZE
, offset
= 0, last_end
= 0;
217 buf
= HeapAlloc(GetProcessHeap(), 0, size
+ 1);
221 buf
= HeapReAlloc(GetProcessHeap(), 0, buf
, size
+ 1);
229 hr
= IStream_Read(stm
, buf
+ offset
, size
- offset
, &read
);
230 if(FAILED(hr
)) goto fail
;
235 if(read
== 0) done
= TRUE
;
237 while(!done
&& (end
= strstr(buf
+ last_end
, "\r\n")))
239 DWORD new_end
= end
- buf
+ 2;
240 if(new_end
- last_end
== 2)
243 off
.QuadPart
= new_end
;
244 IStream_Seek(stm
, off
, STREAM_SEEK_SET
, NULL
);
257 HeapFree(GetProcessHeap(), 0, buf
);
261 static header_t
*read_prop(MimeBody
*body
, char **ptr
)
263 char *colon
= strchr(*ptr
, ':');
264 const property_t
*prop
;
267 if(!colon
) return NULL
;
271 for(prop
= default_props
; prop
->name
; prop
++)
273 if(!lstrcmpiA(*ptr
, prop
->name
))
275 TRACE("%s: found match with default property id %d\n", *ptr
, prop
->id
);
282 property_list_entry_t
*prop_entry
;
283 LIST_FOR_EACH_ENTRY(prop_entry
, &body
->new_props
, property_list_entry_t
, entry
)
285 if(!lstrcmpiA(*ptr
, prop_entry
->prop
.name
))
287 TRACE("%s: found match with already added new property id %d\n", *ptr
, prop_entry
->prop
.id
);
288 prop
= &prop_entry
->prop
;
294 prop_entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(*prop_entry
));
295 prop_entry
->prop
.name
= strdupA(*ptr
);
296 prop_entry
->prop
.id
= body
->next_prop_id
++;
297 prop_entry
->prop
.flags
= 0;
298 prop_entry
->prop
.default_vt
= VT_LPSTR
;
299 list_add_tail(&body
->new_props
, &prop_entry
->entry
);
300 prop
= &prop_entry
->prop
;
301 TRACE("%s: allocating new prop id %d\n", *ptr
, prop_entry
->prop
.id
);
305 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ret
));
307 PropVariantInit(&ret
->value
);
308 list_init(&ret
->params
);
314 static void unfold_header(char *header
, int len
)
316 char *start
= header
, *cp
= header
;
319 while(*cp
== ' ' || *cp
== '\t')
325 memmove(start
, cp
, len
+ 1);
327 cp
= strstr(start
, "\r\n");
334 } while(*cp
== ' ' || *cp
== '\t');
339 static char *unquote_string(const char *str
)
344 while(*str
== ' ' || *str
== '\t') str
++;
352 for(cp
= ret
; *cp
; cp
++)
355 memmove(cp
, cp
+ 1, strlen(cp
+ 1) + 1);
360 WARN("quote in unquoted string\n");
372 static void add_param(header_t
*header
, const char *p
)
374 const char *key
= p
, *value
, *cp
= p
;
378 TRACE("got param %s\n", p
);
380 while (*key
== ' ' || *key
== '\t' ) key
++;
382 cp
= strchr(key
, '=');
385 WARN("malformed parameter - skipping\n");
389 name
= HeapAlloc(GetProcessHeap(), 0, cp
- key
+ 1);
390 memcpy(name
, key
, cp
- key
);
391 name
[cp
- key
] = '\0';
395 param
= HeapAlloc(GetProcessHeap(), 0, sizeof(*param
));
397 param
->value
= unquote_string(value
);
398 list_add_tail(&header
->params
, ¶m
->entry
);
401 static void split_params(header_t
*header
, char *value
)
403 char *cp
= value
, *start
= value
;
404 BOOL in_quotes
= FALSE
, done_value
= FALSE
;
408 if(!in_quotes
&& *cp
== ';')
411 if(done_value
) add_param(header
, start
);
416 in_quotes
= !in_quotes
;
419 if(done_value
) add_param(header
, start
);
422 static void read_value(header_t
*header
, char **cur
)
424 char *end
= *cur
, *value
;
428 end
= strstr(end
, "\r\n");
430 } while(*end
== ' ' || *end
== '\t');
433 value
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
434 memcpy(value
, *cur
, len
);
437 unfold_header(value
, len
);
438 TRACE("value %s\n", debugstr_a(value
));
440 if(header
->prop
->flags
& MPF_HASPARAMS
)
442 split_params(header
, value
);
443 TRACE("value w/o params %s\n", debugstr_a(value
));
446 header
->value
.vt
= VT_LPSTR
;
447 header
->value
.u
.pszVal
= value
;
452 static void init_content_type(MimeBody
*body
, header_t
*header
)
457 if(header
->prop
->id
!= PID_HDR_CNTTYPE
)
459 ERR("called with header %s\n", header
->prop
->name
);
463 slash
= strchr(header
->value
.u
.pszVal
, '/');
466 WARN("malformed context type value\n");
469 len
= slash
- header
->value
.u
.pszVal
;
470 body
->content_pri_type
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
471 memcpy(body
->content_pri_type
, header
->value
.u
.pszVal
, len
);
472 body
->content_pri_type
[len
] = '\0';
473 body
->content_sub_type
= strdupA(slash
+ 1);
476 static HRESULT
parse_headers(MimeBody
*body
, IStream
*stm
)
478 char *header_buf
, *cur_header_ptr
;
482 hr
= copy_headers_to_buf(stm
, &header_buf
);
483 if(FAILED(hr
)) return hr
;
485 cur_header_ptr
= header_buf
;
486 while((header
= read_prop(body
, &cur_header_ptr
)))
488 read_value(header
, &cur_header_ptr
);
489 list_add_tail(&body
->headers
, &header
->entry
);
491 if(header
->prop
->id
== PID_HDR_CNTTYPE
)
492 init_content_type(body
, header
);
495 HeapFree(GetProcessHeap(), 0, header_buf
);
499 static void empty_param_list(struct list
*list
)
501 param_t
*param
, *cursor2
;
503 LIST_FOR_EACH_ENTRY_SAFE(param
, cursor2
, list
, param_t
, entry
)
505 list_remove(¶m
->entry
);
506 HeapFree(GetProcessHeap(), 0, param
->name
);
507 HeapFree(GetProcessHeap(), 0, param
->value
);
508 HeapFree(GetProcessHeap(), 0, param
);
512 static void empty_header_list(struct list
*list
)
514 header_t
*header
, *cursor2
;
516 LIST_FOR_EACH_ENTRY_SAFE(header
, cursor2
, list
, header_t
, entry
)
518 list_remove(&header
->entry
);
519 PropVariantClear(&header
->value
);
520 empty_param_list(&header
->params
);
521 HeapFree(GetProcessHeap(), 0, header
);
525 static void empty_new_prop_list(struct list
*list
)
527 property_list_entry_t
*prop
, *cursor2
;
529 LIST_FOR_EACH_ENTRY_SAFE(prop
, cursor2
, list
, property_list_entry_t
, entry
)
531 list_remove(&prop
->entry
);
532 HeapFree(GetProcessHeap(), 0, (char *)prop
->prop
.name
);
533 HeapFree(GetProcessHeap(), 0, prop
);
537 static void release_data(REFIID riid
, void *data
)
541 if(IsEqualIID(riid
, &IID_IStream
))
542 IStream_Release((IStream
*)data
);
544 FIXME("Unhandled data format %s\n", debugstr_guid(riid
));
547 static HRESULT
find_prop(MimeBody
*body
, const char *name
, header_t
**prop
)
553 LIST_FOR_EACH_ENTRY(header
, &body
->headers
, header_t
, entry
)
557 if(STRTOPID(name
) == header
->prop
->id
)
563 else if(!lstrcmpiA(name
, header
->prop
->name
))
570 return MIME_E_NOT_FOUND
;
573 static const property_t
*find_default_prop(const char *name
)
575 const property_t
*prop_def
= NULL
;
577 for(prop_def
= default_props
; prop_def
->name
; prop_def
++)
581 if(STRTOPID(name
) == prop_def
->id
)
586 else if(!lstrcmpiA(name
, prop_def
->name
))
593 TRACE("%s: found match with default property id %d\n", prop_def
->name
, prop_def
->id
);
600 static HRESULT WINAPI
MimeBody_QueryInterface(IMimeBody
* iface
,
604 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppvObject
);
608 if (IsEqualIID(riid
, &IID_IUnknown
) ||
609 IsEqualIID(riid
, &IID_IPersist
) ||
610 IsEqualIID(riid
, &IID_IPersistStreamInit
) ||
611 IsEqualIID(riid
, &IID_IMimePropertySet
) ||
612 IsEqualIID(riid
, &IID_IMimeBody
))
619 IUnknown_AddRef((IUnknown
*)*ppvObject
);
623 FIXME("no interface for %s\n", debugstr_guid(riid
));
624 return E_NOINTERFACE
;
627 static ULONG WINAPI
MimeBody_AddRef(IMimeBody
*iface
)
629 MimeBody
*This
= impl_from_IMimeBody(iface
);
630 LONG ref
= InterlockedIncrement(&This
->ref
);
632 TRACE("(%p) ref=%d\n", This
, ref
);
637 static ULONG WINAPI
MimeBody_Release(IMimeBody
*iface
)
639 MimeBody
*This
= impl_from_IMimeBody(iface
);
640 LONG ref
= InterlockedDecrement(&This
->ref
);
642 TRACE("(%p) ref=%d\n", This
, ref
);
646 empty_header_list(&This
->headers
);
647 empty_new_prop_list(&This
->new_props
);
649 HeapFree(GetProcessHeap(), 0, This
->content_pri_type
);
650 HeapFree(GetProcessHeap(), 0, This
->content_sub_type
);
652 release_data(&This
->data_iid
, This
->data
);
654 HeapFree(GetProcessHeap(), 0, This
);
660 static HRESULT WINAPI
MimeBody_GetClassID(
664 MimeBody
*This
= impl_from_IMimeBody(iface
);
665 FIXME("(%p)->(%p) stub\n", This
, pClassID
);
670 static HRESULT WINAPI
MimeBody_IsDirty(
673 MimeBody
*This
= impl_from_IMimeBody(iface
);
674 FIXME("(%p)->() stub\n", This
);
678 static HRESULT WINAPI
MimeBody_Load(IMimeBody
*iface
, IStream
*pStm
)
680 MimeBody
*This
= impl_from_IMimeBody(iface
);
681 TRACE("(%p)->(%p)\n", This
, pStm
);
682 return parse_headers(This
, pStm
);
685 static HRESULT WINAPI
MimeBody_Save(IMimeBody
*iface
, IStream
*pStm
, BOOL fClearDirty
)
687 MimeBody
*This
= impl_from_IMimeBody(iface
);
688 FIXME("(%p)->(%p, %d)\n", This
, pStm
, fClearDirty
);
692 static HRESULT WINAPI
MimeBody_GetSizeMax(
694 ULARGE_INTEGER
* pcbSize
)
696 MimeBody
*This
= impl_from_IMimeBody(iface
);
697 FIXME("(%p)->(%p) stub\n", This
, pcbSize
);
701 static HRESULT WINAPI
MimeBody_InitNew(
704 MimeBody
*This
= impl_from_IMimeBody(iface
);
705 TRACE("(%p)->()\n", This
);
709 static HRESULT WINAPI
MimeBody_GetPropInfo(
712 LPMIMEPROPINFO pInfo
)
714 MimeBody
*This
= impl_from_IMimeBody(iface
);
717 DWORD supported
= PIM_PROPID
| PIM_VTDEFAULT
;
719 TRACE("(%p)->(%s, %p) semi-stub\n", This
, debugstr_a(pszName
), pInfo
);
721 if(!pszName
|| !pInfo
)
724 TRACE("mask 0x%04x\n", pInfo
->dwMask
);
726 if(pInfo
->dwMask
& ~supported
)
727 FIXME("Unsupported mask flags 0x%04x\n", pInfo
->dwMask
& ~supported
);
729 hr
= find_prop(This
, pszName
, &header
);
732 if(pInfo
->dwMask
& PIM_CHARSET
)
734 if(pInfo
->dwMask
& PIM_FLAGS
)
735 pInfo
->dwFlags
= 0x00000000;
736 if(pInfo
->dwMask
& PIM_ROWNUMBER
)
737 pInfo
->dwRowNumber
= 0;
738 if(pInfo
->dwMask
& PIM_ENCODINGTYPE
)
739 pInfo
->ietEncoding
= 0;
740 if(pInfo
->dwMask
& PIM_VALUES
)
742 if(pInfo
->dwMask
& PIM_PROPID
)
743 pInfo
->dwPropId
= header
->prop
->id
;
744 if(pInfo
->dwMask
& PIM_VTDEFAULT
)
745 pInfo
->vtDefault
= header
->prop
->default_vt
;
746 if(pInfo
->dwMask
& PIM_VTCURRENT
)
747 pInfo
->vtCurrent
= 0;
753 static HRESULT WINAPI
MimeBody_SetPropInfo(
756 LPCMIMEPROPINFO pInfo
)
758 MimeBody
*This
= impl_from_IMimeBody(iface
);
759 FIXME("(%p)->(%s, %p) stub\n", This
, debugstr_a(pszName
), pInfo
);
763 static HRESULT WINAPI
MimeBody_GetProp(
767 LPPROPVARIANT pValue
)
769 MimeBody
*This
= impl_from_IMimeBody(iface
);
773 TRACE("(%p)->(%s, 0x%x, %p)\n", This
, debugstr_a(pszName
), dwFlags
, pValue
);
775 if(!pszName
|| !pValue
)
778 if(!ISPIDSTR(pszName
) && !lstrcmpiA(pszName
, "att:pri-content-type"))
780 PropVariantClear(pValue
);
781 pValue
->vt
= VT_LPSTR
;
782 pValue
->u
.pszVal
= strdupA(This
->content_pri_type
);
786 hr
= find_prop(This
, pszName
, &header
);
789 TRACE("type %d->%d\n", header
->value
.vt
, pValue
->vt
);
791 hr
= PropVariantChangeType(pValue
, &header
->value
, 0, pValue
->vt
);
793 FIXME("Conversion not currently supported (%d->%d)\n", header
->value
.vt
, pValue
->vt
);
799 static HRESULT WINAPI
MimeBody_SetProp(
803 LPCPROPVARIANT pValue
)
805 MimeBody
*This
= impl_from_IMimeBody(iface
);
809 TRACE("(%p)->(%s, 0x%x, %p)\n", This
, debugstr_a(pszName
), dwFlags
, pValue
);
811 if(!pszName
|| !pValue
)
814 hr
= find_prop(This
, pszName
, &header
);
817 property_list_entry_t
*prop_entry
;
818 const property_t
*prop
= NULL
;
820 LIST_FOR_EACH_ENTRY(prop_entry
, &This
->new_props
, property_list_entry_t
, entry
)
822 if(ISPIDSTR(pszName
))
824 if(STRTOPID(pszName
) == prop_entry
->prop
.id
)
826 TRACE("Found match with already added new property id %d\n", prop_entry
->prop
.id
);
827 prop
= &prop_entry
->prop
;
831 else if(!lstrcmpiA(pszName
, prop_entry
->prop
.name
))
833 TRACE("Found match with already added new property id %d\n", prop_entry
->prop
.id
);
834 prop
= &prop_entry
->prop
;
839 header
= HeapAlloc(GetProcessHeap(), 0, sizeof(*header
));
841 return E_OUTOFMEMORY
;
845 const property_t
*prop_def
= NULL
;
846 prop_entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(*prop_entry
));
849 HeapFree(GetProcessHeap(), 0, header
);
850 return E_OUTOFMEMORY
;
853 prop_def
= find_default_prop(pszName
);
856 prop_entry
->prop
.name
= strdupA(prop_def
->name
);
857 prop_entry
->prop
.id
= prop_def
->id
;
861 if(ISPIDSTR(pszName
))
863 HeapFree(GetProcessHeap(), 0, prop_entry
);
864 HeapFree(GetProcessHeap(), 0, header
);
865 return MIME_E_NOT_FOUND
;
868 prop_entry
->prop
.name
= strdupA(pszName
);
869 prop_entry
->prop
.id
= This
->next_prop_id
++;
872 prop_entry
->prop
.flags
= 0;
873 prop_entry
->prop
.default_vt
= pValue
->vt
;
874 list_add_tail(&This
->new_props
, &prop_entry
->entry
);
875 prop
= &prop_entry
->prop
;
876 TRACE("Allocating new prop id %d\n", prop_entry
->prop
.id
);
880 PropVariantInit(&header
->value
);
881 list_init(&header
->params
);
882 list_add_tail(&This
->headers
, &header
->entry
);
885 PropVariantCopy(&header
->value
, pValue
);
890 static HRESULT WINAPI
MimeBody_AppendProp(
894 LPPROPVARIANT pValue
)
896 MimeBody
*This
= impl_from_IMimeBody(iface
);
897 FIXME("(%p)->(%s, 0x%x, %p) stub\n", This
, debugstr_a(pszName
), dwFlags
, pValue
);
901 static HRESULT WINAPI
MimeBody_DeleteProp(
905 MimeBody
*This
= impl_from_IMimeBody(iface
);
909 TRACE("(%p)->(%s) stub\n", This
, debugstr_a(pszName
));
911 LIST_FOR_EACH_ENTRY(cursor
, &This
->headers
, header_t
, entry
)
913 if(ISPIDSTR(pszName
))
914 found
= STRTOPID(pszName
) == cursor
->prop
->id
;
916 found
= !lstrcmpiA(pszName
, cursor
->prop
->name
);
920 list_remove(&cursor
->entry
);
921 HeapFree(GetProcessHeap(), 0, cursor
);
926 return MIME_E_NOT_FOUND
;
929 static HRESULT WINAPI
MimeBody_CopyProps(
933 IMimePropertySet
* pPropertySet
)
935 MimeBody
*This
= impl_from_IMimeBody(iface
);
936 FIXME("(%p)->(%d, %p, %p) stub\n", This
, cNames
, prgszName
, pPropertySet
);
940 static HRESULT WINAPI
MimeBody_MoveProps(
944 IMimePropertySet
* pPropertySet
)
946 MimeBody
*This
= impl_from_IMimeBody(iface
);
947 FIXME("(%p)->(%d, %p, %p) stub\n", This
, cNames
, prgszName
, pPropertySet
);
951 static HRESULT WINAPI
MimeBody_DeleteExcept(
956 MimeBody
*This
= impl_from_IMimeBody(iface
);
957 FIXME("(%p)->(%d, %p) stub\n", This
, cNames
, prgszName
);
961 static HRESULT WINAPI
MimeBody_QueryProp(
966 boolean fCaseSensitive
)
968 MimeBody
*This
= impl_from_IMimeBody(iface
);
969 FIXME("(%p)->(%s, %s, %d, %d) stub\n", This
, debugstr_a(pszName
), debugstr_a(pszCriteria
), fSubString
, fCaseSensitive
);
973 static HRESULT WINAPI
MimeBody_GetCharset(
975 LPHCHARSET phCharset
)
977 MimeBody
*This
= impl_from_IMimeBody(iface
);
978 FIXME("(%p)->(%p) stub\n", This
, phCharset
);
983 static HRESULT WINAPI
MimeBody_SetCharset(
986 CSETAPPLYTYPE applytype
)
988 MimeBody
*This
= impl_from_IMimeBody(iface
);
989 FIXME("(%p)->(%p, %d) stub\n", This
, hCharset
, applytype
);
993 static HRESULT WINAPI
MimeBody_GetParameters(
997 LPMIMEPARAMINFO
* pprgParam
)
999 MimeBody
*This
= impl_from_IMimeBody(iface
);
1003 TRACE("(%p)->(%s, %p, %p)\n", iface
, debugstr_a(pszName
), pcParams
, pprgParam
);
1008 hr
= find_prop(This
, pszName
, &header
);
1009 if(hr
!= S_OK
) return hr
;
1011 *pcParams
= list_count(&header
->params
);
1014 IMimeAllocator
*alloc
;
1016 MIMEPARAMINFO
*info
;
1018 MimeOleGetAllocator(&alloc
);
1020 *pprgParam
= info
= IMimeAllocator_Alloc(alloc
, *pcParams
* sizeof(**pprgParam
));
1021 LIST_FOR_EACH_ENTRY(param
, &header
->params
, param_t
, entry
)
1025 len
= strlen(param
->name
) + 1;
1026 info
->pszName
= IMimeAllocator_Alloc(alloc
, len
);
1027 memcpy(info
->pszName
, param
->name
, len
);
1028 len
= strlen(param
->value
) + 1;
1029 info
->pszData
= IMimeAllocator_Alloc(alloc
, len
);
1030 memcpy(info
->pszData
, param
->value
, len
);
1033 IMimeAllocator_Release(alloc
);
1038 static HRESULT WINAPI
MimeBody_IsContentType(
1043 MimeBody
*This
= impl_from_IMimeBody(iface
);
1045 TRACE("(%p)->(%s, %s)\n", This
, debugstr_a(pszPriType
), debugstr_a(pszSubType
));
1048 const char *pri
= This
->content_pri_type
;
1049 if(!pri
) pri
= "text";
1050 if(lstrcmpiA(pri
, pszPriType
)) return S_FALSE
;
1055 const char *sub
= This
->content_sub_type
;
1056 if(!sub
) sub
= "plain";
1057 if(lstrcmpiA(sub
, pszSubType
)) return S_FALSE
;
1063 static HRESULT WINAPI
MimeBody_BindToObject(
1068 MimeBody
*This
= impl_from_IMimeBody(iface
);
1069 FIXME("(%p)->(%s, %p) stub\n", This
, debugstr_guid(riid
), ppvObject
);
1073 static HRESULT WINAPI
MimeBody_Clone(
1075 IMimePropertySet
** ppPropertySet
)
1077 MimeBody
*This
= impl_from_IMimeBody(iface
);
1078 FIXME("(%p)->(%p) stub\n", This
, ppPropertySet
);
1082 static HRESULT WINAPI
MimeBody_SetOption(
1085 LPCPROPVARIANT pValue
)
1087 MimeBody
*This
= impl_from_IMimeBody(iface
);
1088 HRESULT hr
= E_NOTIMPL
;
1089 TRACE("(%p)->(%08x, %p)\n", This
, oid
, pValue
);
1091 if(pValue
->vt
!= TYPEDID_TYPE(oid
))
1093 WARN("Called with vartype %04x and oid %08x\n", pValue
->vt
, oid
);
1094 return E_INVALIDARG
;
1099 case OID_SECURITY_HWND_OWNER
:
1100 FIXME("OID_SECURITY_HWND_OWNER (value %08x): ignoring\n", pValue
->u
.ulVal
);
1103 case OID_TRANSMIT_BODY_ENCODING
:
1104 FIXME("OID_TRANSMIT_BODY_ENCODING (value %08x): ignoring\n", pValue
->u
.ulVal
);
1108 FIXME("Unhandled oid %08x\n", oid
);
1114 static HRESULT WINAPI
MimeBody_GetOption(
1117 LPPROPVARIANT pValue
)
1119 MimeBody
*This
= impl_from_IMimeBody(iface
);
1120 FIXME("(%p)->(%08x, %p): stub\n", This
, oid
, pValue
);
1124 static HRESULT WINAPI
MimeBody_EnumProps(
1127 IMimeEnumProperties
** ppEnum
)
1129 MimeBody
*This
= impl_from_IMimeBody(iface
);
1130 FIXME("(%p)->(0x%x, %p) stub\n", This
, dwFlags
, ppEnum
);
1134 static HRESULT WINAPI
MimeBody_IsType(
1136 IMSGBODYTYPE bodytype
)
1138 MimeBody
*This
= impl_from_IMimeBody(iface
);
1140 TRACE("(%p)->(%d)\n", This
, bodytype
);
1144 return This
->data
? S_FALSE
: S_OK
;
1146 FIXME("Unimplemented bodytype %d - returning S_OK\n", bodytype
);
1151 static HRESULT WINAPI
MimeBody_SetDisplayName(
1155 MimeBody
*This
= impl_from_IMimeBody(iface
);
1156 FIXME("(%p)->(%s) stub\n", This
, debugstr_a(pszDisplay
));
1160 static HRESULT WINAPI
MimeBody_GetDisplayName(
1164 MimeBody
*This
= impl_from_IMimeBody(iface
);
1165 FIXME("(%p)->(%p) stub\n", This
, ppszDisplay
);
1169 static HRESULT WINAPI
MimeBody_GetOffsets(
1171 LPBODYOFFSETS pOffsets
)
1173 MimeBody
*This
= impl_from_IMimeBody(iface
);
1174 TRACE("(%p)->(%p)\n", This
, pOffsets
);
1176 *pOffsets
= This
->body_offsets
;
1178 if(This
->body_offsets
.cbBodyEnd
== 0) return MIME_E_NO_DATA
;
1182 static HRESULT WINAPI
MimeBody_GetCurrentEncoding(
1184 ENCODINGTYPE
* pietEncoding
)
1186 MimeBody
*This
= impl_from_IMimeBody(iface
);
1188 TRACE("(%p)->(%p)\n", This
, pietEncoding
);
1190 *pietEncoding
= This
->encoding
;
1194 static HRESULT WINAPI
MimeBody_SetCurrentEncoding(
1196 ENCODINGTYPE ietEncoding
)
1198 MimeBody
*This
= impl_from_IMimeBody(iface
);
1200 TRACE("(%p)->(%d)\n", This
, ietEncoding
);
1202 This
->encoding
= ietEncoding
;
1206 static HRESULT WINAPI
MimeBody_GetEstimatedSize(
1208 ENCODINGTYPE ietEncoding
,
1211 MimeBody
*This
= impl_from_IMimeBody(iface
);
1212 FIXME("(%p)->(%d, %p) stub\n", This
, ietEncoding
, pcbSize
);
1216 static HRESULT WINAPI
MimeBody_GetDataHere(
1218 ENCODINGTYPE ietEncoding
,
1221 MimeBody
*This
= impl_from_IMimeBody(iface
);
1222 FIXME("(%p)->(%d, %p) stub\n", This
, ietEncoding
, pStream
);
1226 static HRESULT WINAPI
MimeBody_GetData(
1228 ENCODINGTYPE ietEncoding
,
1231 MimeBody
*This
= impl_from_IMimeBody(iface
);
1232 FIXME("(%p)->(%d, %p). Ignoring encoding type.\n", This
, ietEncoding
, ppStream
);
1234 *ppStream
= This
->data
;
1235 IStream_AddRef(*ppStream
);
1239 static HRESULT WINAPI
MimeBody_SetData(
1241 ENCODINGTYPE ietEncoding
,
1247 MimeBody
*This
= impl_from_IMimeBody(iface
);
1248 TRACE("(%p)->(%d, %s, %s, %s %p)\n", This
, ietEncoding
, debugstr_a(pszPriType
), debugstr_a(pszSubType
),
1249 debugstr_guid(riid
), pvObject
);
1251 if(IsEqualIID(riid
, &IID_IStream
))
1252 IStream_AddRef((IStream
*)pvObject
);
1255 FIXME("Unhandled object type %s\n", debugstr_guid(riid
));
1256 return E_INVALIDARG
;
1260 FIXME("release old data\n");
1262 This
->data_iid
= *riid
;
1263 This
->data
= pvObject
;
1265 IMimeBody_SetCurrentEncoding(iface
, ietEncoding
);
1267 /* FIXME: Update the content type.
1268 If pszPriType == NULL use 'application'
1269 If pszSubType == NULL use 'octet-stream' */
1274 static HRESULT WINAPI
MimeBody_EmptyData(
1277 MimeBody
*This
= impl_from_IMimeBody(iface
);
1278 FIXME("(%p)->() stub\n", This
);
1282 static HRESULT WINAPI
MimeBody_CopyTo(
1286 MimeBody
*This
= impl_from_IMimeBody(iface
);
1287 FIXME("(%p)->(%p) stub\n", This
, pBody
);
1291 static HRESULT WINAPI
MimeBody_GetTransmitInfo(
1293 LPTRANSMITINFO pTransmitInfo
)
1295 MimeBody
*This
= impl_from_IMimeBody(iface
);
1296 FIXME("(%p)->(%p) stub\n", This
, pTransmitInfo
);
1300 static HRESULT WINAPI
MimeBody_SaveToFile(
1302 ENCODINGTYPE ietEncoding
,
1305 MimeBody
*This
= impl_from_IMimeBody(iface
);
1306 FIXME("(%p)->(%d, %s) stub\n", This
, ietEncoding
, debugstr_a(pszFilePath
));
1310 static HRESULT WINAPI
MimeBody_GetHandle(
1314 MimeBody
*This
= impl_from_IMimeBody(iface
);
1315 TRACE("(%p)->(%p)\n", iface
, phBody
);
1318 return E_INVALIDARG
;
1320 *phBody
= This
->handle
;
1321 return This
->handle
? S_OK
: MIME_E_NO_DATA
;
1324 static IMimeBodyVtbl body_vtbl
=
1326 MimeBody_QueryInterface
,
1329 MimeBody_GetClassID
,
1333 MimeBody_GetSizeMax
,
1335 MimeBody_GetPropInfo
,
1336 MimeBody_SetPropInfo
,
1339 MimeBody_AppendProp
,
1340 MimeBody_DeleteProp
,
1343 MimeBody_DeleteExcept
,
1345 MimeBody_GetCharset
,
1346 MimeBody_SetCharset
,
1347 MimeBody_GetParameters
,
1348 MimeBody_IsContentType
,
1349 MimeBody_BindToObject
,
1355 MimeBody_SetDisplayName
,
1356 MimeBody_GetDisplayName
,
1357 MimeBody_GetOffsets
,
1358 MimeBody_GetCurrentEncoding
,
1359 MimeBody_SetCurrentEncoding
,
1360 MimeBody_GetEstimatedSize
,
1361 MimeBody_GetDataHere
,
1366 MimeBody_GetTransmitInfo
,
1367 MimeBody_SaveToFile
,
1371 static HRESULT
MimeBody_set_offsets(MimeBody
*body
, const BODYOFFSETS
*offsets
)
1373 TRACE("setting offsets to %d, %d, %d, %d\n", offsets
->cbBoundaryStart
,
1374 offsets
->cbHeaderStart
, offsets
->cbBodyStart
, offsets
->cbBodyEnd
);
1376 body
->body_offsets
= *offsets
;
1380 #define FIRST_CUSTOM_PROP_ID 0x100
1382 static MimeBody
*mimebody_create(void)
1385 BODYOFFSETS body_offsets
;
1387 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1391 This
->IMimeBody_iface
.lpVtbl
= &body_vtbl
;
1393 This
->handle
= NULL
;
1394 list_init(&This
->headers
);
1395 list_init(&This
->new_props
);
1396 This
->next_prop_id
= FIRST_CUSTOM_PROP_ID
;
1397 This
->content_pri_type
= NULL
;
1398 This
->content_sub_type
= NULL
;
1399 This
->encoding
= IET_7BIT
;
1401 This
->data_iid
= IID_NULL
;
1403 body_offsets
.cbBoundaryStart
= body_offsets
.cbHeaderStart
= 0;
1404 body_offsets
.cbBodyStart
= body_offsets
.cbBodyEnd
= 0;
1405 MimeBody_set_offsets(This
, &body_offsets
);
1410 HRESULT
MimeBody_create(IUnknown
*outer
, void **ppv
)
1415 return CLASS_E_NOAGGREGATION
;
1417 if ((mb
= mimebody_create()))
1419 *ppv
= &mb
->IMimeBody_iface
;
1425 return E_OUTOFMEMORY
;
1433 IStream IStream_iface
;
1436 ULARGE_INTEGER pos
, start
, length
;
1439 static inline sub_stream_t
*impl_from_IStream(IStream
*iface
)
1441 return CONTAINING_RECORD(iface
, sub_stream_t
, IStream_iface
);
1444 static HRESULT WINAPI
sub_stream_QueryInterface(IStream
*iface
, REFIID riid
, void **ppv
)
1446 sub_stream_t
*This
= impl_from_IStream(iface
);
1448 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
1451 if(IsEqualIID(riid
, &IID_IUnknown
) ||
1452 IsEqualIID(riid
, &IID_ISequentialStream
) ||
1453 IsEqualIID(riid
, &IID_IStream
))
1455 IStream_AddRef(iface
);
1459 return E_NOINTERFACE
;
1462 static ULONG WINAPI
sub_stream_AddRef(IStream
*iface
)
1464 sub_stream_t
*This
= impl_from_IStream(iface
);
1465 LONG ref
= InterlockedIncrement(&This
->ref
);
1467 TRACE("(%p) ref=%d\n", This
, ref
);
1472 static ULONG WINAPI
sub_stream_Release(IStream
*iface
)
1474 sub_stream_t
*This
= impl_from_IStream(iface
);
1475 LONG ref
= InterlockedDecrement(&This
->ref
);
1477 TRACE("(%p) ref=%d\n", This
, ref
);
1481 IStream_Release(This
->base
);
1482 HeapFree(GetProcessHeap(), 0, This
);
1487 static HRESULT WINAPI
sub_stream_Read(
1493 sub_stream_t
*This
= impl_from_IStream(iface
);
1495 ULARGE_INTEGER base_pos
;
1496 LARGE_INTEGER tmp_pos
;
1498 TRACE("(%p, %d, %p)\n", pv
, cb
, pcbRead
);
1500 tmp_pos
.QuadPart
= 0;
1501 IStream_Seek(This
->base
, tmp_pos
, STREAM_SEEK_CUR
, &base_pos
);
1502 tmp_pos
.QuadPart
= This
->pos
.QuadPart
+ This
->start
.QuadPart
;
1503 IStream_Seek(This
->base
, tmp_pos
, STREAM_SEEK_SET
, NULL
);
1505 if(This
->pos
.QuadPart
+ cb
> This
->length
.QuadPart
)
1506 cb
= This
->length
.QuadPart
- This
->pos
.QuadPart
;
1508 hr
= IStream_Read(This
->base
, pv
, cb
, pcbRead
);
1510 This
->pos
.QuadPart
+= *pcbRead
;
1512 tmp_pos
.QuadPart
= base_pos
.QuadPart
;
1513 IStream_Seek(This
->base
, tmp_pos
, STREAM_SEEK_SET
, NULL
);
1518 static HRESULT WINAPI
sub_stream_Write(
1528 static HRESULT WINAPI
sub_stream_Seek(
1530 LARGE_INTEGER dlibMove
,
1532 ULARGE_INTEGER
*plibNewPosition
)
1534 sub_stream_t
*This
= impl_from_IStream(iface
);
1535 LARGE_INTEGER new_pos
;
1537 TRACE("(%08x.%08x, %x, %p)\n", dlibMove
.u
.HighPart
, dlibMove
.u
.LowPart
, dwOrigin
, plibNewPosition
);
1541 case STREAM_SEEK_SET
:
1544 case STREAM_SEEK_CUR
:
1545 new_pos
.QuadPart
= This
->pos
.QuadPart
+ dlibMove
.QuadPart
;
1547 case STREAM_SEEK_END
:
1548 new_pos
.QuadPart
= This
->length
.QuadPart
+ dlibMove
.QuadPart
;
1551 return STG_E_INVALIDFUNCTION
;
1554 if(new_pos
.QuadPart
< 0) new_pos
.QuadPart
= 0;
1555 else if(new_pos
.QuadPart
> This
->length
.QuadPart
) new_pos
.QuadPart
= This
->length
.QuadPart
;
1557 This
->pos
.QuadPart
= new_pos
.QuadPart
;
1559 if(plibNewPosition
) *plibNewPosition
= This
->pos
;
1563 static HRESULT WINAPI
sub_stream_SetSize(
1565 ULARGE_INTEGER libNewSize
)
1571 static HRESULT WINAPI
sub_stream_CopyTo(
1575 ULARGE_INTEGER
*pcbRead
,
1576 ULARGE_INTEGER
*pcbWritten
)
1579 BYTE tmpBuffer
[128];
1580 ULONG bytesRead
, bytesWritten
, copySize
;
1581 ULARGE_INTEGER totalBytesRead
;
1582 ULARGE_INTEGER totalBytesWritten
;
1584 TRACE("(%p)->(%p, %d, %p, %p)\n", iface
, pstm
, cb
.u
.LowPart
, pcbRead
, pcbWritten
);
1586 totalBytesRead
.QuadPart
= 0;
1587 totalBytesWritten
.QuadPart
= 0;
1589 while ( cb
.QuadPart
> 0 )
1591 if ( cb
.QuadPart
>= sizeof(tmpBuffer
) )
1592 copySize
= sizeof(tmpBuffer
);
1594 copySize
= cb
.u
.LowPart
;
1596 hr
= IStream_Read(iface
, tmpBuffer
, copySize
, &bytesRead
);
1597 if (FAILED(hr
)) break;
1599 totalBytesRead
.QuadPart
+= bytesRead
;
1603 hr
= IStream_Write(pstm
, tmpBuffer
, bytesRead
, &bytesWritten
);
1604 if (FAILED(hr
)) break;
1605 totalBytesWritten
.QuadPart
+= bytesWritten
;
1608 if (bytesRead
!= copySize
)
1611 cb
.QuadPart
-= bytesRead
;
1614 if (pcbRead
) pcbRead
->QuadPart
= totalBytesRead
.QuadPart
;
1615 if (pcbWritten
) pcbWritten
->QuadPart
= totalBytesWritten
.QuadPart
;
1620 static HRESULT WINAPI
sub_stream_Commit(
1622 DWORD grfCommitFlags
)
1628 static HRESULT WINAPI
sub_stream_Revert(
1635 static HRESULT WINAPI
sub_stream_LockRegion(
1637 ULARGE_INTEGER libOffset
,
1645 static HRESULT WINAPI
sub_stream_UnlockRegion(
1647 ULARGE_INTEGER libOffset
,
1655 static HRESULT WINAPI
sub_stream_Stat(
1660 sub_stream_t
*This
= impl_from_IStream(iface
);
1661 FIXME("(%p)->(%p, %08x)\n", This
, pstatstg
, grfStatFlag
);
1662 memset(pstatstg
, 0, sizeof(*pstatstg
));
1663 pstatstg
->cbSize
= This
->length
;
1667 static HRESULT WINAPI
sub_stream_Clone(
1675 static struct IStreamVtbl sub_stream_vtbl
=
1677 sub_stream_QueryInterface
,
1687 sub_stream_LockRegion
,
1688 sub_stream_UnlockRegion
,
1693 static HRESULT
create_sub_stream(IStream
*stream
, ULARGE_INTEGER start
, ULARGE_INTEGER length
, IStream
**out
)
1698 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1699 if(!This
) return E_OUTOFMEMORY
;
1701 This
->IStream_iface
.lpVtbl
= &sub_stream_vtbl
;
1703 This
->start
= start
;
1704 This
->length
= length
;
1705 This
->pos
.QuadPart
= 0;
1706 IStream_AddRef(stream
);
1707 This
->base
= stream
;
1709 *out
= &This
->IStream_iface
;
1714 typedef struct body_t
1718 MimeBody
*mime_body
;
1720 struct body_t
*parent
;
1721 struct list children
;
1724 typedef struct MimeMessage
1726 IMimeMessage IMimeMessage_iface
;
1730 struct list body_tree
;
1734 static inline MimeMessage
*impl_from_IMimeMessage(IMimeMessage
*iface
)
1736 return CONTAINING_RECORD(iface
, MimeMessage
, IMimeMessage_iface
);
1739 static HRESULT WINAPI
MimeMessage_QueryInterface(IMimeMessage
*iface
, REFIID riid
, void **ppv
)
1741 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
1743 if (IsEqualIID(riid
, &IID_IUnknown
) ||
1744 IsEqualIID(riid
, &IID_IPersist
) ||
1745 IsEqualIID(riid
, &IID_IPersistStreamInit
) ||
1746 IsEqualIID(riid
, &IID_IMimeMessageTree
) ||
1747 IsEqualIID(riid
, &IID_IMimeMessage
))
1750 IMimeMessage_AddRef(iface
);
1754 FIXME("no interface for %s\n", debugstr_guid(riid
));
1756 return E_NOINTERFACE
;
1759 static ULONG WINAPI
MimeMessage_AddRef(IMimeMessage
*iface
)
1761 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
1762 ULONG ref
= InterlockedIncrement(&This
->ref
);
1764 TRACE("(%p) ref=%d\n", This
, ref
);
1769 static void empty_body_list(struct list
*list
)
1771 body_t
*body
, *cursor2
;
1772 LIST_FOR_EACH_ENTRY_SAFE(body
, cursor2
, list
, body_t
, entry
)
1774 empty_body_list(&body
->children
);
1775 list_remove(&body
->entry
);
1776 IMimeBody_Release(&body
->mime_body
->IMimeBody_iface
);
1777 HeapFree(GetProcessHeap(), 0, body
);
1781 static ULONG WINAPI
MimeMessage_Release(IMimeMessage
*iface
)
1783 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
1784 ULONG ref
= InterlockedDecrement(&This
->ref
);
1786 TRACE("(%p) ref=%d\n", This
, ref
);
1790 empty_body_list(&This
->body_tree
);
1792 if(This
->stream
) IStream_Release(This
->stream
);
1793 HeapFree(GetProcessHeap(), 0, This
);
1799 /*** IPersist methods ***/
1800 static HRESULT WINAPI
MimeMessage_GetClassID(
1801 IMimeMessage
*iface
,
1804 FIXME("(%p)->(%p)\n", iface
, pClassID
);
1808 /*** IPersistStreamInit methods ***/
1809 static HRESULT WINAPI
MimeMessage_IsDirty(
1810 IMimeMessage
*iface
)
1812 FIXME("(%p)->()\n", iface
);
1816 static body_t
*new_body_entry(MimeBody
*mime_body
, DWORD index
, body_t
*parent
)
1818 body_t
*body
= HeapAlloc(GetProcessHeap(), 0, sizeof(*body
));
1821 body
->mime_body
= mime_body
;
1822 body
->index
= index
;
1823 list_init(&body
->children
);
1824 body
->parent
= parent
;
1826 mime_body
->handle
= UlongToHandle(body
->index
);
1834 BODYOFFSETS offsets
;
1837 static HRESULT
create_body_offset_list(IStream
*stm
, const char *boundary
, struct list
*body_offsets
)
1841 int boundary_len
= strlen(boundary
);
1842 char *buf
, *nl_boundary
, *ptr
, *overlap
;
1843 DWORD start
= 0, overlap_no
;
1844 offset_entry_t
*cur_body
= NULL
;
1848 list_init(body_offsets
);
1849 nl_boundary
= HeapAlloc(GetProcessHeap(), 0, 4 + boundary_len
+ 1);
1850 memcpy(nl_boundary
, "\r\n--", 4);
1851 memcpy(nl_boundary
+ 4, boundary
, boundary_len
+ 1);
1853 overlap_no
= boundary_len
+ 5;
1855 overlap
= buf
= HeapAlloc(GetProcessHeap(), 0, overlap_no
+ PARSER_BUF_SIZE
+ 1);
1858 hr
= IStream_Seek(stm
, zero
, STREAM_SEEK_CUR
, &cur
);
1859 start
= cur
.u
.LowPart
;
1862 hr
= IStream_Read(stm
, overlap
, PARSER_BUF_SIZE
, &read
);
1863 if(FAILED(hr
)) goto end
;
1864 if(read
== 0) break;
1865 overlap
[read
] = '\0';
1869 ptr
= strstr(ptr
, nl_boundary
);
1872 DWORD boundary_start
= start
+ ptr
- buf
;
1873 char *end
= ptr
+ boundary_len
+ 4;
1875 if(*end
== '\0' || *(end
+ 1) == '\0')
1878 if(*end
== '\r' && *(end
+ 1) == '\n')
1882 cur_body
->offsets
.cbBodyEnd
= boundary_start
;
1883 list_add_tail(body_offsets
, &cur_body
->entry
);
1885 cur_body
= HeapAlloc(GetProcessHeap(), 0, sizeof(*cur_body
));
1886 cur_body
->offsets
.cbBoundaryStart
= boundary_start
+ 2; /* doesn't including the leading \r\n */
1887 cur_body
->offsets
.cbHeaderStart
= boundary_start
+ boundary_len
+ 6;
1889 else if(*end
== '-' && *(end
+ 1) == '-')
1893 cur_body
->offsets
.cbBodyEnd
= boundary_start
;
1894 list_add_tail(body_offsets
, &cur_body
->entry
);
1902 if(overlap
== buf
) /* 1st iteration */
1904 memmove(buf
, buf
+ PARSER_BUF_SIZE
- overlap_no
, overlap_no
);
1905 overlap
= buf
+ overlap_no
;
1906 start
+= read
- overlap_no
;
1910 memmove(buf
, buf
+ PARSER_BUF_SIZE
, overlap_no
);
1916 HeapFree(GetProcessHeap(), 0, nl_boundary
);
1917 HeapFree(GetProcessHeap(), 0, buf
);
1921 static body_t
*create_sub_body(MimeMessage
*msg
, IStream
*pStm
, BODYOFFSETS
*offset
, body_t
*parent
)
1923 MimeBody
*mime_body
;
1929 mime_body
= mimebody_create();
1930 IMimeBody_Load(&mime_body
->IMimeBody_iface
, pStm
);
1932 hr
= IStream_Seek(pStm
, zero
, STREAM_SEEK_CUR
, &cur
);
1933 offset
->cbBodyStart
= cur
.u
.LowPart
+ offset
->cbHeaderStart
;
1934 if (parent
) MimeBody_set_offsets(mime_body
, offset
);
1935 IMimeBody_SetData(&mime_body
->IMimeBody_iface
, IET_BINARY
, NULL
, NULL
, &IID_IStream
, pStm
);
1936 body
= new_body_entry(mime_body
, msg
->next_index
++, parent
);
1938 if(IMimeBody_IsContentType(&mime_body
->IMimeBody_iface
, "multipart", NULL
) == S_OK
)
1940 MIMEPARAMINFO
*param_info
;
1942 IMimeAllocator
*alloc
;
1944 hr
= IMimeBody_GetParameters(&mime_body
->IMimeBody_iface
, "Content-Type", &count
,
1946 if(hr
!= S_OK
|| count
== 0) return body
;
1948 MimeOleGetAllocator(&alloc
);
1950 for(i
= 0; i
< count
; i
++)
1952 if(!lstrcmpiA(param_info
[i
].pszName
, "boundary"))
1954 struct list offset_list
;
1955 offset_entry_t
*cur
, *cursor2
;
1956 hr
= create_body_offset_list(pStm
, param_info
[i
].pszData
, &offset_list
);
1957 LIST_FOR_EACH_ENTRY_SAFE(cur
, cursor2
, &offset_list
, offset_entry_t
, entry
)
1960 IStream
*sub_stream
;
1961 ULARGE_INTEGER start
, length
;
1963 start
.QuadPart
= cur
->offsets
.cbHeaderStart
;
1964 length
.QuadPart
= cur
->offsets
.cbBodyEnd
- cur
->offsets
.cbHeaderStart
;
1965 create_sub_stream(pStm
, start
, length
, &sub_stream
);
1966 sub_body
= create_sub_body(msg
, sub_stream
, &cur
->offsets
, body
);
1967 IStream_Release(sub_stream
);
1968 list_add_tail(&body
->children
, &sub_body
->entry
);
1969 list_remove(&cur
->entry
);
1970 HeapFree(GetProcessHeap(), 0, cur
);
1975 IMimeAllocator_FreeParamInfoArray(alloc
, count
, param_info
, TRUE
);
1976 IMimeAllocator_Release(alloc
);
1981 static HRESULT WINAPI
MimeMessage_Load(IMimeMessage
*iface
, IStream
*pStm
)
1983 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
1985 BODYOFFSETS offsets
;
1989 TRACE("(%p)->(%p)\n", iface
, pStm
);
1993 FIXME("already loaded a message\n");
1997 empty_body_list(&This
->body_tree
);
1999 IStream_AddRef(pStm
);
2000 This
->stream
= pStm
;
2001 offsets
.cbBoundaryStart
= offsets
.cbHeaderStart
= 0;
2002 offsets
.cbBodyStart
= offsets
.cbBodyEnd
= 0;
2004 root_body
= create_sub_body(This
, pStm
, &offsets
, NULL
);
2007 IStream_Seek(pStm
, zero
, STREAM_SEEK_END
, &cur
);
2008 offsets
.cbBodyEnd
= cur
.u
.LowPart
;
2009 MimeBody_set_offsets(root_body
->mime_body
, &offsets
);
2011 list_add_head(&This
->body_tree
, &root_body
->entry
);
2016 static HRESULT WINAPI
MimeMessage_Save(IMimeMessage
*iface
, IStream
*pStm
, BOOL fClearDirty
)
2018 FIXME("(%p)->(%p, %s)\n", iface
, pStm
, fClearDirty
? "TRUE" : "FALSE");
2022 static HRESULT WINAPI
MimeMessage_GetSizeMax(
2023 IMimeMessage
*iface
,
2024 ULARGE_INTEGER
*pcbSize
)
2026 FIXME("(%p)->(%p)\n", iface
, pcbSize
);
2030 static HRESULT WINAPI
MimeMessage_InitNew(
2031 IMimeMessage
*iface
)
2033 FIXME("(%p)->()\n", iface
);
2037 /*** IMimeMessageTree methods ***/
2038 static HRESULT WINAPI
MimeMessage_GetMessageSource(IMimeMessage
*iface
, IStream
**ppStream
,
2041 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2043 FIXME("(%p)->(%p, 0x%x)\n", iface
, ppStream
, dwFlags
);
2045 IStream_AddRef(This
->stream
);
2046 *ppStream
= This
->stream
;
2050 static HRESULT WINAPI
MimeMessage_GetMessageSize(
2051 IMimeMessage
*iface
,
2055 FIXME("(%p)->(%p, 0x%x)\n", iface
, pcbSize
, dwFlags
);
2059 static HRESULT WINAPI
MimeMessage_LoadOffsetTable(
2060 IMimeMessage
*iface
,
2063 FIXME("(%p)->(%p)\n", iface
, pStream
);
2067 static HRESULT WINAPI
MimeMessage_SaveOffsetTable(
2068 IMimeMessage
*iface
,
2072 FIXME("(%p)->(%p, 0x%x)\n", iface
, pStream
, dwFlags
);
2077 static HRESULT WINAPI
MimeMessage_GetFlags(
2078 IMimeMessage
*iface
,
2081 FIXME("(%p)->(%p)\n", iface
, pdwFlags
);
2085 static HRESULT WINAPI
MimeMessage_Commit(
2086 IMimeMessage
*iface
,
2089 FIXME("(%p)->(0x%x)\n", iface
, dwFlags
);
2094 static HRESULT WINAPI
MimeMessage_HandsOffStorage(
2095 IMimeMessage
*iface
)
2097 FIXME("(%p)->()\n", iface
);
2101 static HRESULT
find_body(struct list
*list
, HBODY hbody
, body_t
**body
)
2106 if(hbody
== HBODY_ROOT
)
2108 *body
= LIST_ENTRY(list_head(list
), body_t
, entry
);
2112 LIST_FOR_EACH_ENTRY(cur
, list
, body_t
, entry
)
2114 if(cur
->index
== HandleToUlong(hbody
))
2119 hr
= find_body(&cur
->children
, hbody
, body
);
2120 if(hr
== S_OK
) return S_OK
;
2125 static HRESULT WINAPI
MimeMessage_BindToObject(IMimeMessage
*iface
, const HBODY hBody
, REFIID riid
,
2128 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2132 TRACE("(%p)->(%p, %s, %p)\n", iface
, hBody
, debugstr_guid(riid
), ppvObject
);
2134 hr
= find_body(&This
->body_tree
, hBody
, &body
);
2136 if(hr
!= S_OK
) return hr
;
2138 if(IsEqualIID(riid
, &IID_IMimeBody
))
2140 IMimeBody_AddRef(&body
->mime_body
->IMimeBody_iface
);
2141 *ppvObject
= &body
->mime_body
->IMimeBody_iface
;
2145 return E_NOINTERFACE
;
2148 static HRESULT WINAPI
MimeMessage_SaveBody(
2149 IMimeMessage
*iface
,
2154 FIXME("(%p)->(%p, 0x%x, %p)\n", iface
, hBody
, dwFlags
, pStream
);
2158 static HRESULT
get_body(MimeMessage
*msg
, BODYLOCATION location
, HBODY pivot
, body_t
**out
)
2160 body_t
*root
= LIST_ENTRY(list_head(&msg
->body_tree
), body_t
, entry
);
2165 if(location
== IBL_ROOT
)
2171 hr
= find_body(&msg
->body_tree
, pivot
, &body
);
2179 *out
= body
->parent
;
2181 hr
= MIME_E_NOT_FOUND
;
2185 list
= list_head(&body
->children
);
2187 *out
= LIST_ENTRY(list
, body_t
, entry
);
2189 hr
= MIME_E_NOT_FOUND
;
2193 list
= list_tail(&body
->children
);
2195 *out
= LIST_ENTRY(list
, body_t
, entry
);
2197 hr
= MIME_E_NOT_FOUND
;
2201 list
= list_next(&body
->parent
->children
, &body
->entry
);
2203 *out
= LIST_ENTRY(list
, body_t
, entry
);
2205 hr
= MIME_E_NOT_FOUND
;
2209 list
= list_prev(&body
->parent
->children
, &body
->entry
);
2211 *out
= LIST_ENTRY(list
, body_t
, entry
);
2213 hr
= MIME_E_NOT_FOUND
;
2226 static HRESULT WINAPI
MimeMessage_InsertBody(
2227 IMimeMessage
*iface
,
2228 BODYLOCATION location
,
2232 FIXME("(%p)->(%d, %p, %p)\n", iface
, location
, hPivot
, phBody
);
2236 static HRESULT WINAPI
MimeMessage_GetBody(IMimeMessage
*iface
, BODYLOCATION location
, HBODY hPivot
,
2239 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2243 TRACE("(%p)->(%d, %p, %p)\n", iface
, location
, hPivot
, phBody
);
2246 return E_INVALIDARG
;
2250 hr
= get_body(This
, location
, hPivot
, &body
);
2252 if(hr
== S_OK
) *phBody
= UlongToHandle(body
->index
);
2257 static HRESULT WINAPI
MimeMessage_DeleteBody(
2258 IMimeMessage
*iface
,
2262 FIXME("(%p)->(%p, %08x)\n", iface
, hBody
, dwFlags
);
2266 static HRESULT WINAPI
MimeMessage_MoveBody(
2267 IMimeMessage
*iface
,
2269 BODYLOCATION location
)
2271 FIXME("(%p)->(%d)\n", iface
, location
);
2275 static void count_children(body_t
*body
, boolean recurse
, ULONG
*count
)
2279 LIST_FOR_EACH_ENTRY(child
, &body
->children
, body_t
, entry
)
2282 if(recurse
) count_children(child
, recurse
, count
);
2286 static HRESULT WINAPI
MimeMessage_CountBodies(IMimeMessage
*iface
, HBODY hParent
, boolean fRecurse
,
2290 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2293 TRACE("(%p)->(%p, %s, %p)\n", iface
, hParent
, fRecurse
? "TRUE" : "FALSE", pcBodies
);
2295 hr
= find_body(&This
->body_tree
, hParent
, &body
);
2296 if(hr
!= S_OK
) return hr
;
2299 count_children(body
, fRecurse
, pcBodies
);
2304 static HRESULT
find_next(MimeMessage
*This
, body_t
*body
, FINDBODY
*find
, HBODY
*out
)
2311 if (!body
) ptr
= list_head( &This
->body_tree
);
2314 ptr
= list_head( &body
->children
);
2317 if (!body
->parent
) return MIME_E_NOT_FOUND
;
2318 if (!(ptr
= list_next( &body
->parent
->children
, &body
->entry
))) body
= body
->parent
;
2322 body
= LIST_ENTRY( ptr
, body_t
, entry
);
2323 next
= UlongToHandle( body
->index
);
2324 find
->dwReserved
= body
->index
;
2325 if (IMimeBody_IsContentType(&body
->mime_body
->IMimeBody_iface
, find
->pszPriType
,
2326 find
->pszSubType
) == S_OK
)
2332 return MIME_E_NOT_FOUND
;
2335 static HRESULT WINAPI
MimeMessage_FindFirst(IMimeMessage
*iface
, FINDBODY
*pFindBody
, HBODY
*phBody
)
2337 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2339 TRACE("(%p)->(%p, %p)\n", iface
, pFindBody
, phBody
);
2341 pFindBody
->dwReserved
= 0;
2342 return find_next(This
, NULL
, pFindBody
, phBody
);
2345 static HRESULT WINAPI
MimeMessage_FindNext(IMimeMessage
*iface
, FINDBODY
*pFindBody
, HBODY
*phBody
)
2347 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2351 TRACE("(%p)->(%p, %p)\n", iface
, pFindBody
, phBody
);
2353 hr
= find_body( &This
->body_tree
, UlongToHandle( pFindBody
->dwReserved
), &body
);
2354 if (hr
!= S_OK
) return MIME_E_NOT_FOUND
;
2355 return find_next(This
, body
, pFindBody
, phBody
);
2358 static HRESULT WINAPI
MimeMessage_ResolveURL(
2359 IMimeMessage
*iface
,
2366 FIXME("(%p)->(%p, %s, %s, 0x%x, %p)\n", iface
, hRelated
, pszBase
, pszURL
, dwFlags
, phBody
);
2370 static HRESULT WINAPI
MimeMessage_ToMultipart(
2371 IMimeMessage
*iface
,
2374 LPHBODY phMultipart
)
2376 FIXME("(%p)->(%p, %s, %p)\n", iface
, hBody
, pszSubType
, phMultipart
);
2380 static HRESULT WINAPI
MimeMessage_GetBodyOffsets(
2381 IMimeMessage
*iface
,
2383 LPBODYOFFSETS pOffsets
)
2385 FIXME("(%p)->(%p, %p)\n", iface
, hBody
, pOffsets
);
2389 static HRESULT WINAPI
MimeMessage_GetCharset(
2390 IMimeMessage
*iface
,
2391 LPHCHARSET phCharset
)
2393 FIXME("(%p)->(%p)\n", iface
, phCharset
);
2398 static HRESULT WINAPI
MimeMessage_SetCharset(
2399 IMimeMessage
*iface
,
2401 CSETAPPLYTYPE applytype
)
2403 FIXME("(%p)->(%p, %d)\n", iface
, hCharset
, applytype
);
2407 static HRESULT WINAPI
MimeMessage_IsBodyType(
2408 IMimeMessage
*iface
,
2410 IMSGBODYTYPE bodytype
)
2413 IMimeBody
*mime_body
;
2414 TRACE("(%p)->(%p, %d)\n", iface
, hBody
, bodytype
);
2416 hr
= IMimeMessage_BindToObject(iface
, hBody
, &IID_IMimeBody
, (void**)&mime_body
);
2417 if(hr
!= S_OK
) return hr
;
2419 hr
= IMimeBody_IsType(mime_body
, bodytype
);
2420 MimeBody_Release(mime_body
);
2424 static HRESULT WINAPI
MimeMessage_IsContentType(
2425 IMimeMessage
*iface
,
2431 IMimeBody
*mime_body
;
2432 TRACE("(%p)->(%p, %s, %s)\n", iface
, hBody
, debugstr_a(pszPriType
),
2433 debugstr_a(pszSubType
));
2435 hr
= IMimeMessage_BindToObject(iface
, hBody
, &IID_IMimeBody
, (void**)&mime_body
);
2436 if(FAILED(hr
)) return hr
;
2438 hr
= IMimeBody_IsContentType(mime_body
, pszPriType
, pszSubType
);
2439 IMimeBody_Release(mime_body
);
2443 static HRESULT WINAPI
MimeMessage_QueryBodyProp(
2444 IMimeMessage
*iface
,
2449 boolean fCaseSensitive
)
2451 FIXME("(%p)->(%p, %s, %s, %s, %s)\n", iface
, hBody
, pszName
, pszCriteria
, fSubString
? "TRUE" : "FALSE", fCaseSensitive
? "TRUE" : "FALSE");
2455 static HRESULT WINAPI
MimeMessage_GetBodyProp(
2456 IMimeMessage
*iface
,
2460 LPPROPVARIANT pValue
)
2463 IMimeBody
*mime_body
;
2465 TRACE("(%p)->(%p, %s, 0x%x, %p)\n", iface
, hBody
, pszName
, dwFlags
, pValue
);
2467 hr
= IMimeMessage_BindToObject(iface
, hBody
, &IID_IMimeBody
, (void**)&mime_body
);
2468 if(hr
!= S_OK
) return hr
;
2470 hr
= IMimeBody_GetProp(mime_body
, pszName
, dwFlags
, pValue
);
2471 IMimeBody_Release(mime_body
);
2476 static HRESULT WINAPI
MimeMessage_SetBodyProp(
2477 IMimeMessage
*iface
,
2481 LPCPROPVARIANT pValue
)
2483 FIXME("(%p)->(%p, %s, 0x%x, %p)\n", iface
, hBody
, pszName
, dwFlags
, pValue
);
2487 static HRESULT WINAPI
MimeMessage_DeleteBodyProp(
2488 IMimeMessage
*iface
,
2492 FIXME("(%p)->(%p, %s)\n", iface
, hBody
, pszName
);
2496 static HRESULT WINAPI
MimeMessage_SetOption(
2497 IMimeMessage
*iface
,
2499 LPCPROPVARIANT pValue
)
2502 TRACE("(%p)->(%08x, %p)\n", iface
, oid
, pValue
);
2504 /* Message ID is checked before type.
2505 * OID 0x4D -> 0x56 and 0x58 aren't defined but will filtered out later.
2507 if(TYPEDID_ID(oid
) < TYPEDID_ID(OID_ALLOW_8BIT_HEADER
) || TYPEDID_ID(oid
) > TYPEDID_ID(OID_SECURITY_2KEY_CERT_BAG_64
))
2509 WARN("oid (%08x) out of range\n", oid
);
2510 return MIME_E_INVALID_OPTION_ID
;
2513 if(pValue
->vt
!= TYPEDID_TYPE(oid
))
2515 WARN("Called with vartype %04x and oid %08x\n", pValue
->vt
, oid
);
2521 case OID_HIDE_TNEF_ATTACHMENTS
:
2522 FIXME("OID_HIDE_TNEF_ATTACHMENTS (value %d): ignoring\n", pValue
->u
.boolVal
);
2524 case OID_SHOW_MACBINARY
:
2525 FIXME("OID_SHOW_MACBINARY (value %d): ignoring\n", pValue
->u
.boolVal
);
2527 case OID_SAVEBODY_KEEPBOUNDARY
:
2528 FIXME("OID_SAVEBODY_KEEPBOUNDARY (value %d): ignoring\n", pValue
->u
.boolVal
);
2530 case OID_CLEANUP_TREE_ON_SAVE
:
2531 FIXME("OID_CLEANUP_TREE_ON_SAVE (value %d): ignoring\n", pValue
->u
.boolVal
);
2534 FIXME("Unhandled oid %08x\n", oid
);
2535 hr
= MIME_E_INVALID_OPTION_ID
;
2541 static HRESULT WINAPI
MimeMessage_GetOption(
2542 IMimeMessage
*iface
,
2544 LPPROPVARIANT pValue
)
2546 FIXME("(%p)->(%08x, %p)\n", iface
, oid
, pValue
);
2550 /*** IMimeMessage methods ***/
2551 static HRESULT WINAPI
MimeMessage_CreateWebPage(
2552 IMimeMessage
*iface
,
2554 LPWEBPAGEOPTIONS pOptions
,
2555 IMimeMessageCallback
*pCallback
,
2556 IMoniker
**ppMoniker
)
2558 FIXME("(%p)->(%p, %p, %p, %p)\n", iface
, pRootStm
, pOptions
, pCallback
, ppMoniker
);
2563 static HRESULT WINAPI
MimeMessage_GetProp(
2564 IMimeMessage
*iface
,
2567 LPPROPVARIANT pValue
)
2569 FIXME("(%p)->(%s, 0x%x, %p)\n", iface
, pszName
, dwFlags
, pValue
);
2573 static HRESULT WINAPI
MimeMessage_SetProp(
2574 IMimeMessage
*iface
,
2577 LPCPROPVARIANT pValue
)
2579 FIXME("(%p)->(%s, 0x%x, %p)\n", iface
, pszName
, dwFlags
, pValue
);
2583 static HRESULT WINAPI
MimeMessage_DeleteProp(
2584 IMimeMessage
*iface
,
2587 FIXME("(%p)->(%s)\n", iface
, pszName
);
2591 static HRESULT WINAPI
MimeMessage_QueryProp(
2592 IMimeMessage
*iface
,
2596 boolean fCaseSensitive
)
2598 FIXME("(%p)->(%s, %s, %s, %s)\n", iface
, pszName
, pszCriteria
, fSubString
? "TRUE" : "FALSE", fCaseSensitive
? "TRUE" : "FALSE");
2602 static HRESULT WINAPI
MimeMessage_GetTextBody(
2603 IMimeMessage
*iface
,
2605 ENCODINGTYPE ietEncoding
,
2611 FINDBODY find_struct
;
2612 IMimeBody
*mime_body
;
2613 static char text
[] = "text";
2614 static char plain
[] = "plain";
2615 static char html
[] = "html";
2617 TRACE("(%p)->(%d, %d, %p, %p)\n", iface
, dwTxtType
, ietEncoding
, pStream
, phBody
);
2619 find_struct
.pszPriType
= text
;
2624 find_struct
.pszSubType
= plain
;
2627 find_struct
.pszSubType
= html
;
2630 return MIME_E_INVALID_TEXT_TYPE
;
2633 hr
= IMimeMessage_FindFirst(iface
, &find_struct
, &hbody
);
2636 TRACE("not found hr %08x\n", hr
);
2641 IMimeMessage_BindToObject(iface
, hbody
, &IID_IMimeBody
, (void**)&mime_body
);
2643 IMimeBody_GetData(mime_body
, ietEncoding
, pStream
);
2645 IMimeBody_Release(mime_body
);
2649 static HRESULT WINAPI
MimeMessage_SetTextBody(
2650 IMimeMessage
*iface
,
2652 ENCODINGTYPE ietEncoding
,
2657 FIXME("(%p)->(%d, %d, %p, %p, %p)\n", iface
, dwTxtType
, ietEncoding
, hAlternative
, pStream
, phBody
);
2661 static HRESULT WINAPI
MimeMessage_AttachObject(
2662 IMimeMessage
*iface
,
2667 FIXME("(%p)->(%s, %p, %p)\n", iface
, debugstr_guid(riid
), pvObject
, phBody
);
2671 static HRESULT WINAPI
MimeMessage_AttachFile(
2672 IMimeMessage
*iface
,
2677 FIXME("(%p)->(%s, %p, %p)\n", iface
, pszFilePath
, pstmFile
, phBody
);
2681 static HRESULT WINAPI
MimeMessage_AttachURL(
2682 IMimeMessage
*iface
,
2690 FIXME("(%p)->(%s, %s, 0x%x, %p, %p, %p)\n", iface
, pszBase
, pszURL
, dwFlags
, pstmURL
, ppszCIDURL
, phBody
);
2694 static HRESULT WINAPI
MimeMessage_GetAttachments(
2695 IMimeMessage
*iface
,
2697 LPHBODY
*pprghAttach
)
2700 FINDBODY find_struct
;
2705 TRACE("(%p)->(%p, %p)\n", iface
, pcAttach
, pprghAttach
);
2708 array
= CoTaskMemAlloc(size
* sizeof(HBODY
));
2710 find_struct
.pszPriType
= find_struct
.pszSubType
= NULL
;
2711 hr
= IMimeMessage_FindFirst(iface
, &find_struct
, &hbody
);
2714 hr
= IMimeMessage_IsContentType(iface
, hbody
, "multipart", NULL
);
2715 TRACE("IsCT rets %08x %d\n", hr
, *pcAttach
);
2718 if(*pcAttach
+ 1 > size
)
2721 array
= CoTaskMemRealloc(array
, size
* sizeof(HBODY
));
2723 array
[*pcAttach
] = hbody
;
2726 hr
= IMimeMessage_FindNext(iface
, &find_struct
, &hbody
);
2729 *pprghAttach
= array
;
2733 static HRESULT WINAPI
MimeMessage_GetAddressTable(
2734 IMimeMessage
*iface
,
2735 IMimeAddressTable
**ppTable
)
2737 FIXME("(%p)->(%p)\n", iface
, ppTable
);
2741 static HRESULT WINAPI
MimeMessage_GetSender(
2742 IMimeMessage
*iface
,
2743 LPADDRESSPROPS pAddress
)
2745 FIXME("(%p)->(%p)\n", iface
, pAddress
);
2749 static HRESULT WINAPI
MimeMessage_GetAddressTypes(
2750 IMimeMessage
*iface
,
2753 LPADDRESSLIST pList
)
2755 FIXME("(%p)->(%d, %d, %p)\n", iface
, dwAdrTypes
, dwProps
, pList
);
2759 static HRESULT WINAPI
MimeMessage_GetAddressFormat(
2760 IMimeMessage
*iface
,
2762 ADDRESSFORMAT format
,
2765 FIXME("(%p)->(%d, %d, %p)\n", iface
, dwAdrTypes
, format
, ppszFormat
);
2769 static HRESULT WINAPI
MimeMessage_EnumAddressTypes(
2770 IMimeMessage
*iface
,
2773 IMimeEnumAddressTypes
**ppEnum
)
2775 FIXME("(%p)->(%d, %d, %p)\n", iface
, dwAdrTypes
, dwProps
, ppEnum
);
2779 static HRESULT WINAPI
MimeMessage_SplitMessage(
2780 IMimeMessage
*iface
,
2782 IMimeMessageParts
**ppParts
)
2784 FIXME("(%p)->(%d, %p)\n", iface
, cbMaxPart
, ppParts
);
2788 static HRESULT WINAPI
MimeMessage_GetRootMoniker(
2789 IMimeMessage
*iface
,
2790 IMoniker
**ppMoniker
)
2792 FIXME("(%p)->(%p)\n", iface
, ppMoniker
);
2796 static const IMimeMessageVtbl MimeMessageVtbl
=
2798 MimeMessage_QueryInterface
,
2800 MimeMessage_Release
,
2801 MimeMessage_GetClassID
,
2802 MimeMessage_IsDirty
,
2805 MimeMessage_GetSizeMax
,
2806 MimeMessage_InitNew
,
2807 MimeMessage_GetMessageSource
,
2808 MimeMessage_GetMessageSize
,
2809 MimeMessage_LoadOffsetTable
,
2810 MimeMessage_SaveOffsetTable
,
2811 MimeMessage_GetFlags
,
2813 MimeMessage_HandsOffStorage
,
2814 MimeMessage_BindToObject
,
2815 MimeMessage_SaveBody
,
2816 MimeMessage_InsertBody
,
2817 MimeMessage_GetBody
,
2818 MimeMessage_DeleteBody
,
2819 MimeMessage_MoveBody
,
2820 MimeMessage_CountBodies
,
2821 MimeMessage_FindFirst
,
2822 MimeMessage_FindNext
,
2823 MimeMessage_ResolveURL
,
2824 MimeMessage_ToMultipart
,
2825 MimeMessage_GetBodyOffsets
,
2826 MimeMessage_GetCharset
,
2827 MimeMessage_SetCharset
,
2828 MimeMessage_IsBodyType
,
2829 MimeMessage_IsContentType
,
2830 MimeMessage_QueryBodyProp
,
2831 MimeMessage_GetBodyProp
,
2832 MimeMessage_SetBodyProp
,
2833 MimeMessage_DeleteBodyProp
,
2834 MimeMessage_SetOption
,
2835 MimeMessage_GetOption
,
2836 MimeMessage_CreateWebPage
,
2837 MimeMessage_GetProp
,
2838 MimeMessage_SetProp
,
2839 MimeMessage_DeleteProp
,
2840 MimeMessage_QueryProp
,
2841 MimeMessage_GetTextBody
,
2842 MimeMessage_SetTextBody
,
2843 MimeMessage_AttachObject
,
2844 MimeMessage_AttachFile
,
2845 MimeMessage_AttachURL
,
2846 MimeMessage_GetAttachments
,
2847 MimeMessage_GetAddressTable
,
2848 MimeMessage_GetSender
,
2849 MimeMessage_GetAddressTypes
,
2850 MimeMessage_GetAddressFormat
,
2851 MimeMessage_EnumAddressTypes
,
2852 MimeMessage_SplitMessage
,
2853 MimeMessage_GetRootMoniker
,
2856 HRESULT
MimeMessage_create(IUnknown
*outer
, void **obj
)
2859 MimeBody
*mime_body
;
2862 TRACE("(%p, %p)\n", outer
, obj
);
2866 FIXME("outer unknown not supported yet\n");
2872 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
2873 if (!This
) return E_OUTOFMEMORY
;
2875 This
->IMimeMessage_iface
.lpVtbl
= &MimeMessageVtbl
;
2877 This
->stream
= NULL
;
2878 list_init(&This
->body_tree
);
2879 This
->next_index
= 1;
2881 mime_body
= mimebody_create();
2882 root_body
= new_body_entry(mime_body
, This
->next_index
++, NULL
);
2883 list_add_head(&This
->body_tree
, &root_body
->entry
);
2885 *obj
= &This
->IMimeMessage_iface
;
2889 /***********************************************************************
2890 * MimeOleCreateMessage (INETCOMM.@)
2892 HRESULT WINAPI
MimeOleCreateMessage(IUnknown
*pUnkOuter
, IMimeMessage
**ppMessage
)
2894 TRACE("(%p, %p)\n", pUnkOuter
, ppMessage
);
2895 return MimeMessage_create(NULL
, (void **)ppMessage
);
2898 /***********************************************************************
2899 * MimeOleSetCompatMode (INETCOMM.@)
2901 HRESULT WINAPI
MimeOleSetCompatMode(DWORD dwMode
)
2903 FIXME("(0x%x)\n", dwMode
);
2907 /***********************************************************************
2908 * MimeOleCreateVirtualStream (INETCOMM.@)
2910 HRESULT WINAPI
MimeOleCreateVirtualStream(IStream
**ppStream
)
2913 FIXME("(%p)\n", ppStream
);
2915 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, ppStream
);
2919 typedef struct MimeSecurity
2921 IMimeSecurity IMimeSecurity_iface
;
2925 static inline MimeSecurity
*impl_from_IMimeSecurity(IMimeSecurity
*iface
)
2927 return CONTAINING_RECORD(iface
, MimeSecurity
, IMimeSecurity_iface
);
2930 static HRESULT WINAPI
MimeSecurity_QueryInterface(IMimeSecurity
*iface
, REFIID riid
, void **ppv
)
2932 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
2934 if (IsEqualIID(riid
, &IID_IUnknown
) ||
2935 IsEqualIID(riid
, &IID_IMimeSecurity
))
2938 IMimeSecurity_AddRef(iface
);
2942 FIXME("no interface for %s\n", debugstr_guid(riid
));
2944 return E_NOINTERFACE
;
2947 static ULONG WINAPI
MimeSecurity_AddRef(IMimeSecurity
*iface
)
2949 MimeSecurity
*This
= impl_from_IMimeSecurity(iface
);
2950 LONG ref
= InterlockedIncrement(&This
->ref
);
2952 TRACE("(%p) ref=%d\n", This
, ref
);
2957 static ULONG WINAPI
MimeSecurity_Release(IMimeSecurity
*iface
)
2959 MimeSecurity
*This
= impl_from_IMimeSecurity(iface
);
2960 LONG ref
= InterlockedDecrement(&This
->ref
);
2962 TRACE("(%p) ref=%d\n", This
, ref
);
2965 HeapFree(GetProcessHeap(), 0, This
);
2970 static HRESULT WINAPI
MimeSecurity_InitNew(
2971 IMimeSecurity
* iface
)
2973 FIXME("(%p)->(): stub\n", iface
);
2977 static HRESULT WINAPI
MimeSecurity_CheckInit(
2978 IMimeSecurity
* iface
)
2980 FIXME("(%p)->(): stub\n", iface
);
2984 static HRESULT WINAPI
MimeSecurity_EncodeMessage(
2985 IMimeSecurity
* iface
,
2986 IMimeMessageTree
* pTree
,
2989 FIXME("(%p)->(%p, %08x): stub\n", iface
, pTree
, dwFlags
);
2993 static HRESULT WINAPI
MimeSecurity_EncodeBody(
2994 IMimeSecurity
* iface
,
2995 IMimeMessageTree
* pTree
,
2999 FIXME("(%p)->(%p, %p, %08x): stub\n", iface
, pTree
, hEncodeRoot
, dwFlags
);
3003 static HRESULT WINAPI
MimeSecurity_DecodeMessage(
3004 IMimeSecurity
* iface
,
3005 IMimeMessageTree
* pTree
,
3008 FIXME("(%p)->(%p, %08x): stub\n", iface
, pTree
, dwFlags
);
3012 static HRESULT WINAPI
MimeSecurity_DecodeBody(
3013 IMimeSecurity
* iface
,
3014 IMimeMessageTree
* pTree
,
3018 FIXME("(%p)->(%p, %p, %08x): stub\n", iface
, pTree
, hDecodeRoot
, dwFlags
);
3022 static HRESULT WINAPI
MimeSecurity_EnumCertificates(
3023 IMimeSecurity
* iface
,
3029 FIXME("(%p)->(%p, %08x, %p, %p): stub\n", iface
, hc
, dwUsage
, pPrev
, ppCert
);
3033 static HRESULT WINAPI
MimeSecurity_GetCertificateName(
3034 IMimeSecurity
* iface
,
3035 const PCX509CERT pX509Cert
,
3036 const CERTNAMETYPE cn
,
3039 FIXME("(%p)->(%p, %08x, %p): stub\n", iface
, pX509Cert
, cn
, ppszName
);
3043 static HRESULT WINAPI
MimeSecurity_GetMessageType(
3044 IMimeSecurity
* iface
,
3045 const HWND hwndParent
,
3049 FIXME("(%p)->(%p, %p, %p): stub\n", iface
, hwndParent
, pBody
, pdwSecType
);
3053 static HRESULT WINAPI
MimeSecurity_GetCertData(
3054 IMimeSecurity
* iface
,
3055 const PCX509CERT pX509Cert
,
3056 const CERTDATAID dataid
,
3057 LPPROPVARIANT pValue
)
3059 FIXME("(%p)->(%p, %x, %p): stub\n", iface
, pX509Cert
, dataid
, pValue
);
3064 static const IMimeSecurityVtbl MimeSecurityVtbl
=
3066 MimeSecurity_QueryInterface
,
3067 MimeSecurity_AddRef
,
3068 MimeSecurity_Release
,
3069 MimeSecurity_InitNew
,
3070 MimeSecurity_CheckInit
,
3071 MimeSecurity_EncodeMessage
,
3072 MimeSecurity_EncodeBody
,
3073 MimeSecurity_DecodeMessage
,
3074 MimeSecurity_DecodeBody
,
3075 MimeSecurity_EnumCertificates
,
3076 MimeSecurity_GetCertificateName
,
3077 MimeSecurity_GetMessageType
,
3078 MimeSecurity_GetCertData
3081 HRESULT
MimeSecurity_create(IUnknown
*outer
, void **obj
)
3087 if (outer
) return CLASS_E_NOAGGREGATION
;
3089 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
3090 if (!This
) return E_OUTOFMEMORY
;
3092 This
->IMimeSecurity_iface
.lpVtbl
= &MimeSecurityVtbl
;
3095 *obj
= &This
->IMimeSecurity_iface
;
3099 /***********************************************************************
3100 * MimeOleCreateSecurity (INETCOMM.@)
3102 HRESULT WINAPI
MimeOleCreateSecurity(IMimeSecurity
**ppSecurity
)
3104 return MimeSecurity_create(NULL
, (void **)ppSecurity
);
3107 static HRESULT WINAPI
MimeAlloc_QueryInterface(
3108 IMimeAllocator
* iface
,
3112 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), obj
);
3114 if (IsEqualIID(riid
, &IID_IUnknown
) ||
3115 IsEqualIID(riid
, &IID_IMalloc
) ||
3116 IsEqualIID(riid
, &IID_IMimeAllocator
))
3119 IMimeAllocator_AddRef(iface
);
3123 FIXME("no interface for %s\n", debugstr_guid(riid
));
3125 return E_NOINTERFACE
;
3128 static ULONG WINAPI
MimeAlloc_AddRef(
3129 IMimeAllocator
* iface
)
3134 static ULONG WINAPI
MimeAlloc_Release(
3135 IMimeAllocator
* iface
)
3140 static LPVOID WINAPI
MimeAlloc_Alloc(
3141 IMimeAllocator
* iface
,
3144 return CoTaskMemAlloc(cb
);
3147 static LPVOID WINAPI
MimeAlloc_Realloc(
3148 IMimeAllocator
* iface
,
3152 return CoTaskMemRealloc(pv
, cb
);
3155 static void WINAPI
MimeAlloc_Free(
3156 IMimeAllocator
* iface
,
3162 static SIZE_T WINAPI
MimeAlloc_GetSize(
3163 IMimeAllocator
* iface
,
3170 static int WINAPI
MimeAlloc_DidAlloc(
3171 IMimeAllocator
* iface
,
3178 static void WINAPI
MimeAlloc_HeapMinimize(
3179 IMimeAllocator
* iface
)
3185 static HRESULT WINAPI
MimeAlloc_FreeParamInfoArray(
3186 IMimeAllocator
* iface
,
3188 LPMIMEPARAMINFO prgParam
,
3192 TRACE("(%p)->(%d, %p, %d)\n", iface
, cParams
, prgParam
, fFreeArray
);
3194 for(i
= 0; i
< cParams
; i
++)
3196 IMimeAllocator_Free(iface
, prgParam
[i
].pszName
);
3197 IMimeAllocator_Free(iface
, prgParam
[i
].pszData
);
3199 if(fFreeArray
) IMimeAllocator_Free(iface
, prgParam
);
3203 static HRESULT WINAPI
MimeAlloc_FreeAddressList(
3204 IMimeAllocator
* iface
,
3205 LPADDRESSLIST pList
)
3211 static HRESULT WINAPI
MimeAlloc_FreeAddressProps(
3212 IMimeAllocator
* iface
,
3213 LPADDRESSPROPS pAddress
)
3219 static HRESULT WINAPI
MimeAlloc_ReleaseObjects(
3220 IMimeAllocator
* iface
,
3222 IUnknown
**prgpUnknown
,
3230 static HRESULT WINAPI
MimeAlloc_FreeEnumHeaderRowArray(
3231 IMimeAllocator
* iface
,
3233 LPENUMHEADERROW prgRow
,
3240 static HRESULT WINAPI
MimeAlloc_FreeEnumPropertyArray(
3241 IMimeAllocator
* iface
,
3243 LPENUMPROPERTY prgProp
,
3250 static HRESULT WINAPI
MimeAlloc_FreeThumbprint(
3251 IMimeAllocator
* iface
,
3252 THUMBBLOB
*pthumbprint
)
3259 static HRESULT WINAPI
MimeAlloc_PropVariantClear(
3260 IMimeAllocator
* iface
,
3261 LPPROPVARIANT pProp
)
3267 static IMimeAllocatorVtbl mime_alloc_vtbl
=
3269 MimeAlloc_QueryInterface
,
3277 MimeAlloc_HeapMinimize
,
3278 MimeAlloc_FreeParamInfoArray
,
3279 MimeAlloc_FreeAddressList
,
3280 MimeAlloc_FreeAddressProps
,
3281 MimeAlloc_ReleaseObjects
,
3282 MimeAlloc_FreeEnumHeaderRowArray
,
3283 MimeAlloc_FreeEnumPropertyArray
,
3284 MimeAlloc_FreeThumbprint
,
3285 MimeAlloc_PropVariantClear
3288 static IMimeAllocator mime_allocator
=
3293 HRESULT
MimeAllocator_create(IUnknown
*outer
, void **obj
)
3295 if(outer
) return CLASS_E_NOAGGREGATION
;
3297 *obj
= &mime_allocator
;
3301 HRESULT WINAPI
MimeOleGetAllocator(IMimeAllocator
**alloc
)
3303 return MimeAllocator_create(NULL
, (void**)alloc
);
3306 HRESULT
VirtualStream_create(IUnknown
*outer
, void **obj
)
3308 FIXME("(%p, %p)\n", outer
, obj
);
3311 if (outer
) return CLASS_E_NOAGGREGATION
;
3313 return MimeOleCreateVirtualStream((IStream
**)obj
);
3316 /* IMimePropertySchema Interface */
3317 static HRESULT WINAPI
propschema_QueryInterface(IMimePropertySchema
*iface
, REFIID riid
, void **out
)
3319 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3320 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), out
);
3324 if (IsEqualIID(riid
, &IID_IUnknown
) ||
3325 IsEqualIID(riid
, &IID_IMimePropertySchema
))
3331 FIXME("no interface for %s\n", debugstr_guid(riid
));
3332 return E_NOINTERFACE
;
3335 IMimePropertySchema_AddRef(iface
);
3339 static ULONG WINAPI
propschema_AddRef(IMimePropertySchema
*iface
)
3341 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3342 LONG ref
= InterlockedIncrement(&This
->ref
);
3344 TRACE("(%p) ref=%d\n", This
, ref
);
3349 static ULONG WINAPI
propschema_Release(IMimePropertySchema
*iface
)
3351 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3352 LONG ref
= InterlockedDecrement(&This
->ref
);
3354 TRACE("(%p) ref=%d\n", This
, ref
);
3358 HeapFree(GetProcessHeap(), 0, This
);
3364 static HRESULT WINAPI
propschema_RegisterProperty(IMimePropertySchema
*iface
, const char *name
, DWORD flags
,
3365 DWORD rownumber
, VARTYPE vtdefault
, DWORD
*propid
)
3367 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3368 FIXME("(%p)->(%s, %x, %d, %d, %p) stub\n", This
, debugstr_a(name
), flags
, rownumber
, vtdefault
, propid
);
3372 static HRESULT WINAPI
propschema_ModifyProperty(IMimePropertySchema
*iface
, const char *name
, DWORD flags
,
3373 DWORD rownumber
, VARTYPE vtdefault
)
3375 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3376 FIXME("(%p)->(%s, %x, %d, %d) stub\n", This
, debugstr_a(name
), flags
, rownumber
, vtdefault
);
3380 static HRESULT WINAPI
propschema_GetPropertyId(IMimePropertySchema
*iface
, const char *name
, DWORD
*propid
)
3382 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3383 FIXME("(%p)->(%s, %p) stub\n", This
, debugstr_a(name
), propid
);
3387 static HRESULT WINAPI
propschema_GetPropertyName(IMimePropertySchema
*iface
, DWORD propid
, char **name
)
3389 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3390 FIXME("(%p)->(%d, %p) stub\n", This
, propid
, name
);
3394 static HRESULT WINAPI
propschema_RegisterAddressType(IMimePropertySchema
*iface
, const char *name
, DWORD
*adrtype
)
3396 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3397 FIXME("(%p)->(%s, %p) stub\n", This
, debugstr_a(name
), adrtype
);
3401 static IMimePropertySchemaVtbl prop_schema_vtbl
=
3403 propschema_QueryInterface
,
3406 propschema_RegisterProperty
,
3407 propschema_ModifyProperty
,
3408 propschema_GetPropertyId
,
3409 propschema_GetPropertyName
,
3410 propschema_RegisterAddressType
3414 HRESULT WINAPI
MimeOleGetPropertySchema(IMimePropertySchema
**schema
)
3418 TRACE("(%p) stub\n", schema
);
3420 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
3422 return E_OUTOFMEMORY
;
3424 This
->IMimePropertySchema_iface
.lpVtbl
= &prop_schema_vtbl
;
3427 *schema
= &This
->IMimePropertySchema_iface
;
3432 HRESULT WINAPI
MimeGetAddressFormatW(REFIID riid
, void *object
, DWORD addr_type
,
3433 ADDRESSFORMAT addr_format
, WCHAR
**address
)
3435 FIXME("(%s, %p, %d, %d, %p) stub\n", debugstr_guid(riid
), object
, addr_type
, addr_format
, address
);