ReactOS 0.4.15-dev-5666-gc548b97
mimeole.c
Go to the documentation of this file.
1/*
2 * MIME OLE Interfaces
3 *
4 * Copyright 2006 Robert Shearman for CodeWeavers
5 * Copyright 2007 Huw Davies for CodeWeavers
6 *
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.
11 *
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.
16 *
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
20 */
21
22#define COBJMACROS
23#define NONAMELESSUNION
24
25#include <stdarg.h>
26#include <stdio.h>
27
28#include "windef.h"
29#include "winbase.h"
30#include "wine/winternl.h"
31#include "winuser.h"
32#include "objbase.h"
33#include "ole2.h"
34#include "mimeole.h"
35#ifdef __REACTOS__
36#include <winreg.h>
37#endif
38#include "propvarutil.h"
39
40#include "wine/heap.h"
41#include "wine/list.h"
42#include "wine/debug.h"
43
44#include "inetcomm_private.h"
45
47
48typedef struct
49{
52 DWORD flags; /* MIMEPROPFLAGS */
55
56typedef struct
57{
58 struct list entry;
61
62static const property_t default_props[] =
63{
64 {"X-Newsgroup", PID_HDR_NEWSGROUP, 0, VT_LPSTR},
65 {"Newsgroups", PID_HDR_NEWSGROUPS, 0, VT_LPSTR},
66 {"References", PID_HDR_REFS, 0, VT_LPSTR},
67 {"Subject", PID_HDR_SUBJECT, 0, VT_LPSTR},
68 {"From", PID_HDR_FROM, MPF_ADDRESS, VT_LPSTR},
69 {"Message-ID", PID_HDR_MESSAGEID, 0, VT_LPSTR},
70 {"Return-Path", PID_HDR_RETURNPATH, MPF_ADDRESS, VT_LPSTR},
71 {"Rr", PID_HDR_RR, 0, VT_LPSTR},
72 {"Return-Receipt-To", PID_HDR_RETRCPTO, MPF_ADDRESS, VT_LPSTR},
73 {"Apparently-To", PID_HDR_APPARTO, MPF_ADDRESS, VT_LPSTR},
74 {"Date", PID_HDR_DATE, 0, VT_LPSTR},
75 {"Received", PID_HDR_RECEIVED, 0, VT_LPSTR},
76 {"Reply-To", PID_HDR_REPLYTO, MPF_ADDRESS, VT_LPSTR},
77 {"X-Mailer", PID_HDR_XMAILER, 0, VT_LPSTR},
78 {"Bcc", PID_HDR_BCC, MPF_ADDRESS, VT_LPSTR},
79 {"MIME-Version", PID_HDR_MIMEVER, MPF_MIME, VT_LPSTR},
80 {"Content-Type", PID_HDR_CNTTYPE, MPF_MIME | MPF_HASPARAMS, VT_LPSTR},
81 {"Content-Transfer-Encoding", PID_HDR_CNTXFER, MPF_MIME, VT_LPSTR},
82 {"Content-ID", PID_HDR_CNTID, MPF_MIME, VT_LPSTR},
83 {"Content-Description", PID_HDR_CNTDESC, MPF_MIME, VT_LPSTR},
84 {"Content-Disposition", PID_HDR_CNTDISP, MPF_MIME | MPF_HASPARAMS, VT_LPSTR},
85 {"Content-Base", PID_HDR_CNTBASE, MPF_MIME, VT_LPSTR},
86 {"Content-Location", PID_HDR_CNTLOC, MPF_MIME, VT_LPSTR},
87 {"To", PID_HDR_TO, MPF_ADDRESS, VT_LPSTR},
88 {"Path", PID_HDR_PATH, 0, VT_LPSTR},
89 {"Followup-To", PID_HDR_FOLLOWUPTO, 0, VT_LPSTR},
90 {"Expires", PID_HDR_EXPIRES, 0, VT_LPSTR},
91 {"Cc", PID_HDR_CC, MPF_ADDRESS, VT_LPSTR},
92 {"Control", PID_HDR_CONTROL, 0, VT_LPSTR},
93 {"Distribution", PID_HDR_DISTRIB, 0, VT_LPSTR},
94 {"Keywords", PID_HDR_KEYWORDS, 0, VT_LPSTR},
95 {"Summary", PID_HDR_SUMMARY, 0, VT_LPSTR},
96 {"Approved", PID_HDR_APPROVED, 0, VT_LPSTR},
97 {"Lines", PID_HDR_LINES, 0, VT_LPSTR},
98 {"Xref", PID_HDR_XREF, 0, VT_LPSTR},
99 {"Organization", PID_HDR_ORG, 0, VT_LPSTR},
100 {"X-Newsreader", PID_HDR_XNEWSRDR, 0, VT_LPSTR},
101 {"X-Priority", PID_HDR_XPRI, 0, VT_LPSTR},
102 {"X-MSMail-Priority", PID_HDR_XMSPRI, 0, VT_LPSTR},
103 {"par:content-disposition:filename", PID_PAR_FILENAME, 0, VT_LPSTR},
104 {"par:content-type:boundary", PID_PAR_BOUNDARY, 0, VT_LPSTR},
105 {"par:content-type:charset", PID_PAR_CHARSET, 0, VT_LPSTR},
106 {"par:content-type:name", PID_PAR_NAME, 0, VT_LPSTR},
107 {"att:filename", PID_ATT_FILENAME, 0, VT_LPSTR},
108 {"att:pri-content-type", PID_ATT_PRITYPE, 0, VT_LPSTR},
109 {"att:sub-content-type", PID_ATT_SUBTYPE, 0, VT_LPSTR},
110 {"att:illegal-lines", PID_ATT_ILLEGAL, 0, VT_LPSTR},
111 {"att:rendered", PID_ATT_RENDERED, 0, VT_LPSTR},
112 {"att:sent-time", PID_ATT_SENTTIME, 0, VT_LPSTR},
113 {"att:priority", PID_ATT_PRIORITY, 0, VT_LPSTR},
114 {"Comment", PID_HDR_COMMENT, 0, VT_LPSTR},
115 {"Encoding", PID_HDR_ENCODING, 0, VT_LPSTR},
116 {"Encrypted", PID_HDR_ENCRYPTED, 0, VT_LPSTR},
117 {"X-Offsets", PID_HDR_OFFSETS, 0, VT_LPSTR},
118 {"X-Unsent", PID_HDR_XUNSENT, 0, VT_LPSTR},
119 {"X-ArticleId", PID_HDR_ARTICLEID, 0, VT_LPSTR},
120 {"Sender", PID_HDR_SENDER, MPF_ADDRESS, VT_LPSTR},
121 {"att:athena-server", PID_ATT_SERVER, 0, VT_LPSTR},
122 {"att:athena-account-id", PID_ATT_ACCOUNT, 0, VT_LPSTR},
123 {"att:athena-pop3-uidl", PID_ATT_UIDL, 0, VT_LPSTR},
124 {"att:athena-store-msgid", PID_ATT_STOREMSGID, 0, VT_LPSTR},
125 {"att:athena-user-name", PID_ATT_USERNAME, 0, VT_LPSTR},
126 {"att:athena-forward-to", PID_ATT_FORWARDTO, 0, VT_LPSTR},
127 {"att:athena-store-fdrid", PID_ATT_STOREFOLDERID,0, VT_LPSTR},
128 {"att:athena-ghosted", PID_ATT_GHOSTED, 0, VT_LPSTR},
129 {"att:athena-uncachedsize", PID_ATT_UNCACHEDSIZE, 0, VT_LPSTR},
130 {"att:athena-combined", PID_ATT_COMBINED, 0, VT_LPSTR},
131 {"att:auto-inlined", PID_ATT_AUTOINLINED, 0, VT_LPSTR},
132 {"Disposition-Notification-To", PID_HDR_DISP_NOTIFICATION_TO, 0, VT_LPSTR},
133 {"par:Content-Type:reply-type", PID_PAR_REPLYTYPE, 0, VT_LPSTR},
134 {"par:Content-Type:format", PID_PAR_FORMAT , 0, VT_LPSTR},
135 {"att:format", PID_ATT_FORMAT , 0, VT_LPSTR},
136 {"In-Reply-To", PID_HDR_INREPLYTO, 0, VT_LPSTR},
137 {"att:athena-account-name", PID_ATT_ACCOUNTNAME, 0, VT_LPSTR},
138 {NULL, 0, 0, 0}
139};
140
141typedef struct
142{
143 struct list entry;
144 char *name;
145 char *value;
146} param_t;
147
148typedef struct
149{
150 struct list entry;
152 PROPVARIANT value;
153 struct list params;
154} header_t;
155
156typedef struct MimeBody
157{
160
161 HBODY handle;
162
163 struct list headers;
164 struct list new_props; /* FIXME: This should be in a PropertySchema */
168 ENCODINGTYPE encoding;
169 void *data;
171 BODYOFFSETS body_offsets;
173
174typedef struct
175{
181
183{
184 return CONTAINING_RECORD(iface, sub_stream_t, IStream_iface);
185}
186
188{
190
191 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
192 *ppv = NULL;
193
195 IsEqualIID(riid, &IID_ISequentialStream) ||
196 IsEqualIID(riid, &IID_IStream))
197 {
198 IStream_AddRef(iface);
199 *ppv = iface;
200 return S_OK;
201 }
202 return E_NOINTERFACE;
203}
204
206{
209
210 TRACE("(%p) ref=%d\n", This, ref);
211
212 return ref;
213}
214
216{
219
220 TRACE("(%p) ref=%d\n", This, ref);
221
222 if(!ref)
223 {
224 IStream_Release(This->base);
226 }
227 return ref;
228}
229
231 IStream* iface,
232 void *pv,
233 ULONG cb,
234 ULONG *pcbRead)
235{
237 HRESULT hr;
238 LARGE_INTEGER tmp_pos;
239
240 TRACE("(%p, %d, %p)\n", pv, cb, pcbRead);
241
242 tmp_pos.QuadPart = This->pos.QuadPart + This->start.QuadPart;
243 IStream_Seek(This->base, tmp_pos, STREAM_SEEK_SET, NULL);
244
245 if(This->pos.QuadPart + cb > This->length.QuadPart)
246 cb = This->length.QuadPart - This->pos.QuadPart;
247
248 hr = IStream_Read(This->base, pv, cb, pcbRead);
249
250 This->pos.QuadPart += *pcbRead;
251
252 return hr;
253}
254
256 IStream* iface,
257 const void *pv,
258 ULONG cb,
259 ULONG *pcbWritten)
260{
261 FIXME("stub\n");
262 return E_NOTIMPL;
263}
264
266 IStream* iface,
267 LARGE_INTEGER dlibMove,
268 DWORD dwOrigin,
269 ULARGE_INTEGER *plibNewPosition)
270{
272 LARGE_INTEGER new_pos;
273
274 TRACE("(%08x.%08x, %x, %p)\n", dlibMove.u.HighPart, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
275
276 switch(dwOrigin)
277 {
278 case STREAM_SEEK_SET:
279 new_pos = dlibMove;
280 break;
281 case STREAM_SEEK_CUR:
282 new_pos.QuadPart = This->pos.QuadPart + dlibMove.QuadPart;
283 break;
284 case STREAM_SEEK_END:
285 new_pos.QuadPart = This->length.QuadPart + dlibMove.QuadPart;
286 break;
287 default:
289 }
290
291 if(new_pos.QuadPart < 0) new_pos.QuadPart = 0;
292 else if(new_pos.QuadPart > This->length.QuadPart) new_pos.QuadPart = This->length.QuadPart;
293
294 This->pos.QuadPart = new_pos.QuadPart;
295
296 if(plibNewPosition) *plibNewPosition = This->pos;
297 return S_OK;
298}
299
301 IStream* iface,
302 ULARGE_INTEGER libNewSize)
303{
304 FIXME("stub\n");
305 return E_NOTIMPL;
306}
307
309 IStream* iface,
310 IStream *pstm,
312 ULARGE_INTEGER *pcbRead,
313 ULARGE_INTEGER *pcbWritten)
314{
315 HRESULT hr = S_OK;
316 BYTE tmpBuffer[128];
317 ULONG bytesRead, bytesWritten, copySize;
318 ULARGE_INTEGER totalBytesRead;
319 ULARGE_INTEGER totalBytesWritten;
320
321 TRACE("(%p)->(%p, %d, %p, %p)\n", iface, pstm, cb.u.LowPart, pcbRead, pcbWritten);
322
323 totalBytesRead.QuadPart = 0;
324 totalBytesWritten.QuadPart = 0;
325
326 while ( cb.QuadPart > 0 )
327 {
328 if ( cb.QuadPart >= sizeof(tmpBuffer) )
329 copySize = sizeof(tmpBuffer);
330 else
331 copySize = cb.u.LowPart;
332
333 hr = IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
334 if (FAILED(hr)) break;
335
336 totalBytesRead.QuadPart += bytesRead;
337
338 if (bytesRead)
339 {
340 hr = IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
341 if (FAILED(hr)) break;
342 totalBytesWritten.QuadPart += bytesWritten;
343 }
344
345 if (bytesRead != copySize)
346 cb.QuadPart = 0;
347 else
348 cb.QuadPart -= bytesRead;
349 }
350
351 if (pcbRead) pcbRead->QuadPart = totalBytesRead.QuadPart;
352 if (pcbWritten) pcbWritten->QuadPart = totalBytesWritten.QuadPart;
353
354 return hr;
355}
356
358 IStream* iface,
359 DWORD grfCommitFlags)
360{
361 FIXME("stub\n");
362 return E_NOTIMPL;
363}
364
366 IStream* iface)
367{
368 FIXME("stub\n");
369 return E_NOTIMPL;
370}
371
373 IStream* iface,
374 ULARGE_INTEGER libOffset,
376 DWORD dwLockType)
377{
378 FIXME("stub\n");
379 return E_NOTIMPL;
380}
381
383 IStream* iface,
384 ULARGE_INTEGER libOffset,
386 DWORD dwLockType)
387{
388 FIXME("stub\n");
389 return E_NOTIMPL;
390}
391
393 IStream* iface,
394 STATSTG *pstatstg,
395 DWORD grfStatFlag)
396{
398 FIXME("(%p)->(%p, %08x)\n", This, pstatstg, grfStatFlag);
399 memset(pstatstg, 0, sizeof(*pstatstg));
400 pstatstg->cbSize = This->length;
401 return S_OK;
402}
403
405 IStream* iface,
406 IStream **ppstm)
407{
408 FIXME("stub\n");
409 return E_NOTIMPL;
410}
411
412static struct IStreamVtbl sub_stream_vtbl =
413{
428};
429
431{
433
434 *out = NULL;
435 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
436 if(!This) return E_OUTOFMEMORY;
437
438 This->IStream_iface.lpVtbl = &sub_stream_vtbl;
439 This->ref = 1;
440 This->start = start;
441 This->length = length;
442 This->pos.QuadPart = 0;
443 IStream_AddRef(stream);
444 This->base = stream;
445
446 *out = &This->IStream_iface;
447 return S_OK;
448}
449
451{
452 STATSTG statstg = {NULL};
455
456 hres = IStream_Stat(stream, &statstg, STATFLAG_NONAME);
457 if(SUCCEEDED(hres)) {
458 *size = statstg.cbSize;
459 return S_OK;
460 }
461
462 zero.QuadPart = 0;
463 return IStream_Seek(stream, zero, STREAM_SEEK_END, size);
464}
465
467{
468 return CONTAINING_RECORD(iface, MimeBody, IMimeBody_iface);
469}
470
471typedef struct propschema
472{
473 IMimePropertySchema IMimePropertySchema_iface;
476
477static inline propschema *impl_from_IMimePropertySchema(IMimePropertySchema *iface)
478{
479 return CONTAINING_RECORD(iface, propschema, IMimePropertySchema_iface);
480}
481
483{
484 char *ret;
485 int len = strlen(str);
486 ret = HeapAlloc(GetProcessHeap(), 0, len + 1);
487 memcpy(ret, str, len + 1);
488 return ret;
489}
490
491#define PARSER_BUF_SIZE 1024
492
493/*****************************************************
494 * copy_headers_to_buf [internal]
495 *
496 * Copies the headers into a '\0' terminated memory block and leave
497 * the stream's current position set to after the blank line.
498 */
500{
501 char *buf = NULL;
502 DWORD size = PARSER_BUF_SIZE, offset = 0, last_end = 0;
503 HRESULT hr;
504 BOOL done = FALSE;
505
506 *ptr = NULL;
507
508 do
509 {
510 char *end;
511 DWORD read;
512
513 if(!buf)
514 buf = HeapAlloc(GetProcessHeap(), 0, size + 1);
515 else
516 {
517 size *= 2;
518 buf = HeapReAlloc(GetProcessHeap(), 0, buf, size + 1);
519 }
520 if(!buf)
521 {
523 goto fail;
524 }
525
526 hr = IStream_Read(stm, buf + offset, size - offset, &read);
527 if(FAILED(hr)) goto fail;
528
529 offset += read;
530 buf[offset] = '\0';
531
532 if(read == 0) done = TRUE;
533
534 while(!done && (end = strstr(buf + last_end, "\r\n")))
535 {
536 DWORD new_end = end - buf + 2;
537 if(new_end - last_end == 2)
538 {
539 LARGE_INTEGER off;
540 off.QuadPart = (LONGLONG)new_end - offset;
541 IStream_Seek(stm, off, STREAM_SEEK_CUR, NULL);
542 buf[new_end] = '\0';
543 done = TRUE;
544 }
545 else
546 last_end = new_end;
547 }
548 } while(!done);
549
550 *ptr = buf;
551 return S_OK;
552
553fail:
555 return hr;
556}
557
559{
560 char *colon = strchr(*ptr, ':');
561 const property_t *prop;
562 header_t *ret;
563
564 if(!colon) return NULL;
565
566 *colon = '\0';
567
568 for(prop = default_props; prop->name; prop++)
569 {
570 if(!lstrcmpiA(*ptr, prop->name))
571 {
572 TRACE("%s: found match with default property id %d\n", *ptr, prop->id);
573 break;
574 }
575 }
576
577 if(!prop->name)
578 {
579 property_list_entry_t *prop_entry;
580 LIST_FOR_EACH_ENTRY(prop_entry, &body->new_props, property_list_entry_t, entry)
581 {
582 if(!lstrcmpiA(*ptr, prop_entry->prop.name))
583 {
584 TRACE("%s: found match with already added new property id %d\n", *ptr, prop_entry->prop.id);
585 prop = &prop_entry->prop;
586 break;
587 }
588 }
589 if(!prop->name)
590 {
591 prop_entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*prop_entry));
592 prop_entry->prop.name = strdupA(*ptr);
593 prop_entry->prop.id = body->next_prop_id++;
594 prop_entry->prop.flags = 0;
595 prop_entry->prop.default_vt = VT_LPSTR;
596 list_add_tail(&body->new_props, &prop_entry->entry);
597 prop = &prop_entry->prop;
598 TRACE("%s: allocating new prop id %d\n", *ptr, prop_entry->prop.id);
599 }
600 }
601
602 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(*ret));
603 ret->prop = prop;
604 PropVariantInit(&ret->value);
605 list_init(&ret->params);
606 *ptr = colon + 1;
607
608 return ret;
609}
610
611static void unfold_header(char *header, int len)
612{
613 char *start = header, *cp = header;
614
615 do {
616 while(*cp == ' ' || *cp == '\t')
617 {
618 cp++;
619 len--;
620 }
621 if(cp != start)
622 memmove(start, cp, len + 1);
623
624 cp = strstr(start, "\r\n");
625 len -= (cp - start);
626 start = cp;
627 *start = ' ';
628 start++;
629 len--;
630 cp += 2;
631 } while(*cp == ' ' || *cp == '\t');
632
633 *(start - 1) = '\0';
634}
635
636static char *unquote_string(const char *str)
637{
638 BOOL quoted = FALSE;
639 char *ret, *cp;
640
641 while(*str == ' ' || *str == '\t') str++;
642
643 if(*str == '"')
644 {
645 quoted = TRUE;
646 str++;
647 }
648 ret = strdupA(str);
649 for(cp = ret; *cp; cp++)
650 {
651 if(*cp == '\\')
652 memmove(cp, cp + 1, strlen(cp + 1) + 1);
653 else if(*cp == '"')
654 {
655 if(!quoted)
656 {
657 WARN("quote in unquoted string\n");
658 }
659 else
660 {
661 *cp = '\0';
662 break;
663 }
664 }
665 }
666 return ret;
667}
668
669static void add_param(header_t *header, const char *p)
670{
671 const char *key = p, *value, *cp = p;
672 param_t *param;
673 char *name;
674
675 TRACE("got param %s\n", p);
676
677 while (*key == ' ' || *key == '\t' ) key++;
678
679 cp = strchr(key, '=');
680 if(!cp)
681 {
682 WARN("malformed parameter - skipping\n");
683 return;
684 }
685
686 name = HeapAlloc(GetProcessHeap(), 0, cp - key + 1);
687 memcpy(name, key, cp - key);
688 name[cp - key] = '\0';
689
690 value = cp + 1;
691
692 param = HeapAlloc(GetProcessHeap(), 0, sizeof(*param));
693 param->name = name;
694 param->value = unquote_string(value);
695 list_add_tail(&header->params, &param->entry);
696}
697
698static void split_params(header_t *header, char *value)
699{
700 char *cp = value, *start = value;
701 BOOL in_quotes = FALSE, done_value = FALSE;
702
703 while(*cp)
704 {
705 if(!in_quotes && *cp == ';')
706 {
707 *cp = '\0';
708 if(done_value) add_param(header, start);
709 done_value = TRUE;
710 start = cp + 1;
711 }
712 else if(*cp == '"')
713 in_quotes = !in_quotes;
714 cp++;
715 }
716 if(done_value) add_param(header, start);
717}
718
719static void read_value(header_t *header, char **cur)
720{
721 char *end = *cur, *value;
722 DWORD len;
723
724 do {
725 end = strstr(end, "\r\n");
726 end += 2;
727 } while(*end == ' ' || *end == '\t');
728
729 len = end - *cur;
730 value = HeapAlloc(GetProcessHeap(), 0, len + 1);
731 memcpy(value, *cur, len);
732 value[len] = '\0';
733
735 TRACE("value %s\n", debugstr_a(value));
736
737 if(header->prop->flags & MPF_HASPARAMS)
738 {
740 TRACE("value w/o params %s\n", debugstr_a(value));
741 }
742
743 header->value.vt = VT_LPSTR;
744 header->value.u.pszVal = value;
745
746 *cur = end;
747}
748
750{
751 char *slash;
752 DWORD len;
753
754 slash = strchr(header->value.u.pszVal, '/');
755 if(!slash)
756 {
757 WARN("malformed context type value\n");
758 return;
759 }
760 len = slash - header->value.u.pszVal;
761 body->content_pri_type = HeapAlloc(GetProcessHeap(), 0, len + 1);
762 memcpy(body->content_pri_type, header->value.u.pszVal, len);
763 body->content_pri_type[len] = '\0';
764 body->content_sub_type = strdupA(slash + 1);
765}
766
768{
769 const char *encoding = header->value.u.pszVal;
770
771 if(!_strnicmp(encoding, "base64", -1))
772 body->encoding = IET_BASE64;
773 else if(!_strnicmp(encoding, "quoted-printable", -1))
774 body->encoding = IET_QP;
775 else if(!_strnicmp(encoding, "7bit", -1))
776 body->encoding = IET_7BIT;
777 else if(!_strnicmp(encoding, "8bit", -1))
778 body->encoding = IET_8BIT;
779 else
780 FIXME("unknown encoding %s\n", debugstr_a(encoding));
781}
782
784{
785 char *header_buf, *cur_header_ptr;
786 HRESULT hr;
788
789 hr = copy_headers_to_buf(stm, &header_buf);
790 if(FAILED(hr)) return hr;
791
792 cur_header_ptr = header_buf;
793 while((header = read_prop(body, &cur_header_ptr)))
794 {
795 read_value(header, &cur_header_ptr);
796 list_add_tail(&body->headers, &header->entry);
797
798 switch(header->prop->id) {
799 case PID_HDR_CNTTYPE:
801 break;
802 case PID_HDR_CNTXFER:
804 break;
805 }
806 }
807
808 HeapFree(GetProcessHeap(), 0, header_buf);
809 return hr;
810}
811
812static void empty_param_list(struct list *list)
813{
814 param_t *param, *cursor2;
815
817 {
818 list_remove(&param->entry);
822 }
823}
824
826{
827 list_remove(&header->entry);
829 empty_param_list(&header->params);
831}
832
833static void empty_header_list(struct list *list)
834{
835 header_t *header, *cursor2;
836
838 {
840 }
841}
842
843static void empty_new_prop_list(struct list *list)
844{
845 property_list_entry_t *prop, *cursor2;
846
848 {
849 list_remove(&prop->entry);
850 HeapFree(GetProcessHeap(), 0, (char *)prop->prop.name);
851 HeapFree(GetProcessHeap(), 0, prop);
852 }
853}
854
855static void release_data(REFIID riid, void *data)
856{
857 if(!data) return;
858
859 if(IsEqualIID(riid, &IID_IStream))
860 IStream_Release((IStream *)data);
861 else
862 FIXME("Unhandled data format %s\n", debugstr_guid(riid));
863}
864
865static HRESULT find_prop(MimeBody *body, const char *name, header_t **prop)
866{
868
869 *prop = NULL;
870
872 {
873 if(ISPIDSTR(name))
874 {
875 if(STRTOPID(name) == header->prop->id)
876 {
877 *prop = header;
878 return S_OK;
879 }
880 }
881 else if(!lstrcmpiA(name, header->prop->name))
882 {
883 *prop = header;
884 return S_OK;
885 }
886 }
887
888 return MIME_E_NOT_FOUND;
889}
890
891static const property_t *find_default_prop(const char *name)
892{
893 const property_t *prop_def = NULL;
894
895 for(prop_def = default_props; prop_def->name; prop_def++)
896 {
897 if(ISPIDSTR(name))
898 {
899 if(STRTOPID(name) == prop_def->id)
900 {
901 break;
902 }
903 }
904 else if(!lstrcmpiA(name, prop_def->name))
905 {
906 break;
907 }
908 }
909
910 if(prop_def->id)
911 TRACE("%s: found match with default property id %d\n", prop_def->name, prop_def->id);
912 else
913 prop_def = NULL;
914
915 return prop_def;
916}
917
919 REFIID riid,
920 void** ppvObject)
921{
922 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppvObject);
923
924 *ppvObject = NULL;
925
929 IsEqualIID(riid, &IID_IMimePropertySet) ||
930 IsEqualIID(riid, &IID_IMimeBody))
931 {
932 *ppvObject = iface;
933 }
934
935 if(*ppvObject)
936 {
937 IUnknown_AddRef((IUnknown*)*ppvObject);
938 return S_OK;
939 }
940
941 FIXME("no interface for %s\n", debugstr_guid(riid));
942 return E_NOINTERFACE;
943}
944
946{
949
950 TRACE("(%p) ref=%d\n", This, ref);
951
952 return ref;
953}
954
956{
959
960 TRACE("(%p) ref=%d\n", This, ref);
961
962 if (!ref)
963 {
964 empty_header_list(&This->headers);
965 empty_new_prop_list(&This->new_props);
966
967 HeapFree(GetProcessHeap(), 0, This->content_pri_type);
968 HeapFree(GetProcessHeap(), 0, This->content_sub_type);
969
970 release_data(&This->data_iid, This->data);
971
973 }
974
975 return ref;
976}
977
979 IMimeBody* iface,
980 CLSID* pClassID)
981{
983
984 TRACE("(%p)->(%p)\n", This, pClassID);
985
986 if(!pClassID)
987 return E_INVALIDARG;
988
989 *pClassID = IID_IMimeBody;
990 return S_OK;
991}
992
994 IMimeBody* iface)
995{
997 FIXME("(%p)->() stub\n", This);
998 return E_NOTIMPL;
999}
1000
1002{
1004 TRACE("(%p)->(%p)\n", This, pStm);
1005 return parse_headers(This, pStm);
1006}
1007
1008static HRESULT WINAPI MimeBody_Save(IMimeBody *iface, IStream *pStm, BOOL fClearDirty)
1009{
1011 FIXME("(%p)->(%p, %d)\n", This, pStm, fClearDirty);
1012 return E_NOTIMPL;
1013}
1014
1016 IMimeBody* iface,
1017 ULARGE_INTEGER* pcbSize)
1018{
1020 FIXME("(%p)->(%p) stub\n", This, pcbSize);
1021 return E_NOTIMPL;
1022}
1023
1025 IMimeBody* iface)
1026{
1028 TRACE("(%p)->()\n", This);
1029 return S_OK;
1030}
1031
1033 IMimeBody* iface,
1034 LPCSTR pszName,
1035 LPMIMEPROPINFO pInfo)
1036{
1039 HRESULT hr;
1040 DWORD supported = PIM_PROPID | PIM_VTDEFAULT;
1041
1042 TRACE("(%p)->(%s, %p) semi-stub\n", This, debugstr_a(pszName), pInfo);
1043
1044 if(!pszName || !pInfo)
1045 return E_INVALIDARG;
1046
1047 TRACE("mask 0x%04x\n", pInfo->dwMask);
1048
1049 if(pInfo->dwMask & ~supported)
1050 FIXME("Unsupported mask flags 0x%04x\n", pInfo->dwMask & ~supported);
1051
1052 hr = find_prop(This, pszName, &header);
1053 if(hr == S_OK)
1054 {
1055 if(pInfo->dwMask & PIM_CHARSET)
1056 pInfo->hCharset = 0;
1057 if(pInfo->dwMask & PIM_FLAGS)
1058 pInfo->dwFlags = 0x00000000;
1059 if(pInfo->dwMask & PIM_ROWNUMBER)
1060 pInfo->dwRowNumber = 0;
1061 if(pInfo->dwMask & PIM_ENCODINGTYPE)
1062 pInfo->ietEncoding = 0;
1063 if(pInfo->dwMask & PIM_VALUES)
1064 pInfo->cValues = 0;
1065 if(pInfo->dwMask & PIM_PROPID)
1066 pInfo->dwPropId = header->prop->id;
1067 if(pInfo->dwMask & PIM_VTDEFAULT)
1068 pInfo->vtDefault = header->prop->default_vt;
1069 if(pInfo->dwMask & PIM_VTCURRENT)
1070 pInfo->vtCurrent = 0;
1071 }
1072
1073 return hr;
1074}
1075
1077 IMimeBody* iface,
1078 LPCSTR pszName,
1079 LPCMIMEPROPINFO pInfo)
1080{
1082 FIXME("(%p)->(%s, %p) stub\n", This, debugstr_a(pszName), pInfo);
1083 return E_NOTIMPL;
1084}
1085
1087 IMimeBody* iface,
1088 LPCSTR pszName,
1089 DWORD dwFlags,
1090 LPPROPVARIANT pValue)
1091{
1094 HRESULT hr;
1095
1096 TRACE("(%p)->(%s, 0x%x, %p)\n", This, debugstr_a(pszName), dwFlags, pValue);
1097
1098 if(!pszName || !pValue)
1099 return E_INVALIDARG;
1100
1101 if(!ISPIDSTR(pszName) && !lstrcmpiA(pszName, "att:pri-content-type"))
1102 {
1104 pValue->vt = VT_LPSTR;
1105 pValue->u.pszVal = strdupA(This->content_pri_type);
1106 return S_OK;
1107 }
1108
1109 hr = find_prop(This, pszName, &header);
1110 if(hr == S_OK)
1111 {
1112 TRACE("type %d->%d\n", header->value.vt, pValue->vt);
1113
1115 if(FAILED(hr))
1116 FIXME("Conversion not currently supported (%d->%d)\n", header->value.vt, pValue->vt);
1117 }
1118
1119 return hr;
1120}
1121
1123 IMimeBody* iface,
1124 LPCSTR pszName,
1125 DWORD dwFlags,
1126 LPCPROPVARIANT pValue)
1127{
1130 HRESULT hr;
1131
1132 TRACE("(%p)->(%s, 0x%x, %p)\n", This, debugstr_a(pszName), dwFlags, pValue);
1133
1134 if(!pszName || !pValue)
1135 return E_INVALIDARG;
1136
1137 hr = find_prop(This, pszName, &header);
1138 if(hr != S_OK)
1139 {
1140 property_list_entry_t *prop_entry;
1141 const property_t *prop = NULL;
1142
1143 LIST_FOR_EACH_ENTRY(prop_entry, &This->new_props, property_list_entry_t, entry)
1144 {
1145 if(ISPIDSTR(pszName))
1146 {
1147 if(STRTOPID(pszName) == prop_entry->prop.id)
1148 {
1149 TRACE("Found match with already added new property id %d\n", prop_entry->prop.id);
1150 prop = &prop_entry->prop;
1151 break;
1152 }
1153 }
1154 else if(!lstrcmpiA(pszName, prop_entry->prop.name))
1155 {
1156 TRACE("Found match with already added new property id %d\n", prop_entry->prop.id);
1157 prop = &prop_entry->prop;
1158 break;
1159 }
1160 }
1161
1162 header = HeapAlloc(GetProcessHeap(), 0, sizeof(*header));
1163 if(!header)
1164 return E_OUTOFMEMORY;
1165
1166 if(!prop)
1167 {
1168 const property_t *prop_def = NULL;
1169 prop_entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*prop_entry));
1170 if(!prop_entry)
1171 {
1173 return E_OUTOFMEMORY;
1174 }
1175
1176 prop_def = find_default_prop(pszName);
1177 if(prop_def)
1178 {
1179 prop_entry->prop.name = strdupA(prop_def->name);
1180 prop_entry->prop.id = prop_def->id;
1181 }
1182 else
1183 {
1184 if(ISPIDSTR(pszName))
1185 {
1186 HeapFree(GetProcessHeap(), 0, prop_entry);
1188 return MIME_E_NOT_FOUND;
1189 }
1190
1191 prop_entry->prop.name = strdupA(pszName);
1192 prop_entry->prop.id = This->next_prop_id++;
1193 }
1194
1195 prop_entry->prop.flags = 0;
1196 prop_entry->prop.default_vt = pValue->vt;
1197 list_add_tail(&This->new_props, &prop_entry->entry);
1198 prop = &prop_entry->prop;
1199 TRACE("Allocating new prop id %d\n", prop_entry->prop.id);
1200 }
1201
1202 header->prop = prop;
1203 PropVariantInit(&header->value);
1204 list_init(&header->params);
1205 list_add_tail(&This->headers, &header->entry);
1206 }
1207
1209
1210 return S_OK;
1211}
1212
1214 IMimeBody* iface,
1215 LPCSTR pszName,
1216 DWORD dwFlags,
1217 LPPROPVARIANT pValue)
1218{
1220 FIXME("(%p)->(%s, 0x%x, %p) stub\n", This, debugstr_a(pszName), dwFlags, pValue);
1221 return E_NOTIMPL;
1222}
1223
1225 IMimeBody* iface,
1226 LPCSTR pszName)
1227{
1230 BOOL found;
1231
1232 TRACE("(%p)->(%s) stub\n", This, debugstr_a(pszName));
1233
1235 {
1236 if(ISPIDSTR(pszName))
1237 found = STRTOPID(pszName) == cursor->prop->id;
1238 else
1239 found = !lstrcmpiA(pszName, cursor->prop->name);
1240
1241 if(found)
1242 {
1244 return S_OK;
1245 }
1246 }
1247
1248 return MIME_E_NOT_FOUND;
1249}
1250
1252 IMimeBody* iface,
1253 ULONG cNames,
1254 LPCSTR* prgszName,
1255 IMimePropertySet* pPropertySet)
1256{
1258 FIXME("(%p)->(%d, %p, %p) stub\n", This, cNames, prgszName, pPropertySet);
1259 return E_NOTIMPL;
1260}
1261
1263 IMimeBody* iface,
1264 ULONG cNames,
1265 LPCSTR* prgszName,
1266 IMimePropertySet* pPropertySet)
1267{
1269 FIXME("(%p)->(%d, %p, %p) stub\n", This, cNames, prgszName, pPropertySet);
1270 return E_NOTIMPL;
1271}
1272
1274 IMimeBody* iface,
1275 ULONG cNames,
1276 LPCSTR* prgszName)
1277{
1279 FIXME("(%p)->(%d, %p) stub\n", This, cNames, prgszName);
1280 return E_NOTIMPL;
1281}
1282
1284 IMimeBody* iface,
1285 LPCSTR pszName,
1286 LPCSTR pszCriteria,
1287 boolean fSubString,
1288 boolean fCaseSensitive)
1289{
1291 FIXME("(%p)->(%s, %s, %d, %d) stub\n", This, debugstr_a(pszName), debugstr_a(pszCriteria), fSubString, fCaseSensitive);
1292 return E_NOTIMPL;
1293}
1294
1296 IMimeBody* iface,
1297 LPHCHARSET phCharset)
1298{
1300 FIXME("(%p)->(%p) stub\n", This, phCharset);
1301 *phCharset = NULL;
1302 return S_OK;
1303}
1304
1306 IMimeBody* iface,
1307 HCHARSET hCharset,
1308 CSETAPPLYTYPE applytype)
1309{
1311 FIXME("(%p)->(%p, %d) stub\n", This, hCharset, applytype);
1312 return E_NOTIMPL;
1313}
1314
1316 IMimeBody* iface,
1317 LPCSTR pszName,
1318 ULONG* pcParams,
1319 LPMIMEPARAMINFO* pprgParam)
1320{
1322 HRESULT hr;
1324
1325 TRACE("(%p)->(%s, %p, %p)\n", iface, debugstr_a(pszName), pcParams, pprgParam);
1326
1327 *pprgParam = NULL;
1328 *pcParams = 0;
1329
1330 hr = find_prop(This, pszName, &header);
1331 if(hr != S_OK) return hr;
1332
1333 *pcParams = list_count(&header->params);
1334 if(*pcParams)
1335 {
1336 IMimeAllocator *alloc;
1337 param_t *param;
1338 MIMEPARAMINFO *info;
1339
1341
1342 *pprgParam = info = IMimeAllocator_Alloc(alloc, *pcParams * sizeof(**pprgParam));
1344 {
1345 int len;
1346
1347 len = strlen(param->name) + 1;
1348 info->pszName = IMimeAllocator_Alloc(alloc, len);
1349 memcpy(info->pszName, param->name, len);
1350 len = strlen(param->value) + 1;
1351 info->pszData = IMimeAllocator_Alloc(alloc, len);
1352 memcpy(info->pszData, param->value, len);
1353 info++;
1354 }
1355 IMimeAllocator_Release(alloc);
1356 }
1357 return S_OK;
1358}
1359
1361 IMimeBody* iface,
1362 LPCSTR pszPriType,
1363 LPCSTR pszSubType)
1364{
1366
1367 TRACE("(%p)->(%s, %s)\n", This, debugstr_a(pszPriType), debugstr_a(pszSubType));
1368 if(pszPriType)
1369 {
1370 const char *pri = This->content_pri_type;
1371 if(!pri) pri = "text";
1372 if(lstrcmpiA(pri, pszPriType)) return S_FALSE;
1373 }
1374
1375 if(pszSubType)
1376 {
1377 const char *sub = This->content_sub_type;
1378 if(!sub) sub = "plain";
1379 if(lstrcmpiA(sub, pszSubType)) return S_FALSE;
1380 }
1381
1382 return S_OK;
1383}
1384
1386 IMimeBody* iface,
1387 REFIID riid,
1388 void** ppvObject)
1389{
1391 FIXME("(%p)->(%s, %p) stub\n", This, debugstr_guid(riid), ppvObject);
1392 return E_NOTIMPL;
1393}
1394
1396 IMimeBody* iface,
1397 IMimePropertySet** ppPropertySet)
1398{
1400 FIXME("(%p)->(%p) stub\n", This, ppPropertySet);
1401 return E_NOTIMPL;
1402}
1403
1405 IMimeBody* iface,
1406 const TYPEDID oid,
1407 LPCPROPVARIANT pValue)
1408{
1411 TRACE("(%p)->(%08x, %p)\n", This, oid, pValue);
1412
1413 if(pValue->vt != TYPEDID_TYPE(oid))
1414 {
1415 WARN("Called with vartype %04x and oid %08x\n", pValue->vt, oid);
1416 return E_INVALIDARG;
1417 }
1418
1419 switch(oid)
1420 {
1421 case OID_SECURITY_HWND_OWNER:
1422 FIXME("OID_SECURITY_HWND_OWNER (value %08x): ignoring\n", pValue->u.ulVal);
1423 hr = S_OK;
1424 break;
1425 case OID_TRANSMIT_BODY_ENCODING:
1426 FIXME("OID_TRANSMIT_BODY_ENCODING (value %08x): ignoring\n", pValue->u.ulVal);
1427 hr = S_OK;
1428 break;
1429 default:
1430 FIXME("Unhandled oid %08x\n", oid);
1431 }
1432
1433 return hr;
1434}
1435
1437 IMimeBody* iface,
1438 const TYPEDID oid,
1439 LPPROPVARIANT pValue)
1440{
1442 FIXME("(%p)->(%08x, %p): stub\n", This, oid, pValue);
1443 return E_NOTIMPL;
1444}
1445
1447 IMimeBody* iface,
1448 DWORD dwFlags,
1449 IMimeEnumProperties** ppEnum)
1450{
1452 FIXME("(%p)->(0x%x, %p) stub\n", This, dwFlags, ppEnum);
1453 return E_NOTIMPL;
1454}
1455
1457 IMimeBody* iface,
1458 IMSGBODYTYPE bodytype)
1459{
1461
1462 TRACE("(%p)->(%d)\n", This, bodytype);
1463 switch(bodytype)
1464 {
1465 case IBT_EMPTY:
1466 return This->data ? S_FALSE : S_OK;
1467 default:
1468 FIXME("Unimplemented bodytype %d - returning S_OK\n", bodytype);
1469 }
1470 return S_OK;
1471}
1472
1474 IMimeBody* iface,
1475 LPCSTR pszDisplay)
1476{
1478 FIXME("(%p)->(%s) stub\n", This, debugstr_a(pszDisplay));
1479 return E_NOTIMPL;
1480}
1481
1483 IMimeBody* iface,
1484 LPSTR* ppszDisplay)
1485{
1487 FIXME("(%p)->(%p) stub\n", This, ppszDisplay);
1488 return E_NOTIMPL;
1489}
1490
1492 IMimeBody* iface,
1493 LPBODYOFFSETS pOffsets)
1494{
1496 TRACE("(%p)->(%p)\n", This, pOffsets);
1497
1498 *pOffsets = This->body_offsets;
1499
1500 if(This->body_offsets.cbBodyEnd == 0) return MIME_E_NO_DATA;
1501 return S_OK;
1502}
1503
1505 IMimeBody* iface,
1506 ENCODINGTYPE* pietEncoding)
1507{
1509
1510 TRACE("(%p)->(%p)\n", This, pietEncoding);
1511
1512 *pietEncoding = This->encoding;
1513 return S_OK;
1514}
1515
1517 IMimeBody* iface,
1518 ENCODINGTYPE ietEncoding)
1519{
1521
1522 TRACE("(%p)->(%d)\n", This, ietEncoding);
1523
1524 This->encoding = ietEncoding;
1525 return S_OK;
1526}
1527
1529 IMimeBody* iface,
1530 ENCODINGTYPE ietEncoding,
1531 ULONG* pcbSize)
1532{
1534 FIXME("(%p)->(%d, %p) stub\n", This, ietEncoding, pcbSize);
1535 return E_NOTIMPL;
1536}
1537
1539 IMimeBody* iface,
1540 ENCODINGTYPE ietEncoding,
1541 IStream* pStream)
1542{
1544 FIXME("(%p)->(%d, %p) stub\n", This, ietEncoding, pStream);
1545 return E_NOTIMPL;
1546}
1547
1548static const signed char base64_decode_table[] =
1549{
1550 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00 */
1551 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10 */
1552 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 0x20 */
1553 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 0x30 */
1554 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40 */
1555 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 0x50 */
1556 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60 */
1557 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 /* 0x70 */
1558};
1559
1561{
1562 const unsigned char *ptr, *end;
1563 unsigned char buf[1024];
1565 unsigned char *ret;
1566 unsigned char in[4];
1567 IStream *output;
1568 DWORD size;
1569 int n = 0;
1570 HRESULT hres;
1571
1572 pos.QuadPart = 0;
1573 hres = IStream_Seek(input, pos, STREAM_SEEK_SET, NULL);
1574 if(FAILED(hres))
1575 return hres;
1576
1577 hres = CreateStreamOnHGlobal(NULL, TRUE, &output);
1578 if(FAILED(hres))
1579 return hres;
1580
1581 while(1) {
1582 hres = IStream_Read(input, buf, sizeof(buf), &size);
1583 if(FAILED(hres) || !size)
1584 break;
1585
1586 ptr = ret = buf;
1587 end = buf + size;
1588
1589 while(1) {
1590 /* skip invalid chars */
1591 while(ptr < end && (*ptr >= ARRAY_SIZE(base64_decode_table)
1592 || base64_decode_table[*ptr] == -1))
1593 ptr++;
1594 if(ptr == end)
1595 break;
1596
1597 in[n++] = base64_decode_table[*ptr++];
1598 switch(n) {
1599 case 2:
1600 *ret++ = in[0] << 2 | in[1] >> 4;
1601 continue;
1602 case 3:
1603 *ret++ = in[1] << 4 | in[2] >> 2;
1604 continue;
1605 case 4:
1606 *ret++ = ((in[2] << 6) & 0xc0) | in[3];
1607 n = 0;
1608 }
1609 }
1610
1611 if(ret > buf) {
1612 hres = IStream_Write(output, buf, ret - buf, NULL);
1613 if(FAILED(hres))
1614 break;
1615 }
1616 }
1617
1618 if(SUCCEEDED(hres))
1619 hres = IStream_Seek(output, pos, STREAM_SEEK_SET, NULL);
1620 if(FAILED(hres)) {
1621 IStream_Release(output);
1622 return hres;
1623 }
1624
1625 *ret_stream = output;
1626 return S_OK;
1627}
1628
1629static int hex_digit(char c)
1630{
1631 if('0' <= c && c <= '9')
1632 return c - '0';
1633 if('A' <= c && c <= 'F')
1634 return c - 'A' + 10;
1635 if('a' <= c && c <= 'f')
1636 return c - 'a' + 10;
1637 return -1;
1638}
1639
1640static HRESULT decode_qp(IStream *input, IStream **ret_stream)
1641{
1642 const unsigned char *ptr, *end;
1643 unsigned char *ret, prev = 0;
1644 unsigned char buf[1024];
1646 IStream *output;
1647 DWORD size;
1648 int n = -1;
1649 HRESULT hres;
1650
1651 pos.QuadPart = 0;
1652 hres = IStream_Seek(input, pos, STREAM_SEEK_SET, NULL);
1653 if(FAILED(hres))
1654 return hres;
1655
1656 hres = CreateStreamOnHGlobal(NULL, TRUE, &output);
1657 if(FAILED(hres))
1658 return hres;
1659
1660 while(1) {
1661 hres = IStream_Read(input, buf, sizeof(buf), &size);
1662 if(FAILED(hres) || !size)
1663 break;
1664
1665 ptr = ret = buf;
1666 end = buf + size;
1667
1668 while(ptr < end) {
1669 unsigned char byte = *ptr++;
1670
1671 switch(n) {
1672 case -1:
1673 if(byte == '=')
1674 n = 0;
1675 else
1676 *ret++ = byte;
1677 continue;
1678 case 0:
1679 prev = byte;
1680 n = 1;
1681 continue;
1682 case 1:
1683 if(prev != '\r' || byte != '\n') {
1684 int h1 = hex_digit(prev), h2 = hex_digit(byte);
1685 if(h1 != -1 && h2 != -1)
1686 *ret++ = (h1 << 4) | h2;
1687 else
1688 *ret++ = '=';
1689 }
1690 n = -1;
1691 continue;
1692 }
1693 }
1694
1695 if(ret > buf) {
1696 hres = IStream_Write(output, buf, ret - buf, NULL);
1697 if(FAILED(hres))
1698 break;
1699 }
1700 }
1701
1702 if(SUCCEEDED(hres))
1703 hres = IStream_Seek(output, pos, STREAM_SEEK_SET, NULL);
1704 if(FAILED(hres)) {
1705 IStream_Release(output);
1706 return hres;
1707 }
1708
1709 *ret_stream = output;
1710 return S_OK;
1711}
1712
1714 IMimeBody* iface,
1715 ENCODINGTYPE ietEncoding,
1716 IStream** ppStream)
1717{
1720 HRESULT hres;
1721
1722 TRACE("(%p)->(%d %p)\n", This, ietEncoding, ppStream);
1723
1724 if(This->encoding != ietEncoding) {
1725 switch(This->encoding) {
1726 case IET_BASE64:
1727 hres = decode_base64(This->data, ppStream);
1728 break;
1729 case IET_QP:
1730 hres = decode_qp(This->data, ppStream);
1731 break;
1732 default:
1733 FIXME("Decoding %d is not supported.\n", This->encoding);
1734 hres = S_FALSE;
1735 }
1736 if(ietEncoding != IET_BINARY)
1737 FIXME("Encoding %d is not supported.\n", ietEncoding);
1738 if(hres != S_FALSE)
1739 return hres;
1740 }
1741
1742 start.QuadPart = 0;
1743 hres = get_stream_size(This->data, &size);
1744 if(SUCCEEDED(hres))
1745 hres = create_sub_stream(This->data, start, size, ppStream);
1746 return hres;
1747}
1748
1750 IMimeBody* iface,
1751 ENCODINGTYPE ietEncoding,
1752 LPCSTR pszPriType,
1753 LPCSTR pszSubType,
1754 REFIID riid,
1755 LPVOID pvObject)
1756{
1758 TRACE("(%p)->(%d, %s, %s, %s %p)\n", This, ietEncoding, debugstr_a(pszPriType), debugstr_a(pszSubType),
1759 debugstr_guid(riid), pvObject);
1760
1761 if(IsEqualIID(riid, &IID_IStream))
1762 IStream_AddRef((IStream *)pvObject);
1763 else
1764 {
1765 FIXME("Unhandled object type %s\n", debugstr_guid(riid));
1766 return E_INVALIDARG;
1767 }
1768
1769 if(This->data)
1770 release_data(&This->data_iid, This->data);
1771
1772 This->data_iid = *riid;
1773 This->data = pvObject;
1774
1775 IMimeBody_SetCurrentEncoding(iface, ietEncoding);
1776
1777 /* FIXME: Update the content type.
1778 If pszPriType == NULL use 'application'
1779 If pszSubType == NULL use 'octet-stream' */
1780
1781 return S_OK;
1782}
1783
1785 IMimeBody* iface)
1786{
1788 FIXME("(%p)->() stub\n", This);
1789 return E_NOTIMPL;
1790}
1791
1793 IMimeBody* iface,
1794 IMimeBody* pBody)
1795{
1797 FIXME("(%p)->(%p) stub\n", This, pBody);
1798 return E_NOTIMPL;
1799}
1800
1802 IMimeBody* iface,
1803 LPTRANSMITINFO pTransmitInfo)
1804{
1806 FIXME("(%p)->(%p) stub\n", This, pTransmitInfo);
1807 return E_NOTIMPL;
1808}
1809
1811 IMimeBody* iface,
1812 ENCODINGTYPE ietEncoding,
1813 LPCSTR pszFilePath)
1814{
1816 FIXME("(%p)->(%d, %s) stub\n", This, ietEncoding, debugstr_a(pszFilePath));
1817 return E_NOTIMPL;
1818}
1819
1821 IMimeBody* iface,
1822 LPHBODY phBody)
1823{
1825 TRACE("(%p)->(%p)\n", iface, phBody);
1826
1827 if(!phBody)
1828 return E_INVALIDARG;
1829
1830 *phBody = This->handle;
1831 return This->handle ? S_OK : MIME_E_NO_DATA;
1832}
1833
1834static IMimeBodyVtbl body_vtbl =
1835{
1879};
1880
1882{
1883 TRACE("setting offsets to %d, %d, %d, %d\n", offsets->cbBoundaryStart,
1884 offsets->cbHeaderStart, offsets->cbBodyStart, offsets->cbBodyEnd);
1885
1886 body->body_offsets = *offsets;
1887 return S_OK;
1888}
1889
1890#define FIRST_CUSTOM_PROP_ID 0x100
1891
1893{
1894 MimeBody *This;
1895 BODYOFFSETS body_offsets;
1896
1897 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1898 if (!This)
1899 return NULL;
1900
1901 This->IMimeBody_iface.lpVtbl = &body_vtbl;
1902 This->ref = 1;
1903 This->handle = NULL;
1904 list_init(&This->headers);
1905 list_init(&This->new_props);
1906 This->next_prop_id = FIRST_CUSTOM_PROP_ID;
1907 This->content_pri_type = NULL;
1908 This->content_sub_type = NULL;
1909 This->encoding = IET_7BIT;
1910 This->data = NULL;
1911 This->data_iid = IID_NULL;
1912
1913 body_offsets.cbBoundaryStart = body_offsets.cbHeaderStart = 0;
1914 body_offsets.cbBodyStart = body_offsets.cbBodyEnd = 0;
1915 MimeBody_set_offsets(This, &body_offsets);
1916
1917 return This;
1918}
1919
1921{
1922 MimeBody *mb;
1923
1924 if(outer)
1925 return CLASS_E_NOAGGREGATION;
1926
1927 if ((mb = mimebody_create()))
1928 {
1929 *ppv = &mb->IMimeBody_iface;
1930 return S_OK;
1931 }
1932 else
1933 {
1934 *ppv = NULL;
1935 return E_OUTOFMEMORY;
1936 }
1937}
1938
1939typedef struct body_t
1940{
1941 struct list entry;
1944
1948
1949typedef struct MimeMessage
1950{
1954
1958
1960{
1961 return CONTAINING_RECORD(iface, MimeMessage, IMimeMessage_iface);
1962}
1963
1965{
1966 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1967
1968 if (IsEqualIID(riid, &IID_IUnknown) ||
1971 IsEqualIID(riid, &IID_IMimeMessageTree) ||
1972 IsEqualIID(riid, &IID_IMimeMessage))
1973 {
1974 *ppv = iface;
1975 IMimeMessage_AddRef(iface);
1976 return S_OK;
1977 }
1978
1979 FIXME("no interface for %s\n", debugstr_guid(riid));
1980 *ppv = NULL;
1981 return E_NOINTERFACE;
1982}
1983
1985{
1988
1989 TRACE("(%p) ref=%d\n", This, ref);
1990
1991 return ref;
1992}
1993
1994static void empty_body_list(struct list *list)
1995{
1996 body_t *body, *cursor2;
1998 {
1999 empty_body_list(&body->children);
2000 list_remove(&body->entry);
2001 IMimeBody_Release(&body->mime_body->IMimeBody_iface);
2003 }
2004}
2005
2007{
2010
2011 TRACE("(%p) ref=%d\n", This, ref);
2012
2013 if (!ref)
2014 {
2015 empty_body_list(&This->body_tree);
2016
2017 if(This->stream) IStream_Release(This->stream);
2019 }
2020
2021 return ref;
2022}
2023
2024/*** IPersist methods ***/
2026 IMimeMessage *iface,
2027 CLSID *pClassID)
2028{
2029 FIXME("(%p)->(%p)\n", iface, pClassID);
2030 return E_NOTIMPL;
2031}
2032
2033/*** IPersistStreamInit methods ***/
2035 IMimeMessage *iface)
2036{
2037 FIXME("(%p)->()\n", iface);
2038 return E_NOTIMPL;
2039}
2040
2042{
2043 body_t *body = HeapAlloc(GetProcessHeap(), 0, sizeof(*body));
2044 if(body)
2045 {
2046 body->mime_body = mime_body;
2047 body->index = index;
2048 list_init(&body->children);
2049 body->parent = parent;
2050
2051 mime_body->handle = UlongToHandle(body->index);
2052 }
2053 return body;
2054}
2055
2056typedef struct
2057{
2058 struct list entry;
2059 BODYOFFSETS offsets;
2061
2062static HRESULT create_body_offset_list(IStream *stm, const char *boundary, struct list *body_offsets)
2063{
2064 HRESULT hr;
2065 DWORD read, boundary_start;
2066 int boundary_len = strlen(boundary);
2067 char *buf, *ptr, *overlap;
2068 DWORD start = 0, overlap_no;
2069 offset_entry_t *cur_body = NULL;
2070 BOOL is_first_line = TRUE;
2073
2074 list_init(body_offsets);
2075
2076 overlap_no = boundary_len + 5;
2077
2078 overlap = buf = HeapAlloc(GetProcessHeap(), 0, overlap_no + PARSER_BUF_SIZE + 1);
2079
2080 zero.QuadPart = 0;
2081 hr = IStream_Seek(stm, zero, STREAM_SEEK_CUR, &cur);
2082 start = cur.u.LowPart;
2083
2084 do {
2085 hr = IStream_Read(stm, overlap, PARSER_BUF_SIZE, &read);
2086 if(FAILED(hr)) goto end;
2087 if(read == 0) break;
2088 overlap[read] = '\0';
2089
2090 ptr = buf;
2091 while(1) {
2092 if(is_first_line) {
2093 is_first_line = FALSE;
2094 }else {
2095 ptr = strstr(ptr, "\r\n");
2096 if(!ptr)
2097 break;
2098 ptr += 2;
2099 }
2100
2101 boundary_start = start + ptr - buf;
2102
2103 if(*ptr == '-' && *(ptr + 1) == '-' && !memcmp(ptr + 2, boundary, boundary_len)) {
2104 ptr += boundary_len + 2;
2105
2106 if(*ptr == '\r' && *(ptr + 1) == '\n')
2107 {
2108 ptr += 2;
2109 if(cur_body)
2110 {
2111 cur_body->offsets.cbBodyEnd = boundary_start - 2;
2112 list_add_tail(body_offsets, &cur_body->entry);
2113 }
2114 cur_body = HeapAlloc(GetProcessHeap(), 0, sizeof(*cur_body));
2115 cur_body->offsets.cbBoundaryStart = boundary_start;
2116 cur_body->offsets.cbHeaderStart = start + ptr - buf;
2117 }
2118 else if(*ptr == '-' && *(ptr + 1) == '-')
2119 {
2120 if(cur_body)
2121 {
2122 cur_body->offsets.cbBodyEnd = boundary_start - 2;
2123 list_add_tail(body_offsets, &cur_body->entry);
2124 goto end;
2125 }
2126 }
2127 }
2128 }
2129
2130 if(overlap == buf) /* 1st iteration */
2131 {
2132 memmove(buf, buf + PARSER_BUF_SIZE - overlap_no, overlap_no);
2133 overlap = buf + overlap_no;
2134 start += read - overlap_no;
2135 }
2136 else
2137 {
2138 memmove(buf, buf + PARSER_BUF_SIZE, overlap_no);
2139 start += read;
2140 }
2141 } while(1);
2142
2143end:
2145 return hr;
2146}
2147
2149{
2151 MimeBody *mime_body;
2152 HRESULT hr;
2153 body_t *body;
2155
2156 pos.QuadPart = offset->cbHeaderStart;
2157 IStream_Seek(pStm, pos, STREAM_SEEK_SET, NULL);
2158
2159 mime_body = mimebody_create();
2160 IMimeBody_Load(&mime_body->IMimeBody_iface, pStm);
2161
2162 pos.QuadPart = 0;
2163 hr = IStream_Seek(pStm, pos, STREAM_SEEK_CUR, &start);
2164 offset->cbBodyStart = start.QuadPart;
2165 if (parent) MimeBody_set_offsets(mime_body, offset);
2166
2167 length.QuadPart = offset->cbBodyEnd - offset->cbBodyStart;
2168 create_sub_stream(pStm, start, length, (IStream**)&mime_body->data);
2169 mime_body->data_iid = IID_IStream;
2170
2171 body = new_body_entry(mime_body, msg->next_index++, parent);
2172
2173 if(IMimeBody_IsContentType(&mime_body->IMimeBody_iface, "multipart", NULL) == S_OK)
2174 {
2175 MIMEPARAMINFO *param_info;
2176 ULONG count, i;
2177 IMimeAllocator *alloc;
2178
2179 hr = IMimeBody_GetParameters(&mime_body->IMimeBody_iface, "Content-Type", &count,
2180 &param_info);
2181 if(hr != S_OK || count == 0) return body;
2182
2184
2185 for(i = 0; i < count; i++)
2186 {
2187 if(!lstrcmpiA(param_info[i].pszName, "boundary"))
2188 {
2189 struct list offset_list;
2190 offset_entry_t *cur, *cursor2;
2191 hr = create_body_offset_list(pStm, param_info[i].pszData, &offset_list);
2192 LIST_FOR_EACH_ENTRY_SAFE(cur, cursor2, &offset_list, offset_entry_t, entry)
2193 {
2194 body_t *sub_body;
2195
2196 sub_body = create_sub_body(msg, pStm, &cur->offsets, body);
2197 list_add_tail(&body->children, &sub_body->entry);
2198 list_remove(&cur->entry);
2200 }
2201 break;
2202 }
2203 }
2204 IMimeAllocator_FreeParamInfoArray(alloc, count, param_info, TRUE);
2205 IMimeAllocator_Release(alloc);
2206 }
2207 return body;
2208}
2209
2211{
2213 body_t *root_body;
2214 BODYOFFSETS offsets;
2217
2218 TRACE("(%p)->(%p)\n", iface, pStm);
2219
2220 if(This->stream)
2221 {
2222 FIXME("already loaded a message\n");
2223 return E_FAIL;
2224 }
2225
2226 empty_body_list(&This->body_tree);
2227
2228 IStream_AddRef(pStm);
2229 This->stream = pStm;
2230 offsets.cbBoundaryStart = offsets.cbHeaderStart = 0;
2231 offsets.cbBodyStart = offsets.cbBodyEnd = 0;
2232
2233 root_body = create_sub_body(This, pStm, &offsets, NULL);
2234
2235 zero.QuadPart = 0;
2236 IStream_Seek(pStm, zero, STREAM_SEEK_END, &cur);
2237 offsets.cbBodyEnd = cur.u.LowPart;
2239
2240 list_add_head(&This->body_tree, &root_body->entry);
2241
2242 return S_OK;
2243}
2244
2245static HRESULT WINAPI MimeMessage_Save(IMimeMessage *iface, IStream *pStm, BOOL fClearDirty)
2246{
2247 FIXME("(%p)->(%p, %s)\n", iface, pStm, fClearDirty ? "TRUE" : "FALSE");
2248 return E_NOTIMPL;
2249}
2250
2252 IMimeMessage *iface,
2253 ULARGE_INTEGER *pcbSize)
2254{
2255 FIXME("(%p)->(%p)\n", iface, pcbSize);
2256 return E_NOTIMPL;
2257}
2258
2260 IMimeMessage *iface)
2261{
2262 FIXME("(%p)->()\n", iface);
2263 return E_NOTIMPL;
2264}
2265
2266/*** IMimeMessageTree methods ***/
2268 DWORD dwFlags)
2269{
2271
2272 FIXME("(%p)->(%p, 0x%x)\n", iface, ppStream, dwFlags);
2273
2274 IStream_AddRef(This->stream);
2275 *ppStream = This->stream;
2276 return S_OK;
2277}
2278
2280 IMimeMessage *iface,
2281 ULONG *pcbSize,
2282 DWORD dwFlags)
2283{
2284 FIXME("(%p)->(%p, 0x%x)\n", iface, pcbSize, dwFlags);
2285 return E_NOTIMPL;
2286}
2287
2289 IMimeMessage *iface,
2290 IStream *pStream)
2291{
2292 FIXME("(%p)->(%p)\n", iface, pStream);
2293 return E_NOTIMPL;
2294}
2295
2297 IMimeMessage *iface,
2298 IStream *pStream,
2299 DWORD dwFlags)
2300{
2301 FIXME("(%p)->(%p, 0x%x)\n", iface, pStream, dwFlags);
2302 return E_NOTIMPL;
2303}
2304
2305
2307 IMimeMessage *iface,
2308 DWORD *pdwFlags)
2309{
2310 FIXME("(%p)->(%p)\n", iface, pdwFlags);
2311 return E_NOTIMPL;
2312}
2313
2315 IMimeMessage *iface,
2316 DWORD dwFlags)
2317{
2318 FIXME("(%p)->(0x%x)\n", iface, dwFlags);
2319 return S_OK;
2320}
2321
2322
2324 IMimeMessage *iface)
2325{
2326 FIXME("(%p)->()\n", iface);
2327 return E_NOTIMPL;
2328}
2329
2330static HRESULT find_body(struct list *list, HBODY hbody, body_t **body)
2331{
2332 body_t *cur;
2333 HRESULT hr;
2334
2335 if(hbody == HBODY_ROOT)
2336 {
2338 return S_OK;
2339 }
2340
2342 {
2343 if(cur->index == HandleToUlong(hbody))
2344 {
2345 *body = cur;
2346 return S_OK;
2347 }
2348 hr = find_body(&cur->children, hbody, body);
2349 if(hr == S_OK) return S_OK;
2350 }
2351 return S_FALSE;
2352}
2353
2355 void **ppvObject)
2356{
2358 HRESULT hr;
2359 body_t *body;
2360
2361 TRACE("(%p)->(%p, %s, %p)\n", iface, hBody, debugstr_guid(riid), ppvObject);
2362
2363 hr = find_body(&This->body_tree, hBody, &body);
2364
2365 if(hr != S_OK) return hr;
2366
2367 if(IsEqualIID(riid, &IID_IMimeBody))
2368 {
2369 IMimeBody_AddRef(&body->mime_body->IMimeBody_iface);
2370 *ppvObject = &body->mime_body->IMimeBody_iface;
2371 return S_OK;
2372 }
2373
2374 return E_NOINTERFACE;
2375}
2376
2378 IMimeMessage *iface,
2379 HBODY hBody,
2380 DWORD dwFlags,
2381 IStream *pStream)
2382{
2383 FIXME("(%p)->(%p, 0x%x, %p)\n", iface, hBody, dwFlags, pStream);
2384 return E_NOTIMPL;
2385}
2386
2387static HRESULT get_body(MimeMessage *msg, BODYLOCATION location, HBODY pivot, body_t **out)
2388{
2389 body_t *root = LIST_ENTRY(list_head(&msg->body_tree), body_t, entry);
2390 body_t *body;
2391 HRESULT hr;
2392 struct list *list;
2393
2394 if(location == IBL_ROOT)
2395 {
2396 *out = root;
2397 return S_OK;
2398 }
2399
2400 hr = find_body(&msg->body_tree, pivot, &body);
2401
2402 if(hr == S_OK)
2403 {
2404 switch(location)
2405 {
2406 case IBL_PARENT:
2407 if(body->parent)
2408 *out = body->parent;
2409 else
2410 hr = MIME_E_NOT_FOUND;
2411 break;
2412
2413 case IBL_FIRST:
2414 list = list_head(&body->children);
2415 if(list)
2417 else
2418 hr = MIME_E_NOT_FOUND;
2419 break;
2420
2421 case IBL_LAST:
2422 list = list_tail(&body->children);
2423 if(list)
2425 else
2426 hr = MIME_E_NOT_FOUND;
2427 break;
2428
2429 case IBL_NEXT:
2430 list = list_next(&body->parent->children, &body->entry);
2431 if(list)
2433 else
2434 hr = MIME_E_NOT_FOUND;
2435 break;
2436
2437 case IBL_PREVIOUS:
2438 list = list_prev(&body->parent->children, &body->entry);
2439 if(list)
2441 else
2442 hr = MIME_E_NOT_FOUND;
2443 break;
2444
2445 default:
2446 hr = E_FAIL;
2447 break;
2448 }
2449 }
2450
2451 return hr;
2452}
2453
2454
2456 IMimeMessage *iface,
2457 BODYLOCATION location,
2458 HBODY hPivot,
2459 LPHBODY phBody)
2460{
2461 FIXME("(%p)->(%d, %p, %p)\n", iface, location, hPivot, phBody);
2462 return E_NOTIMPL;
2463}
2464
2465static HRESULT WINAPI MimeMessage_GetBody(IMimeMessage *iface, BODYLOCATION location, HBODY hPivot,
2466 HBODY *phBody)
2467{
2469 body_t *body;
2470 HRESULT hr;
2471
2472 TRACE("(%p)->(%d, %p, %p)\n", iface, location, hPivot, phBody);
2473
2474 if(!phBody)
2475 return E_INVALIDARG;
2476
2477 *phBody = NULL;
2478
2479 hr = get_body(This, location, hPivot, &body);
2480
2481 if(hr == S_OK) *phBody = UlongToHandle(body->index);
2482
2483 return hr;
2484}
2485
2487 IMimeMessage *iface,
2488 HBODY hBody,
2489 DWORD dwFlags)
2490{
2491 FIXME("(%p)->(%p, %08x)\n", iface, hBody, dwFlags);
2492 return E_NOTIMPL;
2493}
2494
2496 IMimeMessage *iface,
2497 HBODY hBody,
2498 BODYLOCATION location)
2499{
2500 FIXME("(%p)->(%d)\n", iface, location);
2501 return E_NOTIMPL;
2502}
2503
2504static void count_children(body_t *body, boolean recurse, ULONG *count)
2505{
2506 body_t *child;
2507
2509 {
2510 (*count)++;
2511 if(recurse) count_children(child, recurse, count);
2512 }
2513}
2514
2515static HRESULT WINAPI MimeMessage_CountBodies(IMimeMessage *iface, HBODY hParent, boolean fRecurse,
2516 ULONG *pcBodies)
2517{
2518 HRESULT hr;
2520 body_t *body;
2521
2522 TRACE("(%p)->(%p, %s, %p)\n", iface, hParent, fRecurse ? "TRUE" : "FALSE", pcBodies);
2523
2524 hr = find_body(&This->body_tree, hParent, &body);
2525 if(hr != S_OK) return hr;
2526
2527 *pcBodies = 1;
2528 count_children(body, fRecurse, pcBodies);
2529
2530 return S_OK;
2531}
2532
2533static HRESULT find_next(MimeMessage *This, body_t *body, FINDBODY *find, HBODY *out)
2534{
2535 struct list *ptr;
2536 HBODY next;
2537
2538 for (;;)
2539 {
2540 if (!body) ptr = list_head( &This->body_tree );
2541 else
2542 {
2543 ptr = list_head( &body->children );
2544 while (!ptr)
2545 {
2546 if (!body->parent) return MIME_E_NOT_FOUND;
2547 if (!(ptr = list_next( &body->parent->children, &body->entry ))) body = body->parent;
2548 }
2549 }
2550
2552 next = UlongToHandle( body->index );
2553 find->dwReserved = body->index;
2554 if (IMimeBody_IsContentType(&body->mime_body->IMimeBody_iface, find->pszPriType,
2555 find->pszSubType) == S_OK)
2556 {
2557 *out = next;
2558 return S_OK;
2559 }
2560 }
2561 return MIME_E_NOT_FOUND;
2562}
2563
2564static HRESULT WINAPI MimeMessage_FindFirst(IMimeMessage *iface, FINDBODY *pFindBody, HBODY *phBody)
2565{
2567
2568 TRACE("(%p)->(%p, %p)\n", iface, pFindBody, phBody);
2569
2570 pFindBody->dwReserved = 0;
2571 return find_next(This, NULL, pFindBody, phBody);
2572}
2573
2574static HRESULT WINAPI MimeMessage_FindNext(IMimeMessage *iface, FINDBODY *pFindBody, HBODY *phBody)
2575{
2577 body_t *body;
2578 HRESULT hr;
2579
2580 TRACE("(%p)->(%p, %p)\n", iface, pFindBody, phBody);
2581
2582 hr = find_body( &This->body_tree, UlongToHandle( pFindBody->dwReserved ), &body );
2583 if (hr != S_OK) return MIME_E_NOT_FOUND;
2584 return find_next(This, body, pFindBody, phBody);
2585}
2586
2588 IMimeMessage *iface,
2589 HBODY hRelated,
2590 LPCSTR pszBase,
2591 LPCSTR pszURL,
2592 DWORD dwFlags,
2593 LPHBODY phBody)
2594{
2595 FIXME("(%p)->(%p, %s, %s, 0x%x, %p)\n", iface, hRelated, pszBase, pszURL, dwFlags, phBody);
2596 return E_NOTIMPL;
2597}
2598
2600 IMimeMessage *iface,
2601 HBODY hBody,
2602 LPCSTR pszSubType,
2603 LPHBODY phMultipart)
2604{
2605 FIXME("(%p)->(%p, %s, %p)\n", iface, hBody, pszSubType, phMultipart);
2606 return E_NOTIMPL;
2607}
2608
2610 IMimeMessage *iface,
2611 HBODY hBody,
2612 LPBODYOFFSETS pOffsets)
2613{
2614 FIXME("(%p)->(%p, %p)\n", iface, hBody, pOffsets);
2615 return E_NOTIMPL;
2616}
2617
2619 IMimeMessage *iface,
2620 LPHCHARSET phCharset)
2621{
2622 FIXME("(%p)->(%p)\n", iface, phCharset);
2623 *phCharset = NULL;
2624 return S_OK;
2625}
2626
2628 IMimeMessage *iface,
2629 HCHARSET hCharset,
2630 CSETAPPLYTYPE applytype)
2631{
2632 FIXME("(%p)->(%p, %d)\n", iface, hCharset, applytype);
2633 return E_NOTIMPL;
2634}
2635
2637 IMimeMessage *iface,
2638 HBODY hBody,
2639 IMSGBODYTYPE bodytype)
2640{
2641 HRESULT hr;
2642 IMimeBody *mime_body;
2643 TRACE("(%p)->(%p, %d)\n", iface, hBody, bodytype);
2644
2645 hr = IMimeMessage_BindToObject(iface, hBody, &IID_IMimeBody, (void**)&mime_body);
2646 if(hr != S_OK) return hr;
2647
2648 hr = IMimeBody_IsType(mime_body, bodytype);
2649 MimeBody_Release(mime_body);
2650 return hr;
2651}
2652
2654 IMimeMessage *iface,
2655 HBODY hBody,
2656 LPCSTR pszPriType,
2657 LPCSTR pszSubType)
2658{
2659 HRESULT hr;
2660 IMimeBody *mime_body;
2661 TRACE("(%p)->(%p, %s, %s)\n", iface, hBody, debugstr_a(pszPriType),
2662 debugstr_a(pszSubType));
2663
2664 hr = IMimeMessage_BindToObject(iface, hBody, &IID_IMimeBody, (void**)&mime_body);
2665 if(FAILED(hr)) return hr;
2666
2667 hr = IMimeBody_IsContentType(mime_body, pszPriType, pszSubType);
2668 IMimeBody_Release(mime_body);
2669 return hr;
2670}
2671
2673 IMimeMessage *iface,
2674 HBODY hBody,
2675 LPCSTR pszName,
2676 LPCSTR pszCriteria,
2677 boolean fSubString,
2678 boolean fCaseSensitive)
2679{
2680 FIXME("(%p)->(%p, %s, %s, %s, %s)\n", iface, hBody, pszName, pszCriteria, fSubString ? "TRUE" : "FALSE", fCaseSensitive ? "TRUE" : "FALSE");
2681 return E_NOTIMPL;
2682}
2683
2685 IMimeMessage *iface,
2686 HBODY hBody,
2687 LPCSTR pszName,
2688 DWORD dwFlags,
2689 LPPROPVARIANT pValue)
2690{
2691 HRESULT hr;
2692 IMimeBody *mime_body;
2693
2694 TRACE("(%p)->(%p, %s, 0x%x, %p)\n", iface, hBody, pszName, dwFlags, pValue);
2695
2696 hr = IMimeMessage_BindToObject(iface, hBody, &IID_IMimeBody, (void**)&mime_body);
2697 if(hr != S_OK) return hr;
2698
2699 hr = IMimeBody_GetProp(mime_body, pszName, dwFlags, pValue);
2700 IMimeBody_Release(mime_body);
2701
2702 return hr;
2703}
2704
2706 IMimeMessage *iface,
2707 HBODY hBody,
2708 LPCSTR pszName,
2709 DWORD dwFlags,
2710 LPCPROPVARIANT pValue)
2711{
2712 FIXME("(%p)->(%p, %s, 0x%x, %p)\n", iface, hBody, pszName, dwFlags, pValue);
2713 return E_NOTIMPL;
2714}
2715
2717 IMimeMessage *iface,
2718 HBODY hBody,
2719 LPCSTR pszName)
2720{
2721 FIXME("(%p)->(%p, %s)\n", iface, hBody, pszName);
2722 return E_NOTIMPL;
2723}
2724
2726 IMimeMessage *iface,
2727 const TYPEDID oid,
2728 LPCPROPVARIANT pValue)
2729{
2730 HRESULT hr = S_OK;
2731 TRACE("(%p)->(%08x, %p)\n", iface, oid, pValue);
2732
2733 /* Message ID is checked before type.
2734 * OID 0x4D -> 0x56 and 0x58 aren't defined but will filtered out later.
2735 */
2736 if(TYPEDID_ID(oid) < TYPEDID_ID(OID_ALLOW_8BIT_HEADER) || TYPEDID_ID(oid) > TYPEDID_ID(OID_SECURITY_2KEY_CERT_BAG_64))
2737 {
2738 WARN("oid (%08x) out of range\n", oid);
2739 return MIME_E_INVALID_OPTION_ID;
2740 }
2741
2742 if(pValue->vt != TYPEDID_TYPE(oid))
2743 {
2744 WARN("Called with vartype %04x and oid %08x\n", pValue->vt, oid);
2745 return S_OK;
2746 }
2747
2748 switch(oid)
2749 {
2750 case OID_HIDE_TNEF_ATTACHMENTS:
2751 FIXME("OID_HIDE_TNEF_ATTACHMENTS (value %d): ignoring\n", pValue->u.boolVal);
2752 break;
2753 case OID_SHOW_MACBINARY:
2754 FIXME("OID_SHOW_MACBINARY (value %d): ignoring\n", pValue->u.boolVal);
2755 break;
2756 case OID_SAVEBODY_KEEPBOUNDARY:
2757 FIXME("OID_SAVEBODY_KEEPBOUNDARY (value %d): ignoring\n", pValue->u.boolVal);
2758 break;
2759 case OID_CLEANUP_TREE_ON_SAVE:
2760 FIXME("OID_CLEANUP_TREE_ON_SAVE (value %d): ignoring\n", pValue->u.boolVal);
2761 break;
2762 default:
2763 FIXME("Unhandled oid %08x\n", oid);
2764 hr = MIME_E_INVALID_OPTION_ID;
2765 }
2766
2767 return hr;
2768}
2769
2771 IMimeMessage *iface,
2772 const TYPEDID oid,
2773 LPPROPVARIANT pValue)
2774{
2775 FIXME("(%p)->(%08x, %p)\n", iface, oid, pValue);
2776 return E_NOTIMPL;
2777}
2778
2779/*** IMimeMessage methods ***/
2781 IMimeMessage *iface,
2782 IStream *pRootStm,
2783 LPWEBPAGEOPTIONS pOptions,
2784 IMimeMessageCallback *pCallback,
2785 IMoniker **ppMoniker)
2786{
2787 FIXME("(%p)->(%p, %p, %p, %p)\n", iface, pRootStm, pOptions, pCallback, ppMoniker);
2788 *ppMoniker = NULL;
2789 return E_NOTIMPL;
2790}
2791
2793 IMimeMessage *iface,
2794 LPCSTR pszName,
2795 DWORD dwFlags,
2796 LPPROPVARIANT pValue)
2797{
2798 FIXME("(%p)->(%s, 0x%x, %p)\n", iface, pszName, dwFlags, pValue);
2799 return E_NOTIMPL;
2800}
2801
2803 IMimeMessage *iface,
2804 LPCSTR pszName,
2805 DWORD dwFlags,
2806 LPCPROPVARIANT pValue)
2807{
2808 FIXME("(%p)->(%s, 0x%x, %p)\n", iface, pszName, dwFlags, pValue);
2809 return E_NOTIMPL;
2810}
2811
2813 IMimeMessage *iface,
2814 LPCSTR pszName)
2815{
2816 FIXME("(%p)->(%s)\n", iface, pszName);
2817 return E_NOTIMPL;
2818}
2819
2821 IMimeMessage *iface,
2822 LPCSTR pszName,
2823 LPCSTR pszCriteria,
2824 boolean fSubString,
2825 boolean fCaseSensitive)
2826{
2827 FIXME("(%p)->(%s, %s, %s, %s)\n", iface, pszName, pszCriteria, fSubString ? "TRUE" : "FALSE", fCaseSensitive ? "TRUE" : "FALSE");
2828 return E_NOTIMPL;
2829}
2830
2832 IMimeMessage *iface,
2833 DWORD dwTxtType,
2834 ENCODINGTYPE ietEncoding,
2835 IStream **pStream,
2836 LPHBODY phBody)
2837{
2838 HRESULT hr;
2839 HBODY hbody;
2840 FINDBODY find_struct;
2841 IMimeBody *mime_body;
2842 static char text[] = "text";
2843 static char plain[] = "plain";
2844 static char html[] = "html";
2845
2846 TRACE("(%p)->(%d, %d, %p, %p)\n", iface, dwTxtType, ietEncoding, pStream, phBody);
2847
2848 find_struct.pszPriType = text;
2849
2850 switch(dwTxtType)
2851 {
2852 case TXT_PLAIN:
2853 find_struct.pszSubType = plain;
2854 break;
2855 case TXT_HTML:
2856 find_struct.pszSubType = html;
2857 break;
2858 default:
2859 return MIME_E_INVALID_TEXT_TYPE;
2860 }
2861
2862 hr = IMimeMessage_FindFirst(iface, &find_struct, &hbody);
2863 if(hr != S_OK)
2864 {
2865 TRACE("not found hr %08x\n", hr);
2866 *phBody = NULL;
2867 return hr;
2868 }
2869
2870 IMimeMessage_BindToObject(iface, hbody, &IID_IMimeBody, (void**)&mime_body);
2871
2872 IMimeBody_GetData(mime_body, ietEncoding, pStream);
2873 *phBody = hbody;
2874 IMimeBody_Release(mime_body);
2875 return hr;
2876}
2877
2879 IMimeMessage *iface,
2880 DWORD dwTxtType,
2881 ENCODINGTYPE ietEncoding,
2882 HBODY hAlternative,
2883 IStream *pStream,
2884 LPHBODY phBody)
2885{
2886 FIXME("(%p)->(%d, %d, %p, %p, %p)\n", iface, dwTxtType, ietEncoding, hAlternative, pStream, phBody);
2887 return E_NOTIMPL;
2888}
2889
2891 IMimeMessage *iface,
2892 REFIID riid,
2893 void *pvObject,
2894 LPHBODY phBody)
2895{
2896 FIXME("(%p)->(%s, %p, %p)\n", iface, debugstr_guid(riid), pvObject, phBody);
2897 return E_NOTIMPL;
2898}
2899
2901 IMimeMessage *iface,
2902 LPCSTR pszFilePath,
2903 IStream *pstmFile,
2904 LPHBODY phBody)
2905{
2906 FIXME("(%p)->(%s, %p, %p)\n", iface, pszFilePath, pstmFile, phBody);
2907 return E_NOTIMPL;
2908}
2909
2911 IMimeMessage *iface,
2912 LPCSTR pszBase,
2913 LPCSTR pszURL,
2914 DWORD dwFlags,
2915 IStream *pstmURL,
2916 LPSTR *ppszCIDURL,
2917 LPHBODY phBody)
2918{
2919 FIXME("(%p)->(%s, %s, 0x%x, %p, %p, %p)\n", iface, pszBase, pszURL, dwFlags, pstmURL, ppszCIDURL, phBody);
2920 return E_NOTIMPL;
2921}
2922
2924 IMimeMessage *iface,
2925 ULONG *pcAttach,
2926 LPHBODY *pprghAttach)
2927{
2928 HRESULT hr;
2929 FINDBODY find_struct;
2930 HBODY hbody;
2931 LPHBODY array;
2932 ULONG size = 10;
2933
2934 TRACE("(%p)->(%p, %p)\n", iface, pcAttach, pprghAttach);
2935
2936 *pcAttach = 0;
2937 array = CoTaskMemAlloc(size * sizeof(HBODY));
2938
2939 find_struct.pszPriType = find_struct.pszSubType = NULL;
2940 hr = IMimeMessage_FindFirst(iface, &find_struct, &hbody);
2941 while(hr == S_OK)
2942 {
2943 hr = IMimeMessage_IsContentType(iface, hbody, "multipart", NULL);
2944 TRACE("IsCT rets %08x %d\n", hr, *pcAttach);
2945 if(hr != S_OK)
2946 {
2947 if(*pcAttach + 1 > size)
2948 {
2949 size *= 2;
2950 array = CoTaskMemRealloc(array, size * sizeof(HBODY));
2951 }
2952 array[*pcAttach] = hbody;
2953 (*pcAttach)++;
2954 }
2955 hr = IMimeMessage_FindNext(iface, &find_struct, &hbody);
2956 }
2957
2958 *pprghAttach = array;
2959 return S_OK;
2960}
2961
2963 IMimeMessage *iface,
2964 IMimeAddressTable **ppTable)
2965{
2966 FIXME("(%p)->(%p)\n", iface, ppTable);
2967 return E_NOTIMPL;
2968}
2969
2971 IMimeMessage *iface,
2972 LPADDRESSPROPS pAddress)
2973{
2974 FIXME("(%p)->(%p)\n", iface, pAddress);
2975 return E_NOTIMPL;
2976}
2977
2979 IMimeMessage *iface,
2980 DWORD dwAdrTypes,
2981 DWORD dwProps,
2982 LPADDRESSLIST pList)
2983{
2984 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, dwProps, pList);
2985 return E_NOTIMPL;
2986}
2987
2989 IMimeMessage *iface,
2990 DWORD dwAdrTypes,
2991 ADDRESSFORMAT format,
2992 LPSTR *ppszFormat)
2993{
2994 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, format, ppszFormat);
2995 return E_NOTIMPL;
2996}
2997
2999 IMimeMessage *iface,
3000 DWORD dwAdrTypes,
3001 DWORD dwProps,
3002 IMimeEnumAddressTypes **ppEnum)
3003{
3004 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, dwProps, ppEnum);
3005 return E_NOTIMPL;
3006}
3007
3009 IMimeMessage *iface,
3010 ULONG cbMaxPart,
3011 IMimeMessageParts **ppParts)
3012{
3013 FIXME("(%p)->(%d, %p)\n", iface, cbMaxPart, ppParts);
3014 return E_NOTIMPL;
3015}
3016
3018 IMimeMessage *iface,
3019 IMoniker **ppMoniker)
3020{
3021 FIXME("(%p)->(%p)\n", iface, ppMoniker);
3022 return E_NOTIMPL;
3023}
3024
3025static const IMimeMessageVtbl MimeMessageVtbl =
3026{
3083};
3084
3086{
3088 MimeBody *mime_body;
3089 body_t *root_body;
3090
3091 TRACE("(%p, %p)\n", outer, obj);
3092
3093 if (outer)
3094 {
3095 FIXME("outer unknown not supported yet\n");
3096 return E_NOTIMPL;
3097 }
3098
3099 *obj = NULL;
3100
3101 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
3102 if (!This) return E_OUTOFMEMORY;
3103
3104 This->IMimeMessage_iface.lpVtbl = &MimeMessageVtbl;
3105 This->ref = 1;
3106 This->stream = NULL;
3107 list_init(&This->body_tree);
3108 This->next_index = 1;
3109
3110 mime_body = mimebody_create();
3111 root_body = new_body_entry(mime_body, This->next_index++, NULL);
3112 list_add_head(&This->body_tree, &root_body->entry);
3113
3114 *obj = &This->IMimeMessage_iface;
3115 return S_OK;
3116}
3117
3118/***********************************************************************
3119 * MimeOleCreateMessage (INETCOMM.@)
3120 */
3122{
3123 TRACE("(%p, %p)\n", pUnkOuter, ppMessage);
3124 return MimeMessage_create(NULL, (void **)ppMessage);
3125}
3126
3127/***********************************************************************
3128 * MimeOleSetCompatMode (INETCOMM.@)
3129 */
3131{
3132 FIXME("(0x%x)\n", dwMode);
3133 return S_OK;
3134}
3135
3136/***********************************************************************
3137 * MimeOleCreateVirtualStream (INETCOMM.@)
3138 */
3140{
3141 HRESULT hr;
3142 FIXME("(%p)\n", ppStream);
3143
3144 hr = CreateStreamOnHGlobal(NULL, TRUE, ppStream);
3145 return hr;
3146}
3147
3148typedef struct MimeSecurity
3149{
3153
3155{
3156 return CONTAINING_RECORD(iface, MimeSecurity, IMimeSecurity_iface);
3157}
3158
3160{
3161 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
3162
3163 if (IsEqualIID(riid, &IID_IUnknown) ||
3164 IsEqualIID(riid, &IID_IMimeSecurity))
3165 {
3166 *ppv = iface;
3167 IMimeSecurity_AddRef(iface);
3168 return S_OK;
3169 }
3170
3171 FIXME("no interface for %s\n", debugstr_guid(riid));
3172 *ppv = NULL;
3173 return E_NOINTERFACE;
3174}
3175
3177{
3180
3181 TRACE("(%p) ref=%d\n", This, ref);
3182
3183 return ref;
3184}
3185
3187{
3190
3191 TRACE("(%p) ref=%d\n", This, ref);
3192
3193 if (!ref)
3195
3196 return ref;
3197}
3198
3200 IMimeSecurity* iface)
3201{
3202 FIXME("(%p)->(): stub\n", iface);
3203 return S_OK;
3204}
3205
3207 IMimeSecurity* iface)
3208{
3209 FIXME("(%p)->(): stub\n", iface);
3210 return E_NOTIMPL;
3211}
3212
3214 IMimeSecurity* iface,
3215 IMimeMessageTree* pTree,
3216 DWORD dwFlags)
3217{
3218 FIXME("(%p)->(%p, %08x): stub\n", iface, pTree, dwFlags);
3219 return E_NOTIMPL;
3220}
3221
3223 IMimeSecurity* iface,
3224 IMimeMessageTree* pTree,
3225 HBODY hEncodeRoot,
3226 DWORD dwFlags)
3227{
3228 FIXME("(%p)->(%p, %p, %08x): stub\n", iface, pTree, hEncodeRoot, dwFlags);
3229 return E_NOTIMPL;
3230}
3231
3233 IMimeSecurity* iface,
3234 IMimeMessageTree* pTree,
3235 DWORD dwFlags)
3236{
3237 FIXME("(%p)->(%p, %08x): stub\n", iface, pTree, dwFlags);
3238 return E_NOTIMPL;
3239}
3240
3242 IMimeSecurity* iface,
3243 IMimeMessageTree* pTree,
3244 HBODY hDecodeRoot,
3245 DWORD dwFlags)
3246{
3247 FIXME("(%p)->(%p, %p, %08x): stub\n", iface, pTree, hDecodeRoot, dwFlags);
3248 return E_NOTIMPL;
3249}
3250
3252 IMimeSecurity* iface,
3253 HCAPICERTSTORE hc,
3254 DWORD dwUsage,
3255 PCX509CERT pPrev,
3256 PCX509CERT* ppCert)
3257{
3258 FIXME("(%p)->(%p, %08x, %p, %p): stub\n", iface, hc, dwUsage, pPrev, ppCert);
3259 return E_NOTIMPL;
3260}
3261
3263 IMimeSecurity* iface,
3264 const PCX509CERT pX509Cert,
3265 const CERTNAMETYPE cn,
3266 LPSTR* ppszName)
3267{
3268 FIXME("(%p)->(%p, %08x, %p): stub\n", iface, pX509Cert, cn, ppszName);
3269 return E_NOTIMPL;
3270}
3271
3273 IMimeSecurity* iface,
3274 const HWND hwndParent,
3275 IMimeBody* pBody,
3276 DWORD* pdwSecType)
3277{
3278 FIXME("(%p)->(%p, %p, %p): stub\n", iface, hwndParent, pBody, pdwSecType);
3279 return E_NOTIMPL;
3280}
3281
3283 IMimeSecurity* iface,
3284 const PCX509CERT pX509Cert,
3285 const CERTDATAID dataid,
3286 LPPROPVARIANT pValue)
3287{
3288 FIXME("(%p)->(%p, %x, %p): stub\n", iface, pX509Cert, dataid, pValue);
3289 return E_NOTIMPL;
3290}
3291
3292
3293static const IMimeSecurityVtbl MimeSecurityVtbl =
3294{
3308};
3309
3311{
3313
3314 *obj = NULL;
3315
3316 if (outer) return CLASS_E_NOAGGREGATION;
3317
3318 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
3319 if (!This) return E_OUTOFMEMORY;
3320
3321 This->IMimeSecurity_iface.lpVtbl = &MimeSecurityVtbl;
3322 This->ref = 1;
3323
3324 *obj = &This->IMimeSecurity_iface;
3325 return S_OK;
3326}
3327
3328/***********************************************************************
3329 * MimeOleCreateSecurity (INETCOMM.@)
3330 */
3332{
3333 return MimeSecurity_create(NULL, (void **)ppSecurity);
3334}
3335
3337 IMimeAllocator* iface,
3338 REFIID riid,
3339 void **obj)
3340{
3341 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), obj);
3342
3343 if (IsEqualIID(riid, &IID_IUnknown) ||
3344 IsEqualIID(riid, &IID_IMalloc) ||
3345 IsEqualIID(riid, &IID_IMimeAllocator))
3346 {
3347 *obj = iface;
3348 IMimeAllocator_AddRef(iface);
3349 return S_OK;
3350 }
3351
3352 FIXME("no interface for %s\n", debugstr_guid(riid));
3353 *obj = NULL;
3354 return E_NOINTERFACE;
3355}
3356
3358 IMimeAllocator* iface)
3359{
3360 return 2;
3361}
3362
3364 IMimeAllocator* iface)
3365{
3366 return 1;
3367}
3368
3370 IMimeAllocator* iface,
3371 SIZE_T cb)
3372{
3373 return CoTaskMemAlloc(cb);
3374}
3375
3377 IMimeAllocator* iface,
3378 LPVOID pv,
3379 SIZE_T cb)
3380{
3381 return CoTaskMemRealloc(pv, cb);
3382}
3383
3385 IMimeAllocator* iface,
3386 LPVOID pv)
3387{
3388 CoTaskMemFree(pv);
3389}
3390
3392 IMimeAllocator* iface,
3393 LPVOID pv)
3394{
3395 FIXME("stub\n");
3396 return 0;
3397}
3398
3400 IMimeAllocator* iface,
3401 LPVOID pv)
3402{
3403 FIXME("stub\n");
3404 return 0;
3405}
3406
3408 IMimeAllocator* iface)
3409{
3410 FIXME("stub\n");
3411 return;
3412}
3413
3415 IMimeAllocator* iface,
3416 ULONG cParams,
3417 LPMIMEPARAMINFO prgParam,
3418 boolean fFreeArray)
3419{
3420 ULONG i;
3421 TRACE("(%p)->(%d, %p, %d)\n", iface, cParams, prgParam, fFreeArray);
3422
3423 for(i = 0; i < cParams; i++)
3424 {
3425 IMimeAllocator_Free(iface, prgParam[i].pszName);
3426 IMimeAllocator_Free(iface, prgParam[i].pszData);
3427 }
3428 if(fFreeArray) IMimeAllocator_Free(iface, prgParam);
3429 return S_OK;
3430}
3431
3433 IMimeAllocator* iface,
3434 LPADDRESSLIST pList)
3435{
3436 FIXME("stub\n");
3437 return E_NOTIMPL;
3438}
3439
3441 IMimeAllocator* iface,
3442 LPADDRESSPROPS pAddress)
3443{
3444 FIXME("stub\n");
3445 return E_NOTIMPL;
3446}
3447
3449 IMimeAllocator* iface,
3450 ULONG cObjects,
3451 IUnknown **prgpUnknown,
3452 boolean fFreeArray)
3453{
3454 FIXME("stub\n");
3455 return E_NOTIMPL;
3456}
3457
3458
3460 IMimeAllocator* iface,
3461 ULONG cRows,
3462 LPENUMHEADERROW prgRow,
3463 boolean fFreeArray)
3464{
3465 FIXME("stub\n");
3466 return E_NOTIMPL;
3467}
3468
3470 IMimeAllocator* iface,
3471 ULONG cProps,
3472 LPENUMPROPERTY prgProp,
3473 boolean fFreeArray)
3474{
3475 FIXME("stub\n");
3476 return E_NOTIMPL;
3477}
3478
3480 IMimeAllocator* iface,
3481 THUMBBLOB *pthumbprint)
3482{
3483 FIXME("stub\n");
3484 return E_NOTIMPL;
3485}
3486
3487
3489 IMimeAllocator* iface,
3490 LPPROPVARIANT pProp)
3491{
3492 FIXME("stub\n");
3493 return E_NOTIMPL;
3494}
3495
3496static IMimeAllocatorVtbl mime_alloc_vtbl =
3497{
3515};
3516
3517static IMimeAllocator mime_allocator =
3518{
3520};
3521
3523{
3524 if(outer) return CLASS_E_NOAGGREGATION;
3525
3526 *obj = &mime_allocator;
3527 return S_OK;
3528}
3529
3531{
3532 return MimeAllocator_create(NULL, (void**)alloc);
3533}
3534
3536{
3537 FIXME("(%p, %p)\n", outer, obj);
3538
3539 *obj = NULL;
3540 if (outer) return CLASS_E_NOAGGREGATION;
3541
3543}
3544
3545/* IMimePropertySchema Interface */
3546static HRESULT WINAPI propschema_QueryInterface(IMimePropertySchema *iface, REFIID riid, void **out)
3547{
3549 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), out);
3550
3551 *out = NULL;
3552
3553 if (IsEqualIID(riid, &IID_IUnknown) ||
3554 IsEqualIID(riid, &IID_IMimePropertySchema))
3555 {
3556 *out = iface;
3557 }
3558 else
3559 {
3560 FIXME("no interface for %s\n", debugstr_guid(riid));
3561 return E_NOINTERFACE;
3562 }
3563
3564 IMimePropertySchema_AddRef(iface);
3565 return S_OK;
3566}
3567
3568static ULONG WINAPI propschema_AddRef(IMimePropertySchema *iface)
3569{
3572
3573 TRACE("(%p) ref=%d\n", This, ref);
3574
3575 return ref;
3576}
3577
3578static ULONG WINAPI propschema_Release(IMimePropertySchema *iface)
3579{
3582
3583 TRACE("(%p) ref=%d\n", This, ref);
3584
3585 if (!ref)
3586 {
3588 }
3589
3590 return ref;
3591}
3592
3593static HRESULT WINAPI propschema_RegisterProperty(IMimePropertySchema *iface, const char *name, DWORD flags,
3594 DWORD rownumber, VARTYPE vtdefault, DWORD *propid)
3595{
3597 FIXME("(%p)->(%s, %x, %d, %d, %p) stub\n", This, debugstr_a(name), flags, rownumber, vtdefault, propid);
3598 return E_NOTIMPL;
3599}
3600
3601static HRESULT WINAPI propschema_ModifyProperty(IMimePropertySchema *iface, const char *name, DWORD flags,
3602 DWORD rownumber, VARTYPE vtdefault)
3603{
3605 FIXME("(%p)->(%s, %x, %d, %d) stub\n", This, debugstr_a(name), flags, rownumber, vtdefault);
3606 return S_OK;
3607}
3608
3609static HRESULT WINAPI propschema_GetPropertyId(IMimePropertySchema *iface, const char *name, DWORD *propid)
3610{
3612 FIXME("(%p)->(%s, %p) stub\n", This, debugstr_a(name), propid);
3613 return E_NOTIMPL;
3614}
3615
3616static HRESULT WINAPI propschema_GetPropertyName(IMimePropertySchema *iface, DWORD propid, char **name)
3617{
3619 FIXME("(%p)->(%d, %p) stub\n", This, propid, name);
3620 return E_NOTIMPL;
3621}
3622
3623static HRESULT WINAPI propschema_RegisterAddressType(IMimePropertySchema *iface, const char *name, DWORD *adrtype)
3624{
3626 FIXME("(%p)->(%s, %p) stub\n", This, debugstr_a(name), adrtype);
3627 return E_NOTIMPL;
3628}
3629
3630static IMimePropertySchemaVtbl prop_schema_vtbl =
3631{
3640};
3641
3642
3644{
3646
3647 TRACE("(%p) stub\n", schema);
3648
3649 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
3650 if (!This)
3651 return E_OUTOFMEMORY;
3652
3653 This->IMimePropertySchema_iface.lpVtbl = &prop_schema_vtbl;
3654 This->ref = 1;
3655
3656 *schema = &This->IMimePropertySchema_iface;
3657
3658 return S_OK;
3659}
3660
3662 ADDRESSFORMAT addr_format, WCHAR **address)
3663{
3664 FIXME("(%s, %p, %d, %d, %p) stub\n", debugstr_guid(riid), object, addr_type, addr_format, address);
3665
3666 return E_NOTIMPL;
3667}
3668
3670{
3671 FIXME("(%s %p)\n", debugstr_guid(riid), ppv);
3672 *ppv = NULL;
3673 return E_NOINTERFACE;
3674}
3675
3677{
3678 TRACE("\n");
3679 return 2;
3680}
3681
3683{
3684 TRACE("\n");
3685 return 1;
3686}
3687
3688static const IUnknownVtbl mime_obj_vtbl = {
3692};
3693
3695
3697 REFIID riid, void **out, IMoniker **moniker_new)
3698{
3699 WCHAR *display_name, *mhtml_url;
3700 size_t len;
3701 HRESULT hres;
3702
3703 static const WCHAR mhtml_prefixW[] = {'m','h','t','m','l',':'};
3704
3705 WARN("(0x%08x, %p, %p, %s, %p, %p) semi-stub\n", bindf, moniker, binding, debugstr_guid(riid), out, moniker_new);
3706
3707 if(!IsEqualGUID(&IID_IUnknown, riid)) {
3708 FIXME("Unsupported riid %s\n", debugstr_guid(riid));
3709 return E_NOINTERFACE;
3710 }
3711
3712 hres = IMoniker_GetDisplayName(moniker, NULL, NULL, &display_name);
3713 if(FAILED(hres))
3714 return hres;
3715
3716 TRACE("display name %s\n", debugstr_w(display_name));
3717
3718 len = lstrlenW(display_name);
3719 mhtml_url = heap_alloc((len+1)*sizeof(WCHAR) + sizeof(mhtml_prefixW));
3720 if(!mhtml_url)
3721 return E_OUTOFMEMORY;
3722
3723 memcpy(mhtml_url, mhtml_prefixW, sizeof(mhtml_prefixW));
3724 lstrcpyW(mhtml_url + ARRAY_SIZE(mhtml_prefixW), display_name);
3725 HeapFree(GetProcessHeap(), 0, display_name);
3726
3727 hres = CreateURLMoniker(NULL, mhtml_url, moniker_new);
3728 heap_free(mhtml_url);
3729 if(FAILED(hres))
3730 return hres;
3731
3732 /* FIXME: We most likely should start binding here and return something more meaningful as mime object. */
3733 *out = &mime_obj;
3734 return S_OK;
3735}
static INT pivot(list_t &list, INT i, INT j)
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define read
Definition: acwin.h:96
static void * heap_alloc(size_t len)
Definition: appwiz.h:65
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define msg(x)
Definition: auth_time.c:54
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(a)
Definition: main.h:24
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
static void list_add_head(struct list_entry *head, struct list_entry *entry)
Definition: list.h:76
static void list_init(struct list_entry *head)
Definition: list.h:51
#define UlongToHandle(ul)
Definition: basetsd.h:97
#define HandleToUlong(h)
Definition: basetsd.h:79
const GUID IID_IUnknown
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
struct _root root
#define hex_digit(c)
Definition: btrfs_drv.h:1748
Definition: list.h:37
static HWND hwndParent
Definition: cryptui.c:300
static TAGID TAGID find
Definition: db.cpp:155
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapReAlloc
Definition: compat.h:734
#define _strnicmp(_String1, _String2, _MaxCount)
Definition: compat.h:23
unsigned short VARTYPE
Definition: compat.h:2254
#define HeapFree(x, y, z)
Definition: compat.h:735
#define lstrcpyW
Definition: compat.h:749
@ VT_LPSTR
Definition: compat.h:2324
#define lstrlenW
Definition: compat.h:750
static HRESULT WINAPI propschema_GetPropertyName(IMimePropertySchema *iface, DWORD propid, char **name)
Definition: mimeole.c:3616
static HRESULT WINAPI MimeMessage_LoadOffsetTable(IMimeMessage *iface, IStream *pStream)
Definition: mimeole.c:2288
HRESULT VirtualStream_create(IUnknown *outer, void **obj)
Definition: mimeole.c:3535
HRESULT WINAPI MimeGetAddressFormatW(REFIID riid, void *object, DWORD addr_type, ADDRESSFORMAT addr_format, WCHAR **address)
Definition: mimeole.c:3661
static HRESULT create_body_offset_list(IStream *stm, const char *boundary, struct list *body_offsets)
Definition: mimeole.c:2062
static HRESULT WINAPI MimeMessage_EnumAddressTypes(IMimeMessage *iface, DWORD dwAdrTypes, DWORD dwProps, IMimeEnumAddressTypes **ppEnum)
Definition: mimeole.c:2998
static HRESULT WINAPI MimeBody_QueryProp(IMimeBody *iface, LPCSTR pszName, LPCSTR pszCriteria, boolean fSubString, boolean fCaseSensitive)
Definition: mimeole.c:1283
static HRESULT WINAPI MimeAlloc_FreeThumbprint(IMimeAllocator *iface, THUMBBLOB *pthumbprint)
Definition: mimeole.c:3479
static HRESULT WINAPI sub_stream_Seek(IStream *iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
Definition: mimeole.c:265
static HRESULT WINAPI MimeMessage_ResolveURL(IMimeMessage *iface, HBODY hRelated, LPCSTR pszBase, LPCSTR pszURL, DWORD dwFlags, LPHBODY phBody)
Definition: mimeole.c:2587
static void WINAPI MimeAlloc_Free(IMimeAllocator *iface, LPVOID pv)
Definition: mimeole.c:3384
static HRESULT WINAPI MimeMessage_GetMessageSize(IMimeMessage *iface, ULONG *pcbSize, DWORD dwFlags)
Definition: mimeole.c:2279
static HRESULT WINAPI MimeBody_CopyTo(IMimeBody *iface, IMimeBody *pBody)
Definition: mimeole.c:1792
static HRESULT WINAPI MimeBody_IsType(IMimeBody *iface, IMSGBODYTYPE bodytype)
Definition: mimeole.c:1456
static ULONG WINAPI MimeSecurity_Release(IMimeSecurity *iface)
Definition: mimeole.c:3186
HRESULT WINAPI MimeOleGetPropertySchema(IMimePropertySchema **schema)
Definition: mimeole.c:3643
static void init_content_encoding(MimeBody *body, header_t *header)
Definition: mimeole.c:767
static HRESULT WINAPI MimeBody_GetTransmitInfo(IMimeBody *iface, LPTRANSMITINFO pTransmitInfo)
Definition: mimeole.c:1801
static HRESULT MimeBody_set_offsets(MimeBody *body, const BODYOFFSETS *offsets)
Definition: mimeole.c:1881
static HRESULT WINAPI MimeMessage_GetRootMoniker(IMimeMessage *iface, IMoniker **ppMoniker)
Definition: mimeole.c:3017
static HRESULT WINAPI MimeMessage_GetMessageSource(IMimeMessage *iface, IStream **ppStream, DWORD dwFlags)
Definition: mimeole.c:2267
static HRESULT WINAPI MimeMessage_AttachObject(IMimeMessage *iface, REFIID riid, void *pvObject, LPHBODY phBody)
Definition: mimeole.c:2890
static void unfold_header(char *header, int len)
Definition: mimeole.c:611
static HRESULT WINAPI MimeBody_GetDisplayName(IMimeBody *iface, LPSTR *ppszDisplay)
Definition: mimeole.c:1482
static sub_stream_t * impl_from_IStream(IStream *iface)
Definition: mimeole.c:182
static HRESULT WINAPI MimeMessage_InitNew(IMimeMessage *iface)
Definition: mimeole.c:2259
static HRESULT get_body(MimeMessage *msg, BODYLOCATION location, HBODY pivot, body_t **out)
Definition: mimeole.c:2387
static HRESULT WINAPI MimeBody_GetData(IMimeBody *iface, ENCODINGTYPE ietEncoding, IStream **ppStream)
Definition: mimeole.c:1713
static const IUnknownVtbl mime_obj_vtbl
Definition: mimeole.c:3688
static HRESULT find_prop(MimeBody *body, const char *name, header_t **prop)
Definition: mimeole.c:865
static LPSTR strdupA(LPCSTR str)
Definition: mimeole.c:482
static HRESULT WINAPI MimeBody_GetParameters(IMimeBody *iface, LPCSTR pszName, ULONG *pcParams, LPMIMEPARAMINFO *pprgParam)
Definition: mimeole.c:1315
static HRESULT WINAPI MimeMessage_GetTextBody(IMimeMessage *iface, DWORD dwTxtType, ENCODINGTYPE ietEncoding, IStream **pStream, LPHBODY phBody)
Definition: mimeole.c:2831
static HRESULT WINAPI propschema_ModifyProperty(IMimePropertySchema *iface, const char *name, DWORD flags, DWORD rownumber, VARTYPE vtdefault)
Definition: mimeole.c:3601
static const IMimeSecurityVtbl MimeSecurityVtbl
Definition: mimeole.c:3293
static HRESULT WINAPI MimeBody_GetClassID(IMimeBody *iface, CLSID *pClassID)
Definition: mimeole.c:978
static HRESULT WINAPI MimeSecurity_DecodeBody(IMimeSecurity *iface, IMimeMessageTree *pTree, HBODY hDecodeRoot, DWORD dwFlags)
Definition: mimeole.c:3241
static void free_header(header_t *header)
Definition: mimeole.c:825
static HRESULT WINAPI propschema_RegisterAddressType(IMimePropertySchema *iface, const char *name, DWORD *adrtype)
Definition: mimeole.c:3623
static HRESULT WINAPI MimeMessage_DeleteProp(IMimeMessage *iface, LPCSTR pszName)
Definition: mimeole.c:2812
static MimeMessage * impl_from_IMimeMessage(IMimeMessage *iface)
Definition: mimeole.c:1959
static char * unquote_string(const char *str)
Definition: mimeole.c:636
static HRESULT WINAPI MimeSecurity_DecodeMessage(IMimeSecurity *iface, IMimeMessageTree *pTree, DWORD dwFlags)
Definition: mimeole.c:3232
static HRESULT WINAPI MimeBody_GetHandle(IMimeBody *iface, LPHBODY phBody)
Definition: mimeole.c:1820
static HRESULT WINAPI MimeBody_IsDirty(IMimeBody *iface)
Definition: mimeole.c:993
static HRESULT WINAPI MimeBody_GetOption(IMimeBody *iface, const TYPEDID oid, LPPROPVARIANT pValue)
Definition: mimeole.c:1436
static void count_children(body_t *body, boolean recurse, ULONG *count)
Definition: mimeole.c:2504
static LPVOID WINAPI MimeAlloc_Alloc(IMimeAllocator *iface, SIZE_T cb)
Definition: mimeole.c:3369
static HRESULT WINAPI MimeMessage_SetCharset(IMimeMessage *iface, HCHARSET hCharset, CSETAPPLYTYPE applytype)
Definition: mimeole.c:2627
static HRESULT WINAPI MimeBody_SetDisplayName(IMimeBody *iface, LPCSTR pszDisplay)
Definition: mimeole.c:1473
static HRESULT WINAPI propschema_QueryInterface(IMimePropertySchema *iface, REFIID riid, void **out)
Definition: mimeole.c:3546
#define PARSER_BUF_SIZE
Definition: mimeole.c:491
static HRESULT WINAPI sub_stream_QueryInterface(IStream *iface, REFIID riid, void **ppv)
Definition: mimeole.c:187
static void init_content_type(MimeBody *body, header_t *header)
Definition: mimeole.c:749
static HRESULT WINAPI MimeSecurity_EncodeMessage(IMimeSecurity *iface, IMimeMessageTree *pTree, DWORD dwFlags)
Definition: mimeole.c:3213
static HRESULT WINAPI MimeAlloc_FreeEnumPropertyArray(IMimeAllocator *iface, ULONG cProps, LPENUMPROPERTY prgProp, boolean fFreeArray)
Definition: mimeole.c:3469
static LPVOID WINAPI MimeAlloc_Realloc(IMimeAllocator *iface, LPVOID pv, SIZE_T cb)
Definition: mimeole.c:3376
static ULONG WINAPI MimeMessage_AddRef(IMimeMessage *iface)
Definition: mimeole.c:1984
static HRESULT WINAPI mime_obj_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
Definition: mimeole.c:3669
static HRESULT decode_base64(IStream *input, IStream **ret_stream)
Definition: mimeole.c:1560
static void empty_body_list(struct list *list)
Definition: mimeole.c:1994
static HRESULT find_next(MimeMessage *This, body_t *body, FINDBODY *find, HBODY *out)
Definition: mimeole.c:2533
static HRESULT WINAPI MimeMessage_GetSender(IMimeMessage *iface, LPADDRESSPROPS pAddress)
Definition: mimeole.c:2970
static MimeBody * mimebody_create(void)
Definition: mimeole.c:1892
static void read_value(header_t *header, char **cur)
Definition: mimeole.c:719
static HRESULT WINAPI MimeSecurity_EncodeBody(IMimeSecurity *iface, IMimeMessageTree *pTree, HBODY hEncodeRoot, DWORD dwFlags)
Definition: mimeole.c:3222
static propschema * impl_from_IMimePropertySchema(IMimePropertySchema *iface)
Definition: mimeole.c:477
static HRESULT WINAPI MimeMessage_BindToObject(IMimeMessage *iface, const HBODY hBody, REFIID riid, void **ppvObject)
Definition: mimeole.c:2354
static HRESULT WINAPI MimeMessage_GetAttachments(IMimeMessage *iface, ULONG *pcAttach, LPHBODY *pprghAttach)
Definition: mimeole.c:2923
static HRESULT WINAPI MimeMessage_SaveOffsetTable(IMimeMessage *iface, IStream *pStream, DWORD dwFlags)
Definition: mimeole.c:2296
static HRESULT WINAPI MimeBody_SetCharset(IMimeBody *iface, HCHARSET hCharset, CSETAPPLYTYPE applytype)
Definition: mimeole.c:1305
static void empty_param_list(struct list *list)
Definition: mimeole.c:812
static HRESULT WINAPI MimeBody_DeleteProp(IMimeBody *iface, LPCSTR pszName)
Definition: mimeole.c:1224
static HRESULT WINAPI sub_stream_Revert(IStream *iface)
Definition: mimeole.c:365
static HRESULT WINAPI MimeMessage_GetCharset(IMimeMessage *iface, LPHCHARSET phCharset)
Definition: mimeole.c:2618
static HRESULT WINAPI MimeSecurity_QueryInterface(IMimeSecurity *iface, REFIID riid, void **ppv)
Definition: mimeole.c:3159
static HRESULT WINAPI MimeMessage_AttachFile(IMimeMessage *iface, LPCSTR pszFilePath, IStream *pstmFile, LPHBODY phBody)
Definition: mimeole.c:2900
static HRESULT WINAPI propschema_GetPropertyId(IMimePropertySchema *iface, const char *name, DWORD *propid)
Definition: mimeole.c:3609
static HRESULT parse_headers(MimeBody *body, IStream *stm)
Definition: mimeole.c:783
static HRESULT WINAPI MimeMessage_GetBodyProp(IMimeMessage *iface, HBODY hBody, LPCSTR pszName, DWORD dwFlags, LPPROPVARIANT pValue)
Definition: mimeole.c:2684
static void add_param(header_t *header, const char *p)
Definition: mimeole.c:669
static HRESULT WINAPI MimeBody_Save(IMimeBody *iface, IStream *pStm, BOOL fClearDirty)
Definition: mimeole.c:1008
static void WINAPI MimeAlloc_HeapMinimize(IMimeAllocator *iface)
Definition: mimeole.c:3407
static HRESULT WINAPI sub_stream_SetSize(IStream *iface, ULARGE_INTEGER libNewSize)
Definition: mimeole.c:300
static HRESULT WINAPI MimeBody_GetCurrentEncoding(IMimeBody *iface, ENCODINGTYPE *pietEncoding)
Definition: mimeole.c:1504
static HRESULT WINAPI MimeBody_GetEstimatedSize(IMimeBody *iface, ENCODINGTYPE ietEncoding, ULONG *pcbSize)
Definition: mimeole.c:1528
static HRESULT decode_qp(IStream *input, IStream **ret_stream)
Definition: mimeole.c:1640
static HRESULT WINAPI MimeAlloc_FreeAddressProps(IMimeAllocator *iface, LPADDRESSPROPS pAddress)
Definition: mimeole.c:3440
static HRESULT WINAPI MimeMessage_GetAddressTable(IMimeMessage *iface, IMimeAddressTable **ppTable)
Definition: mimeole.c:2962
static HRESULT get_stream_size(IStream *stream, ULARGE_INTEGER *size)
Definition: mimeole.c:450
static HRESULT WINAPI MimeMessage_GetProp(IMimeMessage *iface, LPCSTR pszName, DWORD dwFlags, LPPROPVARIANT pValue)
Definition: mimeole.c:2792
static ULONG WINAPI sub_stream_AddRef(IStream *iface)
Definition: mimeole.c:205
HRESULT WINAPI MimeOleObjectFromMoniker(BINDF bindf, IMoniker *moniker, IBindCtx *binding, REFIID riid, void **out, IMoniker **moniker_new)
Definition: mimeole.c:3696
static HRESULT WINAPI MimeMessage_QueryBodyProp(IMimeMessage *iface, HBODY hBody, LPCSTR pszName, LPCSTR pszCriteria, boolean fSubString, boolean fCaseSensitive)
Definition: mimeole.c:2672
static const property_t * find_default_prop(const char *name)
Definition: mimeole.c:891
static HRESULT WINAPI MimeMessage_GetSizeMax(IMimeMessage *iface, ULARGE_INTEGER *pcbSize)
Definition: mimeole.c:2251
static void empty_new_prop_list(struct list *list)
Definition: mimeole.c:843
static ULONG WINAPI MimeSecurity_AddRef(IMimeSecurity *iface)
Definition: mimeole.c:3176
static HRESULT WINAPI MimeMessage_SetOption(IMimeMessage *iface, const TYPEDID oid, LPCPROPVARIANT pValue)
Definition: mimeole.c:2725
static HRESULT WINAPI MimeBody_GetPropInfo(IMimeBody *iface, LPCSTR pszName, LPMIMEPROPINFO pInfo)
Definition: mimeole.c:1032
static const signed char base64_decode_table[]
Definition: mimeole.c:1548
static HRESULT WINAPI MimeBody_IsContentType(IMimeBody *iface, LPCSTR pszPriType, LPCSTR pszSubType)
Definition: mimeole.c:1360
static HRESULT WINAPI MimeSecurity_GetCertData(IMimeSecurity *iface, const PCX509CERT pX509Cert, const CERTDATAID dataid, LPPROPVARIANT pValue)
Definition: mimeole.c:3282
HRESULT WINAPI MimeOleGetAllocator(IMimeAllocator **alloc)
Definition: mimeole.c:3530
static void release_data(REFIID riid, void *data)
Definition: mimeole.c:855
static HRESULT WINAPI sub_stream_LockRegion(IStream *iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
Definition: mimeole.c:372
static HRESULT WINAPI MimeBody_EmptyData(IMimeBody *iface)
Definition: mimeole.c:1784
static HRESULT WINAPI MimeAlloc_FreeParamInfoArray(IMimeAllocator *iface, ULONG cParams, LPMIMEPARAMINFO prgParam, boolean fFreeArray)
Definition: mimeole.c:3414
static ULONG WINAPI MimeAlloc_Release(IMimeAllocator *iface)
Definition: mimeole.c:3363
static HRESULT WINAPI MimeMessage_QueryInterface(IMimeMessage *iface, REFIID riid, void **ppv)
Definition: mimeole.c:1964
static HRESULT WINAPI MimeMessage_IsContentType(IMimeMessage *iface, HBODY hBody, LPCSTR pszPriType, LPCSTR pszSubType)
Definition: mimeole.c:2653
static struct IStreamVtbl sub_stream_vtbl
Definition: mimeole.c:412
static HRESULT WINAPI MimeBody_CopyProps(IMimeBody *iface, ULONG cNames, LPCSTR *prgszName, IMimePropertySet *pPropertySet)
Definition: mimeole.c:1251
static HRESULT WINAPI MimeMessage_SetBodyProp(IMimeMessage *iface, HBODY hBody, LPCSTR pszName, DWORD dwFlags, LPCPROPVARIANT pValue)
Definition: mimeole.c:2705
static HRESULT WINAPI MimeMessage_GetBodyOffsets(IMimeMessage *iface, HBODY hBody, LPBODYOFFSETS pOffsets)
Definition: mimeole.c:2609
#define FIRST_CUSTOM_PROP_ID
Definition: mimeole.c:1890
static HRESULT WINAPI MimeMessage_DeleteBody(IMimeMessage *iface, HBODY hBody, DWORD dwFlags)
Definition: mimeole.c:2486
static HRESULT find_body(struct list *list, HBODY hbody, body_t **body)
Definition: mimeole.c:2330
static HRESULT WINAPI MimeMessage_GetAddressFormat(IMimeMessage *iface, DWORD dwAdrTypes, ADDRESSFORMAT format, LPSTR *ppszFormat)
Definition: mimeole.c:2988
static HRESULT WINAPI MimeBody_GetCharset(IMimeBody *iface, LPHCHARSET phCharset)
Definition: mimeole.c:1295
static HRESULT WINAPI MimeMessage_DeleteBodyProp(IMimeMessage *iface, HBODY hBody, LPCSTR pszName)
Definition: mimeole.c:2716
static HRESULT WINAPI MimeAlloc_PropVariantClear(IMimeAllocator *iface, LPPROPVARIANT pProp)
Definition: mimeole.c:3488
static HRESULT WINAPI MimeBody_AppendProp(IMimeBody *iface, LPCSTR pszName, DWORD dwFlags, LPPROPVARIANT pValue)
Definition: mimeole.c:1213
static IMimePropertySchemaVtbl prop_schema_vtbl
Definition: mimeole.c:3630
static HRESULT WINAPI MimeAlloc_ReleaseObjects(IMimeAllocator *iface, ULONG cObjects, IUnknown **prgpUnknown, boolean fFreeArray)
Definition: mimeole.c:3448
static HRESULT WINAPI MimeMessage_FindNext(IMimeMessage *iface, FINDBODY *pFindBody, HBODY *phBody)
Definition: mimeole.c:2574
static ULONG WINAPI mime_obj_Release(IUnknown *iface)
Definition: mimeole.c:3682
static ULONG WINAPI propschema_Release(IMimePropertySchema *iface)
Definition: mimeole.c:3578
static HRESULT WINAPI MimeBody_GetProp(IMimeBody *iface, LPCSTR pszName, DWORD dwFlags, LPPROPVARIANT pValue)
Definition: mimeole.c:1086
HRESULT WINAPI MimeOleCreateVirtualStream(IStream **ppStream)
Definition: mimeole.c:3139
static HRESULT WINAPI MimeSecurity_CheckInit(IMimeSecurity *iface)
Definition: mimeole.c:3206
static body_t * new_body_entry(MimeBody *mime_body, DWORD index, body_t *parent)
Definition: mimeole.c:2041
static HRESULT WINAPI MimeBody_SaveToFile(IMimeBody *iface, ENCODINGTYPE ietEncoding, LPCSTR pszFilePath)
Definition: mimeole.c:1810
static HRESULT WINAPI sub_stream_Write(IStream *iface, const void *pv, ULONG cb, ULONG *pcbWritten)
Definition: mimeole.c:255
static HRESULT WINAPI MimeMessage_SplitMessage(IMimeMessage *iface, ULONG cbMaxPart, IMimeMessageParts **ppParts)
Definition: mimeole.c:3008
HRESULT MimeAllocator_create(IUnknown *outer, void **obj)
Definition: mimeole.c:3522
static HRESULT WINAPI propschema_RegisterProperty(IMimePropertySchema *iface, const char *name, DWORD flags, DWORD rownumber, VARTYPE vtdefault, DWORD *propid)
Definition: mimeole.c:3593
HRESULT WINAPI MimeOleSetCompatMode(DWORD dwMode)
Definition: mimeole.c:3130
static MimeBody * impl_from_IMimeBody(IMimeBody *iface)
Definition: mimeole.c:466
static void empty_header_list(struct list *list)
Definition: mimeole.c:833
static HRESULT WINAPI MimeSecurity_GetMessageType(IMimeSecurity *iface, const HWND hwndParent, IMimeBody *pBody, DWORD *pdwSecType)
Definition: mimeole.c:3272
static HRESULT WINAPI MimeBody_GetSizeMax(IMimeBody *iface, ULARGE_INTEGER *pcbSize)
Definition: mimeole.c:1015
static ULONG WINAPI mime_obj_AddRef(IUnknown *iface)
Definition: mimeole.c:3676
static HRESULT WINAPI MimeMessage_CreateWebPage(IMimeMessage *iface, IStream *pRootStm, LPWEBPAGEOPTIONS pOptions, IMimeMessageCallback *pCallback, IMoniker **ppMoniker)
Definition: mimeole.c:2780
static HRESULT copy_headers_to_buf(IStream *stm, char **ptr)
Definition: mimeole.c:499
static HRESULT WINAPI MimeBody_DeleteExcept(IMimeBody *iface, ULONG cNames, LPCSTR *prgszName)
Definition: mimeole.c:1273
static HRESULT WINAPI MimeBody_GetDataHere(IMimeBody *iface, ENCODINGTYPE ietEncoding, IStream *pStream)
Definition: mimeole.c:1538
static HRESULT WINAPI MimeMessage_IsBodyType(IMimeMessage *iface, HBODY hBody, IMSGBODYTYPE bodytype)
Definition: mimeole.c:2636
static HRESULT WINAPI MimeMessage_GetBody(IMimeMessage *iface, BODYLOCATION location, HBODY hPivot, HBODY *phBody)
Definition: mimeole.c:2465
static HRESULT WINAPI MimeMessage_SetTextBody(IMimeMessage *iface, DWORD dwTxtType, ENCODINGTYPE ietEncoding, HBODY hAlternative, IStream *pStream, LPHBODY phBody)
Definition: mimeole.c:2878
HRESULT MimeMessage_create(IUnknown *outer, void **obj)
Definition: mimeole.c:3085
static HRESULT WINAPI sub_stream_CopyTo(IStream *iface, IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
Definition: