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
;
171 IStream IStream_iface
;
174 ULARGE_INTEGER pos
, start
, length
;
177 static inline sub_stream_t
*impl_from_IStream(IStream
*iface
)
179 return CONTAINING_RECORD(iface
, sub_stream_t
, IStream_iface
);
182 static HRESULT WINAPI
sub_stream_QueryInterface(IStream
*iface
, REFIID riid
, void **ppv
)
184 sub_stream_t
*This
= impl_from_IStream(iface
);
186 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
189 if(IsEqualIID(riid
, &IID_IUnknown
) ||
190 IsEqualIID(riid
, &IID_ISequentialStream
) ||
191 IsEqualIID(riid
, &IID_IStream
))
193 IStream_AddRef(iface
);
197 return E_NOINTERFACE
;
200 static ULONG WINAPI
sub_stream_AddRef(IStream
*iface
)
202 sub_stream_t
*This
= impl_from_IStream(iface
);
203 LONG ref
= InterlockedIncrement(&This
->ref
);
205 TRACE("(%p) ref=%d\n", This
, ref
);
210 static ULONG WINAPI
sub_stream_Release(IStream
*iface
)
212 sub_stream_t
*This
= impl_from_IStream(iface
);
213 LONG ref
= InterlockedDecrement(&This
->ref
);
215 TRACE("(%p) ref=%d\n", This
, ref
);
219 IStream_Release(This
->base
);
220 HeapFree(GetProcessHeap(), 0, This
);
225 static HRESULT WINAPI
sub_stream_Read(
231 sub_stream_t
*This
= impl_from_IStream(iface
);
233 LARGE_INTEGER tmp_pos
;
235 TRACE("(%p, %d, %p)\n", pv
, cb
, pcbRead
);
237 tmp_pos
.QuadPart
= This
->pos
.QuadPart
+ This
->start
.QuadPart
;
238 IStream_Seek(This
->base
, tmp_pos
, STREAM_SEEK_SET
, NULL
);
240 if(This
->pos
.QuadPart
+ cb
> This
->length
.QuadPart
)
241 cb
= This
->length
.QuadPart
- This
->pos
.QuadPart
;
243 hr
= IStream_Read(This
->base
, pv
, cb
, pcbRead
);
245 This
->pos
.QuadPart
+= *pcbRead
;
250 static HRESULT WINAPI
sub_stream_Write(
260 static HRESULT WINAPI
sub_stream_Seek(
262 LARGE_INTEGER dlibMove
,
264 ULARGE_INTEGER
*plibNewPosition
)
266 sub_stream_t
*This
= impl_from_IStream(iface
);
267 LARGE_INTEGER new_pos
;
269 TRACE("(%08x.%08x, %x, %p)\n", dlibMove
.u
.HighPart
, dlibMove
.u
.LowPart
, dwOrigin
, plibNewPosition
);
273 case STREAM_SEEK_SET
:
276 case STREAM_SEEK_CUR
:
277 new_pos
.QuadPart
= This
->pos
.QuadPart
+ dlibMove
.QuadPart
;
279 case STREAM_SEEK_END
:
280 new_pos
.QuadPart
= This
->length
.QuadPart
+ dlibMove
.QuadPart
;
283 return STG_E_INVALIDFUNCTION
;
286 if(new_pos
.QuadPart
< 0) new_pos
.QuadPart
= 0;
287 else if(new_pos
.QuadPart
> This
->length
.QuadPart
) new_pos
.QuadPart
= This
->length
.QuadPart
;
289 This
->pos
.QuadPart
= new_pos
.QuadPart
;
291 if(plibNewPosition
) *plibNewPosition
= This
->pos
;
295 static HRESULT WINAPI
sub_stream_SetSize(
297 ULARGE_INTEGER libNewSize
)
303 static HRESULT WINAPI
sub_stream_CopyTo(
307 ULARGE_INTEGER
*pcbRead
,
308 ULARGE_INTEGER
*pcbWritten
)
312 ULONG bytesRead
, bytesWritten
, copySize
;
313 ULARGE_INTEGER totalBytesRead
;
314 ULARGE_INTEGER totalBytesWritten
;
316 TRACE("(%p)->(%p, %d, %p, %p)\n", iface
, pstm
, cb
.u
.LowPart
, pcbRead
, pcbWritten
);
318 totalBytesRead
.QuadPart
= 0;
319 totalBytesWritten
.QuadPart
= 0;
321 while ( cb
.QuadPart
> 0 )
323 if ( cb
.QuadPart
>= sizeof(tmpBuffer
) )
324 copySize
= sizeof(tmpBuffer
);
326 copySize
= cb
.u
.LowPart
;
328 hr
= IStream_Read(iface
, tmpBuffer
, copySize
, &bytesRead
);
329 if (FAILED(hr
)) break;
331 totalBytesRead
.QuadPart
+= bytesRead
;
335 hr
= IStream_Write(pstm
, tmpBuffer
, bytesRead
, &bytesWritten
);
336 if (FAILED(hr
)) break;
337 totalBytesWritten
.QuadPart
+= bytesWritten
;
340 if (bytesRead
!= copySize
)
343 cb
.QuadPart
-= bytesRead
;
346 if (pcbRead
) pcbRead
->QuadPart
= totalBytesRead
.QuadPart
;
347 if (pcbWritten
) pcbWritten
->QuadPart
= totalBytesWritten
.QuadPart
;
352 static HRESULT WINAPI
sub_stream_Commit(
354 DWORD grfCommitFlags
)
360 static HRESULT WINAPI
sub_stream_Revert(
367 static HRESULT WINAPI
sub_stream_LockRegion(
369 ULARGE_INTEGER libOffset
,
377 static HRESULT WINAPI
sub_stream_UnlockRegion(
379 ULARGE_INTEGER libOffset
,
387 static HRESULT WINAPI
sub_stream_Stat(
392 sub_stream_t
*This
= impl_from_IStream(iface
);
393 FIXME("(%p)->(%p, %08x)\n", This
, pstatstg
, grfStatFlag
);
394 memset(pstatstg
, 0, sizeof(*pstatstg
));
395 pstatstg
->cbSize
= This
->length
;
399 static HRESULT WINAPI
sub_stream_Clone(
407 static struct IStreamVtbl sub_stream_vtbl
=
409 sub_stream_QueryInterface
,
419 sub_stream_LockRegion
,
420 sub_stream_UnlockRegion
,
425 static HRESULT
create_sub_stream(IStream
*stream
, ULARGE_INTEGER start
, ULARGE_INTEGER length
, IStream
**out
)
430 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
431 if(!This
) return E_OUTOFMEMORY
;
433 This
->IStream_iface
.lpVtbl
= &sub_stream_vtbl
;
436 This
->length
= length
;
437 This
->pos
.QuadPart
= 0;
438 IStream_AddRef(stream
);
441 *out
= &This
->IStream_iface
;
445 static HRESULT
get_stream_size(IStream
*stream
, ULARGE_INTEGER
*size
)
447 STATSTG statstg
= {NULL
};
451 hres
= IStream_Stat(stream
, &statstg
, STATFLAG_NONAME
);
452 if(SUCCEEDED(hres
)) {
453 *size
= statstg
.cbSize
;
458 return IStream_Seek(stream
, zero
, STREAM_SEEK_END
, size
);
461 static inline MimeBody
*impl_from_IMimeBody(IMimeBody
*iface
)
463 return CONTAINING_RECORD(iface
, MimeBody
, IMimeBody_iface
);
466 typedef struct propschema
468 IMimePropertySchema IMimePropertySchema_iface
;
472 static inline propschema
*impl_from_IMimePropertySchema(IMimePropertySchema
*iface
)
474 return CONTAINING_RECORD(iface
, propschema
, IMimePropertySchema_iface
);
477 static LPSTR
strdupA(LPCSTR str
)
480 int len
= strlen(str
);
481 ret
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
482 memcpy(ret
, str
, len
+ 1);
486 #define PARSER_BUF_SIZE 1024
488 /*****************************************************
489 * copy_headers_to_buf [internal]
491 * Copies the headers into a '\0' terminated memory block and leave
492 * the stream's current position set to after the blank line.
494 static HRESULT
copy_headers_to_buf(IStream
*stm
, char **ptr
)
497 DWORD size
= PARSER_BUF_SIZE
, offset
= 0, last_end
= 0;
509 buf
= HeapAlloc(GetProcessHeap(), 0, size
+ 1);
513 buf
= HeapReAlloc(GetProcessHeap(), 0, buf
, size
+ 1);
521 hr
= IStream_Read(stm
, buf
+ offset
, size
- offset
, &read
);
522 if(FAILED(hr
)) goto fail
;
527 if(read
== 0) done
= TRUE
;
529 while(!done
&& (end
= strstr(buf
+ last_end
, "\r\n")))
531 DWORD new_end
= end
- buf
+ 2;
532 if(new_end
- last_end
== 2)
535 off
.QuadPart
= new_end
;
536 IStream_Seek(stm
, off
, STREAM_SEEK_SET
, NULL
);
549 HeapFree(GetProcessHeap(), 0, buf
);
553 static header_t
*read_prop(MimeBody
*body
, char **ptr
)
555 char *colon
= strchr(*ptr
, ':');
556 const property_t
*prop
;
559 if(!colon
) return NULL
;
563 for(prop
= default_props
; prop
->name
; prop
++)
565 if(!lstrcmpiA(*ptr
, prop
->name
))
567 TRACE("%s: found match with default property id %d\n", *ptr
, prop
->id
);
574 property_list_entry_t
*prop_entry
;
575 LIST_FOR_EACH_ENTRY(prop_entry
, &body
->new_props
, property_list_entry_t
, entry
)
577 if(!lstrcmpiA(*ptr
, prop_entry
->prop
.name
))
579 TRACE("%s: found match with already added new property id %d\n", *ptr
, prop_entry
->prop
.id
);
580 prop
= &prop_entry
->prop
;
586 prop_entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(*prop_entry
));
587 prop_entry
->prop
.name
= strdupA(*ptr
);
588 prop_entry
->prop
.id
= body
->next_prop_id
++;
589 prop_entry
->prop
.flags
= 0;
590 prop_entry
->prop
.default_vt
= VT_LPSTR
;
591 list_add_tail(&body
->new_props
, &prop_entry
->entry
);
592 prop
= &prop_entry
->prop
;
593 TRACE("%s: allocating new prop id %d\n", *ptr
, prop_entry
->prop
.id
);
597 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ret
));
599 PropVariantInit(&ret
->value
);
600 list_init(&ret
->params
);
606 static void unfold_header(char *header
, int len
)
608 char *start
= header
, *cp
= header
;
611 while(*cp
== ' ' || *cp
== '\t')
617 memmove(start
, cp
, len
+ 1);
619 cp
= strstr(start
, "\r\n");
626 } while(*cp
== ' ' || *cp
== '\t');
631 static char *unquote_string(const char *str
)
636 while(*str
== ' ' || *str
== '\t') str
++;
644 for(cp
= ret
; *cp
; cp
++)
647 memmove(cp
, cp
+ 1, strlen(cp
+ 1) + 1);
652 WARN("quote in unquoted string\n");
664 static void add_param(header_t
*header
, const char *p
)
666 const char *key
= p
, *value
, *cp
= p
;
670 TRACE("got param %s\n", p
);
672 while (*key
== ' ' || *key
== '\t' ) key
++;
674 cp
= strchr(key
, '=');
677 WARN("malformed parameter - skipping\n");
681 name
= HeapAlloc(GetProcessHeap(), 0, cp
- key
+ 1);
682 memcpy(name
, key
, cp
- key
);
683 name
[cp
- key
] = '\0';
687 param
= HeapAlloc(GetProcessHeap(), 0, sizeof(*param
));
689 param
->value
= unquote_string(value
);
690 list_add_tail(&header
->params
, ¶m
->entry
);
693 static void split_params(header_t
*header
, char *value
)
695 char *cp
= value
, *start
= value
;
696 BOOL in_quotes
= FALSE
, done_value
= FALSE
;
700 if(!in_quotes
&& *cp
== ';')
703 if(done_value
) add_param(header
, start
);
708 in_quotes
= !in_quotes
;
711 if(done_value
) add_param(header
, start
);
714 static void read_value(header_t
*header
, char **cur
)
716 char *end
= *cur
, *value
;
720 end
= strstr(end
, "\r\n");
722 } while(*end
== ' ' || *end
== '\t');
725 value
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
726 memcpy(value
, *cur
, len
);
729 unfold_header(value
, len
);
730 TRACE("value %s\n", debugstr_a(value
));
732 if(header
->prop
->flags
& MPF_HASPARAMS
)
734 split_params(header
, value
);
735 TRACE("value w/o params %s\n", debugstr_a(value
));
738 header
->value
.vt
= VT_LPSTR
;
739 header
->value
.u
.pszVal
= value
;
744 static void init_content_type(MimeBody
*body
, header_t
*header
)
749 if(header
->prop
->id
!= PID_HDR_CNTTYPE
)
751 ERR("called with header %s\n", header
->prop
->name
);
755 slash
= strchr(header
->value
.u
.pszVal
, '/');
758 WARN("malformed context type value\n");
761 len
= slash
- header
->value
.u
.pszVal
;
762 body
->content_pri_type
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
763 memcpy(body
->content_pri_type
, header
->value
.u
.pszVal
, len
);
764 body
->content_pri_type
[len
] = '\0';
765 body
->content_sub_type
= strdupA(slash
+ 1);
768 static HRESULT
parse_headers(MimeBody
*body
, IStream
*stm
)
770 char *header_buf
, *cur_header_ptr
;
774 hr
= copy_headers_to_buf(stm
, &header_buf
);
775 if(FAILED(hr
)) return hr
;
777 cur_header_ptr
= header_buf
;
778 while((header
= read_prop(body
, &cur_header_ptr
)))
780 read_value(header
, &cur_header_ptr
);
781 list_add_tail(&body
->headers
, &header
->entry
);
783 if(header
->prop
->id
== PID_HDR_CNTTYPE
)
784 init_content_type(body
, header
);
787 HeapFree(GetProcessHeap(), 0, header_buf
);
791 static void empty_param_list(struct list
*list
)
793 param_t
*param
, *cursor2
;
795 LIST_FOR_EACH_ENTRY_SAFE(param
, cursor2
, list
, param_t
, entry
)
797 list_remove(¶m
->entry
);
798 HeapFree(GetProcessHeap(), 0, param
->name
);
799 HeapFree(GetProcessHeap(), 0, param
->value
);
800 HeapFree(GetProcessHeap(), 0, param
);
804 static void empty_header_list(struct list
*list
)
806 header_t
*header
, *cursor2
;
808 LIST_FOR_EACH_ENTRY_SAFE(header
, cursor2
, list
, header_t
, entry
)
810 list_remove(&header
->entry
);
811 PropVariantClear(&header
->value
);
812 empty_param_list(&header
->params
);
813 HeapFree(GetProcessHeap(), 0, header
);
817 static void empty_new_prop_list(struct list
*list
)
819 property_list_entry_t
*prop
, *cursor2
;
821 LIST_FOR_EACH_ENTRY_SAFE(prop
, cursor2
, list
, property_list_entry_t
, entry
)
823 list_remove(&prop
->entry
);
824 HeapFree(GetProcessHeap(), 0, (char *)prop
->prop
.name
);
825 HeapFree(GetProcessHeap(), 0, prop
);
829 static void release_data(REFIID riid
, void *data
)
833 if(IsEqualIID(riid
, &IID_IStream
))
834 IStream_Release((IStream
*)data
);
836 FIXME("Unhandled data format %s\n", debugstr_guid(riid
));
839 static HRESULT
find_prop(MimeBody
*body
, const char *name
, header_t
**prop
)
845 LIST_FOR_EACH_ENTRY(header
, &body
->headers
, header_t
, entry
)
849 if(STRTOPID(name
) == header
->prop
->id
)
855 else if(!lstrcmpiA(name
, header
->prop
->name
))
862 return MIME_E_NOT_FOUND
;
865 static const property_t
*find_default_prop(const char *name
)
867 const property_t
*prop_def
= NULL
;
869 for(prop_def
= default_props
; prop_def
->name
; prop_def
++)
873 if(STRTOPID(name
) == prop_def
->id
)
878 else if(!lstrcmpiA(name
, prop_def
->name
))
885 TRACE("%s: found match with default property id %d\n", prop_def
->name
, prop_def
->id
);
892 static HRESULT WINAPI
MimeBody_QueryInterface(IMimeBody
* iface
,
896 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppvObject
);
900 if (IsEqualIID(riid
, &IID_IUnknown
) ||
901 IsEqualIID(riid
, &IID_IPersist
) ||
902 IsEqualIID(riid
, &IID_IPersistStreamInit
) ||
903 IsEqualIID(riid
, &IID_IMimePropertySet
) ||
904 IsEqualIID(riid
, &IID_IMimeBody
))
911 IUnknown_AddRef((IUnknown
*)*ppvObject
);
915 FIXME("no interface for %s\n", debugstr_guid(riid
));
916 return E_NOINTERFACE
;
919 static ULONG WINAPI
MimeBody_AddRef(IMimeBody
*iface
)
921 MimeBody
*This
= impl_from_IMimeBody(iface
);
922 LONG ref
= InterlockedIncrement(&This
->ref
);
924 TRACE("(%p) ref=%d\n", This
, ref
);
929 static ULONG WINAPI
MimeBody_Release(IMimeBody
*iface
)
931 MimeBody
*This
= impl_from_IMimeBody(iface
);
932 LONG ref
= InterlockedDecrement(&This
->ref
);
934 TRACE("(%p) ref=%d\n", This
, ref
);
938 empty_header_list(&This
->headers
);
939 empty_new_prop_list(&This
->new_props
);
941 HeapFree(GetProcessHeap(), 0, This
->content_pri_type
);
942 HeapFree(GetProcessHeap(), 0, This
->content_sub_type
);
944 release_data(&This
->data_iid
, This
->data
);
946 HeapFree(GetProcessHeap(), 0, This
);
952 static HRESULT WINAPI
MimeBody_GetClassID(
956 MimeBody
*This
= impl_from_IMimeBody(iface
);
957 FIXME("(%p)->(%p) stub\n", This
, pClassID
);
962 static HRESULT WINAPI
MimeBody_IsDirty(
965 MimeBody
*This
= impl_from_IMimeBody(iface
);
966 FIXME("(%p)->() stub\n", This
);
970 static HRESULT WINAPI
MimeBody_Load(IMimeBody
*iface
, IStream
*pStm
)
972 MimeBody
*This
= impl_from_IMimeBody(iface
);
973 TRACE("(%p)->(%p)\n", This
, pStm
);
974 return parse_headers(This
, pStm
);
977 static HRESULT WINAPI
MimeBody_Save(IMimeBody
*iface
, IStream
*pStm
, BOOL fClearDirty
)
979 MimeBody
*This
= impl_from_IMimeBody(iface
);
980 FIXME("(%p)->(%p, %d)\n", This
, pStm
, fClearDirty
);
984 static HRESULT WINAPI
MimeBody_GetSizeMax(
986 ULARGE_INTEGER
* pcbSize
)
988 MimeBody
*This
= impl_from_IMimeBody(iface
);
989 FIXME("(%p)->(%p) stub\n", This
, pcbSize
);
993 static HRESULT WINAPI
MimeBody_InitNew(
996 MimeBody
*This
= impl_from_IMimeBody(iface
);
997 TRACE("(%p)->()\n", This
);
1001 static HRESULT WINAPI
MimeBody_GetPropInfo(
1004 LPMIMEPROPINFO pInfo
)
1006 MimeBody
*This
= impl_from_IMimeBody(iface
);
1009 DWORD supported
= PIM_PROPID
| PIM_VTDEFAULT
;
1011 TRACE("(%p)->(%s, %p) semi-stub\n", This
, debugstr_a(pszName
), pInfo
);
1013 if(!pszName
|| !pInfo
)
1014 return E_INVALIDARG
;
1016 TRACE("mask 0x%04x\n", pInfo
->dwMask
);
1018 if(pInfo
->dwMask
& ~supported
)
1019 FIXME("Unsupported mask flags 0x%04x\n", pInfo
->dwMask
& ~supported
);
1021 hr
= find_prop(This
, pszName
, &header
);
1024 if(pInfo
->dwMask
& PIM_CHARSET
)
1025 pInfo
->hCharset
= 0;
1026 if(pInfo
->dwMask
& PIM_FLAGS
)
1027 pInfo
->dwFlags
= 0x00000000;
1028 if(pInfo
->dwMask
& PIM_ROWNUMBER
)
1029 pInfo
->dwRowNumber
= 0;
1030 if(pInfo
->dwMask
& PIM_ENCODINGTYPE
)
1031 pInfo
->ietEncoding
= 0;
1032 if(pInfo
->dwMask
& PIM_VALUES
)
1034 if(pInfo
->dwMask
& PIM_PROPID
)
1035 pInfo
->dwPropId
= header
->prop
->id
;
1036 if(pInfo
->dwMask
& PIM_VTDEFAULT
)
1037 pInfo
->vtDefault
= header
->prop
->default_vt
;
1038 if(pInfo
->dwMask
& PIM_VTCURRENT
)
1039 pInfo
->vtCurrent
= 0;
1045 static HRESULT WINAPI
MimeBody_SetPropInfo(
1048 LPCMIMEPROPINFO pInfo
)
1050 MimeBody
*This
= impl_from_IMimeBody(iface
);
1051 FIXME("(%p)->(%s, %p) stub\n", This
, debugstr_a(pszName
), pInfo
);
1055 static HRESULT WINAPI
MimeBody_GetProp(
1059 LPPROPVARIANT pValue
)
1061 MimeBody
*This
= impl_from_IMimeBody(iface
);
1065 TRACE("(%p)->(%s, 0x%x, %p)\n", This
, debugstr_a(pszName
), dwFlags
, pValue
);
1067 if(!pszName
|| !pValue
)
1068 return E_INVALIDARG
;
1070 if(!ISPIDSTR(pszName
) && !lstrcmpiA(pszName
, "att:pri-content-type"))
1072 PropVariantClear(pValue
);
1073 pValue
->vt
= VT_LPSTR
;
1074 pValue
->u
.pszVal
= strdupA(This
->content_pri_type
);
1078 hr
= find_prop(This
, pszName
, &header
);
1081 TRACE("type %d->%d\n", header
->value
.vt
, pValue
->vt
);
1083 hr
= PropVariantChangeType(pValue
, &header
->value
, 0, pValue
->vt
);
1085 FIXME("Conversion not currently supported (%d->%d)\n", header
->value
.vt
, pValue
->vt
);
1091 static HRESULT WINAPI
MimeBody_SetProp(
1095 LPCPROPVARIANT pValue
)
1097 MimeBody
*This
= impl_from_IMimeBody(iface
);
1101 TRACE("(%p)->(%s, 0x%x, %p)\n", This
, debugstr_a(pszName
), dwFlags
, pValue
);
1103 if(!pszName
|| !pValue
)
1104 return E_INVALIDARG
;
1106 hr
= find_prop(This
, pszName
, &header
);
1109 property_list_entry_t
*prop_entry
;
1110 const property_t
*prop
= NULL
;
1112 LIST_FOR_EACH_ENTRY(prop_entry
, &This
->new_props
, property_list_entry_t
, entry
)
1114 if(ISPIDSTR(pszName
))
1116 if(STRTOPID(pszName
) == prop_entry
->prop
.id
)
1118 TRACE("Found match with already added new property id %d\n", prop_entry
->prop
.id
);
1119 prop
= &prop_entry
->prop
;
1123 else if(!lstrcmpiA(pszName
, prop_entry
->prop
.name
))
1125 TRACE("Found match with already added new property id %d\n", prop_entry
->prop
.id
);
1126 prop
= &prop_entry
->prop
;
1131 header
= HeapAlloc(GetProcessHeap(), 0, sizeof(*header
));
1133 return E_OUTOFMEMORY
;
1137 const property_t
*prop_def
= NULL
;
1138 prop_entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(*prop_entry
));
1141 HeapFree(GetProcessHeap(), 0, header
);
1142 return E_OUTOFMEMORY
;
1145 prop_def
= find_default_prop(pszName
);
1148 prop_entry
->prop
.name
= strdupA(prop_def
->name
);
1149 prop_entry
->prop
.id
= prop_def
->id
;
1153 if(ISPIDSTR(pszName
))
1155 HeapFree(GetProcessHeap(), 0, prop_entry
);
1156 HeapFree(GetProcessHeap(), 0, header
);
1157 return MIME_E_NOT_FOUND
;
1160 prop_entry
->prop
.name
= strdupA(pszName
);
1161 prop_entry
->prop
.id
= This
->next_prop_id
++;
1164 prop_entry
->prop
.flags
= 0;
1165 prop_entry
->prop
.default_vt
= pValue
->vt
;
1166 list_add_tail(&This
->new_props
, &prop_entry
->entry
);
1167 prop
= &prop_entry
->prop
;
1168 TRACE("Allocating new prop id %d\n", prop_entry
->prop
.id
);
1171 header
->prop
= prop
;
1172 PropVariantInit(&header
->value
);
1173 list_init(&header
->params
);
1174 list_add_tail(&This
->headers
, &header
->entry
);
1177 PropVariantCopy(&header
->value
, pValue
);
1182 static HRESULT WINAPI
MimeBody_AppendProp(
1186 LPPROPVARIANT pValue
)
1188 MimeBody
*This
= impl_from_IMimeBody(iface
);
1189 FIXME("(%p)->(%s, 0x%x, %p) stub\n", This
, debugstr_a(pszName
), dwFlags
, pValue
);
1193 static HRESULT WINAPI
MimeBody_DeleteProp(
1197 MimeBody
*This
= impl_from_IMimeBody(iface
);
1201 TRACE("(%p)->(%s) stub\n", This
, debugstr_a(pszName
));
1203 LIST_FOR_EACH_ENTRY(cursor
, &This
->headers
, header_t
, entry
)
1205 if(ISPIDSTR(pszName
))
1206 found
= STRTOPID(pszName
) == cursor
->prop
->id
;
1208 found
= !lstrcmpiA(pszName
, cursor
->prop
->name
);
1212 list_remove(&cursor
->entry
);
1213 HeapFree(GetProcessHeap(), 0, cursor
);
1218 return MIME_E_NOT_FOUND
;
1221 static HRESULT WINAPI
MimeBody_CopyProps(
1225 IMimePropertySet
* pPropertySet
)
1227 MimeBody
*This
= impl_from_IMimeBody(iface
);
1228 FIXME("(%p)->(%d, %p, %p) stub\n", This
, cNames
, prgszName
, pPropertySet
);
1232 static HRESULT WINAPI
MimeBody_MoveProps(
1236 IMimePropertySet
* pPropertySet
)
1238 MimeBody
*This
= impl_from_IMimeBody(iface
);
1239 FIXME("(%p)->(%d, %p, %p) stub\n", This
, cNames
, prgszName
, pPropertySet
);
1243 static HRESULT WINAPI
MimeBody_DeleteExcept(
1248 MimeBody
*This
= impl_from_IMimeBody(iface
);
1249 FIXME("(%p)->(%d, %p) stub\n", This
, cNames
, prgszName
);
1253 static HRESULT WINAPI
MimeBody_QueryProp(
1258 boolean fCaseSensitive
)
1260 MimeBody
*This
= impl_from_IMimeBody(iface
);
1261 FIXME("(%p)->(%s, %s, %d, %d) stub\n", This
, debugstr_a(pszName
), debugstr_a(pszCriteria
), fSubString
, fCaseSensitive
);
1265 static HRESULT WINAPI
MimeBody_GetCharset(
1267 LPHCHARSET phCharset
)
1269 MimeBody
*This
= impl_from_IMimeBody(iface
);
1270 FIXME("(%p)->(%p) stub\n", This
, phCharset
);
1275 static HRESULT WINAPI
MimeBody_SetCharset(
1278 CSETAPPLYTYPE applytype
)
1280 MimeBody
*This
= impl_from_IMimeBody(iface
);
1281 FIXME("(%p)->(%p, %d) stub\n", This
, hCharset
, applytype
);
1285 static HRESULT WINAPI
MimeBody_GetParameters(
1289 LPMIMEPARAMINFO
* pprgParam
)
1291 MimeBody
*This
= impl_from_IMimeBody(iface
);
1295 TRACE("(%p)->(%s, %p, %p)\n", iface
, debugstr_a(pszName
), pcParams
, pprgParam
);
1300 hr
= find_prop(This
, pszName
, &header
);
1301 if(hr
!= S_OK
) return hr
;
1303 *pcParams
= list_count(&header
->params
);
1306 IMimeAllocator
*alloc
;
1308 MIMEPARAMINFO
*info
;
1310 MimeOleGetAllocator(&alloc
);
1312 *pprgParam
= info
= IMimeAllocator_Alloc(alloc
, *pcParams
* sizeof(**pprgParam
));
1313 LIST_FOR_EACH_ENTRY(param
, &header
->params
, param_t
, entry
)
1317 len
= strlen(param
->name
) + 1;
1318 info
->pszName
= IMimeAllocator_Alloc(alloc
, len
);
1319 memcpy(info
->pszName
, param
->name
, len
);
1320 len
= strlen(param
->value
) + 1;
1321 info
->pszData
= IMimeAllocator_Alloc(alloc
, len
);
1322 memcpy(info
->pszData
, param
->value
, len
);
1325 IMimeAllocator_Release(alloc
);
1330 static HRESULT WINAPI
MimeBody_IsContentType(
1335 MimeBody
*This
= impl_from_IMimeBody(iface
);
1337 TRACE("(%p)->(%s, %s)\n", This
, debugstr_a(pszPriType
), debugstr_a(pszSubType
));
1340 const char *pri
= This
->content_pri_type
;
1341 if(!pri
) pri
= "text";
1342 if(lstrcmpiA(pri
, pszPriType
)) return S_FALSE
;
1347 const char *sub
= This
->content_sub_type
;
1348 if(!sub
) sub
= "plain";
1349 if(lstrcmpiA(sub
, pszSubType
)) return S_FALSE
;
1355 static HRESULT WINAPI
MimeBody_BindToObject(
1360 MimeBody
*This
= impl_from_IMimeBody(iface
);
1361 FIXME("(%p)->(%s, %p) stub\n", This
, debugstr_guid(riid
), ppvObject
);
1365 static HRESULT WINAPI
MimeBody_Clone(
1367 IMimePropertySet
** ppPropertySet
)
1369 MimeBody
*This
= impl_from_IMimeBody(iface
);
1370 FIXME("(%p)->(%p) stub\n", This
, ppPropertySet
);
1374 static HRESULT WINAPI
MimeBody_SetOption(
1377 LPCPROPVARIANT pValue
)
1379 MimeBody
*This
= impl_from_IMimeBody(iface
);
1380 HRESULT hr
= E_NOTIMPL
;
1381 TRACE("(%p)->(%08x, %p)\n", This
, oid
, pValue
);
1383 if(pValue
->vt
!= TYPEDID_TYPE(oid
))
1385 WARN("Called with vartype %04x and oid %08x\n", pValue
->vt
, oid
);
1386 return E_INVALIDARG
;
1391 case OID_SECURITY_HWND_OWNER
:
1392 FIXME("OID_SECURITY_HWND_OWNER (value %08x): ignoring\n", pValue
->u
.ulVal
);
1395 case OID_TRANSMIT_BODY_ENCODING
:
1396 FIXME("OID_TRANSMIT_BODY_ENCODING (value %08x): ignoring\n", pValue
->u
.ulVal
);
1400 FIXME("Unhandled oid %08x\n", oid
);
1406 static HRESULT WINAPI
MimeBody_GetOption(
1409 LPPROPVARIANT pValue
)
1411 MimeBody
*This
= impl_from_IMimeBody(iface
);
1412 FIXME("(%p)->(%08x, %p): stub\n", This
, oid
, pValue
);
1416 static HRESULT WINAPI
MimeBody_EnumProps(
1419 IMimeEnumProperties
** ppEnum
)
1421 MimeBody
*This
= impl_from_IMimeBody(iface
);
1422 FIXME("(%p)->(0x%x, %p) stub\n", This
, dwFlags
, ppEnum
);
1426 static HRESULT WINAPI
MimeBody_IsType(
1428 IMSGBODYTYPE bodytype
)
1430 MimeBody
*This
= impl_from_IMimeBody(iface
);
1432 TRACE("(%p)->(%d)\n", This
, bodytype
);
1436 return This
->data
? S_FALSE
: S_OK
;
1438 FIXME("Unimplemented bodytype %d - returning S_OK\n", bodytype
);
1443 static HRESULT WINAPI
MimeBody_SetDisplayName(
1447 MimeBody
*This
= impl_from_IMimeBody(iface
);
1448 FIXME("(%p)->(%s) stub\n", This
, debugstr_a(pszDisplay
));
1452 static HRESULT WINAPI
MimeBody_GetDisplayName(
1456 MimeBody
*This
= impl_from_IMimeBody(iface
);
1457 FIXME("(%p)->(%p) stub\n", This
, ppszDisplay
);
1461 static HRESULT WINAPI
MimeBody_GetOffsets(
1463 LPBODYOFFSETS pOffsets
)
1465 MimeBody
*This
= impl_from_IMimeBody(iface
);
1466 TRACE("(%p)->(%p)\n", This
, pOffsets
);
1468 *pOffsets
= This
->body_offsets
;
1470 if(This
->body_offsets
.cbBodyEnd
== 0) return MIME_E_NO_DATA
;
1474 static HRESULT WINAPI
MimeBody_GetCurrentEncoding(
1476 ENCODINGTYPE
* pietEncoding
)
1478 MimeBody
*This
= impl_from_IMimeBody(iface
);
1480 TRACE("(%p)->(%p)\n", This
, pietEncoding
);
1482 *pietEncoding
= This
->encoding
;
1486 static HRESULT WINAPI
MimeBody_SetCurrentEncoding(
1488 ENCODINGTYPE ietEncoding
)
1490 MimeBody
*This
= impl_from_IMimeBody(iface
);
1492 TRACE("(%p)->(%d)\n", This
, ietEncoding
);
1494 This
->encoding
= ietEncoding
;
1498 static HRESULT WINAPI
MimeBody_GetEstimatedSize(
1500 ENCODINGTYPE ietEncoding
,
1503 MimeBody
*This
= impl_from_IMimeBody(iface
);
1504 FIXME("(%p)->(%d, %p) stub\n", This
, ietEncoding
, pcbSize
);
1508 static HRESULT WINAPI
MimeBody_GetDataHere(
1510 ENCODINGTYPE ietEncoding
,
1513 MimeBody
*This
= impl_from_IMimeBody(iface
);
1514 FIXME("(%p)->(%d, %p) stub\n", This
, ietEncoding
, pStream
);
1518 static const signed char base64_decode_table
[] =
1520 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00 */
1521 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10 */
1522 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 0x20 */
1523 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 0x30 */
1524 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40 */
1525 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 0x50 */
1526 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60 */
1527 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 /* 0x70 */
1530 static HRESULT
decode_base64(IStream
*input
, IStream
**ret_stream
)
1532 const unsigned char *ptr
, *end
;
1533 unsigned char buf
[1024];
1536 unsigned char in
[4];
1543 hres
= IStream_Seek(input
, pos
, STREAM_SEEK_SET
, NULL
);
1547 hres
= CreateStreamOnHGlobal(NULL
, TRUE
, &output
);
1552 hres
= IStream_Read(input
, buf
, sizeof(buf
), &size
);
1553 if(FAILED(hres
) || !size
)
1560 /* skip invalid chars */
1562 (*ptr
>= sizeof(base64_decode_table
)/sizeof(*base64_decode_table
)
1563 || base64_decode_table
[*ptr
] == -1))
1568 in
[n
++] = base64_decode_table
[*ptr
++];
1571 *ret
++ = in
[0] << 2 | in
[1] >> 4;
1574 *ret
++ = in
[1] << 4 | in
[2] >> 2;
1577 *ret
++ = ((in
[2] << 6) & 0xc0) | in
[3];
1583 hres
= IStream_Write(output
, buf
, ret
- buf
, NULL
);
1590 hres
= IStream_Seek(output
, pos
, STREAM_SEEK_SET
, NULL
);
1592 IStream_Release(output
);
1596 *ret_stream
= output
;
1600 static HRESULT WINAPI
MimeBody_GetData(
1602 ENCODINGTYPE ietEncoding
,
1605 MimeBody
*This
= impl_from_IMimeBody(iface
);
1606 ULARGE_INTEGER start
, size
;
1609 TRACE("(%p)->(%d %p)\n", This
, ietEncoding
, ppStream
);
1611 if(This
->encoding
!= ietEncoding
) {
1612 switch(This
->encoding
) {
1614 if(ietEncoding
!= IET_BINARY
)
1615 FIXME("Encofing %d is not supported.\n", ietEncoding
);
1616 return decode_base64(This
->data
, ppStream
);
1618 FIXME("Decoding %d is not supported.\n", This
->encoding
);
1623 hres
= get_stream_size(This
->data
, &size
);
1625 hres
= create_sub_stream(This
->data
, start
, size
, ppStream
);
1629 static HRESULT WINAPI
MimeBody_SetData(
1631 ENCODINGTYPE ietEncoding
,
1637 MimeBody
*This
= impl_from_IMimeBody(iface
);
1638 TRACE("(%p)->(%d, %s, %s, %s %p)\n", This
, ietEncoding
, debugstr_a(pszPriType
), debugstr_a(pszSubType
),
1639 debugstr_guid(riid
), pvObject
);
1641 if(IsEqualIID(riid
, &IID_IStream
))
1642 IStream_AddRef((IStream
*)pvObject
);
1645 FIXME("Unhandled object type %s\n", debugstr_guid(riid
));
1646 return E_INVALIDARG
;
1650 FIXME("release old data\n");
1652 This
->data_iid
= *riid
;
1653 This
->data
= pvObject
;
1655 IMimeBody_SetCurrentEncoding(iface
, ietEncoding
);
1657 /* FIXME: Update the content type.
1658 If pszPriType == NULL use 'application'
1659 If pszSubType == NULL use 'octet-stream' */
1664 static HRESULT WINAPI
MimeBody_EmptyData(
1667 MimeBody
*This
= impl_from_IMimeBody(iface
);
1668 FIXME("(%p)->() stub\n", This
);
1672 static HRESULT WINAPI
MimeBody_CopyTo(
1676 MimeBody
*This
= impl_from_IMimeBody(iface
);
1677 FIXME("(%p)->(%p) stub\n", This
, pBody
);
1681 static HRESULT WINAPI
MimeBody_GetTransmitInfo(
1683 LPTRANSMITINFO pTransmitInfo
)
1685 MimeBody
*This
= impl_from_IMimeBody(iface
);
1686 FIXME("(%p)->(%p) stub\n", This
, pTransmitInfo
);
1690 static HRESULT WINAPI
MimeBody_SaveToFile(
1692 ENCODINGTYPE ietEncoding
,
1695 MimeBody
*This
= impl_from_IMimeBody(iface
);
1696 FIXME("(%p)->(%d, %s) stub\n", This
, ietEncoding
, debugstr_a(pszFilePath
));
1700 static HRESULT WINAPI
MimeBody_GetHandle(
1704 MimeBody
*This
= impl_from_IMimeBody(iface
);
1705 TRACE("(%p)->(%p)\n", iface
, phBody
);
1708 return E_INVALIDARG
;
1710 *phBody
= This
->handle
;
1711 return This
->handle
? S_OK
: MIME_E_NO_DATA
;
1714 static IMimeBodyVtbl body_vtbl
=
1716 MimeBody_QueryInterface
,
1719 MimeBody_GetClassID
,
1723 MimeBody_GetSizeMax
,
1725 MimeBody_GetPropInfo
,
1726 MimeBody_SetPropInfo
,
1729 MimeBody_AppendProp
,
1730 MimeBody_DeleteProp
,
1733 MimeBody_DeleteExcept
,
1735 MimeBody_GetCharset
,
1736 MimeBody_SetCharset
,
1737 MimeBody_GetParameters
,
1738 MimeBody_IsContentType
,
1739 MimeBody_BindToObject
,
1745 MimeBody_SetDisplayName
,
1746 MimeBody_GetDisplayName
,
1747 MimeBody_GetOffsets
,
1748 MimeBody_GetCurrentEncoding
,
1749 MimeBody_SetCurrentEncoding
,
1750 MimeBody_GetEstimatedSize
,
1751 MimeBody_GetDataHere
,
1756 MimeBody_GetTransmitInfo
,
1757 MimeBody_SaveToFile
,
1761 static HRESULT
MimeBody_set_offsets(MimeBody
*body
, const BODYOFFSETS
*offsets
)
1763 TRACE("setting offsets to %d, %d, %d, %d\n", offsets
->cbBoundaryStart
,
1764 offsets
->cbHeaderStart
, offsets
->cbBodyStart
, offsets
->cbBodyEnd
);
1766 body
->body_offsets
= *offsets
;
1770 #define FIRST_CUSTOM_PROP_ID 0x100
1772 static MimeBody
*mimebody_create(void)
1775 BODYOFFSETS body_offsets
;
1777 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1781 This
->IMimeBody_iface
.lpVtbl
= &body_vtbl
;
1783 This
->handle
= NULL
;
1784 list_init(&This
->headers
);
1785 list_init(&This
->new_props
);
1786 This
->next_prop_id
= FIRST_CUSTOM_PROP_ID
;
1787 This
->content_pri_type
= NULL
;
1788 This
->content_sub_type
= NULL
;
1789 This
->encoding
= IET_7BIT
;
1791 This
->data_iid
= IID_NULL
;
1793 body_offsets
.cbBoundaryStart
= body_offsets
.cbHeaderStart
= 0;
1794 body_offsets
.cbBodyStart
= body_offsets
.cbBodyEnd
= 0;
1795 MimeBody_set_offsets(This
, &body_offsets
);
1800 HRESULT
MimeBody_create(IUnknown
*outer
, void **ppv
)
1805 return CLASS_E_NOAGGREGATION
;
1807 if ((mb
= mimebody_create()))
1809 *ppv
= &mb
->IMimeBody_iface
;
1815 return E_OUTOFMEMORY
;
1819 typedef struct body_t
1823 MimeBody
*mime_body
;
1825 struct body_t
*parent
;
1826 struct list children
;
1829 typedef struct MimeMessage
1831 IMimeMessage IMimeMessage_iface
;
1835 struct list body_tree
;
1839 static inline MimeMessage
*impl_from_IMimeMessage(IMimeMessage
*iface
)
1841 return CONTAINING_RECORD(iface
, MimeMessage
, IMimeMessage_iface
);
1844 static HRESULT WINAPI
MimeMessage_QueryInterface(IMimeMessage
*iface
, REFIID riid
, void **ppv
)
1846 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
1848 if (IsEqualIID(riid
, &IID_IUnknown
) ||
1849 IsEqualIID(riid
, &IID_IPersist
) ||
1850 IsEqualIID(riid
, &IID_IPersistStreamInit
) ||
1851 IsEqualIID(riid
, &IID_IMimeMessageTree
) ||
1852 IsEqualIID(riid
, &IID_IMimeMessage
))
1855 IMimeMessage_AddRef(iface
);
1859 FIXME("no interface for %s\n", debugstr_guid(riid
));
1861 return E_NOINTERFACE
;
1864 static ULONG WINAPI
MimeMessage_AddRef(IMimeMessage
*iface
)
1866 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
1867 ULONG ref
= InterlockedIncrement(&This
->ref
);
1869 TRACE("(%p) ref=%d\n", This
, ref
);
1874 static void empty_body_list(struct list
*list
)
1876 body_t
*body
, *cursor2
;
1877 LIST_FOR_EACH_ENTRY_SAFE(body
, cursor2
, list
, body_t
, entry
)
1879 empty_body_list(&body
->children
);
1880 list_remove(&body
->entry
);
1881 IMimeBody_Release(&body
->mime_body
->IMimeBody_iface
);
1882 HeapFree(GetProcessHeap(), 0, body
);
1886 static ULONG WINAPI
MimeMessage_Release(IMimeMessage
*iface
)
1888 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
1889 ULONG ref
= InterlockedDecrement(&This
->ref
);
1891 TRACE("(%p) ref=%d\n", This
, ref
);
1895 empty_body_list(&This
->body_tree
);
1897 if(This
->stream
) IStream_Release(This
->stream
);
1898 HeapFree(GetProcessHeap(), 0, This
);
1904 /*** IPersist methods ***/
1905 static HRESULT WINAPI
MimeMessage_GetClassID(
1906 IMimeMessage
*iface
,
1909 FIXME("(%p)->(%p)\n", iface
, pClassID
);
1913 /*** IPersistStreamInit methods ***/
1914 static HRESULT WINAPI
MimeMessage_IsDirty(
1915 IMimeMessage
*iface
)
1917 FIXME("(%p)->()\n", iface
);
1921 static body_t
*new_body_entry(MimeBody
*mime_body
, DWORD index
, body_t
*parent
)
1923 body_t
*body
= HeapAlloc(GetProcessHeap(), 0, sizeof(*body
));
1926 body
->mime_body
= mime_body
;
1927 body
->index
= index
;
1928 list_init(&body
->children
);
1929 body
->parent
= parent
;
1931 mime_body
->handle
= UlongToHandle(body
->index
);
1939 BODYOFFSETS offsets
;
1942 static HRESULT
create_body_offset_list(IStream
*stm
, const char *boundary
, struct list
*body_offsets
)
1946 int boundary_len
= strlen(boundary
);
1947 char *buf
, *nl_boundary
, *ptr
, *overlap
;
1948 DWORD start
= 0, overlap_no
;
1949 offset_entry_t
*cur_body
= NULL
;
1953 list_init(body_offsets
);
1954 nl_boundary
= HeapAlloc(GetProcessHeap(), 0, 4 + boundary_len
+ 1);
1955 memcpy(nl_boundary
, "\r\n--", 4);
1956 memcpy(nl_boundary
+ 4, boundary
, boundary_len
+ 1);
1958 overlap_no
= boundary_len
+ 5;
1960 overlap
= buf
= HeapAlloc(GetProcessHeap(), 0, overlap_no
+ PARSER_BUF_SIZE
+ 1);
1963 hr
= IStream_Seek(stm
, zero
, STREAM_SEEK_CUR
, &cur
);
1964 start
= cur
.u
.LowPart
;
1967 hr
= IStream_Read(stm
, overlap
, PARSER_BUF_SIZE
, &read
);
1968 if(FAILED(hr
)) goto end
;
1969 if(read
== 0) break;
1970 overlap
[read
] = '\0';
1974 ptr
= strstr(ptr
, nl_boundary
);
1977 DWORD boundary_start
= start
+ ptr
- buf
;
1978 char *end
= ptr
+ boundary_len
+ 4;
1980 if(*end
== '\0' || *(end
+ 1) == '\0')
1983 if(*end
== '\r' && *(end
+ 1) == '\n')
1987 cur_body
->offsets
.cbBodyEnd
= boundary_start
;
1988 list_add_tail(body_offsets
, &cur_body
->entry
);
1990 cur_body
= HeapAlloc(GetProcessHeap(), 0, sizeof(*cur_body
));
1991 cur_body
->offsets
.cbBoundaryStart
= boundary_start
+ 2; /* doesn't including the leading \r\n */
1992 cur_body
->offsets
.cbHeaderStart
= boundary_start
+ boundary_len
+ 6;
1994 else if(*end
== '-' && *(end
+ 1) == '-')
1998 cur_body
->offsets
.cbBodyEnd
= boundary_start
;
1999 list_add_tail(body_offsets
, &cur_body
->entry
);
2007 if(overlap
== buf
) /* 1st iteration */
2009 memmove(buf
, buf
+ PARSER_BUF_SIZE
- overlap_no
, overlap_no
);
2010 overlap
= buf
+ overlap_no
;
2011 start
+= read
- overlap_no
;
2015 memmove(buf
, buf
+ PARSER_BUF_SIZE
, overlap_no
);
2021 HeapFree(GetProcessHeap(), 0, nl_boundary
);
2022 HeapFree(GetProcessHeap(), 0, buf
);
2026 static body_t
*create_sub_body(MimeMessage
*msg
, IStream
*pStm
, BODYOFFSETS
*offset
, body_t
*parent
)
2028 MimeBody
*mime_body
;
2034 mime_body
= mimebody_create();
2035 IMimeBody_Load(&mime_body
->IMimeBody_iface
, pStm
);
2037 hr
= IStream_Seek(pStm
, zero
, STREAM_SEEK_CUR
, &cur
);
2038 offset
->cbBodyStart
= cur
.u
.LowPart
+ offset
->cbHeaderStart
;
2039 if (parent
) MimeBody_set_offsets(mime_body
, offset
);
2040 IMimeBody_SetData(&mime_body
->IMimeBody_iface
, IET_BINARY
, NULL
, NULL
, &IID_IStream
, pStm
);
2041 body
= new_body_entry(mime_body
, msg
->next_index
++, parent
);
2043 if(IMimeBody_IsContentType(&mime_body
->IMimeBody_iface
, "multipart", NULL
) == S_OK
)
2045 MIMEPARAMINFO
*param_info
;
2047 IMimeAllocator
*alloc
;
2049 hr
= IMimeBody_GetParameters(&mime_body
->IMimeBody_iface
, "Content-Type", &count
,
2051 if(hr
!= S_OK
|| count
== 0) return body
;
2053 MimeOleGetAllocator(&alloc
);
2055 for(i
= 0; i
< count
; i
++)
2057 if(!lstrcmpiA(param_info
[i
].pszName
, "boundary"))
2059 struct list offset_list
;
2060 offset_entry_t
*cur
, *cursor2
;
2061 hr
= create_body_offset_list(pStm
, param_info
[i
].pszData
, &offset_list
);
2062 LIST_FOR_EACH_ENTRY_SAFE(cur
, cursor2
, &offset_list
, offset_entry_t
, entry
)
2065 IStream
*sub_stream
;
2066 ULARGE_INTEGER start
, length
;
2068 start
.QuadPart
= cur
->offsets
.cbHeaderStart
;
2069 length
.QuadPart
= cur
->offsets
.cbBodyEnd
- cur
->offsets
.cbHeaderStart
;
2070 create_sub_stream(pStm
, start
, length
, &sub_stream
);
2071 sub_body
= create_sub_body(msg
, sub_stream
, &cur
->offsets
, body
);
2072 IStream_Release(sub_stream
);
2073 list_add_tail(&body
->children
, &sub_body
->entry
);
2074 list_remove(&cur
->entry
);
2075 HeapFree(GetProcessHeap(), 0, cur
);
2080 IMimeAllocator_FreeParamInfoArray(alloc
, count
, param_info
, TRUE
);
2081 IMimeAllocator_Release(alloc
);
2086 static HRESULT WINAPI
MimeMessage_Load(IMimeMessage
*iface
, IStream
*pStm
)
2088 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2090 BODYOFFSETS offsets
;
2094 TRACE("(%p)->(%p)\n", iface
, pStm
);
2098 FIXME("already loaded a message\n");
2102 empty_body_list(&This
->body_tree
);
2104 IStream_AddRef(pStm
);
2105 This
->stream
= pStm
;
2106 offsets
.cbBoundaryStart
= offsets
.cbHeaderStart
= 0;
2107 offsets
.cbBodyStart
= offsets
.cbBodyEnd
= 0;
2109 root_body
= create_sub_body(This
, pStm
, &offsets
, NULL
);
2112 IStream_Seek(pStm
, zero
, STREAM_SEEK_END
, &cur
);
2113 offsets
.cbBodyEnd
= cur
.u
.LowPart
;
2114 MimeBody_set_offsets(root_body
->mime_body
, &offsets
);
2116 list_add_head(&This
->body_tree
, &root_body
->entry
);
2121 static HRESULT WINAPI
MimeMessage_Save(IMimeMessage
*iface
, IStream
*pStm
, BOOL fClearDirty
)
2123 FIXME("(%p)->(%p, %s)\n", iface
, pStm
, fClearDirty
? "TRUE" : "FALSE");
2127 static HRESULT WINAPI
MimeMessage_GetSizeMax(
2128 IMimeMessage
*iface
,
2129 ULARGE_INTEGER
*pcbSize
)
2131 FIXME("(%p)->(%p)\n", iface
, pcbSize
);
2135 static HRESULT WINAPI
MimeMessage_InitNew(
2136 IMimeMessage
*iface
)
2138 FIXME("(%p)->()\n", iface
);
2142 /*** IMimeMessageTree methods ***/
2143 static HRESULT WINAPI
MimeMessage_GetMessageSource(IMimeMessage
*iface
, IStream
**ppStream
,
2146 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2148 FIXME("(%p)->(%p, 0x%x)\n", iface
, ppStream
, dwFlags
);
2150 IStream_AddRef(This
->stream
);
2151 *ppStream
= This
->stream
;
2155 static HRESULT WINAPI
MimeMessage_GetMessageSize(
2156 IMimeMessage
*iface
,
2160 FIXME("(%p)->(%p, 0x%x)\n", iface
, pcbSize
, dwFlags
);
2164 static HRESULT WINAPI
MimeMessage_LoadOffsetTable(
2165 IMimeMessage
*iface
,
2168 FIXME("(%p)->(%p)\n", iface
, pStream
);
2172 static HRESULT WINAPI
MimeMessage_SaveOffsetTable(
2173 IMimeMessage
*iface
,
2177 FIXME("(%p)->(%p, 0x%x)\n", iface
, pStream
, dwFlags
);
2182 static HRESULT WINAPI
MimeMessage_GetFlags(
2183 IMimeMessage
*iface
,
2186 FIXME("(%p)->(%p)\n", iface
, pdwFlags
);
2190 static HRESULT WINAPI
MimeMessage_Commit(
2191 IMimeMessage
*iface
,
2194 FIXME("(%p)->(0x%x)\n", iface
, dwFlags
);
2199 static HRESULT WINAPI
MimeMessage_HandsOffStorage(
2200 IMimeMessage
*iface
)
2202 FIXME("(%p)->()\n", iface
);
2206 static HRESULT
find_body(struct list
*list
, HBODY hbody
, body_t
**body
)
2211 if(hbody
== HBODY_ROOT
)
2213 *body
= LIST_ENTRY(list_head(list
), body_t
, entry
);
2217 LIST_FOR_EACH_ENTRY(cur
, list
, body_t
, entry
)
2219 if(cur
->index
== HandleToUlong(hbody
))
2224 hr
= find_body(&cur
->children
, hbody
, body
);
2225 if(hr
== S_OK
) return S_OK
;
2230 static HRESULT WINAPI
MimeMessage_BindToObject(IMimeMessage
*iface
, const HBODY hBody
, REFIID riid
,
2233 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2237 TRACE("(%p)->(%p, %s, %p)\n", iface
, hBody
, debugstr_guid(riid
), ppvObject
);
2239 hr
= find_body(&This
->body_tree
, hBody
, &body
);
2241 if(hr
!= S_OK
) return hr
;
2243 if(IsEqualIID(riid
, &IID_IMimeBody
))
2245 IMimeBody_AddRef(&body
->mime_body
->IMimeBody_iface
);
2246 *ppvObject
= &body
->mime_body
->IMimeBody_iface
;
2250 return E_NOINTERFACE
;
2253 static HRESULT WINAPI
MimeMessage_SaveBody(
2254 IMimeMessage
*iface
,
2259 FIXME("(%p)->(%p, 0x%x, %p)\n", iface
, hBody
, dwFlags
, pStream
);
2263 static HRESULT
get_body(MimeMessage
*msg
, BODYLOCATION location
, HBODY pivot
, body_t
**out
)
2265 body_t
*root
= LIST_ENTRY(list_head(&msg
->body_tree
), body_t
, entry
);
2270 if(location
== IBL_ROOT
)
2276 hr
= find_body(&msg
->body_tree
, pivot
, &body
);
2284 *out
= body
->parent
;
2286 hr
= MIME_E_NOT_FOUND
;
2290 list
= list_head(&body
->children
);
2292 *out
= LIST_ENTRY(list
, body_t
, entry
);
2294 hr
= MIME_E_NOT_FOUND
;
2298 list
= list_tail(&body
->children
);
2300 *out
= LIST_ENTRY(list
, body_t
, entry
);
2302 hr
= MIME_E_NOT_FOUND
;
2306 list
= list_next(&body
->parent
->children
, &body
->entry
);
2308 *out
= LIST_ENTRY(list
, body_t
, entry
);
2310 hr
= MIME_E_NOT_FOUND
;
2314 list
= list_prev(&body
->parent
->children
, &body
->entry
);
2316 *out
= LIST_ENTRY(list
, body_t
, entry
);
2318 hr
= MIME_E_NOT_FOUND
;
2331 static HRESULT WINAPI
MimeMessage_InsertBody(
2332 IMimeMessage
*iface
,
2333 BODYLOCATION location
,
2337 FIXME("(%p)->(%d, %p, %p)\n", iface
, location
, hPivot
, phBody
);
2341 static HRESULT WINAPI
MimeMessage_GetBody(IMimeMessage
*iface
, BODYLOCATION location
, HBODY hPivot
,
2344 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2348 TRACE("(%p)->(%d, %p, %p)\n", iface
, location
, hPivot
, phBody
);
2351 return E_INVALIDARG
;
2355 hr
= get_body(This
, location
, hPivot
, &body
);
2357 if(hr
== S_OK
) *phBody
= UlongToHandle(body
->index
);
2362 static HRESULT WINAPI
MimeMessage_DeleteBody(
2363 IMimeMessage
*iface
,
2367 FIXME("(%p)->(%p, %08x)\n", iface
, hBody
, dwFlags
);
2371 static HRESULT WINAPI
MimeMessage_MoveBody(
2372 IMimeMessage
*iface
,
2374 BODYLOCATION location
)
2376 FIXME("(%p)->(%d)\n", iface
, location
);
2380 static void count_children(body_t
*body
, boolean recurse
, ULONG
*count
)
2384 LIST_FOR_EACH_ENTRY(child
, &body
->children
, body_t
, entry
)
2387 if(recurse
) count_children(child
, recurse
, count
);
2391 static HRESULT WINAPI
MimeMessage_CountBodies(IMimeMessage
*iface
, HBODY hParent
, boolean fRecurse
,
2395 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2398 TRACE("(%p)->(%p, %s, %p)\n", iface
, hParent
, fRecurse
? "TRUE" : "FALSE", pcBodies
);
2400 hr
= find_body(&This
->body_tree
, hParent
, &body
);
2401 if(hr
!= S_OK
) return hr
;
2404 count_children(body
, fRecurse
, pcBodies
);
2409 static HRESULT
find_next(MimeMessage
*This
, body_t
*body
, FINDBODY
*find
, HBODY
*out
)
2416 if (!body
) ptr
= list_head( &This
->body_tree
);
2419 ptr
= list_head( &body
->children
);
2422 if (!body
->parent
) return MIME_E_NOT_FOUND
;
2423 if (!(ptr
= list_next( &body
->parent
->children
, &body
->entry
))) body
= body
->parent
;
2427 body
= LIST_ENTRY( ptr
, body_t
, entry
);
2428 next
= UlongToHandle( body
->index
);
2429 find
->dwReserved
= body
->index
;
2430 if (IMimeBody_IsContentType(&body
->mime_body
->IMimeBody_iface
, find
->pszPriType
,
2431 find
->pszSubType
) == S_OK
)
2437 return MIME_E_NOT_FOUND
;
2440 static HRESULT WINAPI
MimeMessage_FindFirst(IMimeMessage
*iface
, FINDBODY
*pFindBody
, HBODY
*phBody
)
2442 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2444 TRACE("(%p)->(%p, %p)\n", iface
, pFindBody
, phBody
);
2446 pFindBody
->dwReserved
= 0;
2447 return find_next(This
, NULL
, pFindBody
, phBody
);
2450 static HRESULT WINAPI
MimeMessage_FindNext(IMimeMessage
*iface
, FINDBODY
*pFindBody
, HBODY
*phBody
)
2452 MimeMessage
*This
= impl_from_IMimeMessage(iface
);
2456 TRACE("(%p)->(%p, %p)\n", iface
, pFindBody
, phBody
);
2458 hr
= find_body( &This
->body_tree
, UlongToHandle( pFindBody
->dwReserved
), &body
);
2459 if (hr
!= S_OK
) return MIME_E_NOT_FOUND
;
2460 return find_next(This
, body
, pFindBody
, phBody
);
2463 static HRESULT WINAPI
MimeMessage_ResolveURL(
2464 IMimeMessage
*iface
,
2471 FIXME("(%p)->(%p, %s, %s, 0x%x, %p)\n", iface
, hRelated
, pszBase
, pszURL
, dwFlags
, phBody
);
2475 static HRESULT WINAPI
MimeMessage_ToMultipart(
2476 IMimeMessage
*iface
,
2479 LPHBODY phMultipart
)
2481 FIXME("(%p)->(%p, %s, %p)\n", iface
, hBody
, pszSubType
, phMultipart
);
2485 static HRESULT WINAPI
MimeMessage_GetBodyOffsets(
2486 IMimeMessage
*iface
,
2488 LPBODYOFFSETS pOffsets
)
2490 FIXME("(%p)->(%p, %p)\n", iface
, hBody
, pOffsets
);
2494 static HRESULT WINAPI
MimeMessage_GetCharset(
2495 IMimeMessage
*iface
,
2496 LPHCHARSET phCharset
)
2498 FIXME("(%p)->(%p)\n", iface
, phCharset
);
2503 static HRESULT WINAPI
MimeMessage_SetCharset(
2504 IMimeMessage
*iface
,
2506 CSETAPPLYTYPE applytype
)
2508 FIXME("(%p)->(%p, %d)\n", iface
, hCharset
, applytype
);
2512 static HRESULT WINAPI
MimeMessage_IsBodyType(
2513 IMimeMessage
*iface
,
2515 IMSGBODYTYPE bodytype
)
2518 IMimeBody
*mime_body
;
2519 TRACE("(%p)->(%p, %d)\n", iface
, hBody
, bodytype
);
2521 hr
= IMimeMessage_BindToObject(iface
, hBody
, &IID_IMimeBody
, (void**)&mime_body
);
2522 if(hr
!= S_OK
) return hr
;
2524 hr
= IMimeBody_IsType(mime_body
, bodytype
);
2525 MimeBody_Release(mime_body
);
2529 static HRESULT WINAPI
MimeMessage_IsContentType(
2530 IMimeMessage
*iface
,
2536 IMimeBody
*mime_body
;
2537 TRACE("(%p)->(%p, %s, %s)\n", iface
, hBody
, debugstr_a(pszPriType
),
2538 debugstr_a(pszSubType
));
2540 hr
= IMimeMessage_BindToObject(iface
, hBody
, &IID_IMimeBody
, (void**)&mime_body
);
2541 if(FAILED(hr
)) return hr
;
2543 hr
= IMimeBody_IsContentType(mime_body
, pszPriType
, pszSubType
);
2544 IMimeBody_Release(mime_body
);
2548 static HRESULT WINAPI
MimeMessage_QueryBodyProp(
2549 IMimeMessage
*iface
,
2554 boolean fCaseSensitive
)
2556 FIXME("(%p)->(%p, %s, %s, %s, %s)\n", iface
, hBody
, pszName
, pszCriteria
, fSubString
? "TRUE" : "FALSE", fCaseSensitive
? "TRUE" : "FALSE");
2560 static HRESULT WINAPI
MimeMessage_GetBodyProp(
2561 IMimeMessage
*iface
,
2565 LPPROPVARIANT pValue
)
2568 IMimeBody
*mime_body
;
2570 TRACE("(%p)->(%p, %s, 0x%x, %p)\n", iface
, hBody
, pszName
, dwFlags
, pValue
);
2572 hr
= IMimeMessage_BindToObject(iface
, hBody
, &IID_IMimeBody
, (void**)&mime_body
);
2573 if(hr
!= S_OK
) return hr
;
2575 hr
= IMimeBody_GetProp(mime_body
, pszName
, dwFlags
, pValue
);
2576 IMimeBody_Release(mime_body
);
2581 static HRESULT WINAPI
MimeMessage_SetBodyProp(
2582 IMimeMessage
*iface
,
2586 LPCPROPVARIANT pValue
)
2588 FIXME("(%p)->(%p, %s, 0x%x, %p)\n", iface
, hBody
, pszName
, dwFlags
, pValue
);
2592 static HRESULT WINAPI
MimeMessage_DeleteBodyProp(
2593 IMimeMessage
*iface
,
2597 FIXME("(%p)->(%p, %s)\n", iface
, hBody
, pszName
);
2601 static HRESULT WINAPI
MimeMessage_SetOption(
2602 IMimeMessage
*iface
,
2604 LPCPROPVARIANT pValue
)
2607 TRACE("(%p)->(%08x, %p)\n", iface
, oid
, pValue
);
2609 /* Message ID is checked before type.
2610 * OID 0x4D -> 0x56 and 0x58 aren't defined but will filtered out later.
2612 if(TYPEDID_ID(oid
) < TYPEDID_ID(OID_ALLOW_8BIT_HEADER
) || TYPEDID_ID(oid
) > TYPEDID_ID(OID_SECURITY_2KEY_CERT_BAG_64
))
2614 WARN("oid (%08x) out of range\n", oid
);
2615 return MIME_E_INVALID_OPTION_ID
;
2618 if(pValue
->vt
!= TYPEDID_TYPE(oid
))
2620 WARN("Called with vartype %04x and oid %08x\n", pValue
->vt
, oid
);
2626 case OID_HIDE_TNEF_ATTACHMENTS
:
2627 FIXME("OID_HIDE_TNEF_ATTACHMENTS (value %d): ignoring\n", pValue
->u
.boolVal
);
2629 case OID_SHOW_MACBINARY
:
2630 FIXME("OID_SHOW_MACBINARY (value %d): ignoring\n", pValue
->u
.boolVal
);
2632 case OID_SAVEBODY_KEEPBOUNDARY
:
2633 FIXME("OID_SAVEBODY_KEEPBOUNDARY (value %d): ignoring\n", pValue
->u
.boolVal
);
2635 case OID_CLEANUP_TREE_ON_SAVE
:
2636 FIXME("OID_CLEANUP_TREE_ON_SAVE (value %d): ignoring\n", pValue
->u
.boolVal
);
2639 FIXME("Unhandled oid %08x\n", oid
);
2640 hr
= MIME_E_INVALID_OPTION_ID
;
2646 static HRESULT WINAPI
MimeMessage_GetOption(
2647 IMimeMessage
*iface
,
2649 LPPROPVARIANT pValue
)
2651 FIXME("(%p)->(%08x, %p)\n", iface
, oid
, pValue
);
2655 /*** IMimeMessage methods ***/
2656 static HRESULT WINAPI
MimeMessage_CreateWebPage(
2657 IMimeMessage
*iface
,
2659 LPWEBPAGEOPTIONS pOptions
,
2660 IMimeMessageCallback
*pCallback
,
2661 IMoniker
**ppMoniker
)
2663 FIXME("(%p)->(%p, %p, %p, %p)\n", iface
, pRootStm
, pOptions
, pCallback
, ppMoniker
);
2668 static HRESULT WINAPI
MimeMessage_GetProp(
2669 IMimeMessage
*iface
,
2672 LPPROPVARIANT pValue
)
2674 FIXME("(%p)->(%s, 0x%x, %p)\n", iface
, pszName
, dwFlags
, pValue
);
2678 static HRESULT WINAPI
MimeMessage_SetProp(
2679 IMimeMessage
*iface
,
2682 LPCPROPVARIANT pValue
)
2684 FIXME("(%p)->(%s, 0x%x, %p)\n", iface
, pszName
, dwFlags
, pValue
);
2688 static HRESULT WINAPI
MimeMessage_DeleteProp(
2689 IMimeMessage
*iface
,
2692 FIXME("(%p)->(%s)\n", iface
, pszName
);
2696 static HRESULT WINAPI
MimeMessage_QueryProp(
2697 IMimeMessage
*iface
,
2701 boolean fCaseSensitive
)
2703 FIXME("(%p)->(%s, %s, %s, %s)\n", iface
, pszName
, pszCriteria
, fSubString
? "TRUE" : "FALSE", fCaseSensitive
? "TRUE" : "FALSE");
2707 static HRESULT WINAPI
MimeMessage_GetTextBody(
2708 IMimeMessage
*iface
,
2710 ENCODINGTYPE ietEncoding
,
2716 FINDBODY find_struct
;
2717 IMimeBody
*mime_body
;
2718 static char text
[] = "text";
2719 static char plain
[] = "plain";
2720 static char html
[] = "html";
2722 TRACE("(%p)->(%d, %d, %p, %p)\n", iface
, dwTxtType
, ietEncoding
, pStream
, phBody
);
2724 find_struct
.pszPriType
= text
;
2729 find_struct
.pszSubType
= plain
;
2732 find_struct
.pszSubType
= html
;
2735 return MIME_E_INVALID_TEXT_TYPE
;
2738 hr
= IMimeMessage_FindFirst(iface
, &find_struct
, &hbody
);
2741 TRACE("not found hr %08x\n", hr
);
2746 IMimeMessage_BindToObject(iface
, hbody
, &IID_IMimeBody
, (void**)&mime_body
);
2748 IMimeBody_GetData(mime_body
, ietEncoding
, pStream
);
2750 IMimeBody_Release(mime_body
);
2754 static HRESULT WINAPI
MimeMessage_SetTextBody(
2755 IMimeMessage
*iface
,
2757 ENCODINGTYPE ietEncoding
,
2762 FIXME("(%p)->(%d, %d, %p, %p, %p)\n", iface
, dwTxtType
, ietEncoding
, hAlternative
, pStream
, phBody
);
2766 static HRESULT WINAPI
MimeMessage_AttachObject(
2767 IMimeMessage
*iface
,
2772 FIXME("(%p)->(%s, %p, %p)\n", iface
, debugstr_guid(riid
), pvObject
, phBody
);
2776 static HRESULT WINAPI
MimeMessage_AttachFile(
2777 IMimeMessage
*iface
,
2782 FIXME("(%p)->(%s, %p, %p)\n", iface
, pszFilePath
, pstmFile
, phBody
);
2786 static HRESULT WINAPI
MimeMessage_AttachURL(
2787 IMimeMessage
*iface
,
2795 FIXME("(%p)->(%s, %s, 0x%x, %p, %p, %p)\n", iface
, pszBase
, pszURL
, dwFlags
, pstmURL
, ppszCIDURL
, phBody
);
2799 static HRESULT WINAPI
MimeMessage_GetAttachments(
2800 IMimeMessage
*iface
,
2802 LPHBODY
*pprghAttach
)
2805 FINDBODY find_struct
;
2810 TRACE("(%p)->(%p, %p)\n", iface
, pcAttach
, pprghAttach
);
2813 array
= CoTaskMemAlloc(size
* sizeof(HBODY
));
2815 find_struct
.pszPriType
= find_struct
.pszSubType
= NULL
;
2816 hr
= IMimeMessage_FindFirst(iface
, &find_struct
, &hbody
);
2819 hr
= IMimeMessage_IsContentType(iface
, hbody
, "multipart", NULL
);
2820 TRACE("IsCT rets %08x %d\n", hr
, *pcAttach
);
2823 if(*pcAttach
+ 1 > size
)
2826 array
= CoTaskMemRealloc(array
, size
* sizeof(HBODY
));
2828 array
[*pcAttach
] = hbody
;
2831 hr
= IMimeMessage_FindNext(iface
, &find_struct
, &hbody
);
2834 *pprghAttach
= array
;
2838 static HRESULT WINAPI
MimeMessage_GetAddressTable(
2839 IMimeMessage
*iface
,
2840 IMimeAddressTable
**ppTable
)
2842 FIXME("(%p)->(%p)\n", iface
, ppTable
);
2846 static HRESULT WINAPI
MimeMessage_GetSender(
2847 IMimeMessage
*iface
,
2848 LPADDRESSPROPS pAddress
)
2850 FIXME("(%p)->(%p)\n", iface
, pAddress
);
2854 static HRESULT WINAPI
MimeMessage_GetAddressTypes(
2855 IMimeMessage
*iface
,
2858 LPADDRESSLIST pList
)
2860 FIXME("(%p)->(%d, %d, %p)\n", iface
, dwAdrTypes
, dwProps
, pList
);
2864 static HRESULT WINAPI
MimeMessage_GetAddressFormat(
2865 IMimeMessage
*iface
,
2867 ADDRESSFORMAT format
,
2870 FIXME("(%p)->(%d, %d, %p)\n", iface
, dwAdrTypes
, format
, ppszFormat
);
2874 static HRESULT WINAPI
MimeMessage_EnumAddressTypes(
2875 IMimeMessage
*iface
,
2878 IMimeEnumAddressTypes
**ppEnum
)
2880 FIXME("(%p)->(%d, %d, %p)\n", iface
, dwAdrTypes
, dwProps
, ppEnum
);
2884 static HRESULT WINAPI
MimeMessage_SplitMessage(
2885 IMimeMessage
*iface
,
2887 IMimeMessageParts
**ppParts
)
2889 FIXME("(%p)->(%d, %p)\n", iface
, cbMaxPart
, ppParts
);
2893 static HRESULT WINAPI
MimeMessage_GetRootMoniker(
2894 IMimeMessage
*iface
,
2895 IMoniker
**ppMoniker
)
2897 FIXME("(%p)->(%p)\n", iface
, ppMoniker
);
2901 static const IMimeMessageVtbl MimeMessageVtbl
=
2903 MimeMessage_QueryInterface
,
2905 MimeMessage_Release
,
2906 MimeMessage_GetClassID
,
2907 MimeMessage_IsDirty
,
2910 MimeMessage_GetSizeMax
,
2911 MimeMessage_InitNew
,
2912 MimeMessage_GetMessageSource
,
2913 MimeMessage_GetMessageSize
,
2914 MimeMessage_LoadOffsetTable
,
2915 MimeMessage_SaveOffsetTable
,
2916 MimeMessage_GetFlags
,
2918 MimeMessage_HandsOffStorage
,
2919 MimeMessage_BindToObject
,
2920 MimeMessage_SaveBody
,
2921 MimeMessage_InsertBody
,
2922 MimeMessage_GetBody
,
2923 MimeMessage_DeleteBody
,
2924 MimeMessage_MoveBody
,
2925 MimeMessage_CountBodies
,
2926 MimeMessage_FindFirst
,
2927 MimeMessage_FindNext
,
2928 MimeMessage_ResolveURL
,
2929 MimeMessage_ToMultipart
,
2930 MimeMessage_GetBodyOffsets
,
2931 MimeMessage_GetCharset
,
2932 MimeMessage_SetCharset
,
2933 MimeMessage_IsBodyType
,
2934 MimeMessage_IsContentType
,
2935 MimeMessage_QueryBodyProp
,
2936 MimeMessage_GetBodyProp
,
2937 MimeMessage_SetBodyProp
,
2938 MimeMessage_DeleteBodyProp
,
2939 MimeMessage_SetOption
,
2940 MimeMessage_GetOption
,
2941 MimeMessage_CreateWebPage
,
2942 MimeMessage_GetProp
,
2943 MimeMessage_SetProp
,
2944 MimeMessage_DeleteProp
,
2945 MimeMessage_QueryProp
,
2946 MimeMessage_GetTextBody
,
2947 MimeMessage_SetTextBody
,
2948 MimeMessage_AttachObject
,
2949 MimeMessage_AttachFile
,
2950 MimeMessage_AttachURL
,
2951 MimeMessage_GetAttachments
,
2952 MimeMessage_GetAddressTable
,
2953 MimeMessage_GetSender
,
2954 MimeMessage_GetAddressTypes
,
2955 MimeMessage_GetAddressFormat
,
2956 MimeMessage_EnumAddressTypes
,
2957 MimeMessage_SplitMessage
,
2958 MimeMessage_GetRootMoniker
,
2961 HRESULT
MimeMessage_create(IUnknown
*outer
, void **obj
)
2964 MimeBody
*mime_body
;
2967 TRACE("(%p, %p)\n", outer
, obj
);
2971 FIXME("outer unknown not supported yet\n");
2977 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
2978 if (!This
) return E_OUTOFMEMORY
;
2980 This
->IMimeMessage_iface
.lpVtbl
= &MimeMessageVtbl
;
2982 This
->stream
= NULL
;
2983 list_init(&This
->body_tree
);
2984 This
->next_index
= 1;
2986 mime_body
= mimebody_create();
2987 root_body
= new_body_entry(mime_body
, This
->next_index
++, NULL
);
2988 list_add_head(&This
->body_tree
, &root_body
->entry
);
2990 *obj
= &This
->IMimeMessage_iface
;
2994 /***********************************************************************
2995 * MimeOleCreateMessage (INETCOMM.@)
2997 HRESULT WINAPI
MimeOleCreateMessage(IUnknown
*pUnkOuter
, IMimeMessage
**ppMessage
)
2999 TRACE("(%p, %p)\n", pUnkOuter
, ppMessage
);
3000 return MimeMessage_create(NULL
, (void **)ppMessage
);
3003 /***********************************************************************
3004 * MimeOleSetCompatMode (INETCOMM.@)
3006 HRESULT WINAPI
MimeOleSetCompatMode(DWORD dwMode
)
3008 FIXME("(0x%x)\n", dwMode
);
3012 /***********************************************************************
3013 * MimeOleCreateVirtualStream (INETCOMM.@)
3015 HRESULT WINAPI
MimeOleCreateVirtualStream(IStream
**ppStream
)
3018 FIXME("(%p)\n", ppStream
);
3020 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, ppStream
);
3024 typedef struct MimeSecurity
3026 IMimeSecurity IMimeSecurity_iface
;
3030 static inline MimeSecurity
*impl_from_IMimeSecurity(IMimeSecurity
*iface
)
3032 return CONTAINING_RECORD(iface
, MimeSecurity
, IMimeSecurity_iface
);
3035 static HRESULT WINAPI
MimeSecurity_QueryInterface(IMimeSecurity
*iface
, REFIID riid
, void **ppv
)
3037 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
3039 if (IsEqualIID(riid
, &IID_IUnknown
) ||
3040 IsEqualIID(riid
, &IID_IMimeSecurity
))
3043 IMimeSecurity_AddRef(iface
);
3047 FIXME("no interface for %s\n", debugstr_guid(riid
));
3049 return E_NOINTERFACE
;
3052 static ULONG WINAPI
MimeSecurity_AddRef(IMimeSecurity
*iface
)
3054 MimeSecurity
*This
= impl_from_IMimeSecurity(iface
);
3055 LONG ref
= InterlockedIncrement(&This
->ref
);
3057 TRACE("(%p) ref=%d\n", This
, ref
);
3062 static ULONG WINAPI
MimeSecurity_Release(IMimeSecurity
*iface
)
3064 MimeSecurity
*This
= impl_from_IMimeSecurity(iface
);
3065 LONG ref
= InterlockedDecrement(&This
->ref
);
3067 TRACE("(%p) ref=%d\n", This
, ref
);
3070 HeapFree(GetProcessHeap(), 0, This
);
3075 static HRESULT WINAPI
MimeSecurity_InitNew(
3076 IMimeSecurity
* iface
)
3078 FIXME("(%p)->(): stub\n", iface
);
3082 static HRESULT WINAPI
MimeSecurity_CheckInit(
3083 IMimeSecurity
* iface
)
3085 FIXME("(%p)->(): stub\n", iface
);
3089 static HRESULT WINAPI
MimeSecurity_EncodeMessage(
3090 IMimeSecurity
* iface
,
3091 IMimeMessageTree
* pTree
,
3094 FIXME("(%p)->(%p, %08x): stub\n", iface
, pTree
, dwFlags
);
3098 static HRESULT WINAPI
MimeSecurity_EncodeBody(
3099 IMimeSecurity
* iface
,
3100 IMimeMessageTree
* pTree
,
3104 FIXME("(%p)->(%p, %p, %08x): stub\n", iface
, pTree
, hEncodeRoot
, dwFlags
);
3108 static HRESULT WINAPI
MimeSecurity_DecodeMessage(
3109 IMimeSecurity
* iface
,
3110 IMimeMessageTree
* pTree
,
3113 FIXME("(%p)->(%p, %08x): stub\n", iface
, pTree
, dwFlags
);
3117 static HRESULT WINAPI
MimeSecurity_DecodeBody(
3118 IMimeSecurity
* iface
,
3119 IMimeMessageTree
* pTree
,
3123 FIXME("(%p)->(%p, %p, %08x): stub\n", iface
, pTree
, hDecodeRoot
, dwFlags
);
3127 static HRESULT WINAPI
MimeSecurity_EnumCertificates(
3128 IMimeSecurity
* iface
,
3134 FIXME("(%p)->(%p, %08x, %p, %p): stub\n", iface
, hc
, dwUsage
, pPrev
, ppCert
);
3138 static HRESULT WINAPI
MimeSecurity_GetCertificateName(
3139 IMimeSecurity
* iface
,
3140 const PCX509CERT pX509Cert
,
3141 const CERTNAMETYPE cn
,
3144 FIXME("(%p)->(%p, %08x, %p): stub\n", iface
, pX509Cert
, cn
, ppszName
);
3148 static HRESULT WINAPI
MimeSecurity_GetMessageType(
3149 IMimeSecurity
* iface
,
3150 const HWND hwndParent
,
3154 FIXME("(%p)->(%p, %p, %p): stub\n", iface
, hwndParent
, pBody
, pdwSecType
);
3158 static HRESULT WINAPI
MimeSecurity_GetCertData(
3159 IMimeSecurity
* iface
,
3160 const PCX509CERT pX509Cert
,
3161 const CERTDATAID dataid
,
3162 LPPROPVARIANT pValue
)
3164 FIXME("(%p)->(%p, %x, %p): stub\n", iface
, pX509Cert
, dataid
, pValue
);
3169 static const IMimeSecurityVtbl MimeSecurityVtbl
=
3171 MimeSecurity_QueryInterface
,
3172 MimeSecurity_AddRef
,
3173 MimeSecurity_Release
,
3174 MimeSecurity_InitNew
,
3175 MimeSecurity_CheckInit
,
3176 MimeSecurity_EncodeMessage
,
3177 MimeSecurity_EncodeBody
,
3178 MimeSecurity_DecodeMessage
,
3179 MimeSecurity_DecodeBody
,
3180 MimeSecurity_EnumCertificates
,
3181 MimeSecurity_GetCertificateName
,
3182 MimeSecurity_GetMessageType
,
3183 MimeSecurity_GetCertData
3186 HRESULT
MimeSecurity_create(IUnknown
*outer
, void **obj
)
3192 if (outer
) return CLASS_E_NOAGGREGATION
;
3194 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
3195 if (!This
) return E_OUTOFMEMORY
;
3197 This
->IMimeSecurity_iface
.lpVtbl
= &MimeSecurityVtbl
;
3200 *obj
= &This
->IMimeSecurity_iface
;
3204 /***********************************************************************
3205 * MimeOleCreateSecurity (INETCOMM.@)
3207 HRESULT WINAPI
MimeOleCreateSecurity(IMimeSecurity
**ppSecurity
)
3209 return MimeSecurity_create(NULL
, (void **)ppSecurity
);
3212 static HRESULT WINAPI
MimeAlloc_QueryInterface(
3213 IMimeAllocator
* iface
,
3217 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), obj
);
3219 if (IsEqualIID(riid
, &IID_IUnknown
) ||
3220 IsEqualIID(riid
, &IID_IMalloc
) ||
3221 IsEqualIID(riid
, &IID_IMimeAllocator
))
3224 IMimeAllocator_AddRef(iface
);
3228 FIXME("no interface for %s\n", debugstr_guid(riid
));
3230 return E_NOINTERFACE
;
3233 static ULONG WINAPI
MimeAlloc_AddRef(
3234 IMimeAllocator
* iface
)
3239 static ULONG WINAPI
MimeAlloc_Release(
3240 IMimeAllocator
* iface
)
3245 static LPVOID WINAPI
MimeAlloc_Alloc(
3246 IMimeAllocator
* iface
,
3249 return CoTaskMemAlloc(cb
);
3252 static LPVOID WINAPI
MimeAlloc_Realloc(
3253 IMimeAllocator
* iface
,
3257 return CoTaskMemRealloc(pv
, cb
);
3260 static void WINAPI
MimeAlloc_Free(
3261 IMimeAllocator
* iface
,
3267 static SIZE_T WINAPI
MimeAlloc_GetSize(
3268 IMimeAllocator
* iface
,
3275 static int WINAPI
MimeAlloc_DidAlloc(
3276 IMimeAllocator
* iface
,
3283 static void WINAPI
MimeAlloc_HeapMinimize(
3284 IMimeAllocator
* iface
)
3290 static HRESULT WINAPI
MimeAlloc_FreeParamInfoArray(
3291 IMimeAllocator
* iface
,
3293 LPMIMEPARAMINFO prgParam
,
3297 TRACE("(%p)->(%d, %p, %d)\n", iface
, cParams
, prgParam
, fFreeArray
);
3299 for(i
= 0; i
< cParams
; i
++)
3301 IMimeAllocator_Free(iface
, prgParam
[i
].pszName
);
3302 IMimeAllocator_Free(iface
, prgParam
[i
].pszData
);
3304 if(fFreeArray
) IMimeAllocator_Free(iface
, prgParam
);
3308 static HRESULT WINAPI
MimeAlloc_FreeAddressList(
3309 IMimeAllocator
* iface
,
3310 LPADDRESSLIST pList
)
3316 static HRESULT WINAPI
MimeAlloc_FreeAddressProps(
3317 IMimeAllocator
* iface
,
3318 LPADDRESSPROPS pAddress
)
3324 static HRESULT WINAPI
MimeAlloc_ReleaseObjects(
3325 IMimeAllocator
* iface
,
3327 IUnknown
**prgpUnknown
,
3335 static HRESULT WINAPI
MimeAlloc_FreeEnumHeaderRowArray(
3336 IMimeAllocator
* iface
,
3338 LPENUMHEADERROW prgRow
,
3345 static HRESULT WINAPI
MimeAlloc_FreeEnumPropertyArray(
3346 IMimeAllocator
* iface
,
3348 LPENUMPROPERTY prgProp
,
3355 static HRESULT WINAPI
MimeAlloc_FreeThumbprint(
3356 IMimeAllocator
* iface
,
3357 THUMBBLOB
*pthumbprint
)
3364 static HRESULT WINAPI
MimeAlloc_PropVariantClear(
3365 IMimeAllocator
* iface
,
3366 LPPROPVARIANT pProp
)
3372 static IMimeAllocatorVtbl mime_alloc_vtbl
=
3374 MimeAlloc_QueryInterface
,
3382 MimeAlloc_HeapMinimize
,
3383 MimeAlloc_FreeParamInfoArray
,
3384 MimeAlloc_FreeAddressList
,
3385 MimeAlloc_FreeAddressProps
,
3386 MimeAlloc_ReleaseObjects
,
3387 MimeAlloc_FreeEnumHeaderRowArray
,
3388 MimeAlloc_FreeEnumPropertyArray
,
3389 MimeAlloc_FreeThumbprint
,
3390 MimeAlloc_PropVariantClear
3393 static IMimeAllocator mime_allocator
=
3398 HRESULT
MimeAllocator_create(IUnknown
*outer
, void **obj
)
3400 if(outer
) return CLASS_E_NOAGGREGATION
;
3402 *obj
= &mime_allocator
;
3406 HRESULT WINAPI
MimeOleGetAllocator(IMimeAllocator
**alloc
)
3408 return MimeAllocator_create(NULL
, (void**)alloc
);
3411 HRESULT
VirtualStream_create(IUnknown
*outer
, void **obj
)
3413 FIXME("(%p, %p)\n", outer
, obj
);
3416 if (outer
) return CLASS_E_NOAGGREGATION
;
3418 return MimeOleCreateVirtualStream((IStream
**)obj
);
3421 /* IMimePropertySchema Interface */
3422 static HRESULT WINAPI
propschema_QueryInterface(IMimePropertySchema
*iface
, REFIID riid
, void **out
)
3424 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3425 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), out
);
3429 if (IsEqualIID(riid
, &IID_IUnknown
) ||
3430 IsEqualIID(riid
, &IID_IMimePropertySchema
))
3436 FIXME("no interface for %s\n", debugstr_guid(riid
));
3437 return E_NOINTERFACE
;
3440 IMimePropertySchema_AddRef(iface
);
3444 static ULONG WINAPI
propschema_AddRef(IMimePropertySchema
*iface
)
3446 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3447 LONG ref
= InterlockedIncrement(&This
->ref
);
3449 TRACE("(%p) ref=%d\n", This
, ref
);
3454 static ULONG WINAPI
propschema_Release(IMimePropertySchema
*iface
)
3456 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3457 LONG ref
= InterlockedDecrement(&This
->ref
);
3459 TRACE("(%p) ref=%d\n", This
, ref
);
3463 HeapFree(GetProcessHeap(), 0, This
);
3469 static HRESULT WINAPI
propschema_RegisterProperty(IMimePropertySchema
*iface
, const char *name
, DWORD flags
,
3470 DWORD rownumber
, VARTYPE vtdefault
, DWORD
*propid
)
3472 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3473 FIXME("(%p)->(%s, %x, %d, %d, %p) stub\n", This
, debugstr_a(name
), flags
, rownumber
, vtdefault
, propid
);
3477 static HRESULT WINAPI
propschema_ModifyProperty(IMimePropertySchema
*iface
, const char *name
, DWORD flags
,
3478 DWORD rownumber
, VARTYPE vtdefault
)
3480 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3481 FIXME("(%p)->(%s, %x, %d, %d) stub\n", This
, debugstr_a(name
), flags
, rownumber
, vtdefault
);
3485 static HRESULT WINAPI
propschema_GetPropertyId(IMimePropertySchema
*iface
, const char *name
, DWORD
*propid
)
3487 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3488 FIXME("(%p)->(%s, %p) stub\n", This
, debugstr_a(name
), propid
);
3492 static HRESULT WINAPI
propschema_GetPropertyName(IMimePropertySchema
*iface
, DWORD propid
, char **name
)
3494 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3495 FIXME("(%p)->(%d, %p) stub\n", This
, propid
, name
);
3499 static HRESULT WINAPI
propschema_RegisterAddressType(IMimePropertySchema
*iface
, const char *name
, DWORD
*adrtype
)
3501 propschema
*This
= impl_from_IMimePropertySchema(iface
);
3502 FIXME("(%p)->(%s, %p) stub\n", This
, debugstr_a(name
), adrtype
);
3506 static IMimePropertySchemaVtbl prop_schema_vtbl
=
3508 propschema_QueryInterface
,
3511 propschema_RegisterProperty
,
3512 propschema_ModifyProperty
,
3513 propschema_GetPropertyId
,
3514 propschema_GetPropertyName
,
3515 propschema_RegisterAddressType
3519 HRESULT WINAPI
MimeOleGetPropertySchema(IMimePropertySchema
**schema
)
3523 TRACE("(%p) stub\n", schema
);
3525 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
3527 return E_OUTOFMEMORY
;
3529 This
->IMimePropertySchema_iface
.lpVtbl
= &prop_schema_vtbl
;
3532 *schema
= &This
->IMimePropertySchema_iface
;
3537 HRESULT WINAPI
MimeGetAddressFormatW(REFIID riid
, void *object
, DWORD addr_type
,
3538 ADDRESSFORMAT addr_format
, WCHAR
**address
)
3540 FIXME("(%s, %p, %d, %d, %p) stub\n", debugstr_guid(riid
), object
, addr_type
, addr_format
, address
);
3545 HRESULT WINAPI
MimeOleObjectFromMoniker(BINDF bindf
, IMoniker
*moniker
, IBindCtx
*binding
,
3546 REFIID riid
, void **out
, IMoniker
**moniker_new
)
3548 FIXME("(0x%08x, %p, %p, %s, %p, %p) stub\n", bindf
, moniker
, binding
, debugstr_guid(riid
), out
, moniker_new
);