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/heap.h"
37 #include "wine/list.h"
38 #include "wine/debug.h"
39 #include "wine/unicode.h"
41 #include "inetcomm_private.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(inetcomm
);
49 DWORD flags
; /* MIMEPROPFLAGS */
57 } property_list_entry_t
;
59 static const property_t default_props
[] =
61 {"X-Newsgroup", PID_HDR_NEWSGROUP
, 0, VT_LPSTR
},
62 {"Newsgroups", PID_HDR_NEWSGROUPS
, 0, VT_LPSTR
},
63 {"References", PID_HDR_REFS
, 0, VT_LPSTR
},
64 {"Subject", PID_HDR_SUBJECT
, 0, VT_LPSTR
},
65 {"From", PID_HDR_FROM
, MPF_ADDRESS
, VT_LPSTR
},
66 {"Message-ID", PID_HDR_MESSAGEID
, 0, VT_LPSTR
},
67 {"Return-Path", PID_HDR_RETURNPATH
, MPF_ADDRESS
, VT_LPSTR
},
68 {"Rr", PID_HDR_RR
, 0, VT_LPSTR
},
69 {"Return-Receipt-To", PID_HDR_RETRCPTO
, MPF_ADDRESS
, VT_LPSTR
},
70 {"Apparently-To", PID_HDR_APPARTO
, MPF_ADDRESS
, VT_LPSTR
},
71 {"Date", PID_HDR_DATE
, 0, VT_LPSTR
},
72 {"Received", PID_HDR_RECEIVED
, 0, VT_LPSTR
},
73 {"Reply-To", PID_HDR_REPLYTO
, MPF_ADDRESS
, VT_LPSTR
},
74 {"X-Mailer", PID_HDR_XMAILER
, 0, VT_LPSTR
},
75 {"Bcc", PID_HDR_BCC
, MPF_ADDRESS
, VT_LPSTR
},
76 {"MIME-Version", PID_HDR_MIMEVER
, MPF_MIME
, VT_LPSTR
},
77 {"Content-Type", PID_HDR_CNTTYPE
, MPF_MIME
| MPF_HASPARAMS
, VT_LPSTR
},
78 {"Content-Transfer-Encoding", PID_HDR_CNTXFER
, MPF_MIME
, VT_LPSTR
},
79 {"Content-ID", PID_HDR_CNTID
, MPF_MIME
, VT_LPSTR
},
80 {"Content-Description", PID_HDR_CNTDESC
, MPF_MIME
, VT_LPSTR
},
81 {"Content-Disposition", PID_HDR_CNTDISP
, MPF_MIME
| MPF_HASPARAMS
, VT_LPSTR
},
82 {"Content-Base", PID_HDR_CNTBASE
, MPF_MIME
, VT_LPSTR
},
83 {"Content-Location", PID_HDR_CNTLOC
, MPF_MIME
, VT_LPSTR
},
84 {"To", PID_HDR_TO
, MPF_ADDRESS
, VT_LPSTR
},
85 {"Path", PID_HDR_PATH
, 0, VT_LPSTR
},
86 {"Followup-To", PID_HDR_FOLLOWUPTO
, 0, VT_LPSTR
},
87 {"Expires", PID_HDR_EXPIRES
, 0, VT_LPSTR
},
88 {"Cc", PID_HDR_CC
, MPF_ADDRESS
, VT_LPSTR
},
89 {"Control", PID_HDR_CONTROL
, 0, VT_LPSTR
},
90 {"Distribution", PID_HDR_DISTRIB
, 0, VT_LPSTR
},
91 {"Keywords", PID_HDR_KEYWORDS
, 0, VT_LPSTR
},
92 {"Summary", PID_HDR_SUMMARY
, 0, VT_LPSTR
},
93 {"Approved", PID_HDR_APPROVED
, 0, VT_LPSTR
},
94 {"Lines", PID_HDR_LINES
, 0, VT_LPSTR
},
95 {"Xref", PID_HDR_XREF
, 0, VT_LPSTR
},
96 {"Organization", PID_HDR_ORG
, 0, VT_LPSTR
},
97 {"X-Newsreader", PID_HDR_XNEWSRDR
, 0, VT_LPSTR
},
98 {"X-Priority", PID_HDR_XPRI
, 0, VT_LPSTR
},
99 {"X-MSMail-Priority", PID_HDR_XMSPRI
, 0, VT_LPSTR
},
100 {"par:content-disposition:filename", PID_PAR_FILENAME
, 0, VT_LPSTR
},
101 {"par:content-type:boundary", PID_PAR_BOUNDARY
, 0, VT_LPSTR
},
102 {"par:content-type:charset", PID_PAR_CHARSET
, 0, VT_LPSTR
},
103 {"par:content-type:name", PID_PAR_NAME
, 0, VT_LPSTR
},
104 {"att:filename", PID_ATT_FILENAME
, 0, VT_LPSTR
},
105 {"att:pri-content-type", PID_ATT_PRITYPE
, 0, VT_LPSTR
},
106 {"att:sub-content-type", PID_ATT_SUBTYPE
, 0, VT_LPSTR
},
107 {"att:illegal-lines", PID_ATT_ILLEGAL
, 0, VT_LPSTR
},
108 {"att:rendered", PID_ATT_RENDERED
, 0, VT_LPSTR
},
109 {"att:sent-time", PID_ATT_SENTTIME
, 0, VT_LPSTR
},
110 {"att:priority", PID_ATT_PRIORITY
, 0, VT_LPSTR
},
111 {"Comment", PID_HDR_COMMENT
, 0, VT_LPSTR
},
112 {"Encoding", PID_HDR_ENCODING
, 0, VT_LPSTR
},
113 {"Encrypted", PID_HDR_ENCRYPTED
, 0, VT_LPSTR
},
114 {"X-Offsets", PID_HDR_OFFSETS
, 0, VT_LPSTR
},
115 {"X-Unsent", PID_HDR_XUNSENT
, 0, VT_LPSTR
},
116 {"X-ArticleId", PID_HDR_ARTICLEID
, 0, VT_LPSTR
},
117 {"Sender", PID_HDR_SENDER
, MPF_ADDRESS
, VT_LPSTR
},
118 {"att:athena-server", PID_ATT_SERVER
, 0, VT_LPSTR
},
119 {"att:athena-account-id", PID_ATT_ACCOUNT
, 0, VT_LPSTR
},
120 {"att:athena-pop3-uidl", PID_ATT_UIDL
, 0, VT_LPSTR
},
121 {"att:athena-store-msgid", PID_ATT_STOREMSGID
, 0, VT_LPSTR
},
122 {"att:athena-user-name", PID_ATT_USERNAME
, 0, VT_LPSTR
},
123 {"att:athena-forward-to", PID_ATT_FORWARDTO
, 0, VT_LPSTR
},
124 {"att:athena-store-fdrid", PID_ATT_STOREFOLDERID
,0, VT_LPSTR
},
125 {"att:athena-ghosted", PID_ATT_GHOSTED
, 0, VT_LPSTR
},
126 {"att:athena-uncachedsize", PID_ATT_UNCACHEDSIZE
, 0, VT_LPSTR
},
127 {"att:athena-combined", PID_ATT_COMBINED
, 0, VT_LPSTR
},
128 {"att:auto-inlined", PID_ATT_AUTOINLINED
, 0, VT_LPSTR
},
129 {"Disposition-Notification-To", PID_HDR_DISP_NOTIFICATION_TO
, 0, VT_LPSTR
},
130 {"par:Content-Type:reply-type", PID_PAR_REPLYTYPE
, 0, VT_LPSTR
},
131 {"par:Content-Type:format", PID_PAR_FORMAT
, 0, VT_LPSTR
},
132 {"att:format", PID_ATT_FORMAT
, 0, VT_LPSTR
},
133 {"In-Reply-To", PID_HDR_INREPLYTO
, 0, VT_LPSTR
},
134 {"att:athena-account-name", PID_ATT_ACCOUNTNAME
, 0, VT_LPSTR
},
148 const property_t
*prop
;
153 typedef struct MimeBody
155 IMimeBody IMimeBody_iface
;
161 struct list new_props
; /* FIXME: This should be in a PropertySchema */
163 char *content_pri_type
;
164 char *content_sub_type
;
165 ENCODINGTYPE encoding
;
168 BODYOFFSETS body_offsets
;
173 IStream IStream_iface
;
176 ULARGE_INTEGER pos
, start
, length
;
179 static inline sub_stream_t
*impl_from_IStream(IStream
*iface
)
181 return CONTAINING_RECORD(iface
, sub_stream_t
, IStream_iface
);
184 static HRESULT WINAPI
sub_stream_QueryInterface(IStream
*iface
, REFIID riid
, void **ppv
)
186 sub_stream_t
*This
= impl_from_IStream(iface
);
188 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
191 if(IsEqualIID(riid
, &IID_IUnknown
) ||
192 IsEqualIID(riid
, &IID_ISequentialStream
) ||
193 IsEqualIID(riid
, &IID_IStream
))
195 IStream_AddRef(iface
);
199 return E_NOINTERFACE
;
202 static ULONG WINAPI
sub_stream_AddRef(IStream
*iface
)
204 sub_stream_t
*This
= impl_from_IStream(iface
);
205 LONG ref
= InterlockedIncrement(&This
->ref
);
207 TRACE("(%p) ref=%d\n", This
, ref
);
212 static ULONG WINAPI
sub_stream_Release(IStream
*iface
)
214 sub_stream_t
*This
= impl_from_IStream(iface
);
215 LONG ref
= InterlockedDecrement(&This
->ref
);
217 TRACE("(%p) ref=%d\n", This
, ref
);
221 IStream_Release(This
->base
);
222 HeapFree(GetProcessHeap(), 0, This
);
227 static HRESULT WINAPI
sub_stream_Read(
233 sub_stream_t
*This
= impl_from_IStream(iface
);
235 LARGE_INTEGER tmp_pos
;
237 TRACE("(%p, %d, %p)\n", pv
, cb
, pcbRead
);
239 tmp_pos
.QuadPart
= This
->pos
.QuadPart
+ This
->start
.QuadPart
;
240 IStream_Seek(This
->base
, tmp_pos
, STREAM_SEEK_SET
, NULL
);
242 if(This
->pos
.QuadPart
+ cb
> This
->length
.QuadPart
)
243 cb
= This
->length
.QuadPart
- This
->pos
.QuadPart
;
245 hr
= IStream_Read(This
->base
, pv
, cb
, pcbRead
);
247 This
->pos
.QuadPart
+= *pcbRead
;
252 static HRESULT WINAPI
sub_stream_Write(
262 static HRESULT WINAPI
sub_stream_Seek(
264 LARGE_INTEGER dlibMove
,
266 ULARGE_INTEGER
*plibNewPosition
)
268 sub_stream_t
*This
= impl_from_IStream(iface
);
269 LARGE_INTEGER new_pos
;
271 TRACE("(%08x.%08x, %x, %p)\n", dlibMove
.u
.HighPart
, dlibMove
.u
.LowPart
, dwOrigin
, plibNewPosition
);
275 case STREAM_SEEK_SET
:
278 case STREAM_SEEK_CUR
:
279 new_pos
.QuadPart
= This
->pos
.QuadPart
+ dlibMove
.QuadPart
;
281 case STREAM_SEEK_END
:
282 new_pos
.QuadPart
= This
->length
.QuadPart
+ dlibMove
.QuadPart
;
285 return STG_E_INVALIDFUNCTION
;
288 if(new_pos
.QuadPart
< 0) new_pos
.QuadPart
= 0;
289 else if(new_pos
.QuadPart
> This
->length
.QuadPart
) new_pos
.QuadPart
= This
->length
.QuadPart
;
291 This
->pos
.QuadPart
= new_pos
.QuadPart
;
293 if(plibNewPosition
) *plibNewPosition
= This
->pos
;
297 static HRESULT WINAPI
sub_stream_SetSize(
299 ULARGE_INTEGER libNewSize
)
305 static HRESULT WINAPI
sub_stream_CopyTo(
309 ULARGE_INTEGER
*pcbRead
,
310 ULARGE_INTEGER
*pcbWritten
)
314 ULONG bytesRead
, bytesWritten
, copySize
;
315 ULARGE_INTEGER totalBytesRead
;
316 ULARGE_INTEGER totalBytesWritten
;
318 TRACE("(%p)->(%p, %d, %p, %p)\n", iface
, pstm
, cb
.u
.LowPart
, pcbRead
, pcbWritten
);
320 totalBytesRead
.QuadPart
= 0;
321 totalBytesWritten
.QuadPart
= 0;
323 while ( cb
.QuadPart
> 0 )
325 if ( cb
.QuadPart
>= sizeof(tmpBuffer
) )
326 copySize
= sizeof(tmpBuffer
);
328 copySize
= cb
.u
.LowPart
;
330 hr
= IStream_Read(iface
, tmpBuffer
, copySize
, &bytesRead
);
331 if (FAILED(hr
)) break;
333 totalBytesRead
.QuadPart
+= bytesRead
;
337 hr
= IStream_Write(pstm
, tmpBuffer
, bytesRead
, &bytesWritten
);
338 if (FAILED(hr
)) break;
339 totalBytesWritten
.QuadPart
+= bytesWritten
;
342 if (bytesRead
!= copySize
)
345 cb
.QuadPart
-= bytesRead
;
348 if (pcbRead
) pcbRead
->QuadPart
= totalBytesRead
.QuadPart
;
349 if (pcbWritten
) pcbWritten
->QuadPart
= totalBytesWritten
.QuadPart
;
354 static HRESULT WINAPI
sub_stream_Commit(
356 DWORD grfCommitFlags
)
362 static HRESULT WINAPI
sub_stream_Revert(
369 static HRESULT WINAPI
sub_stream_LockRegion(
371 ULARGE_INTEGER libOffset
,
379 static HRESULT WINAPI
sub_stream_UnlockRegion(
381 ULARGE_INTEGER libOffset
,
389 static HRESULT WINAPI
sub_stream_Stat(
394 sub_stream_t
*This
= impl_from_IStream(iface
);
395 FIXME("(%p)->(%p, %08x)\n", This
, pstatstg
, grfStatFlag
);
396 memset(pstatstg
, 0, sizeof(*pstatstg
));
397 pstatstg
->cbSize
= This
->length
;
401 static HRESULT WINAPI
sub_stream_Clone(
409 static struct IStreamVtbl sub_stream_vtbl
=
411 sub_stream_QueryInterface
,
421 sub_stream_LockRegion
,
422 sub_stream_UnlockRegion
,
427 static HRESULT
create_sub_stream(IStream
*stream
, ULARGE_INTEGER start
, ULARGE_INTEGER length
, IStream
**out
)
432 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
433 if(!This
) return E_OUTOFMEMORY
;
435 This
->IStream_iface
.lpVtbl
= &sub_stream_vtbl
;
438 This
->length
= length
;
439 This
->pos
.QuadPart
= 0;
440 IStream_AddRef(stream
);
443 *out
= &This
->IStream_iface
;
447 static HRESULT
get_stream_size(IStream
*stream
, ULARGE_INTEGER
*size
)
449 STATSTG statstg
= {NULL
};
453 hres
= IStream_Stat(stream
, &statstg
, STATFLAG_NONAME
);
454 if(SUCCEEDED(hres
)) {
455 *size
= statstg
.cbSize
;
460 return IStream_Seek(stream
, zero
, STREAM_SEEK_END
, size
);
463 static inline MimeBody
*impl_from_IMimeBody(IMimeBody
*iface
)
465 return CONTAINING_RECORD(iface
, MimeBody
, IMimeBody_iface
);
468 typedef struct propschema
470 IMimePropertySchema IMimePropertySchema_iface
;
474 static inline propschema
*impl_from_IMimePropertySchema(IMimePropertySchema
*iface
)
476 return CONTAINING_RECORD(iface
, propschema
, IMimePropertySchema_iface
);
479 static LPSTR
strdupA(LPCSTR str
)
482 int len
= strlen(str
);
483 ret
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
484 memcpy(ret
, str
, len
+ 1);
488 #define PARSER_BUF_SIZE 1024
490 /*****************************************************
491 * copy_headers_to_buf [internal]
493 * Copies the headers into a '\0' terminated memory block and leave
494 * the stream's current position set to after the blank line.
496 static HRESULT
copy_headers_to_buf(IStream
*stm
, char **ptr
)
499 DWORD size
= PARSER_BUF_SIZE
, offset
= 0, last_end
= 0;
511 buf
= HeapAlloc(GetProcessHeap(), 0, size
+ 1);
515 buf
= HeapReAlloc(GetProcessHeap(), 0, buf
, size
+ 1);
523 hr
= IStream_Read(stm
, buf
+ offset
, size
- offset
, &read
);
524 if(FAILED(hr
)) goto fail
;
529 if(read
== 0) done
= TRUE
;
531 while(!done
&& (end
= strstr(buf
+ last_end
, "\r\n")))
533 DWORD new_end
= end
- buf
+ 2;
534 if(new_end
- last_end
== 2)
537 off
.QuadPart
= (LONGLONG
)new_end
- offset
;
538 IStream_Seek(stm
, off
, STREAM_SEEK_CUR
, NULL
);
551 HeapFree(GetProcessHeap(), 0, buf
);
555 static header_t
*read_prop(MimeBody
*body
, char **ptr
)
557 char *colon
= strchr(*ptr
, ':');
558 const property_t
*prop
;
561 if(!colon
) return NULL
;
565 for(prop
= default_props
; prop
->name
; prop
++)
567 if(!lstrcmpiA(*ptr
, prop
->name
))
569 TRACE("%s: found match with default property id %d\n", *ptr
, prop
->id
);
576 property_list_entry_t
*prop_entry
;
577 LIST_FOR_EACH_ENTRY(prop_entry
, &body
->new_props
, property_list_entry_t
, entry
)
579 if(!lstrcmpiA(*ptr
, prop_entry
->prop
.name
))
581 TRACE("%s: found match with already added new property id %d\n", *ptr
, prop_entry
->prop
.id
);
582 prop
= &prop_entry
->prop
;
588 prop_entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(*prop_entry
));
589 prop_entry
->prop
.name
= strdupA(*ptr
);
590 prop_entry
->prop
.id
= body
->next_prop_id
++;
591 prop_entry
->prop
.flags
= 0;
592 prop_entry
->prop
.default_vt
= VT_LPSTR
;
593 list_add_tail(&body
->new_props
, &prop_entry
->entry
);
594 prop
= &prop_entry
->prop
;
595 TRACE("%s: allocating new prop id %d\n", *ptr
, prop_entry
->prop
.id
);
599 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ret
));
601 PropVariantInit(&ret
->value
);
602 list_init(&ret
->params
);
608 static void unfold_header(char *header
, int len
)
610 char *start
= header
, *cp
= header
;
613 while(*cp
== ' ' || *cp
== '\t')
619 memmove(start
, cp
, len
+ 1);
621 cp
= strstr(start
, "\r\n");
628 } while(*cp
== ' ' || *cp
== '\t');
633 static char *unquote_string(const char *str
)
638 while(*str
== ' ' || *str
== '\t') str
++;
646 for(cp
= ret
; *cp
; cp
++)
649 memmove(cp
, cp
+ 1, strlen(cp
+ 1) + 1);
654 WARN("quote in unquoted string\n");
666 static void add_param(header_t
*header
, const char *p
)
668 const char *key
= p
, *value
, *cp
= p
;
672 TRACE("got param %s\n", p
);
674 while (*key
== ' ' || *key
== '\t' ) key
++;
676 cp
= strchr(key
, '=');
679 WARN("malformed parameter - skipping\n");
683 name
= HeapAlloc(GetProcessHeap(), 0, cp
- key
+ 1);
684 memcpy(name
, key
, cp
- key
);
685 name
[cp
- key
] = '\0';
689 param
= HeapAlloc(GetProcessHeap(), 0, sizeof(*param
));
691 param
->value
= unquote_string(value
);
692 list_add_tail(&header
->params
, ¶m
->entry
);
695 static void split_params(header_t
*header
, char *value
)
697 char *cp
= value
, *start
= value
;
698 BOOL in_quotes
= FALSE
, done_value
= FALSE
;
702 if(!in_quotes
&& *cp
== ';')
705 if(done_value
) add_param(header
, start
);
710 in_quotes
= !in_quotes
;
713 if(done_value
) add_param(header
, start
);
716 static void read_value(header_t
*header
, char **cur
)
718 char *end
= *cur
, *value
;
722 end
= strstr(end
, "\r\n");
724 } while(*end
== ' ' || *end
== '\t');
727 value
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
728 memcpy(value
, *cur
, len
);
731 unfold_header(value
, len
);
732 TRACE("value %s\n", debugstr_a(value
));
734 if(header
->prop
->flags
& MPF_HASPARAMS
)
736 split_params(header
, value
);
737 TRACE("value w/o params %s\n", debugstr_a(value
));
740 header
->value
.vt
= VT_LPSTR
;
741 header
->value
.u
.pszVal
= value
;
746 static void init_content_type(MimeBody
*body
, header_t
*header
)
751 slash
= strchr(header
->value
.u
.pszVal
, '/');
754 WARN("malformed context type value\n");
757 len
= slash
- header
->value
.u
.pszVal
;
758 body
->content_pri_type
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
759 memcpy(body
->content_pri_type
, header
->value
.u
.pszVal
, len
);
760 body
->content_pri_type
[len
] = '\0';
761 body
->content_sub_type
= strdupA(slash
+ 1);
764 static void init_content_encoding(MimeBody
*body
, header_t
*header
)
766 const char *encoding
= header
->value
.u
.pszVal
;
768 if(!strcasecmp(encoding
, "base64"))
769 body
->encoding
= IET_BASE64
;
770 else if(!strcasecmp(encoding
, "quoted-printable"))
771 body
->encoding
= IET_QP
;
772 else if(!strcasecmp(encoding
, "7bit"))
773 body
->encoding
= IET_7BIT
;
774 else if(!strcasecmp(encoding
, "8bit"))
775 body
->encoding
= IET_8BIT
;
777 FIXME("unknown encoding %s\n", debugstr_a(encoding
));
780 static HRESULT
parse_headers(MimeBody
*body
, IStream
*stm
)
782 char *header_buf
, *cur_header_ptr
;
786 hr
= copy_headers_to_buf(stm
, &header_buf
);
787 if(FAILED(hr
)) return hr
;
789 cur_header_ptr
= header_buf
;
790 while((header
= read_prop(body
, &cur_header_ptr
)))
792 read_value(header
, &cur_header_ptr
);
793 list_add_tail(&body
->headers
, &header
->entry
);
795 switch(header
->prop
->id
) {
796 case PID_HDR_CNTTYPE
:
797 init_content_type(body
, header
);
799 case PID_HDR_CNTXFER
:
800 init_content_encoding(body
, header
);
805 HeapFree(GetProcessHeap(), 0, header_buf
);
809 static void empty_param_list(struct list
*list
)
811 param_t
*param
, *cursor2
;
813 LIST_FOR_EACH_ENTRY_SAFE(param
, cursor2
, list
, param_t
, entry
)
815 list_remove(¶m
->entry
);
816 HeapFree(GetProcessHeap(), 0, param
->name
);
817 HeapFree(GetProcessHeap(), 0, param
->value
);
818 HeapFree(GetProcessHeap(), 0, param
);
822 static void empty_header_list(struct list
*list
)
824 header_t
*header
, *cursor2
;
826 LIST_FOR_EACH_ENTRY_SAFE(header
, cursor2
, list
, header_t
, entry
)
828 list_remove(&header
->entry
);
829 PropVariantClear(&header
->value
);
830 empty_param_list(&header
->params
);
831 HeapFree(GetProcessHeap(), 0, header
);
835 static void empty_new_prop_list(struct list
*list
)
837 property_list_entry_t
*prop
, *cursor2
;
839 LIST_FOR_EACH_ENTRY_SAFE(prop
, cursor2
, list
, property_list_entry_t
, entry
)
841 list_remove(&prop
->entry
);
842 HeapFree(GetProcessHeap(), 0, (char *)prop
->prop
.name
);
843 HeapFree(GetProcessHeap(), 0, prop
);
847 static void release_data(REFIID riid
, void *data
)
851 if(IsEqualIID(riid
, &IID_IStream
))
852 IStream_Release((IStream
*)data
);
854 FIXME("Unhandled data format %s\n", debugstr_guid(riid
));
857 static HRESULT
find_prop(MimeBody
*body
, const char *name
, header_t
**prop
)
863 LIST_FOR_EACH_ENTRY(header
, &body
->headers
, header_t
, entry
)
867 if(STRTOPID(name
) == header
->prop
->id
)
873 else if(!lstrcmpiA(name
, header
->prop
->name
))
880 return MIME_E_NOT_FOUND
;
883 static const property_t
*find_default_prop(const char *name
)
885 const property_t
*prop_def
= NULL
;
887 for(prop_def
= default_props
; prop_def
->name
; prop_def
++)
891 if(STRTOPID(name
) == prop_def
->id
)
896 else if(!lstrcmpiA(name
, prop_def
->name
))
903 TRACE("%s: found match with default property id %d\n", prop_def
->name
, prop_def
->id
);
910 static HRESULT WINAPI
MimeBody_QueryInterface(IMimeBody
* iface
,
914 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppvObject
);
918 if (IsEqualIID(riid
, &IID_IUnknown
) ||
919 IsEqualIID(riid
, &IID_IPersist
) ||
920 IsEqualIID(riid
, &IID_IPersistStreamInit
) ||
921 IsEqualIID(riid
, &IID_IMimePropertySet
) ||
922 IsEqualIID(riid
, &IID_IMimeBody
))
929 IUnknown_AddRef((IUnknown
*)*ppvObject
);
933 FIXME("no interface for %s\n", debugstr_guid(riid
));
934 return E_NOINTERFACE
;
937 static ULONG WINAPI
MimeBody_AddRef(IMimeBody
*iface
)
939 MimeBody
*This
= impl_from_IMimeBody(iface
);
940 LONG ref
= InterlockedIncrement(&This
->ref
);
942 TRACE("(%p) ref=%d\n", This
, ref
);
947 static ULONG WINAPI
MimeBody_Release(IMimeBody
*iface
)
949 MimeBody
*This
= impl_from_IMimeBody(iface
);
950 LONG ref
= InterlockedDecrement(&This
->ref
);
952 TRACE("(%p) ref=%d\n", This
, ref
);
956 empty_header_list(&This
->headers
);
957 empty_new_prop_list(&This
->new_props
);
959 HeapFree(GetProcessHeap(), 0, This
->content_pri_type
);
960 HeapFree(GetProcessHeap(), 0, This
->content_sub_type
);
962 release_data(&This
->data_iid
, This
->data
);
964 HeapFree(GetProcessHeap(), 0, This
);
970 static HRESULT WINAPI
MimeBody_GetClassID(
974 MimeBody
*This
= impl_from_IMimeBody(iface
);
976 TRACE("(%p)->(%p)\n", This
, pClassID
);
981 *pClassID
= IID_IMimeBody
;
985 static HRESULT WINAPI
MimeBody_IsDirty(
988 MimeBody
*This
= impl_from_IMimeBody(iface
);
989 FIXME("(%p)->() stub\n", This
);
993 static HRESULT WINAPI
MimeBody_Load(IMimeBody
*iface
, IStream
*pStm
)
995 MimeBody
*This
= impl_from_IMimeBody(iface
);
996 TRACE("(%p)->(%p)\n", This
, pStm
);
997 return parse_headers(This
, pStm
);
1000 static HRESULT WINAPI
MimeBody_Save(IMimeBody
*iface
, IStream
*pStm
, BOOL fClearDirty
)
1002 MimeBody
*This
= impl_from_IMimeBody(iface
);
1003 FIXME("(%p)->(%p, %d)\n", This
, pStm
, fClearDirty
);
1007 static HRESULT WINAPI
MimeBody_GetSizeMax(
1009 ULARGE_INTEGER
* pcbSize
)
1011 MimeBody
*This
= impl_from_IMimeBody(iface
);
1012 FIXME("(%p)->(%p) stub\n", This
, pcbSize
);
1016 static HRESULT WINAPI
MimeBody_InitNew(
1019 MimeBody
*This
= impl_from_IMimeBody(iface
);
1020 TRACE("(%p)->()\n", This
);
1024 static HRESULT WINAPI
MimeBody_GetPropInfo(
1027 LPMIMEPROPINFO pInfo
)
1029 MimeBody
*This
= impl_from_IMimeBody(iface
);
1032 DWORD supported
= PIM_PROPID
| PIM_VTDEFAULT
;
1034 TRACE("(%p)->(%s, %p) semi-stub\n", This
, debugstr_a(pszName
), pInfo
);
1036 if(!pszName
|| !pInfo
)
1037 return E_INVALIDARG
;
1039 TRACE("mask 0x%04x\n", pInfo
->dwMask
);
1041 if(pInfo
->dwMask
& ~supported
)
1042 FIXME("Unsupported mask flags 0x%04x\n", pInfo
->dwMask
& ~supported
);
1044 hr
= find_prop(This
, pszName
, &header
);
1047 if(pInfo
->dwMask
& PIM_CHARSET
)
1048 pInfo
->hCharset
= 0;
1049 if(pInfo
->dwMask
& PIM_FLAGS
)
1050 pInfo
->dwFlags
= 0x00000000;
1051 if(pInfo
->dwMask
& PIM_ROWNUMBER
)
1052 pInfo
->dwRowNumber
= 0;
1053 if(pInfo
->dwMask
& PIM_ENCODINGTYPE
)
1054 pInfo
->ietEncoding
= 0;
1055 if(pInfo
->dwMask
& PIM_VALUES
)
1057 if(pInfo
->dwMask
& PIM_PROPID
)
1058 pInfo
->dwPropId
= header
->prop
->id
;
1059 if(pInfo
->dwMask
& PIM_VTDEFAULT
)
1060 pInfo
->vtDefault
= header
->prop
->default_vt
;
1061 if(pInfo
->dwMask
& PIM_VTCURRENT
)
1062 pInfo
->vtCurrent
= 0;
1068 static HRESULT WINAPI
MimeBody_SetPropInfo(
1071 LPCMIMEPROPINFO pInfo
)
1073 MimeBody
*This
= impl_from_IMimeBody(iface
);
1074 FIXME("(%p)->(%s, %p) stub\n", This
, debugstr_a(pszName
), pInfo
);
1078 static HRESULT WINAPI
MimeBody_GetProp(
1082 LPPROPVARIANT pValue
)
1084 MimeBody
*This
= impl_from_IMimeBody(iface
);
1088 TRACE("(%p)->(%s, 0x%x, %p)\n", This
, debugstr_a(pszName
), dwFlags
, pValue
);
1090 if(!pszName
|| !pValue
)
1091 return E_INVALIDARG
;
1093 if(!ISPIDSTR(pszName
) && !lstrcmpiA(pszName
, "att:pri-content-type"))
1095 PropVariantClear(pValue
);
1096 pValue
->vt
= VT_LPSTR
;
1097 pValue
->u
.pszVal
= strdupA(This
->content_pri_type
);
1101 hr
= find_prop(This
, pszName
, &header
);
1104 TRACE("type %d->%d\n", header
->value
.vt
, pValue
->vt
);
1106 hr
= PropVariantChangeType(pValue
, &header
->value
, 0, pValue
->vt
);
1108 FIXME("Conversion not currently supported (%d->%d)\n", header
->value
.vt
, pValue
->vt
);
1114 static HRESULT WINAPI
MimeBody_SetProp(
1118 LPCPROPVARIANT pValue
)
1120 MimeBody
*This
= impl_from_IMimeBody(iface
);
1124 TRACE("(%p)->(%s, 0x%x, %p)\n", This
, debugstr_a(pszName
), dwFlags
, pValue
);
1126 if(!pszName
|| !pValue
)
1127 return E_INVALIDARG
;
1129 hr
= find_prop(This
, pszName
, &header
);
1132 property_list_entry_t
*prop_entry
;
1133 const property_t
*prop
= NULL
;
1135 LIST_FOR_EACH_ENTRY(prop_entry
, &This
->new_props
, property_list_entry_t
, entry
)
1137 if(ISPIDSTR(pszName
))
1139 if(STRTOPID(pszName
) == prop_entry
->prop
.id
)
1141 TRACE("Found match with already added new property id %d\n", prop_entry
->prop
.id
);
1142 prop
= &prop_entry
->prop
;
1146 else if(!lstrcmpiA(pszName
, prop_entry
->prop
.name
))
1148 TRACE("Found match with already added new property id %d\n", prop_entry
->prop
.id
);
1149 prop
= &prop_entry
->prop
;
1154 header
= HeapAlloc(GetProcessHeap(), 0, sizeof(*header
));
1156 return E_OUTOFMEMORY
;
1160 const property_t
*prop_def
= NULL
;
1161 prop_entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(*prop_entry
));
1164 HeapFree(GetProcessHeap(), 0, header
);
1165 return E_OUTOFMEMORY
;
1168 prop_def
= find_default_prop(pszName
);
1171 prop_entry
->prop
.name
= strdupA(prop_def
->name
);
1172 prop_entry
->prop
.id
= prop_def
->id
;
1176 if(ISPIDSTR(pszName
))
1178 HeapFree(GetProcessHeap(), 0, prop_entry
);
1179 HeapFree(GetProcessHeap(), 0, header
);
1180 return MIME_E_NOT_FOUND
;
1183 prop_entry
->prop
.name
= strdupA(pszName
);
1184 prop_entry
->prop
.id
= This
->next_prop_id
++;
1187 prop_entry
->prop
.flags
= 0;
1188 prop_entry
->prop
.default_vt
= pValue
->vt
;
1189 list_add_tail(&This
->new_props
, &prop_entry
->entry
);
1190 prop
= &prop_entry
->prop
;
1191 TRACE("Allocating new prop id %d\n", prop_entry
->prop
.id
);
1194 header
->prop
= prop
;
1195 PropVariantInit(&header
->value
);
1196 list_init(&header
->params
);
1197 list_add_tail(&This
->headers
, &header
->entry
);
1200 PropVariantCopy(&header
->value
, pValue
);
1205 static HRESULT WINAPI
MimeBody_AppendProp(
1209 LPPROPVARIANT pValue
)
1211 MimeBody
*This
= impl_from_IMimeBody(iface
);
1212 FIXME("(%p)->(%s, 0x%x, %p) stub\n", This
, debugstr_a(pszName
), dwFlags
, pValue
);
1216 static HRESULT WINAPI
MimeBody_DeleteProp(
1220 MimeBody
*This
= impl_from_IMimeBody(iface
);
1224 TRACE("(%p)->(%s) stub\n", This
, debugstr_a(pszName
));
1226 LIST_FOR_EACH_ENTRY(cursor
, &This
->headers
, header_t
, entry
)
1228 if(ISPIDSTR(pszName
))
1229 found
= STRTOPID(pszName
) == cursor
->prop
->id
;
1231 found
= !lstrcmpiA(pszName
, cursor
->prop
->name
);
1235 list_remove(&cursor
->entry
);
1236 HeapFree(GetProcessHeap(), 0, cursor
);
1241 return MIME_E_NOT_FOUND
;
1244 static HRESULT WINAPI
MimeBody_CopyProps(
1248 IMimePropertySet
* pPropertySet
)
1250 MimeBody
*This
= impl_from_IMimeBody(iface
);
1251 FIXME("(%p)->(%d, %p, %p) stub\n", This
, cNames
, prgszName
, pPropertySet
);
1255 static HRESULT WINAPI
MimeBody_MoveProps(
1259 IMimePropertySet
* pPropertySet
)
1261 MimeBody
*This
= impl_from_IMimeBody(iface
);
1262 FIXME("(%p)->(%d, %p, %p) stub\n", This
, cNames
, prgszName
, pPropertySet
);
1266 static HRESULT WINAPI
MimeBody_DeleteExcept(
1271 MimeBody
*This
= impl_from_IMimeBody(iface
);
1272 FIXME("(%p)->(%d, %p) stub\n", This
, cNames
, prgszName
);
1276 static HRESULT WINAPI
MimeBody_QueryProp(
1281 boolean fCaseSensitive
)
1283 MimeBody
*This
= impl_from_IMimeBody(iface
);
1284 FIXME("(%p)->(%s, %s, %d, %d) stub\n", This
, debugstr_a(pszName
), debugstr_a(pszCriteria
), fSubString
, fCaseSensitive
);
1288 static HRESULT WINAPI
MimeBody_GetCharset(
1290 LPHCHARSET phCharset
)
1292 MimeBody
*This
= impl_from_IMimeBody(iface
);
1293 FIXME("(%p)->(%p) stub\n", This
, phCharset
);
1298 static HRESULT WINAPI
MimeBody_SetCharset(
1301 CSETAPPLYTYPE applytype
)
1303 MimeBody
*This
= impl_from_IMimeBody(iface
);
1304 FIXME("(%p)->(%p, %d) stub\n", This
, hCharset
, applytype
);
1308 static HRESULT WINAPI
MimeBody_GetParameters(
1312 LPMIMEPARAMINFO
* pprgParam
)
1314 MimeBody
*This
= impl_from_IMimeBody(iface
);
1318 TRACE("(%p)->(%s, %p, %p)\n", iface
, debugstr_a(pszName
), pcParams
, pprgParam
);
1323 hr
= find_prop(This
, pszName
, &header
);
1324 if(hr
!= S_OK
) return hr
;
1326 *pcParams
= list_count(&header
->params
);
1329 IMimeAllocator
*alloc
;
1331 MIMEPARAMINFO
*info
;
1333 MimeOleGetAllocator(&alloc
);
1335 *pprgParam
= info
= IMimeAllocator_Alloc(alloc
, *pcParams
* sizeof(**pprgParam
));
1336 LIST_FOR_EACH_ENTRY(param
, &header
->params
, param_t
, entry
)
1340 len
= strlen(param
->name
) + 1;
1341 info
->pszName
= IMimeAllocator_Alloc(alloc
, len
);
1342 memcpy(info
->pszName
, param
->name
, len
);
1343 len
= strlen(param
->value
) + 1;
1344 info
->pszData
= IMimeAllocator_Alloc(alloc
, len
);
1345 memcpy(info
->pszData
, param
->value
, len
);
1348 IMimeAllocator_Release(alloc
);
1353 static HRESULT WINAPI
MimeBody_IsContentType(
1358 MimeBody
*This
= impl_from_IMimeBody(iface
);
1360 TRACE("(%p)->(%s, %s)\n", This
, debugstr_a(pszPriType
), debugstr_a(pszSubType
));
1363 const char *pri
= This
->content_pri_type
;
1364 if(!pri
) pri
= "text";
1365 if(lstrcmpiA(pri
, pszPriType
)) return S_FALSE
;
1370 const char *sub
= This
->content_sub_type
;
1371 if(!sub
) sub
= "plain";
1372 if(lstrcmpiA(sub
, pszSubType
)) return S_FALSE
;
1378 static HRESULT WINAPI
MimeBody_BindToObject(
1383 MimeBody
*This
= impl_from_IMimeBody(iface
);
1384 FIXME("(%p)->(%s, %p) stub\n", This
, debugstr_guid(riid
), ppvObject
);
1388 static HRESULT WINAPI
MimeBody_Clone(
1390 IMimePropertySet
** ppPropertySet
)
1392 MimeBody
*This
= impl_from_IMimeBody(iface
);
1393 FIXME("(%p)->(%p) stub\n", This
, ppPropertySet
);
1397 static HRESULT WINAPI
MimeBody_SetOption(
1400 LPCPROPVARIANT pValue
)
1402 MimeBody
*This
= impl_from_IMimeBody(iface
);
1403 HRESULT hr
= E_NOTIMPL
;
1404 TRACE("(%p)->(%08x, %p)\n", This
, oid
, pValue
);
1406 if(pValue
->vt
!= TYPEDID_TYPE(oid
))
1408 WARN("Called with vartype %04x and oid %08x\n", pValue
->vt
, oid
);
1409 return E_INVALIDARG
;
1414 case OID_SECURITY_HWND_OWNER
:
1415 FIXME("OID_SECURITY_HWND_OWNER (value %08x): ignoring\n", pValue
->u
.ulVal
);
1418 case OID_TRANSMIT_BODY_ENCODING
:
1419 FIXME("OID_TRANSMIT_BODY_ENCODING (value %08x): ignoring\n", pValue
->u
.ulVal
);
1423 FIXME("Unhandled oid %08x\n", oid
);
1429 static HRESULT WINAPI
MimeBody_GetOption(
1432 LPPROPVARIANT pValue
)
1434 MimeBody
*This
= impl_from_IMimeBody(iface
);
1435 FIXME("(%p)->(%08x, %p): stub\n", This
, oid
, pValue
);
1439 static HRESULT WINAPI
MimeBody_EnumProps(
1442 IMimeEnumProperties
** ppEnum
)
1444 MimeBody
*This
= impl_from_IMimeBody(iface
);
1445 FIXME("(%p)->(0x%x, %p) stub\n", This
, dwFlags
, ppEnum
);
1449 static HRESULT WINAPI
MimeBody_IsType(
1451 IMSGBODYTYPE bodytype
)
1453 MimeBody
*This
= impl_from_IMimeBody(iface
);
1455 TRACE("(%p)->(%d)\n", This
, bodytype
);
1459 return This
->data
? S_FALSE
: S_OK
;
1461 FIXME("Unimplemented bodytype %d - returning S_OK\n", bodytype
);
1466 static HRESULT WINAPI
MimeBody_SetDisplayName(
1470 MimeBody
*This
= impl_from_IMimeBody(iface
);
1471 FIXME("(%p)->(%s) stub\n", This
, debugstr_a(pszDisplay
));
1475 static HRESULT WINAPI
MimeBody_GetDisplayName(
1479 MimeBody
*This
= impl_from_IMimeBody(iface
);
1480 FIXME("(%p)->(%p) stub\n", This
, ppszDisplay
);
1484 static HRESULT WINAPI
MimeBody_GetOffsets(
1486 LPBODYOFFSETS pOffsets
)
1488 MimeBody
*This
= impl_from_IMimeBody(iface
);
1489 TRACE("(%p)->(%p)\n", This
, pOffsets
);
1491 *pOffsets
= This
->body_offsets
;
1493 if(This
->body_offsets
.cbBodyEnd
== 0) return MIME_E_NO_DATA
;
1497 static HRESULT WINAPI
MimeBody_GetCurrentEncoding(
1499 ENCODINGTYPE
* pietEncoding
)
1501 MimeBody
*This
= impl_from_IMimeBody(iface
);
1503 TRACE("(%p)->(%p)\n", This
, pietEncoding
);
1505 *pietEncoding
= This
->encoding
;
1509 static HRESULT WINAPI
MimeBody_SetCurrentEncoding(
1511 ENCODINGTYPE ietEncoding
)
1513 MimeBody
*This
= impl_from_IMimeBody(iface
);
1515 TRACE("(%p)->(%d)\n", This
, ietEncoding
);
1517 This
->encoding
= ietEncoding
;
1521 static HRESULT WINAPI
MimeBody_GetEstimatedSize(
1523 ENCODINGTYPE ietEncoding
,
1526 MimeBody
*This
= impl_from_IMimeBody(iface
);
1527 FIXME("(%p)->(%d, %p) stub\n", This
, ietEncoding
, pcbSize
);
1531 static HRESULT WINAPI
MimeBody_GetDataHere(
1533 ENCODINGTYPE ietEncoding
,
1536 MimeBody
*This
= impl_from_IMimeBody(iface
);
1537 FIXME("(%p)->(%d, %p) stub\n", This
, ietEncoding
, pStream
);
1541 static const signed char base64_decode_table
[] =
1543 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00 */
1544 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10 */
1545 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 0x20 */
1546 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 0x30 */
1547 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40 */
1548 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 0x50 */
1549 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60 */
1550 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 /* 0x70 */
1553 static HRESULT
decode_base64(IStream
*input
, IStream
**ret_stream
)
1555 const unsigned char *ptr
, *end
;
1556 unsigned char buf
[1024];
1559 unsigned char in
[4];
1566 hres
= IStream_Seek(input
, pos
, STREAM_SEEK_SET
, NULL
);
1570 hres
= CreateStreamOnHGlobal(NULL
, TRUE
, &output
);
1575 hres
= IStream_Read(input
, buf
, sizeof(buf
), &size
);
1576 if(FAILED(hres
) || !size
)
1583 /* skip invalid chars */
1585 (*ptr
>= sizeof(base64_decode_table
)/sizeof(*base64_decode_table
)
1586 || base64_decode_table
[*ptr
] == -1))
1591 in
[n
++] = base64_decode_table
[*ptr
++];
1594 *ret
++ = in
[0] << 2 | in
[1] >> 4;
1597 *ret
++ = in
[1] << 4 | in
[2] >> 2;
1600 *ret
++ = ((in
[2] << 6) & 0xc0) | in
[3];
1606 hres
= IStream_Write(output
, buf
, ret
- buf
, NULL
);
1613 hres
= IStream_Seek(output
, pos
, STREAM_SEEK_SET
, NULL
);
1615 IStream_Release(output
);
1619 *ret_stream
= output
;
1623 static int hex_digit(char c
)
1625 if('0' <= c
&& c
<= '9')
1627 if('A' <= c
&& c
<= 'F')
1628 return c
- 'A' + 10;
1629 if('a' <= c
&& c
<= 'f')
1630 return c
- 'a' + 10;
1634 static HRESULT
decode_qp(IStream
*input
, IStream
**ret_stream
)
1636 const unsigned char *ptr
, *end
;
1637 unsigned char *ret
, prev
= 0;
1638 unsigned char buf
[1024];
1646 hres
= IStream_Seek(input
, pos
, STREAM_SEEK_SET
, NULL
);
1650 hres
= CreateStreamOnHGlobal(NULL
, TRUE
, &output
);
1655 hres
= IStream_Read(input
, buf
, sizeof(buf
), &size
);
1656 if(FAILED(hres
) || !size
)
1663 unsigned char byte
= *ptr
++;
1677 if(prev
!= '\r' || byte
!= '\n') {
1678 int h1
= hex_digit(prev
), h2
= hex_digit(byte
);
1679 if(h1
!= -1 && h2
!= -1)
1680 *ret
++ = (h1
<< 4) | h2
;
1690 hres
= IStream_Write(output
, buf
, ret
- buf
, NULL
);
1697 hres
= IStream_Seek(output
, pos
, STREAM_SEEK_SET
, NULL
);
1699 IStream_Release(output
);
1703 *ret_stream
= output
;
1707 static HRESULT WINAPI
MimeBody_GetData(
1709 ENCODINGTYPE ietEncoding
,
1712 MimeBody
*This
= impl_from_IMimeBody(iface
);
1713 ULARGE_INTEGER start
, size
;
1716 TRACE("(%p)->(%d %p)\n", This
, ietEncoding
, ppStream
);
1718 if(This
->encoding
!= ietEncoding
) {
1719 switch(This
->encoding
) {
1721 hres
= decode_base64(This
->data
, ppStream
);
1724 hres
= decode_qp(This
->data
, ppStream
);
1727 FIXME("Decoding %d is not supported.\n", This
->encoding
);
1730 if(ietEncoding
!= IET_BINARY
)
1731 FIXME("Encoding %d is not supported.\n", ietEncoding
);
1737 hres
= get_stream_size(This
->data
, &size
);
1739 hres
= create_sub_stream(This
->data
, start
, size
, ppStream
);
1743 static HRESULT WINAPI
MimeBody_SetData(
1745 ENCODINGTYPE ietEncoding
,
1751 MimeBody
*This
= impl_from_IMimeBody(iface
);
1752 TRACE("(%p)->(%d, %s, %s, %s %p)\n", This
, ietEncoding
, debugstr_a(pszPriType
), debugstr_a(pszSubType
),
1753 debugstr_guid(riid
), pvObject
);
1755 if(IsEqualIID(riid
, &IID_IStream
))
1756 IStream_AddRef((IStream
*)pvObject
);
1759 FIXME("Unhandled object type %s\n", debugstr_guid(riid
));
1760 return E_INVALIDARG
;
1764 release_data(&This
->data_iid
, This
->data
);
1766 This
->data_iid
= *riid
;
1767 This
->data
= pvObject
;
1769 IMimeBody_SetCurrentEncoding(iface
, ietEncoding
);
1771 /* FIXME: Update the content type.
1772 If pszPriType == NULL use 'application'
1773 If pszSubType == NULL use 'octet-stream' */
1778 static HRESULT WINAPI
MimeBody_EmptyData(
1781 MimeBody
*This
= impl_from_IMimeBody(iface
);
1782 FIXME("(%p)->() stub\n", This
);
1786 static HRESULT WINAPI
MimeBody_CopyTo(
1790 MimeBody
*This
= impl_from_IMimeBody(iface
);
1791 FIXME("(%p)->(%p) stub\n", This
, pBody
);
1795 static HRESULT WINAPI
MimeBody_GetTransmitInfo(
1797 LPTRANSMITINFO pTransmitInfo
)
1799 MimeBody
*This
= impl_from_IMimeBody(iface
);
1800 FIXME("(%p)->(%p) stub\n", This
, pTransmitInfo
);
1804 static HRESULT WINAPI
MimeBody_SaveToFile(
1806 ENCODINGTYPE ietEncoding
,
1809 MimeBody
*This
= impl_from_IMimeBody(iface
);
1810 FIXME("(%p)->(%d, %s) stub\n", This
, ietEncoding
, debugstr_a(pszFilePath
));
1814 static HRESULT WINAPI
MimeBody_GetHandle(
1818 MimeBody
*This
= impl_from_IMimeBody(iface
);
1819 TRACE("(%p)->(%p)\n", iface
, phBody
);
1822 return E_INVALIDARG
;
1824 *phBody
= This
->handle
;
1825 return This
->handle
? S_OK
: MIME_E_NO_DATA
;
1828 static IMimeBodyVtbl body_vtbl
=
1830 MimeBody_QueryInterface
,
1833 MimeBody_GetClassID
,
1837 MimeBody_GetSizeMax
,
1839 MimeBody_GetPropInfo
,
1840 MimeBody_SetPropInfo
,
1843 MimeBody_AppendProp
,
1844 MimeBody_DeleteProp
,
1847 MimeBody_DeleteExcept
,
1849 MimeBody_GetCharset
,
1850 MimeBody_SetCharset
,
1851 MimeBody_GetParameters
,
1852 MimeBody_IsContentType
,
1853 MimeBody_BindToObject
,
1859 MimeBody_SetDisplayName
,
1860 MimeBody_GetDisplayName
,
1861 MimeBody_GetOffsets
,
1862 MimeBody_GetCurrentEncoding
,
1863 MimeBody_SetCurrentEncoding
,
1864 MimeBody_GetEstimatedSize
,
1865 MimeBody_GetDataHere
,
1870 MimeBody_GetTransmitInfo
,
1871 MimeBody_SaveToFile
,
1875 static HRESULT
MimeBody_set_offsets(MimeBody
*body
, const BODYOFFSETS
*offsets
)
1877 TRACE("setting offsets to %d, %d, %d, %d\n", offsets
->cbBoundaryStart
,
1878 offsets
->cbHeaderStart
, offsets
->cbBodyStart
, offsets
->cbBodyEnd
);
1880 body
->body_offsets
= *offsets
;
1884 #define FIRST_CUSTOM_PROP_ID 0x100
1886 static MimeBody
*mimebody_create(void)
1889 BODYOFFSETS body_offsets
;
1891 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1895 This
->IMimeBody_iface
.lpVtbl
= &body_vtbl
;
1897 This
->handle
= NULL
;
1898 list_init(&This
->headers
);
1899 list_init(&This
->new_props
);
1900 This
->next_prop_id
= FIRST_CUSTOM_PROP_ID
;
1901 This
->content_pri_type
= NULL
;
1902 This
->content_sub_type
= NULL
;
1903 This
->encoding
= IET_7BIT
;
1905 This
->data_iid
= IID_NULL
;
1907 body_offsets
.cbBoundaryStart
= body_offsets
.cbHeaderStart
= 0;
1908 body_offsets
.cbBodyStart
= body_offsets
.cbBodyEnd
= 0;
1909 MimeBody_set_offsets(This
, &body_offsets
);
1914 HRESULT
MimeBody_create(IUnknown
*outer
, void **ppv
)
1919 return CLASS_E_NOAGGREGATION
;
1921 if ((mb
= mimebody_create()))
1923 *ppv
= &mb
->IMimeBody_iface
;
1929 return E_OUTOFMEMORY
;
1933 typedef struct body_t
1937 MimeBody
*mime_body
;
1939 struct body_t
*parent
;
1940 struct list children
;
1943 typedef struct MimeMessage
1945 IMimeMessage IMimeMessage_iface
;
1949 struct list body_tree
;
1953 static inline MimeMessage
*impl_from_IMimeMessage(IMimeMessage
*iface
)
1955 return CONTAINING_RECORD(iface
, MimeMessage
, IMimeMessage_iface
);
1958 static HRESULT WINAPI
MimeMessage_QueryInterface(IMimeMessage
*iface
, REFIID riid
, void **ppv
)
1960 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
1962 if (IsEqualIID(riid
, &IID_IUnknown
) ||
1963 IsEqualIID(riid
, &IID_IPersist
) ||
1964 IsEqualIID(riid
, &IID_IPersistStreamInit
) ||
1965 IsEqualIID(riid
, &IID_IMimeMessageTree
) ||
1966 IsEqualIID(riid
, &IID_IMimeMessage
))
1969 IMimeMessage_AddRef(iface
);
1973 FIXME("no interface for %s\n", debugstr_guid(riid
));
1975 return E_NOINTERFACE
;
1978 static ULONG WINAPI
MimeMessage_AddRef(IMimeMessage
*iface
)
1980 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
1981 ULONG ref
= InterlockedIncrement(&This
->ref
);
1983 TRACE("(%p) ref=%d\n", This
, ref
);
1988 static void empty_body_list(struct list
*list
)
1990 body_t
*body
, *cursor2
;
1991 LIST_FOR_EACH_ENTRY_SAFE(body
, cursor2
, list
, body_t
, entry
)
1993 empty_body_list(&body
->children
);
1994 list_remove(&body
->entry
);
1995 IMimeBody_Release(&body
->mime_body
->IMimeBody_iface
);
1996 HeapFree(GetProcessHeap(), 0, body
);
2000 static ULONG WINAPI
MimeMessage_Release(IMimeMessage
*iface
)
2002 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2003 ULONG ref
= InterlockedDecrement(&This
->ref
);
2005 TRACE("(%p) ref=%d\n", This
, ref
);
2009 empty_body_list(&This
->body_tree
);
2011 if(This
->stream
) IStream_Release(This
->stream
);
2012 HeapFree(GetProcessHeap(), 0, This
);
2018 /*** IPersist methods ***/
2019 static HRESULT WINAPI
MimeMessage_GetClassID(
2020 IMimeMessage
*iface
,
2023 FIXME("(%p)->(%p)\n", iface
, pClassID
);
2027 /*** IPersistStreamInit methods ***/
2028 static HRESULT WINAPI
MimeMessage_IsDirty(
2029 IMimeMessage
*iface
)
2031 FIXME("(%p)->()\n", iface
);
2035 static body_t
*new_body_entry(MimeBody
*mime_body
, DWORD index
, body_t
*parent
)
2037 body_t
*body
= HeapAlloc(GetProcessHeap(), 0, sizeof(*body
));
2040 body
->mime_body
= mime_body
;
2041 body
->index
= index
;
2042 list_init(&body
->children
);
2043 body
->parent
= parent
;
2045 mime_body
->handle
= UlongToHandle(body
->index
);
2053 BODYOFFSETS offsets
;
2056 static HRESULT
create_body_offset_list(IStream
*stm
, const char *boundary
, struct list
*body_offsets
)
2059 DWORD read
, boundary_start
;
2060 int boundary_len
= strlen(boundary
);
2061 char *buf
, *ptr
, *overlap
;
2062 DWORD start
= 0, overlap_no
;
2063 offset_entry_t
*cur_body
= NULL
;
2064 BOOL is_first_line
= TRUE
;
2068 list_init(body_offsets
);
2070 overlap_no
= boundary_len
+ 5;
2072 overlap
= buf
= HeapAlloc(GetProcessHeap(), 0, overlap_no
+ PARSER_BUF_SIZE
+ 1);
2075 hr
= IStream_Seek(stm
, zero
, STREAM_SEEK_CUR
, &cur
);
2076 start
= cur
.u
.LowPart
;
2079 hr
= IStream_Read(stm
, overlap
, PARSER_BUF_SIZE
, &read
);
2080 if(FAILED(hr
)) goto end
;
2081 if(read
== 0) break;
2082 overlap
[read
] = '\0';
2087 is_first_line
= FALSE
;
2089 ptr
= strstr(ptr
, "\r\n");
2095 boundary_start
= start
+ ptr
- buf
;
2097 if(*ptr
== '-' && *(ptr
+ 1) == '-' && !memcmp(ptr
+ 2, boundary
, boundary_len
)) {
2098 ptr
+= boundary_len
+ 2;
2100 if(*ptr
== '\r' && *(ptr
+ 1) == '\n')
2105 cur_body
->offsets
.cbBodyEnd
= boundary_start
- 2;
2106 list_add_tail(body_offsets
, &cur_body
->entry
);
2108 cur_body
= HeapAlloc(GetProcessHeap(), 0, sizeof(*cur_body
));
2109 cur_body
->offsets
.cbBoundaryStart
= boundary_start
;
2110 cur_body
->offsets
.cbHeaderStart
= start
+ ptr
- buf
;
2112 else if(*ptr
== '-' && *(ptr
+ 1) == '-')
2116 cur_body
->offsets
.cbBodyEnd
= boundary_start
- 2;
2117 list_add_tail(body_offsets
, &cur_body
->entry
);
2124 if(overlap
== buf
) /* 1st iteration */
2126 memmove(buf
, buf
+ PARSER_BUF_SIZE
- overlap_no
, overlap_no
);
2127 overlap
= buf
+ overlap_no
;
2128 start
+= read
- overlap_no
;
2132 memmove(buf
, buf
+ PARSER_BUF_SIZE
, overlap_no
);
2138 HeapFree(GetProcessHeap(), 0, buf
);
2142 static body_t
*create_sub_body(MimeMessage
*msg
, IStream
*pStm
, BODYOFFSETS
*offset
, body_t
*parent
)
2144 ULARGE_INTEGER start
, length
;
2145 MimeBody
*mime_body
;
2150 pos
.QuadPart
= offset
->cbHeaderStart
;
2151 IStream_Seek(pStm
, pos
, STREAM_SEEK_SET
, NULL
);
2153 mime_body
= mimebody_create();
2154 IMimeBody_Load(&mime_body
->IMimeBody_iface
, pStm
);
2157 hr
= IStream_Seek(pStm
, pos
, STREAM_SEEK_CUR
, &start
);
2158 offset
->cbBodyStart
= start
.QuadPart
;
2159 if (parent
) MimeBody_set_offsets(mime_body
, offset
);
2161 length
.QuadPart
= offset
->cbBodyEnd
- offset
->cbBodyStart
;
2162 create_sub_stream(pStm
, start
, length
, (IStream
**)&mime_body
->data
);
2163 mime_body
->data_iid
= IID_IStream
;
2165 body
= new_body_entry(mime_body
, msg
->next_index
++, parent
);
2167 if(IMimeBody_IsContentType(&mime_body
->IMimeBody_iface
, "multipart", NULL
) == S_OK
)
2169 MIMEPARAMINFO
*param_info
;
2171 IMimeAllocator
*alloc
;
2173 hr
= IMimeBody_GetParameters(&mime_body
->IMimeBody_iface
, "Content-Type", &count
,
2175 if(hr
!= S_OK
|| count
== 0) return body
;
2177 MimeOleGetAllocator(&alloc
);
2179 for(i
= 0; i
< count
; i
++)
2181 if(!lstrcmpiA(param_info
[i
].pszName
, "boundary"))
2183 struct list offset_list
;
2184 offset_entry_t
*cur
, *cursor2
;
2185 hr
= create_body_offset_list(pStm
, param_info
[i
].pszData
, &offset_list
);
2186 LIST_FOR_EACH_ENTRY_SAFE(cur
, cursor2
, &offset_list
, offset_entry_t
, entry
)
2190 sub_body
= create_sub_body(msg
, pStm
, &cur
->offsets
, body
);
2191 list_add_tail(&body
->children
, &sub_body
->entry
);
2192 list_remove(&cur
->entry
);
2193 HeapFree(GetProcessHeap(), 0, cur
);
2198 IMimeAllocator_FreeParamInfoArray(alloc
, count
, param_info
, TRUE
);
2199 IMimeAllocator_Release(alloc
);
2204 static HRESULT WINAPI
MimeMessage_Load(IMimeMessage
*iface
, IStream
*pStm
)
2206 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2208 BODYOFFSETS offsets
;
2212 TRACE("(%p)->(%p)\n", iface
, pStm
);
2216 FIXME("already loaded a message\n");
2220 empty_body_list(&This
->body_tree
);
2222 IStream_AddRef(pStm
);
2223 This
->stream
= pStm
;
2224 offsets
.cbBoundaryStart
= offsets
.cbHeaderStart
= 0;
2225 offsets
.cbBodyStart
= offsets
.cbBodyEnd
= 0;
2227 root_body
= create_sub_body(This
, pStm
, &offsets
, NULL
);
2230 IStream_Seek(pStm
, zero
, STREAM_SEEK_END
, &cur
);
2231 offsets
.cbBodyEnd
= cur
.u
.LowPart
;
2232 MimeBody_set_offsets(root_body
->mime_body
, &offsets
);
2234 list_add_head(&This
->body_tree
, &root_body
->entry
);
2239 static HRESULT WINAPI
MimeMessage_Save(IMimeMessage
*iface
, IStream
*pStm
, BOOL fClearDirty
)
2241 FIXME("(%p)->(%p, %s)\n", iface
, pStm
, fClearDirty
? "TRUE" : "FALSE");
2245 static HRESULT WINAPI
MimeMessage_GetSizeMax(
2246 IMimeMessage
*iface
,
2247 ULARGE_INTEGER
*pcbSize
)
2249 FIXME("(%p)->(%p)\n", iface
, pcbSize
);
2253 static HRESULT WINAPI
MimeMessage_InitNew(
2254 IMimeMessage
*iface
)
2256 FIXME("(%p)->()\n", iface
);
2260 /*** IMimeMessageTree methods ***/
2261 static HRESULT WINAPI
MimeMessage_GetMessageSource(IMimeMessage
*iface
, IStream
**ppStream
,
2264 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2266 FIXME("(%p)->(%p, 0x%x)\n", iface
, ppStream
, dwFlags
);
2268 IStream_AddRef(This
->stream
);
2269 *ppStream
= This
->stream
;
2273 static HRESULT WINAPI
MimeMessage_GetMessageSize(
2274 IMimeMessage
*iface
,
2278 FIXME("(%p)->(%p, 0x%x)\n", iface
, pcbSize
, dwFlags
);
2282 static HRESULT WINAPI
MimeMessage_LoadOffsetTable(
2283 IMimeMessage
*iface
,
2286 FIXME("(%p)->(%p)\n", iface
, pStream
);
2290 static HRESULT WINAPI
MimeMessage_SaveOffsetTable(
2291 IMimeMessage
*iface
,
2295 FIXME("(%p)->(%p, 0x%x)\n", iface
, pStream
, dwFlags
);
2300 static HRESULT WINAPI
MimeMessage_GetFlags(
2301 IMimeMessage
*iface
,
2304 FIXME("(%p)->(%p)\n", iface
, pdwFlags
);
2308 static HRESULT WINAPI
MimeMessage_Commit(
2309 IMimeMessage
*iface
,
2312 FIXME("(%p)->(0x%x)\n", iface
, dwFlags
);
2317 static HRESULT WINAPI
MimeMessage_HandsOffStorage(
2318 IMimeMessage
*iface
)
2320 FIXME("(%p)->()\n", iface
);
2324 static HRESULT
find_body(struct list
*list
, HBODY hbody
, body_t
**body
)
2329 if(hbody
== HBODY_ROOT
)
2331 *body
= LIST_ENTRY(list_head(list
), body_t
, entry
);
2335 LIST_FOR_EACH_ENTRY(cur
, list
, body_t
, entry
)
2337 if(cur
->index
== HandleToUlong(hbody
))
2342 hr
= find_body(&cur
->children
, hbody
, body
);
2343 if(hr
== S_OK
) return S_OK
;
2348 static HRESULT WINAPI
MimeMessage_BindToObject(IMimeMessage
*iface
, const HBODY hBody
, REFIID riid
,
2351 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2355 TRACE("(%p)->(%p, %s, %p)\n", iface
, hBody
, debugstr_guid(riid
), ppvObject
);
2357 hr
= find_body(&This
->body_tree
, hBody
, &body
);
2359 if(hr
!= S_OK
) return hr
;
2361 if(IsEqualIID(riid
, &IID_IMimeBody
))
2363 IMimeBody_AddRef(&body
->mime_body
->IMimeBody_iface
);
2364 *ppvObject
= &body
->mime_body
->IMimeBody_iface
;
2368 return E_NOINTERFACE
;
2371 static HRESULT WINAPI
MimeMessage_SaveBody(
2372 IMimeMessage
*iface
,
2377 FIXME("(%p)->(%p, 0x%x, %p)\n", iface
, hBody
, dwFlags
, pStream
);
2381 static HRESULT
get_body(MimeMessage
*msg
, BODYLOCATION location
, HBODY pivot
, body_t
**out
)
2383 body_t
*root
= LIST_ENTRY(list_head(&msg
->body_tree
), body_t
, entry
);
2388 if(location
== IBL_ROOT
)
2394 hr
= find_body(&msg
->body_tree
, pivot
, &body
);
2402 *out
= body
->parent
;
2404 hr
= MIME_E_NOT_FOUND
;
2408 list
= list_head(&body
->children
);
2410 *out
= LIST_ENTRY(list
, body_t
, entry
);
2412 hr
= MIME_E_NOT_FOUND
;
2416 list
= list_tail(&body
->children
);
2418 *out
= LIST_ENTRY(list
, body_t
, entry
);
2420 hr
= MIME_E_NOT_FOUND
;
2424 list
= list_next(&body
->parent
->children
, &body
->entry
);
2426 *out
= LIST_ENTRY(list
, body_t
, entry
);
2428 hr
= MIME_E_NOT_FOUND
;
2432 list
= list_prev(&body
->parent
->children
, &body
->entry
);
2434 *out
= LIST_ENTRY(list
, body_t
, entry
);
2436 hr
= MIME_E_NOT_FOUND
;
2449 static HRESULT WINAPI
MimeMessage_InsertBody(
2450 IMimeMessage
*iface
,
2451 BODYLOCATION location
,
2455 FIXME("(%p)->(%d, %p, %p)\n", iface
, location
, hPivot
, phBody
);
2459 static HRESULT WINAPI
MimeMessage_GetBody(IMimeMessage
*iface
, BODYLOCATION location
, HBODY hPivot
,
2462 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2466 TRACE("(%p)->(%d, %p, %p)\n", iface
, location
, hPivot
, phBody
);
2469 return E_INVALIDARG
;
2473 hr
= get_body(This
, location
, hPivot
, &body
);
2475 if(hr
== S_OK
) *phBody
= UlongToHandle(body
->index
);
2480 static HRESULT WINAPI
MimeMessage_DeleteBody(
2481 IMimeMessage
*iface
,
2485 FIXME("(%p)->(%p, %08x)\n", iface
, hBody
, dwFlags
);
2489 static HRESULT WINAPI
MimeMessage_MoveBody(
2490 IMimeMessage
*iface
,
2492 BODYLOCATION location
)
2494 FIXME("(%p)->(%d)\n", iface
, location
);
2498 static void count_children(body_t
*body
, boolean recurse
, ULONG
*count
)
2502 LIST_FOR_EACH_ENTRY(child
, &body
->children
, body_t
, entry
)
2505 if(recurse
) count_children(child
, recurse
, count
);
2509 static HRESULT WINAPI
MimeMessage_CountBodies(IMimeMessage
*iface
, HBODY hParent
, boolean fRecurse
,
2513 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2516 TRACE("(%p)->(%p, %s, %p)\n", iface
, hParent
, fRecurse
? "TRUE" : "FALSE", pcBodies
);
2518 hr
= find_body(&This
->body_tree
, hParent
, &body
);
2519 if(hr
!= S_OK
) return hr
;
2522 count_children(body
, fRecurse
, pcBodies
);
2527 static HRESULT
find_next(MimeMessage
*This
, body_t
*body
, FINDBODY
*find
, HBODY
*out
)
2534 if (!body
) ptr
= list_head( &This
->body_tree
);
2537 ptr
= list_head( &body
->children
);
2540 if (!body
->parent
) return MIME_E_NOT_FOUND
;
2541 if (!(ptr
= list_next( &body
->parent
->children
, &body
->entry
))) body
= body
->parent
;
2545 body
= LIST_ENTRY( ptr
, body_t
, entry
);
2546 next
= UlongToHandle( body
->index
);
2547 find
->dwReserved
= body
->index
;
2548 if (IMimeBody_IsContentType(&body
->mime_body
->IMimeBody_iface
, find
->pszPriType
,
2549 find
->pszSubType
) == S_OK
)
2555 return MIME_E_NOT_FOUND
;
2558 static HRESULT WINAPI
MimeMessage_FindFirst(IMimeMessage
*iface
, FINDBODY
*pFindBody
, HBODY
*phBody
)
2560 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2562 TRACE("(%p)->(%p, %p)\n", iface
, pFindBody
, phBody
);
2564 pFindBody
->dwReserved
= 0;
2565 return find_next(This
, NULL
, pFindBody
, phBody
);
2568 static HRESULT WINAPI
MimeMessage_FindNext(IMimeMessage
*iface
, FINDBODY
*pFindBody
, HBODY
*phBody
)
2570 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2574 TRACE("(%p)->(%p, %p)\n", iface
, pFindBody
, phBody
);
2576 hr
= find_body( &This
->body_tree
, UlongToHandle( pFindBody
->dwReserved
), &body
);
2577 if (hr
!= S_OK
) return MIME_E_NOT_FOUND
;
2578 return find_next(This
, body
, pFindBody
, phBody
);
2581 static HRESULT WINAPI
MimeMessage_ResolveURL(
2582 IMimeMessage
*iface
,
2589 FIXME("(%p)->(%p, %s, %s, 0x%x, %p)\n", iface
, hRelated
, pszBase
, pszURL
, dwFlags
, phBody
);
2593 static HRESULT WINAPI
MimeMessage_ToMultipart(
2594 IMimeMessage
*iface
,
2597 LPHBODY phMultipart
)
2599 FIXME("(%p)->(%p, %s, %p)\n", iface
, hBody
, pszSubType
, phMultipart
);
2603 static HRESULT WINAPI
MimeMessage_GetBodyOffsets(
2604 IMimeMessage
*iface
,
2606 LPBODYOFFSETS pOffsets
)
2608 FIXME("(%p)->(%p, %p)\n", iface
, hBody
, pOffsets
);
2612 static HRESULT WINAPI
MimeMessage_GetCharset(
2613 IMimeMessage
*iface
,
2614 LPHCHARSET phCharset
)
2616 FIXME("(%p)->(%p)\n", iface
, phCharset
);
2621 static HRESULT WINAPI
MimeMessage_SetCharset(
2622 IMimeMessage
*iface
,
2624 CSETAPPLYTYPE applytype
)
2626 FIXME("(%p)->(%p, %d)\n", iface
, hCharset
, applytype
);
2630 static HRESULT WINAPI
MimeMessage_IsBodyType(
2631 IMimeMessage
*iface
,
2633 IMSGBODYTYPE bodytype
)
2636 IMimeBody
*mime_body
;
2637 TRACE("(%p)->(%p, %d)\n", iface
, hBody
, bodytype
);
2639 hr
= IMimeMessage_BindToObject(iface
, hBody
, &IID_IMimeBody
, (void**)&mime_body
);
2640 if(hr
!= S_OK
) return hr
;
2642 hr
= IMimeBody_IsType(mime_body
, bodytype
);
2643 MimeBody_Release(mime_body
);
2647 static HRESULT WINAPI
MimeMessage_IsContentType(
2648 IMimeMessage
*iface
,
2654 IMimeBody
*mime_body
;
2655 TRACE("(%p)->(%p, %s, %s)\n", iface
, hBody
, debugstr_a(pszPriType
),
2656 debugstr_a(pszSubType
));
2658 hr
= IMimeMessage_BindToObject(iface
, hBody
, &IID_IMimeBody
, (void**)&mime_body
);
2659 if(FAILED(hr
)) return hr
;
2661 hr
= IMimeBody_IsContentType(mime_body
, pszPriType
, pszSubType
);
2662 IMimeBody_Release(mime_body
);
2666 static HRESULT WINAPI
MimeMessage_QueryBodyProp(
2667 IMimeMessage
*iface
,
2672 boolean fCaseSensitive
)
2674 FIXME("(%p)->(%p, %s, %s, %s, %s)\n", iface
, hBody
, pszName
, pszCriteria
, fSubString
? "TRUE" : "FALSE", fCaseSensitive
? "TRUE" : "FALSE");
2678 static HRESULT WINAPI
MimeMessage_GetBodyProp(
2679 IMimeMessage
*iface
,
2683 LPPROPVARIANT pValue
)
2686 IMimeBody
*mime_body
;
2688 TRACE("(%p)->(%p, %s, 0x%x, %p)\n", iface
, hBody
, pszName
, dwFlags
, pValue
);
2690 hr
= IMimeMessage_BindToObject(iface
, hBody
, &IID_IMimeBody
, (void**)&mime_body
);
2691 if(hr
!= S_OK
) return hr
;
2693 hr
= IMimeBody_GetProp(mime_body
, pszName
, dwFlags
, pValue
);
2694 IMimeBody_Release(mime_body
);
2699 static HRESULT WINAPI
MimeMessage_SetBodyProp(
2700 IMimeMessage
*iface
,
2704 LPCPROPVARIANT pValue
)
2706 FIXME("(%p)->(%p, %s, 0x%x, %p)\n", iface
, hBody
, pszName
, dwFlags
, pValue
);
2710 static HRESULT WINAPI
MimeMessage_DeleteBodyProp(
2711 IMimeMessage
*iface
,
2715 FIXME("(%p)->(%p, %s)\n", iface
, hBody
, pszName
);
2719 static HRESULT WINAPI
MimeMessage_SetOption(
2720 IMimeMessage
*iface
,
2722 LPCPROPVARIANT pValue
)
2725 TRACE("(%p)->(%08x, %p)\n", iface
, oid
, pValue
);
2727 /* Message ID is checked before type.
2728 * OID 0x4D -> 0x56 and 0x58 aren't defined but will filtered out later.
2730 if(TYPEDID_ID(oid
) < TYPEDID_ID(OID_ALLOW_8BIT_HEADER
) || TYPEDID_ID(oid
) > TYPEDID_ID(OID_SECURITY_2KEY_CERT_BAG_64
))
2732 WARN("oid (%08x) out of range\n", oid
);
2733 return MIME_E_INVALID_OPTION_ID
;
2736 if(pValue
->vt
!= TYPEDID_TYPE(oid
))
2738 WARN("Called with vartype %04x and oid %08x\n", pValue
->vt
, oid
);
2744 case OID_HIDE_TNEF_ATTACHMENTS
:
2745 FIXME("OID_HIDE_TNEF_ATTACHMENTS (value %d): ignoring\n", pValue
->u
.boolVal
);
2747 case OID_SHOW_MACBINARY
:
2748 FIXME("OID_SHOW_MACBINARY (value %d): ignoring\n", pValue
->u
.boolVal
);
2750 case OID_SAVEBODY_KEEPBOUNDARY
:
2751 FIXME("OID_SAVEBODY_KEEPBOUNDARY (value %d): ignoring\n", pValue
->u
.boolVal
);
2753 case OID_CLEANUP_TREE_ON_SAVE
:
2754 FIXME("OID_CLEANUP_TREE_ON_SAVE (value %d): ignoring\n", pValue
->u
.boolVal
);
2757 FIXME("Unhandled oid %08x\n", oid
);
2758 hr
= MIME_E_INVALID_OPTION_ID
;
2764 static HRESULT WINAPI
MimeMessage_GetOption(
2765 IMimeMessage
*iface
,
2767 LPPROPVARIANT pValue
)
2769 FIXME("(%p)->(%08x, %p)\n", iface
, oid
, pValue
);
2773 /*** IMimeMessage methods ***/
2774 static HRESULT WINAPI
MimeMessage_CreateWebPage(
2775 IMimeMessage
*iface
,
2777 LPWEBPAGEOPTIONS pOptions
,
2778 IMimeMessageCallback
*pCallback
,
2779 IMoniker
**ppMoniker
)
2781 FIXME("(%p)->(%p, %p, %p, %p)\n", iface
, pRootStm
, pOptions
, pCallback
, ppMoniker
);
2786 static HRESULT WINAPI
MimeMessage_GetProp(
2787 IMimeMessage
*iface
,
2790 LPPROPVARIANT pValue
)
2792 FIXME("(%p)->(%s, 0x%x, %p)\n", iface
, pszName
, dwFlags
, pValue
);
2796 static HRESULT WINAPI
MimeMessage_SetProp(
2797 IMimeMessage
*iface
,
2800 LPCPROPVARIANT pValue
)
2802 FIXME("(%p)->(%s, 0x%x, %p)\n", iface
, pszName
, dwFlags
, pValue
);
2806 static HRESULT WINAPI
MimeMessage_DeleteProp(
2807 IMimeMessage
*iface
,
2810 FIXME("(%p)->(%s)\n", iface
, pszName
);
2814 static HRESULT WINAPI
MimeMessage_QueryProp(
2815 IMimeMessage
*iface
,
2819 boolean fCaseSensitive
)
2821 FIXME("(%p)->(%s, %s, %s, %s)\n", iface
, pszName
, pszCriteria
, fSubString
? "TRUE" : "FALSE", fCaseSensitive
? "TRUE" : "FALSE");
2825 static HRESULT WINAPI
MimeMessage_GetTextBody(
2826 IMimeMessage
*iface
,
2828 ENCODINGTYPE ietEncoding
,
2834 FINDBODY find_struct
;
2835 IMimeBody
*mime_body
;
2836 static char text
[] = "text";
2837 static char plain
[] = "plain";
2838 static char html
[] = "html";
2840 TRACE("(%p)->(%d, %d, %p, %p)\n", iface
, dwTxtType
, ietEncoding
, pStream
, phBody
);
2842 find_struct
.pszPriType
= text
;
2847 find_struct
.pszSubType
= plain
;
2850 find_struct
.pszSubType
= html
;
2853 return MIME_E_INVALID_TEXT_TYPE
;
2856 hr
= IMimeMessage_FindFirst(iface
, &find_struct
, &hbody
);
2859 TRACE("not found hr %08x\n", hr
);
2864 IMimeMessage_BindToObject(iface
, hbody
, &IID_IMimeBody
, (void**)&mime_body
);
2866 IMimeBody_GetData(mime_body
, ietEncoding
, pStream
);
2868 IMimeBody_Release(mime_body
);
2872 static HRESULT WINAPI
MimeMessage_SetTextBody(
2873 IMimeMessage
*iface
,
2875 ENCODINGTYPE ietEncoding
,
2880 FIXME("(%p)->(%d, %d, %p, %p, %p)\n", iface
, dwTxtType
, ietEncoding
, hAlternative
, pStream
, phBody
);
2884 static HRESULT WINAPI
MimeMessage_AttachObject(
2885 IMimeMessage
*iface
,
2890 FIXME("(%p)->(%s, %p, %p)\n", iface
, debugstr_guid(riid
), pvObject
, phBody
);
2894 static HRESULT WINAPI
MimeMessage_AttachFile(
2895 IMimeMessage
*iface
,
2900 FIXME("(%p)->(%s, %p, %p)\n", iface
, pszFilePath
, pstmFile
, phBody
);
2904 static HRESULT WINAPI
MimeMessage_AttachURL(
2905 IMimeMessage
*iface
,
2913 FIXME("(%p)->(%s, %s, 0x%x, %p, %p, %p)\n", iface
, pszBase
, pszURL
, dwFlags
, pstmURL
, ppszCIDURL
, phBody
);
2917 static HRESULT WINAPI
MimeMessage_GetAttachments(
2918 IMimeMessage
*iface
,
2920 LPHBODY
*pprghAttach
)
2923 FINDBODY find_struct
;
2928 TRACE("(%p)->(%p, %p)\n", iface
, pcAttach
, pprghAttach
);
2931 array
= CoTaskMemAlloc(size
* sizeof(HBODY
));
2933 find_struct
.pszPriType
= find_struct
.pszSubType
= NULL
;
2934 hr
= IMimeMessage_FindFirst(iface
, &find_struct
, &hbody
);
2937 hr
= IMimeMessage_IsContentType(iface
, hbody
, "multipart", NULL
);
2938 TRACE("IsCT rets %08x %d\n", hr
, *pcAttach
);
2941 if(*pcAttach
+ 1 > size
)
2944 array
= CoTaskMemRealloc(array
, size
* sizeof(HBODY
));
2946 array
[*pcAttach
] = hbody
;
2949 hr
= IMimeMessage_FindNext(iface
, &find_struct
, &hbody
);
2952 *pprghAttach
= array
;
2956 static HRESULT WINAPI
MimeMessage_GetAddressTable(
2957 IMimeMessage
*iface
,
2958 IMimeAddressTable
**ppTable
)
2960 FIXME("(%p)->(%p)\n", iface
, ppTable
);
2964 static HRESULT WINAPI
MimeMessage_GetSender(
2965 IMimeMessage
*iface
,
2966 LPADDRESSPROPS pAddress
)
2968 FIXME("(%p)->(%p)\n", iface
, pAddress
);
2972 static HRESULT WINAPI
MimeMessage_GetAddressTypes(
2973 IMimeMessage
*iface
,
2976 LPADDRESSLIST pList
)
2978 FIXME("(%p)->(%d, %d, %p)\n", iface
, dwAdrTypes
, dwProps
, pList
);
2982 static HRESULT WINAPI
MimeMessage_GetAddressFormat(
2983 IMimeMessage
*iface
,
2985 ADDRESSFORMAT format
,
2988 FIXME("(%p)->(%d, %d, %p)\n", iface
, dwAdrTypes
, format
, ppszFormat
);
2992 static HRESULT WINAPI
MimeMessage_EnumAddressTypes(
2993 IMimeMessage
*iface
,
2996 IMimeEnumAddressTypes
**ppEnum
)
2998 FIXME("(%p)->(%d, %d, %p)\n", iface
, dwAdrTypes
, dwProps
, ppEnum
);
3002 static HRESULT WINAPI
MimeMessage_SplitMessage(
3003 IMimeMessage
*iface
,
3005 IMimeMessageParts
**ppParts
)
3007 FIXME("(%p)->(%d, %p)\n", iface
, cbMaxPart
, ppParts
);
3011 static HRESULT WINAPI
MimeMessage_GetRootMoniker(
3012 IMimeMessage
*iface
,
3013 IMoniker
**ppMoniker
)
3015 FIXME("(%p)->(%p)\n", iface
, ppMoniker
);
3019 static const IMimeMessageVtbl MimeMessageVtbl
=
3021 MimeMessage_QueryInterface
,
3023 MimeMessage_Release
,
3024 MimeMessage_GetClassID
,
3025 MimeMessage_IsDirty
,
3028 MimeMessage_GetSizeMax
,
3029 MimeMessage_InitNew
,
3030 MimeMessage_GetMessageSource
,
3031 MimeMessage_GetMessageSize
,
3032 MimeMessage_LoadOffsetTable
,
3033 MimeMessage_SaveOffsetTable
,
3034 MimeMessage_GetFlags
,
3036 MimeMessage_HandsOffStorage
,
3037 MimeMessage_BindToObject
,
3038 MimeMessage_SaveBody
,
3039 MimeMessage_InsertBody
,
3040 MimeMessage_GetBody
,
3041 MimeMessage_DeleteBody
,
3042 MimeMessage_MoveBody
,
3043 MimeMessage_CountBodies
,
3044 MimeMessage_FindFirst
,
3045 MimeMessage_FindNext
,
3046 MimeMessage_ResolveURL
,
3047 MimeMessage_ToMultipart
,
3048 MimeMessage_GetBodyOffsets
,
3049 MimeMessage_GetCharset
,
3050 MimeMessage_SetCharset
,
3051 MimeMessage_IsBodyType
,
3052 MimeMessage_IsContentType
,
3053 MimeMessage_QueryBodyProp
,
3054 MimeMessage_GetBodyProp
,
3055 MimeMessage_SetBodyProp
,
3056 MimeMessage_DeleteBodyProp
,
3057 MimeMessage_SetOption
,
3058 MimeMessage_GetOption
,
3059 MimeMessage_CreateWebPage
,
3060 MimeMessage_GetProp
,
3061 MimeMessage_SetProp
,
3062 MimeMessage_DeleteProp
,
3063 MimeMessage_QueryProp
,
3064 MimeMessage_GetTextBody
,
3065 MimeMessage_SetTextBody
,
3066 MimeMessage_AttachObject
,
3067 MimeMessage_AttachFile
,
3068 MimeMessage_AttachURL
,
3069 MimeMessage_GetAttachments
,
3070 MimeMessage_GetAddressTable
,
3071 MimeMessage_GetSender
,
3072 MimeMessage_GetAddressTypes
,
3073 MimeMessage_GetAddressFormat
,
3074 MimeMessage_EnumAddressTypes
,
3075 MimeMessage_SplitMessage
,
3076 MimeMessage_GetRootMoniker
,
3079 HRESULT
MimeMessage_create(IUnknown
*outer
, void **obj
)
3082 MimeBody
*mime_body
;
3085 TRACE("(%p, %p)\n", outer
, obj
);
3089 FIXME("outer unknown not supported yet\n");
3095 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
3096 if (!This
) return E_OUTOFMEMORY
;
3098 This
->IMimeMessage_iface
.lpVtbl
= &MimeMessageVtbl
;
3100 This
->stream
= NULL
;
3101 list_init(&This
->body_tree
);
3102 This
->next_index
= 1;
3104 mime_body
= mimebody_create();
3105 root_body
= new_body_entry(mime_body
, This
->next_index
++, NULL
);
3106 list_add_head(&This
->body_tree
, &root_body
->entry
);
3108 *obj
= &This
->IMimeMessage_iface
;
3112 /***********************************************************************
3113 * MimeOleCreateMessage (INETCOMM.@)
3115 HRESULT WINAPI
MimeOleCreateMessage(IUnknown
*pUnkOuter
, IMimeMessage
**ppMessage
)
3117 TRACE("(%p, %p)\n", pUnkOuter
, ppMessage
);
3118 return MimeMessage_create(NULL
, (void **)ppMessage
);
3121 /***********************************************************************
3122 * MimeOleSetCompatMode (INETCOMM.@)
3124 HRESULT WINAPI
MimeOleSetCompatMode(DWORD dwMode
)
3126 FIXME("(0x%x)\n", dwMode
);
3130 /***********************************************************************
3131 * MimeOleCreateVirtualStream (INETCOMM.@)
3133 HRESULT WINAPI
MimeOleCreateVirtualStream(IStream
**ppStream
)
3136 FIXME("(%p)\n", ppStream
);
3138 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, ppStream
);
3142 typedef struct MimeSecurity
3144 IMimeSecurity IMimeSecurity_iface
;
3148 static inline MimeSecurity
*impl_from_IMimeSecurity(IMimeSecurity
*iface
)
3150 return CONTAINING_RECORD(iface
, MimeSecurity
, IMimeSecurity_iface
);
3153 static HRESULT WINAPI
MimeSecurity_QueryInterface(IMimeSecurity
*iface
, REFIID riid
, void **ppv
)
3155 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
3157 if (IsEqualIID(riid
, &IID_IUnknown
) ||
3158 IsEqualIID(riid
, &IID_IMimeSecurity
))
3161 IMimeSecurity_AddRef(iface
);
3165 FIXME("no interface for %s\n", debugstr_guid(riid
));
3167 return E_NOINTERFACE
;
3170 static ULONG WINAPI
MimeSecurity_AddRef(IMimeSecurity
*iface
)
3172 MimeSecurity
*This
= impl_from_IMimeSecurity(iface
);
3173 LONG ref
= InterlockedIncrement(&This
->ref
);
3175 TRACE("(%p) ref=%d\n", This
, ref
);
3180 static ULONG WINAPI
MimeSecurity_Release(IMimeSecurity
*iface
)
3182 MimeSecurity
*This
= impl_from_IMimeSecurity(iface
);
3183 LONG ref
= InterlockedDecrement(&This
->ref
);
3185 TRACE("(%p) ref=%d\n", This
, ref
);
3188 HeapFree(GetProcessHeap(), 0, This
);
3193 static HRESULT WINAPI
MimeSecurity_InitNew(
3194 IMimeSecurity
* iface
)
3196 FIXME("(%p)->(): stub\n", iface
);
3200 static HRESULT WINAPI
MimeSecurity_CheckInit(
3201 IMimeSecurity
* iface
)
3203 FIXME("(%p)->(): stub\n", iface
);
3207 static HRESULT WINAPI
MimeSecurity_EncodeMessage(
3208 IMimeSecurity
* iface
,
3209 IMimeMessageTree
* pTree
,
3212 FIXME("(%p)->(%p, %08x): stub\n", iface
, pTree
, dwFlags
);
3216 static HRESULT WINAPI
MimeSecurity_EncodeBody(
3217 IMimeSecurity
* iface
,
3218 IMimeMessageTree
* pTree
,
3222 FIXME("(%p)->(%p, %p, %08x): stub\n", iface
, pTree
, hEncodeRoot
, dwFlags
);
3226 static HRESULT WINAPI
MimeSecurity_DecodeMessage(
3227 IMimeSecurity
* iface
,
3228 IMimeMessageTree
* pTree
,
3231 FIXME("(%p)->(%p, %08x): stub\n", iface
, pTree
, dwFlags
);
3235 static HRESULT WINAPI
MimeSecurity_DecodeBody(
3236 IMimeSecurity
* iface
,
3237 IMimeMessageTree
* pTree
,
3241 FIXME("(%p)->(%p, %p, %08x): stub\n", iface
, pTree
, hDecodeRoot
, dwFlags
);
3245 static HRESULT WINAPI
MimeSecurity_EnumCertificates(
3246 IMimeSecurity
* iface
,
3252 FIXME("(%p)->(%p, %08x, %p, %p): stub\n", iface
, hc
, dwUsage
, pPrev
, ppCert
);
3256 static HRESULT WINAPI
MimeSecurity_GetCertificateName(
3257 IMimeSecurity
* iface
,
3258 const PCX509CERT pX509Cert
,
3259 const CERTNAMETYPE cn
,
3262 FIXME("(%p)->(%p, %08x, %p): stub\n", iface
, pX509Cert
, cn
, ppszName
);
3266 static HRESULT WINAPI
MimeSecurity_GetMessageType(
3267 IMimeSecurity
* iface
,
3268 const HWND hwndParent
,
3272 FIXME("(%p)->(%p, %p, %p): stub\n", iface
, hwndParent
, pBody
, pdwSecType
);
3276 static HRESULT WINAPI
MimeSecurity_GetCertData(
3277 IMimeSecurity
* iface
,
3278 const PCX509CERT pX509Cert
,
3279 const CERTDATAID dataid
,
3280 LPPROPVARIANT pValue
)
3282 FIXME("(%p)->(%p, %x, %p): stub\n", iface
, pX509Cert
, dataid
, pValue
);
3287 static const IMimeSecurityVtbl MimeSecurityVtbl
=
3289 MimeSecurity_QueryInterface
,
3290 MimeSecurity_AddRef
,
3291 MimeSecurity_Release
,
3292 MimeSecurity_InitNew
,
3293 MimeSecurity_CheckInit
,
3294 MimeSecurity_EncodeMessage
,
3295 MimeSecurity_EncodeBody
,
3296 MimeSecurity_DecodeMessage
,
3297 MimeSecurity_DecodeBody
,
3298 MimeSecurity_EnumCertificates
,
3299 MimeSecurity_GetCertificateName
,
3300 MimeSecurity_GetMessageType
,
3301 MimeSecurity_GetCertData
3304 HRESULT
MimeSecurity_create(IUnknown
*outer
, void **obj
)
3310 if (outer
) return CLASS_E_NOAGGREGATION
;
3312 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
3313 if (!This
) return E_OUTOFMEMORY
;
3315 This
->IMimeSecurity_iface
.lpVtbl
= &MimeSecurityVtbl
;
3318 *obj
= &This
->IMimeSecurity_iface
;
3322 /***********************************************************************
3323 * MimeOleCreateSecurity (INETCOMM.@)
3325 HRESULT WINAPI
MimeOleCreateSecurity(IMimeSecurity
**ppSecurity
)
3327 return MimeSecurity_create(NULL
, (void **)ppSecurity
);
3330 static HRESULT WINAPI
MimeAlloc_QueryInterface(
3331 IMimeAllocator
* iface
,
3335 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), obj
);
3337 if (IsEqualIID(riid
, &IID_IUnknown
) ||
3338 IsEqualIID(riid
, &IID_IMalloc
) ||
3339 IsEqualIID(riid
, &IID_IMimeAllocator
))
3342 IMimeAllocator_AddRef(iface
);
3346 FIXME("no interface for %s\n", debugstr_guid(riid
));
3348 return E_NOINTERFACE
;
3351 static ULONG WINAPI
MimeAlloc_AddRef(
3352 IMimeAllocator
* iface
)
3357 static ULONG WINAPI
MimeAlloc_Release(
3358 IMimeAllocator
* iface
)
3363 static LPVOID WINAPI
MimeAlloc_Alloc(
3364 IMimeAllocator
* iface
,
3367 return CoTaskMemAlloc(cb
);
3370 static LPVOID WINAPI
MimeAlloc_Realloc(
3371 IMimeAllocator
* iface
,
3375 return CoTaskMemRealloc(pv
, cb
);
3378 static void WINAPI
MimeAlloc_Free(
3379 IMimeAllocator
* iface
,
3385 static SIZE_T WINAPI
MimeAlloc_GetSize(
3386 IMimeAllocator
* iface
,
3393 static int WINAPI
MimeAlloc_DidAlloc(
3394 IMimeAllocator
* iface
,
3401 static void WINAPI
MimeAlloc_HeapMinimize(
3402 IMimeAllocator
* iface
)
3408 static HRESULT WINAPI
MimeAlloc_FreeParamInfoArray(
3409 IMimeAllocator
* iface
,
3411 LPMIMEPARAMINFO prgParam
,
3415 TRACE("(%p)->(%d, %p, %d)\n", iface
, cParams
, prgParam
, fFreeArray
);
3417 for(i
= 0; i
< cParams
; i
++)
3419 IMimeAllocator_Free(iface
, prgParam
[i
].pszName
);
3420 IMimeAllocator_Free(iface
, prgParam
[i
].pszData
);
3422 if(fFreeArray
) IMimeAllocator_Free(iface
, prgParam
);
3426 static HRESULT WINAPI
MimeAlloc_FreeAddressList(
3427 IMimeAllocator
* iface
,
3428 LPADDRESSLIST pList
)
3434 static HRESULT WINAPI
MimeAlloc_FreeAddressProps(
3435 IMimeAllocator
* iface
,
3436 LPADDRESSPROPS pAddress
)
3442 static HRESULT WINAPI
MimeAlloc_ReleaseObjects(
3443 IMimeAllocator
* iface
,
3445 IUnknown
**prgpUnknown
,
3453 static HRESULT WINAPI
MimeAlloc_FreeEnumHeaderRowArray(
3454 IMimeAllocator
* iface
,
3456 LPENUMHEADERROW prgRow
,
3463 static HRESULT WINAPI
MimeAlloc_FreeEnumPropertyArray(
3464 IMimeAllocator
* iface
,
3466 LPENUMPROPERTY prgProp
,
3473 static HRESULT WINAPI
MimeAlloc_FreeThumbprint(
3474 IMimeAllocator
* iface
,
3475 THUMBBLOB
*pthumbprint
)
3482 static HRESULT WINAPI
MimeAlloc_PropVariantClear(
3483 IMimeAllocator
* iface
,
3484 LPPROPVARIANT pProp
)
3490 static IMimeAllocatorVtbl mime_alloc_vtbl
=
3492 MimeAlloc_QueryInterface
,
3500 MimeAlloc_HeapMinimize
,
3501 MimeAlloc_FreeParamInfoArray
,
3502 MimeAlloc_FreeAddressList
,
3503 MimeAlloc_FreeAddressProps
,
3504 MimeAlloc_ReleaseObjects
,
3505 MimeAlloc_FreeEnumHeaderRowArray
,
3506 MimeAlloc_FreeEnumPropertyArray
,
3507 MimeAlloc_FreeThumbprint
,
3508 MimeAlloc_PropVariantClear
3511 static IMimeAllocator mime_allocator
=
3516 HRESULT
MimeAllocator_create(IUnknown
*outer
, void **obj
)
3518 if(outer
) return CLASS_E_NOAGGREGATION
;
3520 *obj
= &mime_allocator
;
3524 HRESULT WINAPI
MimeOleGetAllocator(IMimeAllocator
**alloc
)
3526 return MimeAllocator_create(NULL
, (void**)alloc
);
3529 HRESULT
VirtualStream_create(IUnknown
*outer
, void **obj
)
3531 FIXME("(%p, %p)\n", outer
, obj
);
3534 if (outer
) return CLASS_E_NOAGGREGATION
;
3536 return MimeOleCreateVirtualStream((IStream
**)obj
);
3539 /* IMimePropertySchema Interface */
3540 static HRESULT WINAPI
propschema_QueryInterface(IMimePropertySchema
*iface
, REFIID riid
, void **out
)
3542 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3543 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), out
);
3547 if (IsEqualIID(riid
, &IID_IUnknown
) ||
3548 IsEqualIID(riid
, &IID_IMimePropertySchema
))
3554 FIXME("no interface for %s\n", debugstr_guid(riid
));
3555 return E_NOINTERFACE
;
3558 IMimePropertySchema_AddRef(iface
);
3562 static ULONG WINAPI
propschema_AddRef(IMimePropertySchema
*iface
)
3564 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3565 LONG ref
= InterlockedIncrement(&This
->ref
);
3567 TRACE("(%p) ref=%d\n", This
, ref
);
3572 static ULONG WINAPI
propschema_Release(IMimePropertySchema
*iface
)
3574 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3575 LONG ref
= InterlockedDecrement(&This
->ref
);
3577 TRACE("(%p) ref=%d\n", This
, ref
);
3581 HeapFree(GetProcessHeap(), 0, This
);
3587 static HRESULT WINAPI
propschema_RegisterProperty(IMimePropertySchema
*iface
, const char *name
, DWORD flags
,
3588 DWORD rownumber
, VARTYPE vtdefault
, DWORD
*propid
)
3590 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3591 FIXME("(%p)->(%s, %x, %d, %d, %p) stub\n", This
, debugstr_a(name
), flags
, rownumber
, vtdefault
, propid
);
3595 static HRESULT WINAPI
propschema_ModifyProperty(IMimePropertySchema
*iface
, const char *name
, DWORD flags
,
3596 DWORD rownumber
, VARTYPE vtdefault
)
3598 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3599 FIXME("(%p)->(%s, %x, %d, %d) stub\n", This
, debugstr_a(name
), flags
, rownumber
, vtdefault
);
3603 static HRESULT WINAPI
propschema_GetPropertyId(IMimePropertySchema
*iface
, const char *name
, DWORD
*propid
)
3605 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3606 FIXME("(%p)->(%s, %p) stub\n", This
, debugstr_a(name
), propid
);
3610 static HRESULT WINAPI
propschema_GetPropertyName(IMimePropertySchema
*iface
, DWORD propid
, char **name
)
3612 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3613 FIXME("(%p)->(%d, %p) stub\n", This
, propid
, name
);
3617 static HRESULT WINAPI
propschema_RegisterAddressType(IMimePropertySchema
*iface
, const char *name
, DWORD
*adrtype
)
3619 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3620 FIXME("(%p)->(%s, %p) stub\n", This
, debugstr_a(name
), adrtype
);
3624 static IMimePropertySchemaVtbl prop_schema_vtbl
=
3626 propschema_QueryInterface
,
3629 propschema_RegisterProperty
,
3630 propschema_ModifyProperty
,
3631 propschema_GetPropertyId
,
3632 propschema_GetPropertyName
,
3633 propschema_RegisterAddressType
3637 HRESULT WINAPI
MimeOleGetPropertySchema(IMimePropertySchema
**schema
)
3641 TRACE("(%p) stub\n", schema
);
3643 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
3645 return E_OUTOFMEMORY
;
3647 This
->IMimePropertySchema_iface
.lpVtbl
= &prop_schema_vtbl
;
3650 *schema
= &This
->IMimePropertySchema_iface
;
3655 HRESULT WINAPI
MimeGetAddressFormatW(REFIID riid
, void *object
, DWORD addr_type
,
3656 ADDRESSFORMAT addr_format
, WCHAR
**address
)
3658 FIXME("(%s, %p, %d, %d, %p) stub\n", debugstr_guid(riid
), object
, addr_type
, addr_format
, address
);
3663 static HRESULT WINAPI
mime_obj_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3665 FIXME("(%s %p)\n", debugstr_guid(riid
), ppv
);
3667 return E_NOINTERFACE
;
3670 static ULONG WINAPI
mime_obj_AddRef(IUnknown
*iface
)
3676 static ULONG WINAPI
mime_obj_Release(IUnknown
*iface
)
3682 static const IUnknownVtbl mime_obj_vtbl
= {
3683 mime_obj_QueryInterface
,
3688 static IUnknown mime_obj
= { &mime_obj_vtbl
};
3690 HRESULT WINAPI
MimeOleObjectFromMoniker(BINDF bindf
, IMoniker
*moniker
, IBindCtx
*binding
,
3691 REFIID riid
, void **out
, IMoniker
**moniker_new
)
3693 WCHAR
*display_name
, *mhtml_url
;
3697 static const WCHAR mhtml_prefixW
[] = {'m','h','t','m','l',':'};
3699 WARN("(0x%08x, %p, %p, %s, %p, %p) semi-stub\n", bindf
, moniker
, binding
, debugstr_guid(riid
), out
, moniker_new
);
3701 if(!IsEqualGUID(&IID_IUnknown
, riid
)) {
3702 FIXME("Unsupported riid %s\n", debugstr_guid(riid
));
3703 return E_NOINTERFACE
;
3706 hres
= IMoniker_GetDisplayName(moniker
, NULL
, NULL
, &display_name
);
3710 TRACE("display name %s\n", debugstr_w(display_name
));
3712 len
= strlenW(display_name
);
3713 mhtml_url
= heap_alloc((len
+1)*sizeof(WCHAR
) + sizeof(mhtml_prefixW
));
3715 return E_OUTOFMEMORY
;
3717 memcpy(mhtml_url
, mhtml_prefixW
, sizeof(mhtml_prefixW
));
3718 strcpyW(mhtml_url
+ sizeof(mhtml_prefixW
)/sizeof(WCHAR
), display_name
);
3719 HeapFree(GetProcessHeap(), 0, display_name
);
3721 hres
= CreateURLMoniker(NULL
, mhtml_url
, moniker_new
);
3722 heap_free(mhtml_url
);
3726 /* FIXME: We most likely should start binding here and return something more meaningful as mime object. */