ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

mimeole.c
Go to the documentation of this file.
00001 /*
00002  * MIME OLE Interfaces
00003  *
00004  * Copyright 2006 Robert Shearman for CodeWeavers
00005  * Copyright 2007 Huw Davies for CodeWeavers
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #define COBJMACROS
00023 #define NONAMELESSUNION
00024 
00025 #include <stdarg.h>
00026 #include <stdio.h>
00027 
00028 #include "windef.h"
00029 #include "winbase.h"
00030 #include "winuser.h"
00031 #include "objbase.h"
00032 #include "ole2.h"
00033 #include "mimeole.h"
00034 
00035 #include "wine/list.h"
00036 #include "wine/debug.h"
00037 
00038 #include "inetcomm_private.h"
00039 
00040 WINE_DEFAULT_DEBUG_CHANNEL(inetcomm);
00041 
00042 typedef struct
00043 {
00044     LPCSTR     name;
00045     DWORD      id;
00046     DWORD      flags; /* MIMEPROPFLAGS */
00047     VARTYPE    default_vt;
00048 } property_t;
00049 
00050 typedef struct
00051 {
00052     struct list entry;
00053     property_t prop;
00054 } property_list_entry_t;
00055 
00056 static const property_t default_props[] =
00057 {
00058     {"References",                   PID_HDR_REFS,       0,                               VT_LPSTR},
00059     {"Subject",                      PID_HDR_SUBJECT,    0,                               VT_LPSTR},
00060     {"From",                         PID_HDR_FROM,       MPF_ADDRESS,                     VT_LPSTR},
00061     {"Message-ID",                   PID_HDR_MESSAGEID,  0,                               VT_LPSTR},
00062     {"Return-Path",                  PID_HDR_RETURNPATH, MPF_ADDRESS,                     VT_LPSTR},
00063     {"Date",                         PID_HDR_DATE,       0,                               VT_LPSTR},
00064     {"Received",                     PID_HDR_RECEIVED,   0,                               VT_LPSTR},
00065     {"Reply-To",                     PID_HDR_REPLYTO,    MPF_ADDRESS,                     VT_LPSTR},
00066     {"X-Mailer",                     PID_HDR_XMAILER,    0,                               VT_LPSTR},
00067     {"Bcc",                          PID_HDR_BCC,        MPF_ADDRESS,                     VT_LPSTR},
00068     {"MIME-Version",                 PID_HDR_MIMEVER,    MPF_MIME,                        VT_LPSTR},
00069     {"Content-Type",                 PID_HDR_CNTTYPE,    MPF_MIME | MPF_HASPARAMS,        VT_LPSTR},
00070     {"Content-Transfer-Encoding",    PID_HDR_CNTXFER,    MPF_MIME,                        VT_LPSTR},
00071     {"Content-ID",                   PID_HDR_CNTID,      MPF_MIME,                        VT_LPSTR},
00072     {"Content-Disposition",          PID_HDR_CNTDISP,    MPF_MIME | MPF_HASPARAMS,        VT_LPSTR},
00073     {"To",                           PID_HDR_TO,         MPF_ADDRESS,                     VT_LPSTR},
00074     {"Cc",                           PID_HDR_CC,         MPF_ADDRESS,                     VT_LPSTR},
00075     {"Sender",                       PID_HDR_SENDER,     MPF_ADDRESS,                     VT_LPSTR},
00076     {"In-Reply-To",                  PID_HDR_INREPLYTO,  0,                               VT_LPSTR},
00077     {NULL,                           0,                  0,                               0}
00078 };
00079 
00080 typedef struct
00081 {
00082     struct list entry;
00083     char *name;
00084     char *value;
00085 } param_t;
00086 
00087 typedef struct
00088 {
00089     struct list entry;
00090     const property_t *prop;
00091     PROPVARIANT value;
00092     struct list params;
00093 } header_t;
00094 
00095 typedef struct MimeBody
00096 {
00097     const IMimeBodyVtbl *lpVtbl;
00098     LONG refs;
00099 
00100     HBODY handle;
00101 
00102     struct list headers;
00103     struct list new_props; /* FIXME: This should be in a PropertySchema */
00104     DWORD next_prop_id;
00105     char *content_pri_type;
00106     char *content_sub_type;
00107     ENCODINGTYPE encoding;
00108     void *data;
00109     IID data_iid;
00110     BODYOFFSETS body_offsets;
00111 } MimeBody;
00112 
00113 static inline MimeBody *impl_from_IMimeBody( IMimeBody *iface )
00114 {
00115     return (MimeBody *)((char*)iface - FIELD_OFFSET(MimeBody, lpVtbl));
00116 }
00117 
00118 static LPSTR strdupA(LPCSTR str)
00119 {
00120     char *ret;
00121     int len = strlen(str);
00122     ret = HeapAlloc(GetProcessHeap(), 0, len + 1);
00123     memcpy(ret, str, len + 1);
00124     return ret;
00125 }
00126 
00127 #define PARSER_BUF_SIZE 1024
00128 
00129 /*****************************************************
00130  *        copy_headers_to_buf [internal]
00131  *
00132  * Copies the headers into a '\0' terminated memory block and leave
00133  * the stream's current position set to after the blank line.
00134  */
00135 static HRESULT copy_headers_to_buf(IStream *stm, char **ptr)
00136 {
00137     char *buf = NULL;
00138     DWORD size = PARSER_BUF_SIZE, offset = 0, last_end = 0;
00139     HRESULT hr;
00140     int done = 0;
00141 
00142     *ptr = NULL;
00143 
00144     do
00145     {
00146         char *end;
00147         DWORD read;
00148 
00149         if(!buf)
00150             buf = HeapAlloc(GetProcessHeap(), 0, size + 1);
00151         else
00152         {
00153             size *= 2;
00154             buf = HeapReAlloc(GetProcessHeap(), 0, buf, size + 1);
00155         }
00156         if(!buf)
00157         {
00158             hr = E_OUTOFMEMORY;
00159             goto fail;
00160         }
00161 
00162         hr = IStream_Read(stm, buf + offset, size - offset, &read);
00163         if(FAILED(hr)) goto fail;
00164 
00165         offset += read;
00166         buf[offset] = '\0';
00167 
00168         if(read == 0) done = 1;
00169 
00170         while(!done && (end = strstr(buf + last_end, "\r\n")))
00171         {
00172             DWORD new_end = end - buf + 2;
00173             if(new_end - last_end == 2)
00174             {
00175                 LARGE_INTEGER off;
00176                 off.QuadPart = new_end;
00177                 IStream_Seek(stm, off, STREAM_SEEK_SET, NULL);
00178                 buf[new_end] = '\0';
00179                 done = 1;
00180             }
00181             else
00182                 last_end = new_end;
00183         }
00184     } while(!done);
00185 
00186     *ptr = buf;
00187     return S_OK;
00188 
00189 fail:
00190     HeapFree(GetProcessHeap(), 0, buf);
00191     return hr;
00192 }
00193 
00194 static header_t *read_prop(MimeBody *body, char **ptr)
00195 {
00196     char *colon = strchr(*ptr, ':');
00197     const property_t *prop;
00198     header_t *ret;
00199 
00200     if(!colon) return NULL;
00201 
00202     *colon = '\0';
00203 
00204     for(prop = default_props; prop->name; prop++)
00205     {
00206         if(!strcasecmp(*ptr, prop->name))
00207         {
00208             TRACE("%s: found match with default property id %d\n", *ptr, prop->id);
00209             break;
00210         }
00211     }
00212 
00213     if(!prop->name)
00214     {
00215         property_list_entry_t *prop_entry;
00216         LIST_FOR_EACH_ENTRY(prop_entry, &body->new_props, property_list_entry_t, entry)
00217         {
00218             if(!strcasecmp(*ptr, prop_entry->prop.name))
00219             {
00220                 TRACE("%s: found match with already added new property id %d\n", *ptr, prop_entry->prop.id);
00221                 prop = &prop_entry->prop;
00222                 break;
00223             }
00224         }
00225         if(!prop->name)
00226         {
00227             prop_entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*prop_entry));
00228             prop_entry->prop.name = strdupA(*ptr);
00229             prop_entry->prop.id = body->next_prop_id++;
00230             prop_entry->prop.flags = 0;
00231             prop_entry->prop.default_vt = VT_LPSTR;
00232             list_add_tail(&body->new_props, &prop_entry->entry);
00233             prop = &prop_entry->prop;
00234             TRACE("%s: allocating new prop id %d\n", *ptr, prop_entry->prop.id);
00235         }
00236     }
00237 
00238     ret = HeapAlloc(GetProcessHeap(), 0, sizeof(*ret));
00239     ret->prop = prop;
00240     PropVariantInit(&ret->value);
00241     list_init(&ret->params);
00242     *ptr = colon + 1;
00243 
00244     return ret;
00245 }
00246 
00247 static void unfold_header(char *header, int len)
00248 {
00249     char *start = header, *cp = header;
00250 
00251     do {
00252         while(*cp == ' ' || *cp == '\t')
00253         {
00254             cp++;
00255             len--;
00256         }
00257         if(cp != start)
00258             memmove(start, cp, len + 1);
00259 
00260         cp = strstr(start, "\r\n");
00261         len -= (cp - start);
00262         start = cp;
00263         *start = ' ';
00264         start++;
00265         len--;
00266         cp += 2;
00267     } while(*cp == ' ' || *cp == '\t');
00268 
00269     *(start - 1) = '\0';
00270 }
00271 
00272 static char *unquote_string(const char *str)
00273 {
00274     int quoted = 0;
00275     char *ret, *cp;
00276 
00277     while(*str == ' ' || *str == '\t') str++;
00278 
00279     if(*str == '"')
00280     {
00281         quoted = 1;
00282         str++;
00283     }
00284     ret = strdupA(str);
00285     for(cp = ret; *cp; cp++)
00286     {
00287         if(*cp == '\\')
00288             memmove(cp, cp + 1, strlen(cp + 1) + 1);
00289         else if(*cp == '"')
00290         {
00291             if(!quoted)
00292             {
00293                 WARN("quote in unquoted string\n");
00294             }
00295             else
00296             {
00297                 *cp = '\0';
00298                 break;
00299             }
00300         }
00301     }
00302     return ret;
00303 }
00304 
00305 static void add_param(header_t *header, const char *p)
00306 {
00307     const char *key = p, *value, *cp = p;
00308     param_t *param;
00309     char *name;
00310 
00311     TRACE("got param %s\n", p);
00312 
00313     while (*key == ' ' || *key == '\t' ) key++;
00314 
00315     cp = strchr(key, '=');
00316     if(!cp)
00317     {
00318         WARN("malformed parameter - skipping\n");
00319         return;
00320     }
00321 
00322     name = HeapAlloc(GetProcessHeap(), 0, cp - key + 1);
00323     memcpy(name, key, cp - key);
00324     name[cp - key] = '\0';
00325 
00326     value = cp + 1;
00327 
00328     param = HeapAlloc(GetProcessHeap(), 0, sizeof(*param));
00329     param->name = name;
00330     param->value = unquote_string(value);
00331     list_add_tail(&header->params, &param->entry);
00332 }
00333 
00334 static void split_params(header_t *header, char *value)
00335 {
00336     char *cp = value, *start = value;
00337     int in_quote = 0;
00338     int done_value = 0;
00339 
00340     while(*cp)
00341     {
00342         if(!in_quote && *cp == ';')
00343         {
00344             *cp = '\0';
00345             if(done_value) add_param(header, start);
00346             done_value = 1;
00347             start = cp + 1;
00348         }
00349         else if(*cp == '"')
00350             in_quote = !in_quote;
00351         cp++;
00352     }
00353     if(done_value) add_param(header, start);
00354 }
00355 
00356 static void read_value(header_t *header, char **cur)
00357 {
00358     char *end = *cur, *value;
00359     DWORD len;
00360 
00361     do {
00362         end = strstr(end, "\r\n");
00363         end += 2;
00364     } while(*end == ' ' || *end == '\t');
00365 
00366     len = end - *cur;
00367     value = HeapAlloc(GetProcessHeap(), 0, len + 1);
00368     memcpy(value, *cur, len);
00369     value[len] = '\0';
00370 
00371     unfold_header(value, len);
00372     TRACE("value %s\n", debugstr_a(value));
00373 
00374     if(header->prop->flags & MPF_HASPARAMS)
00375     {
00376         split_params(header, value);
00377         TRACE("value w/o params %s\n", debugstr_a(value));
00378     }
00379 
00380     header->value.vt = VT_LPSTR;
00381     header->value.u.pszVal = value;
00382 
00383     *cur = end;
00384 }
00385 
00386 static void init_content_type(MimeBody *body, header_t *header)
00387 {
00388     char *slash;
00389     DWORD len;
00390 
00391     if(header->prop->id != PID_HDR_CNTTYPE)
00392     {
00393         ERR("called with header %s\n", header->prop->name);
00394         return;
00395     }
00396 
00397     slash = strchr(header->value.u.pszVal, '/');
00398     if(!slash)
00399     {
00400         WARN("malformed context type value\n");
00401         return;
00402     }
00403     len = slash - header->value.u.pszVal;
00404     body->content_pri_type = HeapAlloc(GetProcessHeap(), 0, len + 1);
00405     memcpy(body->content_pri_type, header->value.u.pszVal, len);
00406     body->content_pri_type[len] = '\0';
00407     body->content_sub_type = strdupA(slash + 1);
00408 }
00409 
00410 static HRESULT parse_headers(MimeBody *body, IStream *stm)
00411 {
00412     char *header_buf, *cur_header_ptr;
00413     HRESULT hr;
00414     header_t *header;
00415 
00416     hr = copy_headers_to_buf(stm, &header_buf);
00417     if(FAILED(hr)) return hr;
00418 
00419     cur_header_ptr = header_buf;
00420     while((header = read_prop(body, &cur_header_ptr)))
00421     {
00422         read_value(header, &cur_header_ptr);
00423         list_add_tail(&body->headers, &header->entry);
00424 
00425         if(header->prop->id == PID_HDR_CNTTYPE)
00426             init_content_type(body, header);
00427     }
00428 
00429     HeapFree(GetProcessHeap(), 0, header_buf);
00430     return hr;
00431 }
00432 
00433 static void empty_param_list(struct list *list)
00434 {
00435     param_t *param, *cursor2;
00436 
00437     LIST_FOR_EACH_ENTRY_SAFE(param, cursor2, list, param_t, entry)
00438     {
00439         list_remove(&param->entry);
00440         HeapFree(GetProcessHeap(), 0, param->name);
00441         HeapFree(GetProcessHeap(), 0, param->value);
00442         HeapFree(GetProcessHeap(), 0, param);
00443     }
00444 }
00445 
00446 static void empty_header_list(struct list *list)
00447 {
00448     header_t *header, *cursor2;
00449 
00450     LIST_FOR_EACH_ENTRY_SAFE(header, cursor2, list, header_t, entry)
00451     {
00452         list_remove(&header->entry);
00453         PropVariantClear(&header->value);
00454         empty_param_list(&header->params);
00455         HeapFree(GetProcessHeap(), 0, header);
00456     }
00457 }
00458 
00459 static void empty_new_prop_list(struct list *list)
00460 {
00461     property_list_entry_t *prop, *cursor2;
00462 
00463     LIST_FOR_EACH_ENTRY_SAFE(prop, cursor2, list, property_list_entry_t, entry)
00464     {
00465         list_remove(&prop->entry);
00466         HeapFree(GetProcessHeap(), 0, (char *)prop->prop.name);
00467         HeapFree(GetProcessHeap(), 0, prop);
00468     }
00469 }
00470 
00471 static void release_data(REFIID riid, void *data)
00472 {
00473     if(!data) return;
00474 
00475     if(IsEqualIID(riid, &IID_IStream))
00476         IStream_Release((IStream *)data);
00477     else
00478         FIXME("Unhandled data format %s\n", debugstr_guid(riid));
00479 }
00480 
00481 static HRESULT find_prop(MimeBody *body, const char *name, header_t **prop)
00482 {
00483     header_t *header;
00484 
00485     *prop = NULL;
00486 
00487     LIST_FOR_EACH_ENTRY(header, &body->headers, header_t, entry)
00488     {
00489         if(!strcasecmp(name, header->prop->name))
00490         {
00491             *prop = header;
00492             return S_OK;
00493         }
00494     }
00495 
00496     return MIME_E_NOT_FOUND;
00497 }
00498 
00499 static HRESULT WINAPI MimeBody_QueryInterface(IMimeBody* iface,
00500                                      REFIID riid,
00501                                      void** ppvObject)
00502 {
00503     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppvObject);
00504 
00505     *ppvObject = NULL;
00506 
00507     if (IsEqualIID(riid, &IID_IUnknown) ||
00508         IsEqualIID(riid, &IID_IPersist) ||
00509         IsEqualIID(riid, &IID_IPersistStreamInit) ||
00510         IsEqualIID(riid, &IID_IMimePropertySet) ||
00511         IsEqualIID(riid, &IID_IMimeBody))
00512     {
00513         *ppvObject = iface;
00514     }
00515 
00516     if(*ppvObject)
00517     {
00518         IUnknown_AddRef((IUnknown*)*ppvObject);
00519         return S_OK;
00520     }
00521 
00522     FIXME("no interface for %s\n", debugstr_guid(riid));
00523     return E_NOINTERFACE;
00524 }
00525 
00526 static ULONG WINAPI MimeBody_AddRef(IMimeBody* iface)
00527 {
00528     MimeBody *This = impl_from_IMimeBody(iface);
00529     TRACE("(%p)->()\n", iface);
00530     return InterlockedIncrement(&This->refs);
00531 }
00532 
00533 static ULONG WINAPI MimeBody_Release(IMimeBody* iface)
00534 {
00535     MimeBody *This = impl_from_IMimeBody(iface);
00536     ULONG refs;
00537 
00538     TRACE("(%p)->()\n", iface);
00539 
00540     refs = InterlockedDecrement(&This->refs);
00541     if (!refs)
00542     {
00543         empty_header_list(&This->headers);
00544         empty_new_prop_list(&This->new_props);
00545 
00546         HeapFree(GetProcessHeap(), 0, This->content_pri_type);
00547         HeapFree(GetProcessHeap(), 0, This->content_sub_type);
00548 
00549         release_data(&This->data_iid, This->data);
00550 
00551         HeapFree(GetProcessHeap(), 0, This);
00552     }
00553 
00554     return refs;
00555 }
00556 
00557 static HRESULT WINAPI MimeBody_GetClassID(
00558                                  IMimeBody* iface,
00559                                  CLSID* pClassID)
00560 {
00561     FIXME("stub\n");
00562     return E_NOTIMPL;
00563 }
00564 
00565 
00566 static HRESULT WINAPI MimeBody_IsDirty(
00567                               IMimeBody* iface)
00568 {
00569     FIXME("stub\n");
00570     return E_NOTIMPL;
00571 }
00572 
00573 static HRESULT WINAPI MimeBody_Load(
00574                            IMimeBody* iface,
00575                            LPSTREAM pStm)
00576 {
00577     MimeBody *This = impl_from_IMimeBody(iface);
00578     TRACE("(%p)->(%p)\n", iface, pStm);
00579     return parse_headers(This, pStm);
00580 }
00581 
00582 static HRESULT WINAPI MimeBody_Save(
00583                            IMimeBody* iface,
00584                            LPSTREAM pStm,
00585                            BOOL fClearDirty)
00586 {
00587     FIXME("stub\n");
00588     return E_NOTIMPL;
00589 }
00590 
00591 static HRESULT WINAPI MimeBody_GetSizeMax(
00592                                  IMimeBody* iface,
00593                                  ULARGE_INTEGER* pcbSize)
00594 {
00595     FIXME("stub\n");
00596     return E_NOTIMPL;
00597 }
00598 
00599 static HRESULT WINAPI MimeBody_InitNew(
00600                               IMimeBody* iface)
00601 {
00602     TRACE("%p->()\n", iface);
00603     return S_OK;
00604 }
00605 
00606 static HRESULT WINAPI MimeBody_GetPropInfo(
00607                                   IMimeBody* iface,
00608                                   LPCSTR pszName,
00609                                   LPMIMEPROPINFO pInfo)
00610 {
00611     FIXME("stub\n");
00612     return E_NOTIMPL;
00613 }
00614 
00615 static HRESULT WINAPI MimeBody_SetPropInfo(
00616                                   IMimeBody* iface,
00617                                   LPCSTR pszName,
00618                                   LPCMIMEPROPINFO pInfo)
00619 {
00620     FIXME("stub\n");
00621     return E_NOTIMPL;
00622 }
00623 
00624 static HRESULT WINAPI MimeBody_GetProp(
00625                               IMimeBody* iface,
00626                               LPCSTR pszName,
00627                               DWORD dwFlags,
00628                               LPPROPVARIANT pValue)
00629 {
00630     MimeBody *This = impl_from_IMimeBody(iface);
00631     TRACE("(%p)->(%s, %d, %p)\n", This, pszName, dwFlags, pValue);
00632 
00633     if(!strcasecmp(pszName, "att:pri-content-type"))
00634     {
00635         PropVariantClear(pValue);
00636         pValue->vt = VT_LPSTR;
00637         pValue->u.pszVal = strdupA(This->content_pri_type);
00638         return S_OK;
00639     }
00640 
00641     FIXME("stub!\n");
00642     return E_FAIL;
00643 }
00644 
00645 static HRESULT WINAPI MimeBody_SetProp(
00646                               IMimeBody* iface,
00647                               LPCSTR pszName,
00648                               DWORD dwFlags,
00649                               LPCPROPVARIANT pValue)
00650 {
00651     FIXME("stub\n");
00652     return E_NOTIMPL;
00653 }
00654 
00655 static HRESULT WINAPI MimeBody_AppendProp(
00656                                  IMimeBody* iface,
00657                                  LPCSTR pszName,
00658                                  DWORD dwFlags,
00659                                  LPPROPVARIANT pValue)
00660 {
00661     FIXME("stub\n");
00662     return E_NOTIMPL;
00663 }
00664 
00665 static HRESULT WINAPI MimeBody_DeleteProp(
00666                                  IMimeBody* iface,
00667                                  LPCSTR pszName)
00668 {
00669     FIXME("stub\n");
00670     return E_NOTIMPL;
00671 }
00672 
00673 static HRESULT WINAPI MimeBody_CopyProps(
00674                                 IMimeBody* iface,
00675                                 ULONG cNames,
00676                                 LPCSTR* prgszName,
00677                                 IMimePropertySet* pPropertySet)
00678 {
00679     FIXME("stub\n");
00680     return E_NOTIMPL;
00681 }
00682 
00683 static HRESULT WINAPI MimeBody_MoveProps(
00684                                 IMimeBody* iface,
00685                                 ULONG cNames,
00686                                 LPCSTR* prgszName,
00687                                 IMimePropertySet* pPropertySet)
00688 {
00689     FIXME("stub\n");
00690     return E_NOTIMPL;
00691 }
00692 
00693 static HRESULT WINAPI MimeBody_DeleteExcept(
00694                                    IMimeBody* iface,
00695                                    ULONG cNames,
00696                                    LPCSTR* prgszName)
00697 {
00698     FIXME("stub\n");
00699     return E_NOTIMPL;
00700 }
00701 
00702 static HRESULT WINAPI MimeBody_QueryProp(
00703                                 IMimeBody* iface,
00704                                 LPCSTR pszName,
00705                                 LPCSTR pszCriteria,
00706                                 boolean fSubString,
00707                                 boolean fCaseSensitive)
00708 {
00709     FIXME("stub\n");
00710     return E_NOTIMPL;
00711 }
00712 
00713 static HRESULT WINAPI MimeBody_GetCharset(
00714                                  IMimeBody* iface,
00715                                  LPHCHARSET phCharset)
00716 {
00717     FIXME("stub\n");
00718     *phCharset = NULL;
00719     return S_OK;
00720 }
00721 
00722 static HRESULT WINAPI MimeBody_SetCharset(
00723                                  IMimeBody* iface,
00724                                  HCHARSET hCharset,
00725                                  CSETAPPLYTYPE applytype)
00726 {
00727     FIXME("stub\n");
00728     return E_NOTIMPL;
00729 }
00730 
00731 static HRESULT WINAPI MimeBody_GetParameters(
00732                                     IMimeBody* iface,
00733                                     LPCSTR pszName,
00734                                     ULONG* pcParams,
00735                                     LPMIMEPARAMINFO* pprgParam)
00736 {
00737     MimeBody *This = impl_from_IMimeBody(iface);
00738     HRESULT hr;
00739     header_t *header;
00740 
00741     TRACE("(%p)->(%s, %p, %p)\n", iface, debugstr_a(pszName), pcParams, pprgParam);
00742 
00743     *pprgParam = NULL;
00744     *pcParams = 0;
00745 
00746     hr = find_prop(This, pszName, &header);
00747     if(hr != S_OK) return hr;
00748 
00749     *pcParams = list_count(&header->params);
00750     if(*pcParams)
00751     {
00752         IMimeAllocator *alloc;
00753         param_t *param;
00754         MIMEPARAMINFO *info;
00755 
00756         MimeOleGetAllocator(&alloc);
00757 
00758         *pprgParam = info = IMimeAllocator_Alloc(alloc, *pcParams * sizeof(**pprgParam));
00759         LIST_FOR_EACH_ENTRY(param, &header->params, param_t, entry)
00760         {
00761             int len;
00762 
00763             len = strlen(param->name) + 1;
00764             info->pszName = IMimeAllocator_Alloc(alloc, len);
00765             memcpy(info->pszName, param->name, len);
00766             len = strlen(param->value) + 1;
00767             info->pszData = IMimeAllocator_Alloc(alloc, len);
00768             memcpy(info->pszData, param->value, len);
00769             info++;
00770         }
00771         IMimeAllocator_Release(alloc);
00772     }
00773     return S_OK;
00774 }
00775 
00776 static HRESULT WINAPI MimeBody_IsContentType(
00777                                     IMimeBody* iface,
00778                                     LPCSTR pszPriType,
00779                                     LPCSTR pszSubType)
00780 {
00781     MimeBody *This = impl_from_IMimeBody(iface);
00782 
00783     TRACE("(%p)->(%s, %s)\n", This, debugstr_a(pszPriType), debugstr_a(pszSubType));
00784     if(pszPriType)
00785     {
00786         const char *pri = This->content_pri_type;
00787         if(!pri) pri = "text";
00788         if(strcasecmp(pri, pszPriType)) return S_FALSE;
00789     }
00790 
00791     if(pszSubType)
00792     {
00793         const char *sub = This->content_sub_type;
00794         if(!sub) sub = "plain";
00795         if(strcasecmp(sub, pszSubType)) return S_FALSE;
00796     }
00797 
00798     return S_OK;
00799 }
00800 
00801 static HRESULT WINAPI MimeBody_BindToObject(
00802                                    IMimeBody* iface,
00803                                    REFIID riid,
00804                                    void** ppvObject)
00805 {
00806     FIXME("stub\n");
00807     return E_NOTIMPL;
00808 }
00809 
00810 static HRESULT WINAPI MimeBody_Clone(
00811                             IMimeBody* iface,
00812                             IMimePropertySet** ppPropertySet)
00813 {
00814     FIXME("stub\n");
00815     return E_NOTIMPL;
00816 }
00817 
00818 static HRESULT WINAPI MimeBody_SetOption(
00819                                 IMimeBody* iface,
00820                                 const TYPEDID oid,
00821                                 LPCPROPVARIANT pValue)
00822 {
00823     HRESULT hr = E_NOTIMPL;
00824     TRACE("(%p)->(%08x, %p)\n", iface, oid, pValue);
00825 
00826     if(pValue->vt != TYPEDID_TYPE(oid))
00827     {
00828         WARN("Called with vartype %04x and oid %08x\n", pValue->vt, oid);
00829         return E_INVALIDARG;
00830     }
00831 
00832     switch(oid)
00833     {
00834     case OID_SECURITY_HWND_OWNER:
00835         FIXME("OID_SECURITY_HWND_OWNER (value %08x): ignoring\n", pValue->u.ulVal);
00836         hr = S_OK;
00837         break;
00838     default:
00839         FIXME("Unhandled oid %08x\n", oid);
00840     }
00841 
00842     return hr;
00843 }
00844 
00845 static HRESULT WINAPI MimeBody_GetOption(
00846                                 IMimeBody* iface,
00847                                 const TYPEDID oid,
00848                                 LPPROPVARIANT pValue)
00849 {
00850     FIXME("(%p)->(%08x, %p): stub\n", iface, oid, pValue);
00851     return E_NOTIMPL;
00852 }
00853 
00854 static HRESULT WINAPI MimeBody_EnumProps(
00855                                 IMimeBody* iface,
00856                                 DWORD dwFlags,
00857                                 IMimeEnumProperties** ppEnum)
00858 {
00859     FIXME("stub\n");
00860     return E_NOTIMPL;
00861 }
00862 
00863 static HRESULT WINAPI MimeBody_IsType(
00864                              IMimeBody* iface,
00865                              IMSGBODYTYPE bodytype)
00866 {
00867     MimeBody *This = impl_from_IMimeBody(iface);
00868 
00869     TRACE("(%p)->(%d)\n", iface, bodytype);
00870     switch(bodytype)
00871     {
00872     case IBT_EMPTY:
00873         return This->data ? S_FALSE : S_OK;
00874     default:
00875         FIXME("Unimplemented bodytype %d - returning S_OK\n", bodytype);
00876     }
00877     return S_OK;
00878 }
00879 
00880 static HRESULT WINAPI MimeBody_SetDisplayName(
00881                                      IMimeBody* iface,
00882                                      LPCSTR pszDisplay)
00883 {
00884     FIXME("stub\n");
00885     return E_NOTIMPL;
00886 }
00887 
00888 static HRESULT WINAPI MimeBody_GetDisplayName(
00889                                      IMimeBody* iface,
00890                                      LPSTR* ppszDisplay)
00891 {
00892     FIXME("stub\n");
00893     return E_NOTIMPL;
00894 }
00895 
00896 static HRESULT WINAPI MimeBody_GetOffsets(
00897                                  IMimeBody* iface,
00898                                  LPBODYOFFSETS pOffsets)
00899 {
00900     MimeBody *This = impl_from_IMimeBody(iface);
00901     TRACE("(%p)->(%p)\n", This, pOffsets);
00902 
00903     *pOffsets = This->body_offsets;
00904 
00905     if(This->body_offsets.cbBodyEnd == 0) return MIME_E_NO_DATA;
00906     return S_OK;
00907 }
00908 
00909 static HRESULT WINAPI MimeBody_GetCurrentEncoding(
00910                                          IMimeBody* iface,
00911                                          ENCODINGTYPE* pietEncoding)
00912 {
00913     MimeBody *This = impl_from_IMimeBody(iface);
00914 
00915     TRACE("(%p)->(%p)\n", This, pietEncoding);
00916 
00917     *pietEncoding = This->encoding;
00918     return S_OK;
00919 }
00920 
00921 static HRESULT WINAPI MimeBody_SetCurrentEncoding(
00922                                          IMimeBody* iface,
00923                                          ENCODINGTYPE ietEncoding)
00924 {
00925     MimeBody *This = impl_from_IMimeBody(iface);
00926 
00927     TRACE("(%p)->(%d)\n", This, ietEncoding);
00928 
00929     This->encoding = ietEncoding;
00930     return S_OK;
00931 }
00932 
00933 static HRESULT WINAPI MimeBody_GetEstimatedSize(
00934                                        IMimeBody* iface,
00935                                        ENCODINGTYPE ietEncoding,
00936                                        ULONG* pcbSize)
00937 {
00938     FIXME("stub\n");
00939     return E_NOTIMPL;
00940 }
00941 
00942 static HRESULT WINAPI MimeBody_GetDataHere(
00943                                   IMimeBody* iface,
00944                                   ENCODINGTYPE ietEncoding,
00945                                   IStream* pStream)
00946 {
00947     FIXME("stub\n");
00948     return E_NOTIMPL;
00949 }
00950 
00951 static HRESULT WINAPI MimeBody_GetData(
00952                               IMimeBody* iface,
00953                               ENCODINGTYPE ietEncoding,
00954                               IStream** ppStream)
00955 {
00956     MimeBody *This = impl_from_IMimeBody(iface);
00957     FIXME("(%p)->(%d, %p). Ignoring encoding type.\n", This, ietEncoding, ppStream);
00958 
00959     *ppStream = This->data;
00960     IStream_AddRef(*ppStream);
00961     return S_OK;
00962 }
00963 
00964 static HRESULT WINAPI MimeBody_SetData(
00965                               IMimeBody* iface,
00966                               ENCODINGTYPE ietEncoding,
00967                               LPCSTR pszPriType,
00968                               LPCSTR pszSubType,
00969                               REFIID riid,
00970                               LPVOID pvObject)
00971 {
00972     MimeBody *This = impl_from_IMimeBody(iface);
00973     TRACE("(%p)->(%d, %s, %s, %s %p)\n", This, ietEncoding, debugstr_a(pszPriType), debugstr_a(pszSubType),
00974           debugstr_guid(riid), pvObject);
00975 
00976     if(IsEqualIID(riid, &IID_IStream))
00977         IStream_AddRef((IStream *)pvObject);
00978     else
00979     {
00980         FIXME("Unhandled object type %s\n", debugstr_guid(riid));
00981         return E_INVALIDARG;
00982     }
00983 
00984     if(This->data)
00985         FIXME("release old data\n");
00986 
00987     This->data_iid = *riid;
00988     This->data = pvObject;
00989 
00990     IMimeBody_SetCurrentEncoding(iface, ietEncoding);
00991 
00992     /* FIXME: Update the content type.
00993        If pszPriType == NULL use 'application'
00994        If pszSubType == NULL use 'octet-stream' */
00995 
00996     return S_OK;
00997 }
00998 
00999 static HRESULT WINAPI MimeBody_EmptyData(
01000                                 IMimeBody* iface)
01001 {
01002     FIXME("stub\n");
01003     return E_NOTIMPL;
01004 }
01005 
01006 static HRESULT WINAPI MimeBody_CopyTo(
01007                              IMimeBody* iface,
01008                              IMimeBody* pBody)
01009 {
01010     FIXME("stub\n");
01011     return E_NOTIMPL;
01012 }
01013 
01014 static HRESULT WINAPI MimeBody_GetTransmitInfo(
01015                                       IMimeBody* iface,
01016                                       LPTRANSMITINFO pTransmitInfo)
01017 {
01018     FIXME("stub\n");
01019     return E_NOTIMPL;
01020 }
01021 
01022 static HRESULT WINAPI MimeBody_SaveToFile(
01023                                  IMimeBody* iface,
01024                                  ENCODINGTYPE ietEncoding,
01025                                  LPCSTR pszFilePath)
01026 {
01027     FIXME("stub\n");
01028     return E_NOTIMPL;
01029 }
01030 
01031 static HRESULT WINAPI MimeBody_GetHandle(
01032                                 IMimeBody* iface,
01033                                 LPHBODY phBody)
01034 {
01035     MimeBody *This = impl_from_IMimeBody(iface);
01036     TRACE("(%p)->(%p)\n", iface, phBody);
01037 
01038     *phBody = This->handle;
01039     return This->handle ? S_OK : MIME_E_NO_DATA;
01040 }
01041 
01042 static IMimeBodyVtbl body_vtbl =
01043 {
01044     MimeBody_QueryInterface,
01045     MimeBody_AddRef,
01046     MimeBody_Release,
01047     MimeBody_GetClassID,
01048     MimeBody_IsDirty,
01049     MimeBody_Load,
01050     MimeBody_Save,
01051     MimeBody_GetSizeMax,
01052     MimeBody_InitNew,
01053     MimeBody_GetPropInfo,
01054     MimeBody_SetPropInfo,
01055     MimeBody_GetProp,
01056     MimeBody_SetProp,
01057     MimeBody_AppendProp,
01058     MimeBody_DeleteProp,
01059     MimeBody_CopyProps,
01060     MimeBody_MoveProps,
01061     MimeBody_DeleteExcept,
01062     MimeBody_QueryProp,
01063     MimeBody_GetCharset,
01064     MimeBody_SetCharset,
01065     MimeBody_GetParameters,
01066     MimeBody_IsContentType,
01067     MimeBody_BindToObject,
01068     MimeBody_Clone,
01069     MimeBody_SetOption,
01070     MimeBody_GetOption,
01071     MimeBody_EnumProps,
01072     MimeBody_IsType,
01073     MimeBody_SetDisplayName,
01074     MimeBody_GetDisplayName,
01075     MimeBody_GetOffsets,
01076     MimeBody_GetCurrentEncoding,
01077     MimeBody_SetCurrentEncoding,
01078     MimeBody_GetEstimatedSize,
01079     MimeBody_GetDataHere,
01080     MimeBody_GetData,
01081     MimeBody_SetData,
01082     MimeBody_EmptyData,
01083     MimeBody_CopyTo,
01084     MimeBody_GetTransmitInfo,
01085     MimeBody_SaveToFile,
01086     MimeBody_GetHandle
01087 };
01088 
01089 static HRESULT MimeBody_set_offsets(MimeBody *body, const BODYOFFSETS *offsets)
01090 {
01091     TRACE("setting offsets to %d, %d, %d, %d\n", offsets->cbBoundaryStart,
01092           offsets->cbHeaderStart, offsets->cbBodyStart, offsets->cbBodyEnd);
01093 
01094     body->body_offsets = *offsets;
01095     return S_OK;
01096 }
01097 
01098 #define FIRST_CUSTOM_PROP_ID 0x100
01099 
01100 HRESULT MimeBody_create(IUnknown *outer, void **obj)
01101 {
01102     MimeBody *This;
01103     BODYOFFSETS body_offsets;
01104 
01105     *obj = NULL;
01106 
01107     if(outer) return CLASS_E_NOAGGREGATION;
01108 
01109     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
01110     if (!This) return E_OUTOFMEMORY;
01111 
01112     This->lpVtbl = &body_vtbl;
01113     This->refs = 1;
01114     This->handle = NULL;
01115     list_init(&This->headers);
01116     list_init(&This->new_props);
01117     This->next_prop_id = FIRST_CUSTOM_PROP_ID;
01118     This->content_pri_type = NULL;
01119     This->content_sub_type = NULL;
01120     This->encoding = IET_7BIT;
01121     This->data = NULL;
01122     This->data_iid = IID_NULL;
01123 
01124     body_offsets.cbBoundaryStart = body_offsets.cbHeaderStart = 0;
01125     body_offsets.cbBodyStart     = body_offsets.cbBodyEnd     = 0;
01126     MimeBody_set_offsets(This, &body_offsets);
01127 
01128     *obj = &This->lpVtbl;
01129     return S_OK;
01130 }
01131 
01132 typedef struct
01133 {
01134     IStreamVtbl *lpVtbl;
01135     LONG refs;
01136 
01137     IStream *base;
01138     ULARGE_INTEGER pos, start, length;
01139 } sub_stream_t;
01140 
01141 static inline sub_stream_t *impl_from_IStream( IStream *iface )
01142 {
01143     return (sub_stream_t *)((char*)iface - FIELD_OFFSET(sub_stream_t, lpVtbl));
01144 }
01145 
01146 static HRESULT WINAPI sub_stream_QueryInterface(
01147         IStream* iface,
01148         REFIID riid,
01149         void **ppvObject)
01150 {
01151     sub_stream_t *This = impl_from_IStream(iface);
01152 
01153     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
01154     *ppvObject = NULL;
01155 
01156     if(IsEqualIID(riid, &IID_IUnknown) ||
01157        IsEqualIID(riid, &IID_ISequentialStream) ||
01158        IsEqualIID(riid, &IID_IStream))
01159     {
01160         IStream_AddRef(iface);
01161         *ppvObject = iface;
01162         return S_OK;
01163     }
01164     return E_NOINTERFACE;
01165 }
01166 
01167 static ULONG WINAPI sub_stream_AddRef(
01168          IStream* iface)
01169 {
01170     sub_stream_t *This = impl_from_IStream(iface);
01171 
01172     TRACE("(%p)\n", This);
01173     return InterlockedIncrement(&This->refs);
01174 }
01175 
01176 static ULONG WINAPI  sub_stream_Release(
01177         IStream* iface)
01178 {
01179     sub_stream_t *This = impl_from_IStream(iface);
01180     LONG refs;
01181 
01182     TRACE("(%p)\n", This);
01183     refs = InterlockedDecrement(&This->refs);
01184     if(!refs)
01185     {
01186         IStream_Release(This->base);
01187         HeapFree(GetProcessHeap(), 0, This);
01188     }
01189     return refs;
01190 }
01191 
01192 static HRESULT WINAPI sub_stream_Read(
01193         IStream* iface,
01194         void *pv,
01195         ULONG cb,
01196         ULONG *pcbRead)
01197 {
01198     sub_stream_t *This = impl_from_IStream(iface);
01199     HRESULT hr;
01200     ULARGE_INTEGER base_pos;
01201     LARGE_INTEGER tmp_pos;
01202 
01203     TRACE("(%p, %d, %p)\n", pv, cb, pcbRead);
01204 
01205     tmp_pos.QuadPart = 0;
01206     IStream_Seek(This->base, tmp_pos, STREAM_SEEK_CUR, &base_pos);
01207     tmp_pos.QuadPart = This->pos.QuadPart + This->start.QuadPart;
01208     IStream_Seek(This->base, tmp_pos, STREAM_SEEK_SET, NULL);
01209 
01210     if(This->pos.QuadPart + cb > This->length.QuadPart)
01211         cb = This->length.QuadPart - This->pos.QuadPart;
01212 
01213     hr = IStream_Read(This->base, pv, cb, pcbRead);
01214 
01215     This->pos.QuadPart += *pcbRead;
01216 
01217     tmp_pos.QuadPart = base_pos.QuadPart;
01218     IStream_Seek(This->base, tmp_pos, STREAM_SEEK_SET, NULL);
01219 
01220     return hr;
01221 }
01222 
01223 static HRESULT WINAPI sub_stream_Write(
01224         IStream* iface,
01225         const void *pv,
01226         ULONG cb,
01227         ULONG *pcbWritten)
01228 {
01229     FIXME("stub\n");
01230     return E_NOTIMPL;
01231 }
01232 
01233 static HRESULT WINAPI sub_stream_Seek(
01234         IStream* iface,
01235         LARGE_INTEGER dlibMove,
01236         DWORD dwOrigin,
01237         ULARGE_INTEGER *plibNewPosition)
01238 {
01239     sub_stream_t *This = impl_from_IStream(iface);
01240     LARGE_INTEGER new_pos;
01241 
01242     TRACE("(%08x.%08x, %x, %p)\n", dlibMove.u.HighPart, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
01243 
01244     switch(dwOrigin)
01245     {
01246     case STREAM_SEEK_SET:
01247         new_pos = dlibMove;
01248         break;
01249     case STREAM_SEEK_CUR:
01250         new_pos.QuadPart = This->pos.QuadPart + dlibMove.QuadPart;
01251         break;
01252     case STREAM_SEEK_END:
01253         new_pos.QuadPart = This->length.QuadPart + dlibMove.QuadPart;
01254         break;
01255     default:
01256         return STG_E_INVALIDFUNCTION;
01257     }
01258 
01259     if(new_pos.QuadPart < 0) new_pos.QuadPart = 0;
01260     else if(new_pos.QuadPart > This->length.QuadPart) new_pos.QuadPart = This->length.QuadPart;
01261 
01262     This->pos.QuadPart = new_pos.QuadPart;
01263 
01264     if(plibNewPosition) *plibNewPosition = This->pos;
01265     return S_OK;
01266 }
01267 
01268 static HRESULT WINAPI sub_stream_SetSize(
01269         IStream* iface,
01270         ULARGE_INTEGER libNewSize)
01271 {
01272     FIXME("stub\n");
01273     return E_NOTIMPL;
01274 }
01275 
01276 static HRESULT WINAPI sub_stream_CopyTo(
01277         IStream* iface,
01278         IStream *pstm,
01279         ULARGE_INTEGER cb,
01280         ULARGE_INTEGER *pcbRead,
01281         ULARGE_INTEGER *pcbWritten)
01282 {
01283     HRESULT        hr = S_OK;
01284     BYTE           tmpBuffer[128];
01285     ULONG          bytesRead, bytesWritten, copySize;
01286     ULARGE_INTEGER totalBytesRead;
01287     ULARGE_INTEGER totalBytesWritten;
01288 
01289     TRACE("(%p)->(%p, %d, %p, %p)\n", iface, pstm, cb.u.LowPart, pcbRead, pcbWritten);
01290 
01291     totalBytesRead.QuadPart = 0;
01292     totalBytesWritten.QuadPart = 0;
01293 
01294     while ( cb.QuadPart > 0 )
01295     {
01296         if ( cb.QuadPart >= sizeof(tmpBuffer) )
01297             copySize = sizeof(tmpBuffer);
01298         else
01299             copySize = cb.u.LowPart;
01300 
01301         hr = IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
01302         if (FAILED(hr)) break;
01303 
01304         totalBytesRead.QuadPart += bytesRead;
01305 
01306         if (bytesRead)
01307         {
01308             hr = IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
01309             if (FAILED(hr)) break;
01310             totalBytesWritten.QuadPart += bytesWritten;
01311         }
01312 
01313         if (bytesRead != copySize)
01314             cb.QuadPart = 0;
01315         else
01316             cb.QuadPart -= bytesRead;
01317     }
01318 
01319     if (pcbRead) pcbRead->QuadPart = totalBytesRead.QuadPart;
01320     if (pcbWritten) pcbWritten->QuadPart = totalBytesWritten.QuadPart;
01321 
01322     return hr;
01323 }
01324 
01325 static HRESULT WINAPI sub_stream_Commit(
01326         IStream* iface,
01327         DWORD grfCommitFlags)
01328 {
01329     FIXME("stub\n");
01330     return E_NOTIMPL;
01331 }
01332 
01333 static HRESULT WINAPI sub_stream_Revert(
01334         IStream* iface)
01335 {
01336     FIXME("stub\n");
01337     return E_NOTIMPL;
01338 }
01339 
01340 static HRESULT WINAPI sub_stream_LockRegion(
01341         IStream* iface,
01342         ULARGE_INTEGER libOffset,
01343         ULARGE_INTEGER cb,
01344         DWORD dwLockType)
01345 {
01346     FIXME("stub\n");
01347     return E_NOTIMPL;
01348 }
01349 
01350 static HRESULT WINAPI sub_stream_UnlockRegion(
01351         IStream* iface,
01352         ULARGE_INTEGER libOffset,
01353         ULARGE_INTEGER cb,
01354         DWORD dwLockType)
01355 {
01356     FIXME("stub\n");
01357     return E_NOTIMPL;
01358 }
01359 
01360 static HRESULT WINAPI sub_stream_Stat(
01361         IStream* iface,
01362         STATSTG *pstatstg,
01363         DWORD grfStatFlag)
01364 {
01365     sub_stream_t *This = impl_from_IStream(iface);
01366     FIXME("(%p)->(%p, %08x)\n", This, pstatstg, grfStatFlag);
01367     memset(pstatstg, 0, sizeof(*pstatstg));
01368     pstatstg->cbSize = This->length;
01369     return S_OK;
01370 }
01371 
01372 static HRESULT WINAPI sub_stream_Clone(
01373         IStream* iface,
01374         IStream **ppstm)
01375 {
01376     FIXME("stub\n");
01377     return E_NOTIMPL;
01378 }
01379 
01380 static struct IStreamVtbl sub_stream_vtbl =
01381 {
01382     sub_stream_QueryInterface,
01383     sub_stream_AddRef,
01384     sub_stream_Release,
01385     sub_stream_Read,
01386     sub_stream_Write,
01387     sub_stream_Seek,
01388     sub_stream_SetSize,
01389     sub_stream_CopyTo,
01390     sub_stream_Commit,
01391     sub_stream_Revert,
01392     sub_stream_LockRegion,
01393     sub_stream_UnlockRegion,
01394     sub_stream_Stat,
01395     sub_stream_Clone
01396 };
01397 
01398 static HRESULT create_sub_stream(IStream *stream, ULARGE_INTEGER start, ULARGE_INTEGER length, IStream **out)
01399 {
01400     sub_stream_t *This;
01401 
01402     *out = NULL;
01403     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
01404     if(!This) return E_OUTOFMEMORY;
01405 
01406     This->lpVtbl = &sub_stream_vtbl;
01407     This->refs = 1;
01408     This->start = start;
01409     This->length = length;
01410     This->pos.QuadPart = 0;
01411     IStream_AddRef(stream);
01412     This->base = stream;
01413 
01414     *out = (IStream*)&This->lpVtbl;
01415     return S_OK;
01416 }
01417 
01418 
01419 typedef struct body_t
01420 {
01421     struct list entry;
01422     DWORD index;
01423     IMimeBody *mime_body;
01424 
01425     struct body_t *parent;
01426     struct list children;
01427 } body_t;
01428 
01429 typedef struct MimeMessage
01430 {
01431     const IMimeMessageVtbl *lpVtbl;
01432 
01433     LONG refs;
01434     IStream *stream;
01435 
01436     struct list body_tree;
01437     DWORD next_index;
01438 } MimeMessage;
01439 
01440 static HRESULT WINAPI MimeMessage_QueryInterface(IMimeMessage *iface, REFIID riid, void **ppv)
01441 {
01442     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
01443 
01444     if (IsEqualIID(riid, &IID_IUnknown) ||
01445         IsEqualIID(riid, &IID_IPersist) ||
01446         IsEqualIID(riid, &IID_IPersistStreamInit) ||
01447         IsEqualIID(riid, &IID_IMimeMessageTree) ||
01448         IsEqualIID(riid, &IID_IMimeMessage))
01449     {
01450         *ppv = iface;
01451         IUnknown_AddRef(iface);
01452         return S_OK;
01453     }
01454 
01455     FIXME("no interface for %s\n", debugstr_guid(riid));
01456     *ppv = NULL;
01457     return E_NOINTERFACE;
01458 }
01459 
01460 static ULONG WINAPI MimeMessage_AddRef(IMimeMessage *iface)
01461 {
01462     MimeMessage *This = (MimeMessage *)iface;
01463     TRACE("(%p)->()\n", iface);
01464     return InterlockedIncrement(&This->refs);
01465 }
01466 
01467 static void empty_body_list(struct list *list)
01468 {
01469     body_t *body, *cursor2;
01470     LIST_FOR_EACH_ENTRY_SAFE(body, cursor2, list, body_t, entry)
01471     {
01472         empty_body_list(&body->children);
01473         list_remove(&body->entry);
01474         IMimeBody_Release(body->mime_body);
01475         HeapFree(GetProcessHeap(), 0, body);
01476     }
01477 }
01478 
01479 static ULONG WINAPI MimeMessage_Release(IMimeMessage *iface)
01480 {
01481     MimeMessage *This = (MimeMessage *)iface;
01482     ULONG refs;
01483 
01484     TRACE("(%p)->()\n", iface);
01485 
01486     refs = InterlockedDecrement(&This->refs);
01487     if (!refs)
01488     {
01489         empty_body_list(&This->body_tree);
01490 
01491         if(This->stream) IStream_Release(This->stream);
01492         HeapFree(GetProcessHeap(), 0, This);
01493     }
01494 
01495     return refs;
01496 }
01497 
01498 /*** IPersist methods ***/
01499 static HRESULT WINAPI MimeMessage_GetClassID(
01500     IMimeMessage *iface,
01501     CLSID *pClassID)
01502 {
01503     FIXME("(%p)->(%p)\n", iface, pClassID);
01504     return E_NOTIMPL;
01505 }
01506 
01507 /*** IPersistStreamInit methods ***/
01508 static HRESULT WINAPI MimeMessage_IsDirty(
01509     IMimeMessage *iface)
01510 {
01511     FIXME("(%p)->()\n", iface);
01512     return E_NOTIMPL;
01513 }
01514 
01515 static body_t *new_body_entry(IMimeBody *mime_body, DWORD index, body_t *parent)
01516 {
01517     body_t *body = HeapAlloc(GetProcessHeap(), 0, sizeof(*body));
01518     if(body)
01519     {
01520         body->mime_body = mime_body;
01521         body->index = index;
01522         list_init(&body->children);
01523         body->parent = parent;
01524     }
01525     return body;
01526 }
01527 
01528 typedef struct
01529 {
01530     struct list entry;
01531     BODYOFFSETS offsets;
01532 } offset_entry_t;
01533 
01534 static HRESULT create_body_offset_list(IStream *stm, const char *boundary, struct list *body_offsets)
01535 {
01536     HRESULT hr;
01537     DWORD read;
01538     int boundary_len = strlen(boundary);
01539     char *buf, *nl_boundary, *ptr, *overlap;
01540     DWORD start = 0, overlap_no;
01541     offset_entry_t *cur_body = NULL;
01542     ULARGE_INTEGER cur;
01543     LARGE_INTEGER zero;
01544 
01545     list_init(body_offsets);
01546     nl_boundary = HeapAlloc(GetProcessHeap(), 0, 4 + boundary_len + 1);
01547     memcpy(nl_boundary, "\r\n--", 4);
01548     memcpy(nl_boundary + 4, boundary, boundary_len + 1);
01549 
01550     overlap_no = boundary_len + 5;
01551 
01552     overlap = buf = HeapAlloc(GetProcessHeap(), 0, overlap_no + PARSER_BUF_SIZE + 1);
01553 
01554     zero.QuadPart = 0;
01555     hr = IStream_Seek(stm, zero, STREAM_SEEK_CUR, &cur);
01556     start = cur.u.LowPart;
01557 
01558     do {
01559         hr = IStream_Read(stm, overlap, PARSER_BUF_SIZE, &read);
01560         if(FAILED(hr)) goto end;
01561         if(read == 0) break;
01562         overlap[read] = '\0';
01563 
01564         ptr = buf;
01565         do {
01566             ptr = strstr(ptr, nl_boundary);
01567             if(ptr)
01568             {
01569                 DWORD boundary_start = start + ptr - buf;
01570                 char *end = ptr + boundary_len + 4;
01571 
01572                 if(*end == '\0' || *(end + 1) == '\0')
01573                     break;
01574 
01575                 if(*end == '\r' && *(end + 1) == '\n')
01576                 {
01577                     if(cur_body)
01578                     {
01579                         cur_body->offsets.cbBodyEnd = boundary_start;
01580                         list_add_tail(body_offsets, &cur_body->entry);
01581                     }
01582                     cur_body = HeapAlloc(GetProcessHeap(), 0, sizeof(*cur_body));
01583                     cur_body->offsets.cbBoundaryStart = boundary_start + 2; /* doesn't including the leading \r\n */
01584                     cur_body->offsets.cbHeaderStart = boundary_start + boundary_len + 6;
01585                 }
01586                 else if(*end == '-' && *(end + 1) == '-')
01587                 {
01588                     if(cur_body)
01589                     {
01590                         cur_body->offsets.cbBodyEnd = boundary_start;
01591                         list_add_tail(body_offsets, &cur_body->entry);
01592                         goto end;
01593                     }
01594                 }
01595                 ptr = end + 2;
01596             }
01597         } while(ptr);
01598 
01599         if(overlap == buf) /* 1st iteration */
01600         {
01601             memcpy(buf, buf + PARSER_BUF_SIZE - overlap_no, overlap_no);
01602             overlap = buf + overlap_no;
01603             start += read - overlap_no;
01604         }
01605         else
01606         {
01607             memcpy(buf, buf + PARSER_BUF_SIZE, overlap_no);
01608             start += read;
01609         }
01610     } while(1);
01611 
01612 end:
01613     HeapFree(GetProcessHeap(), 0, nl_boundary);
01614     HeapFree(GetProcessHeap(), 0, buf);
01615     return hr;
01616 }
01617 
01618 static body_t *create_sub_body(MimeMessage *msg, IStream *pStm, BODYOFFSETS *offset, body_t *parent)
01619 {
01620     IMimeBody *mime_body;
01621     HRESULT hr;
01622     body_t *body;
01623     ULARGE_INTEGER cur;
01624     LARGE_INTEGER zero;
01625 
01626     MimeBody_create(NULL, (void**)&mime_body);
01627     IMimeBody_Load(mime_body, pStm);
01628     zero.QuadPart = 0;
01629     hr = IStream_Seek(pStm, zero, STREAM_SEEK_CUR, &cur);
01630     offset->cbBodyStart = cur.u.LowPart + offset->cbHeaderStart;
01631     if(parent) MimeBody_set_offsets(impl_from_IMimeBody(mime_body), offset);
01632     IMimeBody_SetData(mime_body, IET_BINARY, NULL, NULL, &IID_IStream, pStm);
01633     body = new_body_entry(mime_body, msg->next_index++, parent);
01634 
01635     if(IMimeBody_IsContentType(mime_body, "multipart", NULL) == S_OK)
01636     {
01637         MIMEPARAMINFO *param_info;
01638         ULONG count, i;
01639         IMimeAllocator *alloc;
01640 
01641         hr = IMimeBody_GetParameters(mime_body, "Content-Type", &count, &param_info);
01642         if(hr != S_OK || count == 0) return body;
01643 
01644         MimeOleGetAllocator(&alloc);
01645 
01646         for(i = 0; i < count; i++)
01647         {
01648             if(!strcasecmp(param_info[i].pszName, "boundary"))
01649             {
01650                 struct list offset_list;
01651                 offset_entry_t *cur, *cursor2;
01652                 hr = create_body_offset_list(pStm, param_info[i].pszData, &offset_list);
01653                 LIST_FOR_EACH_ENTRY_SAFE(cur, cursor2, &offset_list, offset_entry_t, entry)
01654                 {
01655                     body_t *sub_body;
01656                     IStream *sub_stream;
01657                     ULARGE_INTEGER start, length;
01658 
01659                     start.QuadPart = cur->offsets.cbHeaderStart;
01660                     length.QuadPart = cur->offsets.cbBodyEnd - cur->offsets.cbHeaderStart;
01661                     create_sub_stream(pStm, start, length, &sub_stream);
01662                     sub_body = create_sub_body(msg, sub_stream, &cur->offsets, body);
01663                     IStream_Release(sub_stream);
01664                     list_add_tail(&body->children, &sub_body->entry);
01665                     list_remove(&cur->entry);
01666                     HeapFree(GetProcessHeap(), 0, cur);
01667                 }
01668                 break;
01669             }
01670         }
01671         IMimeAllocator_FreeParamInfoArray(alloc, count, param_info, TRUE);
01672         IMimeAllocator_Release(alloc);
01673     }
01674     return body;
01675 }
01676 
01677 static HRESULT WINAPI MimeMessage_Load(
01678     IMimeMessage *iface,
01679     LPSTREAM pStm)
01680 {
01681     MimeMessage *This = (MimeMessage *)iface;
01682     body_t *root_body;
01683     BODYOFFSETS offsets;
01684     ULARGE_INTEGER cur;
01685     LARGE_INTEGER zero;
01686 
01687     TRACE("(%p)->(%p)\n", iface, pStm);
01688 
01689     if(This->stream)
01690     {
01691         FIXME("already loaded a message\n");
01692         return E_FAIL;
01693     }
01694 
01695     IStream_AddRef(pStm);
01696     This->stream = pStm;
01697     offsets.cbBoundaryStart = offsets.cbHeaderStart = 0;
01698     offsets.cbBodyStart = offsets.cbBodyEnd = 0;
01699 
01700     root_body = create_sub_body(This, pStm, &offsets, NULL);
01701 
01702     zero.QuadPart = 0;
01703     IStream_Seek(pStm, zero, STREAM_SEEK_END, &cur);
01704     offsets.cbBodyEnd = cur.u.LowPart;
01705     MimeBody_set_offsets(impl_from_IMimeBody(root_body->mime_body), &offsets);
01706 
01707     list_add_head(&This->body_tree, &root_body->entry);
01708 
01709     return S_OK;
01710 }
01711 
01712 static HRESULT WINAPI MimeMessage_Save(
01713     IMimeMessage *iface,
01714     LPSTREAM pStm,
01715     BOOL fClearDirty)
01716 {
01717     FIXME("(%p)->(%p, %s)\n", iface, pStm, fClearDirty ? "TRUE" : "FALSE");
01718     return E_NOTIMPL;
01719 }
01720 
01721 static HRESULT WINAPI MimeMessage_GetSizeMax(
01722     IMimeMessage *iface,
01723     ULARGE_INTEGER *pcbSize)
01724 {
01725     FIXME("(%p)->(%p)\n", iface, pcbSize);
01726     return E_NOTIMPL;
01727 }
01728 
01729 static HRESULT WINAPI MimeMessage_InitNew(
01730     IMimeMessage *iface)
01731 {
01732     FIXME("(%p)->()\n", iface);
01733     return E_NOTIMPL;
01734 }
01735 
01736 /*** IMimeMessageTree methods ***/
01737 static HRESULT WINAPI MimeMessage_GetMessageSource(
01738     IMimeMessage *iface,
01739     IStream **ppStream,
01740     DWORD dwFlags)
01741 {
01742     MimeMessage *This = (MimeMessage *)iface;
01743     FIXME("(%p)->(%p, 0x%x)\n", iface, ppStream, dwFlags);
01744 
01745     IStream_AddRef(This->stream);
01746     *ppStream = This->stream;
01747     return S_OK;
01748 }
01749 
01750 static HRESULT WINAPI MimeMessage_GetMessageSize(
01751     IMimeMessage *iface,
01752     ULONG *pcbSize,
01753     DWORD dwFlags)
01754 {
01755     FIXME("(%p)->(%p, 0x%x)\n", iface, pcbSize, dwFlags);
01756     return E_NOTIMPL;
01757 }
01758 
01759 static HRESULT WINAPI MimeMessage_LoadOffsetTable(
01760     IMimeMessage *iface,
01761     IStream *pStream)
01762 {
01763     FIXME("(%p)->(%p)\n", iface, pStream);
01764     return E_NOTIMPL;
01765 }
01766 
01767 static HRESULT WINAPI MimeMessage_SaveOffsetTable(
01768     IMimeMessage *iface,
01769     IStream *pStream,
01770     DWORD dwFlags)
01771 {
01772     FIXME("(%p)->(%p, 0x%x)\n", iface, pStream, dwFlags);
01773     return E_NOTIMPL;
01774 }
01775 
01776 
01777 static HRESULT WINAPI MimeMessage_GetFlags(
01778     IMimeMessage *iface,
01779     DWORD *pdwFlags)
01780 {
01781     FIXME("(%p)->(%p)\n", iface, pdwFlags);
01782     return E_NOTIMPL;
01783 }
01784 
01785 static HRESULT WINAPI MimeMessage_Commit(
01786     IMimeMessage *iface,
01787     DWORD dwFlags)
01788 {
01789     FIXME("(%p)->(0x%x)\n", iface, dwFlags);
01790     return E_NOTIMPL;
01791 }
01792 
01793 
01794 static HRESULT WINAPI MimeMessage_HandsOffStorage(
01795     IMimeMessage *iface)
01796 {
01797     FIXME("(%p)->()\n", iface);
01798     return E_NOTIMPL;
01799 }
01800 
01801 static HRESULT find_body(struct list *list, HBODY hbody, body_t **body)
01802 {
01803     body_t *cur;
01804     HRESULT hr;
01805 
01806     if(hbody == HBODY_ROOT)
01807     {
01808         *body = LIST_ENTRY(list_head(list), body_t, entry);
01809         return S_OK;
01810     }
01811 
01812     LIST_FOR_EACH_ENTRY(cur, list, body_t, entry)
01813     {
01814         if(cur->index == HandleToUlong(hbody))
01815         {
01816             *body = cur;
01817             return S_OK;
01818         }
01819         hr = find_body(&cur->children, hbody, body);
01820         if(hr == S_OK) return S_OK;
01821     }
01822     return S_FALSE;
01823 }
01824 
01825 static HRESULT WINAPI MimeMessage_BindToObject(
01826     IMimeMessage *iface,
01827     const HBODY hBody,
01828     REFIID riid,
01829     void **ppvObject)
01830 {
01831     MimeMessage *This = (MimeMessage *)iface;
01832     HRESULT hr;
01833     body_t *body;
01834 
01835     TRACE("(%p)->(%p, %s, %p)\n", iface, hBody, debugstr_guid(riid), ppvObject);
01836 
01837     hr = find_body(&This->body_tree, hBody, &body);
01838 
01839     if(hr != S_OK) return hr;
01840 
01841     if(IsEqualIID(riid, &IID_IMimeBody))
01842     {
01843         IMimeBody_AddRef(body->mime_body);
01844         *ppvObject = body->mime_body;
01845         return S_OK;
01846     }
01847 
01848     return E_NOINTERFACE;
01849 }
01850 
01851 static HRESULT WINAPI MimeMessage_SaveBody(
01852     IMimeMessage *iface,
01853     HBODY hBody,
01854     DWORD dwFlags,
01855     IStream *pStream)
01856 {
01857     FIXME("(%p)->(%p, 0x%x, %p)\n", iface, hBody, dwFlags, pStream);
01858     return E_NOTIMPL;
01859 }
01860 
01861 static HRESULT get_body(MimeMessage *msg, BODYLOCATION location, HBODY pivot, body_t **out)
01862 {
01863     body_t *root = LIST_ENTRY(list_head(&msg->body_tree), body_t, entry);
01864     body_t *body;
01865     HRESULT hr;
01866     struct list *list;
01867 
01868     if(location == IBL_ROOT)
01869     {
01870         *out = root;
01871         return S_OK;
01872     }
01873 
01874     hr = find_body(&msg->body_tree, pivot, &body);
01875 
01876     if(hr == S_OK)
01877     {
01878         switch(location)
01879         {
01880         case IBL_PARENT:
01881             *out = body->parent;
01882             break;
01883 
01884         case IBL_FIRST:
01885             list = list_head(&body->children);
01886             if(list)
01887                 *out = LIST_ENTRY(list, body_t, entry);
01888             else
01889                 hr = MIME_E_NOT_FOUND;
01890             break;
01891 
01892         case IBL_LAST:
01893             list = list_tail(&body->children);
01894             if(list)
01895                 *out = LIST_ENTRY(list, body_t, entry);
01896             else
01897                 hr = MIME_E_NOT_FOUND;
01898             break;
01899 
01900         case IBL_NEXT:
01901             list = list_next(&body->parent->children, &body->entry);
01902             if(list)
01903                 *out = LIST_ENTRY(list, body_t, entry);
01904             else
01905                 hr = MIME_E_NOT_FOUND;
01906             break;
01907 
01908         case IBL_PREVIOUS:
01909             list = list_prev(&body->parent->children, &body->entry);
01910             if(list)
01911                 *out = LIST_ENTRY(list, body_t, entry);
01912             else
01913                 hr = MIME_E_NOT_FOUND;
01914             break;
01915 
01916         default:
01917             hr = E_FAIL;
01918             break;
01919         }
01920     }
01921 
01922     return hr;
01923 }
01924 
01925 
01926 static HRESULT WINAPI MimeMessage_InsertBody(
01927     IMimeMessage *iface,
01928     BODYLOCATION location,
01929     HBODY hPivot,
01930     LPHBODY phBody)
01931 {
01932     FIXME("(%p)->(%d, %p, %p)\n", iface, location, hPivot, phBody);
01933     return E_NOTIMPL;
01934 }
01935 
01936 static HRESULT WINAPI MimeMessage_GetBody(
01937     IMimeMessage *iface,
01938     BODYLOCATION location,
01939     HBODY hPivot,
01940     LPHBODY phBody)
01941 {
01942     MimeMessage *This = (MimeMessage *)iface;
01943     body_t *body;
01944     HRESULT hr;
01945 
01946     TRACE("(%p)->(%d, %p, %p)\n", iface, location, hPivot, phBody);
01947 
01948     hr = get_body(This, location, hPivot, &body);
01949 
01950     if(hr == S_OK) *phBody = UlongToHandle(body->index);
01951 
01952     return hr;
01953 }
01954 
01955 static HRESULT WINAPI MimeMessage_DeleteBody(
01956     IMimeMessage *iface,
01957     HBODY hBody,
01958     DWORD dwFlags)
01959 {
01960     FIXME("(%p)->(%p, %08x)\n", iface, hBody, dwFlags);
01961     return E_NOTIMPL;
01962 }
01963 
01964 static HRESULT WINAPI MimeMessage_MoveBody(
01965     IMimeMessage *iface,
01966     HBODY hBody,
01967     BODYLOCATION location)
01968 {
01969     FIXME("(%p)->(%d)\n", iface, location);
01970     return E_NOTIMPL;
01971 }
01972 
01973 static void count_children(body_t *body, boolean recurse, ULONG *count)
01974 {
01975     body_t *child;
01976 
01977     LIST_FOR_EACH_ENTRY(child, &body->children, body_t, entry)
01978     {
01979         (*count)++;
01980         if(recurse) count_children(child, recurse, count);
01981     }
01982 }
01983 
01984 static HRESULT WINAPI MimeMessage_CountBodies(
01985     IMimeMessage *iface,
01986     HBODY hParent,
01987     boolean fRecurse,
01988     ULONG *pcBodies)
01989 {
01990     HRESULT hr;
01991     MimeMessage *This = (MimeMessage *)iface;
01992     body_t *body;
01993 
01994     TRACE("(%p)->(%p, %s, %p)\n", iface, hParent, fRecurse ? "TRUE" : "FALSE", pcBodies);
01995 
01996     hr = find_body(&This->body_tree, hParent, &body);
01997     if(hr != S_OK) return hr;
01998 
01999     *pcBodies = 1;
02000     count_children(body, fRecurse, pcBodies);
02001 
02002     return S_OK;
02003 }
02004 
02005 static HRESULT find_next(IMimeMessage *msg, body_t *body, LPFINDBODY find, HBODY *out)
02006 {
02007     MimeMessage *This = (MimeMessage *)msg;
02008     struct list *ptr;
02009     HBODY next;
02010 
02011     for (;;)
02012     {
02013         if (!body) ptr = list_head( &This->body_tree );
02014         else
02015         {
02016             ptr = list_head( &body->children );
02017             while (!ptr)
02018             {
02019                 if (!body->parent) return MIME_E_NOT_FOUND;
02020                 if (!(ptr = list_next( &body->parent->children, &body->entry ))) body = body->parent;
02021             }
02022         }
02023 
02024         body = LIST_ENTRY( ptr, body_t, entry );
02025         next = UlongToHandle( body->index );
02026         find->dwReserved = body->index;
02027         if (IMimeBody_IsContentType(body->mime_body, find->pszPriType, find->pszSubType) == S_OK)
02028         {
02029             *out = next;
02030             return S_OK;
02031         }
02032     }
02033     return MIME_E_NOT_FOUND;
02034 }
02035 
02036 static HRESULT WINAPI MimeMessage_FindFirst(
02037     IMimeMessage *iface,
02038     LPFINDBODY pFindBody,
02039     LPHBODY phBody)
02040 {
02041     TRACE("(%p)->(%p, %p)\n", iface, pFindBody, phBody);
02042 
02043     pFindBody->dwReserved = 0;
02044     return find_next( iface, NULL, pFindBody, phBody );
02045 }
02046 
02047 static HRESULT WINAPI MimeMessage_FindNext(
02048     IMimeMessage *iface,
02049     LPFINDBODY pFindBody,
02050     LPHBODY phBody)
02051 {
02052     MimeMessage *This = (MimeMessage *)iface;
02053     body_t *body;
02054     HRESULT hr;
02055 
02056     TRACE("(%p)->(%p, %p)\n", iface, pFindBody, phBody);
02057 
02058     hr = find_body( &This->body_tree, UlongToHandle( pFindBody->dwReserved ), &body );
02059     if (hr != S_OK) return MIME_E_NOT_FOUND;
02060     return find_next( iface, body, pFindBody, phBody );
02061 }
02062 
02063 static HRESULT WINAPI MimeMessage_ResolveURL(
02064     IMimeMessage *iface,
02065     HBODY hRelated,
02066     LPCSTR pszBase,
02067     LPCSTR pszURL,
02068     DWORD dwFlags,
02069     LPHBODY phBody)
02070 {
02071     FIXME("(%p)->(%p, %s, %s, 0x%x, %p)\n", iface, hRelated, pszBase, pszURL, dwFlags, phBody);
02072     return E_NOTIMPL;
02073 }
02074 
02075 static HRESULT WINAPI MimeMessage_ToMultipart(
02076     IMimeMessage *iface,
02077     HBODY hBody,
02078     LPCSTR pszSubType,
02079     LPHBODY phMultipart)
02080 {
02081     FIXME("(%p)->(%p, %s, %p)\n", iface, hBody, pszSubType, phMultipart);
02082     return E_NOTIMPL;
02083 }
02084 
02085 static HRESULT WINAPI MimeMessage_GetBodyOffsets(
02086     IMimeMessage *iface,
02087     HBODY hBody,
02088     LPBODYOFFSETS pOffsets)
02089 {
02090     FIXME("(%p)->(%p, %p)\n", iface, hBody, pOffsets);
02091     return E_NOTIMPL;
02092 }
02093 
02094 static HRESULT WINAPI MimeMessage_GetCharset(
02095     IMimeMessage *iface,
02096     LPHCHARSET phCharset)
02097 {
02098     FIXME("(%p)->(%p)\n", iface, phCharset);
02099     *phCharset = NULL;
02100     return S_OK;
02101 }
02102 
02103 static HRESULT WINAPI MimeMessage_SetCharset(
02104     IMimeMessage *iface,
02105     HCHARSET hCharset,
02106     CSETAPPLYTYPE applytype)
02107 {
02108     FIXME("(%p)->(%p, %d)\n", iface, hCharset, applytype);
02109     return E_NOTIMPL;
02110 }
02111 
02112 static HRESULT WINAPI MimeMessage_IsBodyType(
02113     IMimeMessage *iface,
02114     HBODY hBody,
02115     IMSGBODYTYPE bodytype)
02116 {
02117     HRESULT hr;
02118     IMimeBody *mime_body;
02119     TRACE("(%p)->(%p, %d)\n", iface, hBody, bodytype);
02120 
02121     hr = IMimeMessage_BindToObject(iface, hBody, &IID_IMimeBody, (void**)&mime_body);
02122     if(hr != S_OK) return hr;
02123 
02124     hr = IMimeBody_IsType(mime_body, bodytype);
02125     MimeBody_Release(mime_body);
02126     return hr;
02127 }
02128 
02129 static HRESULT WINAPI MimeMessage_IsContentType(
02130     IMimeMessage *iface,
02131     HBODY hBody,
02132     LPCSTR pszPriType,
02133     LPCSTR pszSubType)
02134 {
02135     HRESULT hr;
02136     IMimeBody *mime_body;
02137     TRACE("(%p)->(%p, %s, %s)\n", iface, hBody, debugstr_a(pszPriType),
02138           debugstr_a(pszSubType));
02139 
02140     hr = IMimeMessage_BindToObject(iface, hBody, &IID_IMimeBody, (void**)&mime_body);
02141     if(FAILED(hr)) return hr;
02142 
02143     hr = IMimeBody_IsContentType(mime_body, pszPriType, pszSubType);
02144     IMimeBody_Release(mime_body);
02145     return hr;
02146 }
02147 
02148 static HRESULT WINAPI MimeMessage_QueryBodyProp(
02149     IMimeMessage *iface,
02150     HBODY hBody,
02151     LPCSTR pszName,
02152     LPCSTR pszCriteria,
02153     boolean fSubString,
02154     boolean fCaseSensitive)
02155 {
02156     FIXME("(%p)->(%p, %s, %s, %s, %s)\n", iface, hBody, pszName, pszCriteria, fSubString ? "TRUE" : "FALSE", fCaseSensitive ? "TRUE" : "FALSE");
02157     return E_NOTIMPL;
02158 }
02159 
02160 static HRESULT WINAPI MimeMessage_GetBodyProp(
02161     IMimeMessage *iface,
02162     HBODY hBody,
02163     LPCSTR pszName,
02164     DWORD dwFlags,
02165     LPPROPVARIANT pValue)
02166 {
02167     HRESULT hr;
02168     IMimeBody *mime_body;
02169 
02170     TRACE("(%p)->(%p, %s, 0x%x, %p)\n", iface, hBody, pszName, dwFlags, pValue);
02171 
02172     hr = IMimeMessage_BindToObject(iface, hBody, &IID_IMimeBody, (void**)&mime_body);
02173     if(hr != S_OK) return hr;
02174 
02175     hr = IMimeBody_GetProp(mime_body, pszName, dwFlags, pValue);
02176     IMimeBody_Release(mime_body);
02177 
02178     return hr;
02179 }
02180 
02181 static HRESULT WINAPI MimeMessage_SetBodyProp(
02182     IMimeMessage *iface,
02183     HBODY hBody,
02184     LPCSTR pszName,
02185     DWORD dwFlags,
02186     LPCPROPVARIANT pValue)
02187 {
02188     FIXME("(%p)->(%p, %s, 0x%x, %p)\n", iface, hBody, pszName, dwFlags, pValue);
02189     return E_NOTIMPL;
02190 }
02191 
02192 static HRESULT WINAPI MimeMessage_DeleteBodyProp(
02193     IMimeMessage *iface,
02194     HBODY hBody,
02195     LPCSTR pszName)
02196 {
02197     FIXME("(%p)->(%p, %s)\n", iface, hBody, pszName);
02198     return E_NOTIMPL;
02199 }
02200 
02201 static HRESULT WINAPI MimeMessage_SetOption(
02202     IMimeMessage *iface,
02203     const TYPEDID oid,
02204     LPCPROPVARIANT pValue)
02205 {
02206     HRESULT hr = E_NOTIMPL;
02207     TRACE("(%p)->(%08x, %p)\n", iface, oid, pValue);
02208 
02209     if(pValue->vt != TYPEDID_TYPE(oid))
02210     {
02211         WARN("Called with vartype %04x and oid %08x\n", pValue->vt, oid);
02212         return E_INVALIDARG;
02213     }
02214 
02215     switch(oid)
02216     {
02217     case OID_HIDE_TNEF_ATTACHMENTS:
02218         FIXME("OID_HIDE_TNEF_ATTACHMENTS (value %d): ignoring\n", pValue->u.boolVal);
02219         hr = S_OK;
02220         break;
02221     case OID_SHOW_MACBINARY:
02222         FIXME("OID_SHOW_MACBINARY (value %d): ignoring\n", pValue->u.boolVal);
02223         hr = S_OK;
02224         break;
02225     default:
02226         FIXME("Unhandled oid %08x\n", oid);
02227     }
02228 
02229     return hr;
02230 }
02231 
02232 static HRESULT WINAPI MimeMessage_GetOption(
02233     IMimeMessage *iface,
02234     const TYPEDID oid,
02235     LPPROPVARIANT pValue)
02236 {
02237     FIXME("(%p)->(%08x, %p)\n", iface, oid, pValue);
02238     return E_NOTIMPL;
02239 }
02240 
02241 /*** IMimeMessage methods ***/
02242 static HRESULT WINAPI MimeMessage_CreateWebPage(
02243     IMimeMessage *iface,
02244     IStream *pRootStm,
02245     LPWEBPAGEOPTIONS pOptions,
02246     IMimeMessageCallback *pCallback,
02247     IMoniker **ppMoniker)
02248 {
02249     FIXME("(%p)->(%p, %p, %p, %p)\n", iface, pRootStm, pOptions, pCallback, ppMoniker);
02250     *ppMoniker = NULL;
02251     return E_NOTIMPL;
02252 }
02253 
02254 static HRESULT WINAPI MimeMessage_GetProp(
02255     IMimeMessage *iface,
02256     LPCSTR pszName,
02257     DWORD dwFlags,
02258     LPPROPVARIANT pValue)
02259 {
02260     FIXME("(%p)->(%s, 0x%x, %p)\n", iface, pszName, dwFlags, pValue);
02261     return E_NOTIMPL;
02262 }
02263 
02264 static HRESULT WINAPI MimeMessage_SetProp(
02265     IMimeMessage *iface,
02266     LPCSTR pszName,
02267     DWORD dwFlags,
02268     LPCPROPVARIANT pValue)
02269 {
02270     FIXME("(%p)->(%s, 0x%x, %p)\n", iface, pszName, dwFlags, pValue);
02271     return E_NOTIMPL;
02272 }
02273 
02274 static HRESULT WINAPI MimeMessage_DeleteProp(
02275     IMimeMessage *iface,
02276     LPCSTR pszName)
02277 {
02278     FIXME("(%p)->(%s)\n", iface, pszName);
02279     return E_NOTIMPL;
02280 }
02281 
02282 static HRESULT WINAPI MimeMessage_QueryProp(
02283     IMimeMessage *iface,
02284     LPCSTR pszName,
02285     LPCSTR pszCriteria,
02286     boolean fSubString,
02287     boolean fCaseSensitive)
02288 {
02289     FIXME("(%p)->(%s, %s, %s, %s)\n", iface, pszName, pszCriteria, fSubString ? "TRUE" : "FALSE", fCaseSensitive ? "TRUE" : "FALSE");
02290     return E_NOTIMPL;
02291 }
02292 
02293 static HRESULT WINAPI MimeMessage_GetTextBody(
02294     IMimeMessage *iface,
02295     DWORD dwTxtType,
02296     ENCODINGTYPE ietEncoding,
02297     IStream **pStream,
02298     LPHBODY phBody)
02299 {
02300     HRESULT hr;
02301     HBODY hbody;
02302     FINDBODY find_struct;
02303     IMimeBody *mime_body;
02304     static char text[] = "text";
02305     static char plain[] = "plain";
02306     static char html[] = "html";
02307 
02308     TRACE("(%p)->(%d, %d, %p, %p)\n", iface, dwTxtType, ietEncoding, pStream, phBody);
02309 
02310     find_struct.pszPriType = text;
02311 
02312     switch(dwTxtType)
02313     {
02314     case TXT_PLAIN:
02315         find_struct.pszSubType = plain;
02316         break;
02317     case TXT_HTML:
02318         find_struct.pszSubType = html;
02319         break;
02320     default:
02321         return MIME_E_INVALID_TEXT_TYPE;
02322     }
02323 
02324     hr = IMimeMessage_FindFirst(iface, &find_struct, &hbody);
02325     if(hr != S_OK)
02326     {
02327         TRACE("not found hr %08x\n", hr);
02328         *phBody = NULL;
02329         return hr;
02330     }
02331 
02332     IMimeMessage_BindToObject(iface, hbody, &IID_IMimeBody, (void**)&mime_body);
02333 
02334     IMimeBody_GetData(mime_body, ietEncoding, pStream);
02335     *phBody = hbody;
02336     IMimeBody_Release(mime_body);
02337     return hr;
02338 }
02339 
02340 static HRESULT WINAPI MimeMessage_SetTextBody(
02341     IMimeMessage *iface,
02342     DWORD dwTxtType,
02343     ENCODINGTYPE ietEncoding,
02344     HBODY hAlternative,
02345     IStream *pStream,
02346     LPHBODY phBody)
02347 {
02348     FIXME("(%p)->(%d, %d, %p, %p, %p)\n", iface, dwTxtType, ietEncoding, hAlternative, pStream, phBody);
02349     return E_NOTIMPL;
02350 }
02351 
02352 static HRESULT WINAPI MimeMessage_AttachObject(
02353     IMimeMessage *iface,
02354     REFIID riid,
02355     void *pvObject,
02356     LPHBODY phBody)
02357 {
02358     FIXME("(%p)->(%s, %p, %p)\n", iface, debugstr_guid(riid), pvObject, phBody);
02359     return E_NOTIMPL;
02360 }
02361 
02362 static HRESULT WINAPI MimeMessage_AttachFile(
02363     IMimeMessage *iface,
02364     LPCSTR pszFilePath,
02365     IStream *pstmFile,
02366     LPHBODY phBody)
02367 {
02368     FIXME("(%p)->(%s, %p, %p)\n", iface, pszFilePath, pstmFile, phBody);
02369     return E_NOTIMPL;
02370 }
02371 
02372 static HRESULT WINAPI MimeMessage_AttachURL(
02373     IMimeMessage *iface,
02374     LPCSTR pszBase,
02375     LPCSTR pszURL,
02376     DWORD dwFlags,
02377     IStream *pstmURL,
02378     LPSTR *ppszCIDURL,
02379     LPHBODY phBody)
02380 {
02381     FIXME("(%p)->(%s, %s, 0x%x, %p, %p, %p)\n", iface, pszBase, pszURL, dwFlags, pstmURL, ppszCIDURL, phBody);
02382     return E_NOTIMPL;
02383 }
02384 
02385 static HRESULT WINAPI MimeMessage_GetAttachments(
02386     IMimeMessage *iface,
02387     ULONG *pcAttach,
02388     LPHBODY *pprghAttach)
02389 {
02390     HRESULT hr;
02391     FINDBODY find_struct;
02392     HBODY hbody;
02393     LPHBODY array;
02394     ULONG size = 10;
02395 
02396     TRACE("(%p)->(%p, %p)\n", iface, pcAttach, pprghAttach);
02397 
02398     *pcAttach = 0;
02399     array = CoTaskMemAlloc(size * sizeof(HBODY));
02400 
02401     find_struct.pszPriType = find_struct.pszSubType = NULL;
02402     hr = IMimeMessage_FindFirst(iface, &find_struct, &hbody);
02403     while(hr == S_OK)
02404     {
02405         hr = IMimeMessage_IsContentType(iface, hbody, "multipart", NULL);
02406         TRACE("IsCT rets %08x %d\n", hr, *pcAttach);
02407         if(hr != S_OK)
02408         {
02409             if(*pcAttach + 1 > size)
02410             {
02411                 size *= 2;
02412                 array = CoTaskMemRealloc(array, size * sizeof(HBODY));
02413             }
02414             array[*pcAttach] = hbody;
02415             (*pcAttach)++;
02416         }
02417         hr = IMimeMessage_FindNext(iface, &find_struct, &hbody);
02418     }
02419 
02420     *pprghAttach = array;
02421     return S_OK;
02422 }
02423 
02424 static HRESULT WINAPI MimeMessage_GetAddressTable(
02425     IMimeMessage *iface,
02426     IMimeAddressTable **ppTable)
02427 {
02428     FIXME("(%p)->(%p)\n", iface, ppTable);
02429     return E_NOTIMPL;
02430 }
02431 
02432 static HRESULT WINAPI MimeMessage_GetSender(
02433     IMimeMessage *iface,
02434     LPADDRESSPROPS pAddress)
02435 {
02436     FIXME("(%p)->(%p)\n", iface, pAddress);
02437     return E_NOTIMPL;
02438 }
02439 
02440 static HRESULT WINAPI MimeMessage_GetAddressTypes(
02441     IMimeMessage *iface,
02442     DWORD dwAdrTypes,
02443     DWORD dwProps,
02444     LPADDRESSLIST pList)
02445 {
02446     FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, dwProps, pList);
02447     return E_NOTIMPL;
02448 }
02449 
02450 static HRESULT WINAPI MimeMessage_GetAddressFormat(
02451     IMimeMessage *iface,
02452     DWORD dwAdrTypes,
02453     ADDRESSFORMAT format,
02454     LPSTR *ppszFormat)
02455 {
02456     FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, format, ppszFormat);
02457     return E_NOTIMPL;
02458 }
02459 
02460 static HRESULT WINAPI MimeMessage_EnumAddressTypes(
02461     IMimeMessage *iface,
02462     DWORD dwAdrTypes,
02463     DWORD dwProps,
02464     IMimeEnumAddressTypes **ppEnum)
02465 {
02466     FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, dwProps, ppEnum);
02467     return E_NOTIMPL;
02468 }
02469 
02470 static HRESULT WINAPI MimeMessage_SplitMessage(
02471     IMimeMessage *iface,
02472     ULONG cbMaxPart,
02473     IMimeMessageParts **ppParts)
02474 {
02475     FIXME("(%p)->(%d, %p)\n", iface, cbMaxPart, ppParts);
02476     return E_NOTIMPL;
02477 }
02478 
02479 static HRESULT WINAPI MimeMessage_GetRootMoniker(
02480     IMimeMessage *iface,
02481     IMoniker **ppMoniker)
02482 {
02483     FIXME("(%p)->(%p)\n", iface, ppMoniker);
02484     return E_NOTIMPL;
02485 }
02486 
02487 static const IMimeMessageVtbl MimeMessageVtbl =
02488 {
02489     MimeMessage_QueryInterface,
02490     MimeMessage_AddRef,
02491     MimeMessage_Release,
02492     MimeMessage_GetClassID,
02493     MimeMessage_IsDirty,
02494     MimeMessage_Load,
02495     MimeMessage_Save,
02496     MimeMessage_GetSizeMax,
02497     MimeMessage_InitNew,
02498     MimeMessage_GetMessageSource,
02499     MimeMessage_GetMessageSize,
02500     MimeMessage_LoadOffsetTable,
02501     MimeMessage_SaveOffsetTable,
02502     MimeMessage_GetFlags,
02503     MimeMessage_Commit,
02504     MimeMessage_HandsOffStorage,
02505     MimeMessage_BindToObject,
02506     MimeMessage_SaveBody,
02507     MimeMessage_InsertBody,
02508     MimeMessage_GetBody,
02509     MimeMessage_DeleteBody,
02510     MimeMessage_MoveBody,
02511     MimeMessage_CountBodies,
02512     MimeMessage_FindFirst,
02513     MimeMessage_FindNext,
02514     MimeMessage_ResolveURL,
02515     MimeMessage_ToMultipart,
02516     MimeMessage_GetBodyOffsets,
02517     MimeMessage_GetCharset,
02518     MimeMessage_SetCharset,
02519     MimeMessage_IsBodyType,
02520     MimeMessage_IsContentType,
02521     MimeMessage_QueryBodyProp,
02522     MimeMessage_GetBodyProp,
02523     MimeMessage_SetBodyProp,
02524     MimeMessage_DeleteBodyProp,
02525     MimeMessage_SetOption,
02526     MimeMessage_GetOption,
02527     MimeMessage_CreateWebPage,
02528     MimeMessage_GetProp,
02529     MimeMessage_SetProp,
02530     MimeMessage_DeleteProp,
02531     MimeMessage_QueryProp,
02532     MimeMessage_GetTextBody,
02533     MimeMessage_SetTextBody,
02534     MimeMessage_AttachObject,
02535     MimeMessage_AttachFile,
02536     MimeMessage_AttachURL,
02537     MimeMessage_GetAttachments,
02538     MimeMessage_GetAddressTable,
02539     MimeMessage_GetSender,
02540     MimeMessage_GetAddressTypes,
02541     MimeMessage_GetAddressFormat,
02542     MimeMessage_EnumAddressTypes,
02543     MimeMessage_SplitMessage,
02544     MimeMessage_GetRootMoniker,
02545 };
02546 
02547 HRESULT MimeMessage_create(IUnknown *outer, void **obj)
02548 {
02549     MimeMessage *This;
02550 
02551     TRACE("(%p, %p)\n", outer, obj);
02552 
02553     if (outer)
02554     {
02555         FIXME("outer unknown not supported yet\n");
02556         return E_NOTIMPL;
02557     }
02558 
02559     *obj = NULL;
02560 
02561     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
02562     if (!This) return E_OUTOFMEMORY;
02563 
02564     This->lpVtbl = &MimeMessageVtbl;
02565     This->refs = 1;
02566     This->stream = NULL;
02567     list_init(&This->body_tree);
02568     This->next_index = 1;
02569 
02570     *obj = &This->lpVtbl;
02571     return S_OK;
02572 }
02573 
02574 /***********************************************************************
02575  *              MimeOleCreateMessage (INETCOMM.@)
02576  */
02577 HRESULT WINAPI MimeOleCreateMessage(IUnknown *pUnkOuter, IMimeMessage **ppMessage)
02578 {
02579     TRACE("(%p, %p)\n", pUnkOuter, ppMessage);
02580     return MimeMessage_create(NULL, (void **)ppMessage);
02581 }
02582 
02583 /***********************************************************************
02584  *              MimeOleSetCompatMode (INETCOMM.@)
02585  */
02586 HRESULT WINAPI MimeOleSetCompatMode(DWORD dwMode)
02587 {
02588     FIXME("(0x%x)\n", dwMode);
02589     return S_OK;
02590 }
02591 
02592 /***********************************************************************
02593  *              MimeOleCreateVirtualStream (INETCOMM.@)
02594  */
02595 HRESULT WINAPI MimeOleCreateVirtualStream(IStream **ppStream)
02596 {
02597     HRESULT hr;
02598     FIXME("(%p)\n", ppStream);
02599 
02600     hr = CreateStreamOnHGlobal(NULL, TRUE, ppStream);
02601     return hr;
02602 }
02603 
02604 typedef struct MimeSecurity
02605 {
02606     const IMimeSecurityVtbl *lpVtbl;
02607 
02608     LONG refs;
02609 } MimeSecurity;
02610 
02611 static HRESULT WINAPI MimeSecurity_QueryInterface(
02612         IMimeSecurity* iface,
02613         REFIID riid,
02614         void** obj)
02615 {
02616     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), obj);
02617 
02618     if (IsEqualIID(riid, &IID_IUnknown) ||
02619         IsEqualIID(riid, &IID_IMimeSecurity))
02620     {
02621         *obj = iface;
02622         IUnknown_AddRef(iface);
02623         return S_OK;
02624     }
02625 
02626     FIXME("no interface for %s\n", debugstr_guid(riid));
02627     *obj = NULL;
02628     return E_NOINTERFACE;
02629 }
02630 
02631 static ULONG WINAPI MimeSecurity_AddRef(
02632         IMimeSecurity* iface)
02633 {
02634     MimeSecurity *This = (MimeSecurity *)iface;
02635     TRACE("(%p)->()\n", iface);
02636     return InterlockedIncrement(&This->refs);
02637 }
02638 
02639 static ULONG WINAPI MimeSecurity_Release(
02640         IMimeSecurity* iface)
02641 {
02642     MimeSecurity *This = (MimeSecurity *)iface;
02643     ULONG refs;
02644 
02645     TRACE("(%p)->()\n", iface);
02646 
02647     refs = InterlockedDecrement(&This->refs);
02648     if (!refs)
02649     {
02650         HeapFree(GetProcessHeap(), 0, This);
02651     }
02652 
02653     return refs;
02654 }
02655 
02656 static HRESULT WINAPI MimeSecurity_InitNew(
02657         IMimeSecurity* iface)
02658 {
02659     FIXME("(%p)->(): stub\n", iface);
02660     return S_OK;
02661 }
02662 
02663 static HRESULT WINAPI MimeSecurity_CheckInit(
02664         IMimeSecurity* iface)
02665 {
02666     FIXME("(%p)->(): stub\n", iface);
02667     return E_NOTIMPL;
02668 }
02669 
02670 static HRESULT WINAPI MimeSecurity_EncodeMessage(
02671         IMimeSecurity* iface,
02672         IMimeMessageTree* pTree,
02673         DWORD dwFlags)
02674 {
02675     FIXME("(%p)->(%p, %08x): stub\n", iface, pTree, dwFlags);
02676     return E_NOTIMPL;
02677 }
02678 
02679 static HRESULT WINAPI MimeSecurity_EncodeBody(
02680         IMimeSecurity* iface,
02681         IMimeMessageTree* pTree,
02682         HBODY hEncodeRoot,
02683         DWORD dwFlags)
02684 {
02685     FIXME("(%p)->(%p, %p, %08x): stub\n", iface, pTree, hEncodeRoot, dwFlags);
02686     return E_NOTIMPL;
02687 }
02688 
02689 static HRESULT WINAPI MimeSecurity_DecodeMessage(
02690         IMimeSecurity* iface,
02691         IMimeMessageTree* pTree,
02692         DWORD dwFlags)
02693 {
02694     FIXME("(%p)->(%p, %08x): stub\n", iface, pTree, dwFlags);
02695     return E_NOTIMPL;
02696 }
02697 
02698 static HRESULT WINAPI MimeSecurity_DecodeBody(
02699         IMimeSecurity* iface,
02700         IMimeMessageTree* pTree,
02701         HBODY hDecodeRoot,
02702         DWORD dwFlags)
02703 {
02704     FIXME("(%p)->(%p, %p, %08x): stub\n", iface, pTree, hDecodeRoot, dwFlags);
02705     return E_NOTIMPL;
02706 }
02707 
02708 static HRESULT WINAPI MimeSecurity_EnumCertificates(
02709         IMimeSecurity* iface,
02710         HCAPICERTSTORE hc,
02711         DWORD dwUsage,
02712         PCX509CERT pPrev,
02713         PCX509CERT* ppCert)
02714 {
02715     FIXME("(%p)->(%p, %08x, %p, %p): stub\n", iface, hc, dwUsage, pPrev, ppCert);
02716     return E_NOTIMPL;
02717 }
02718 
02719 static HRESULT WINAPI MimeSecurity_GetCertificateName(
02720         IMimeSecurity* iface,
02721         const PCX509CERT pX509Cert,
02722         const CERTNAMETYPE cn,
02723         LPSTR* ppszName)
02724 {
02725     FIXME("(%p)->(%p, %08x, %p): stub\n", iface, pX509Cert, cn, ppszName);
02726     return E_NOTIMPL;
02727 }
02728 
02729 static HRESULT WINAPI MimeSecurity_GetMessageType(
02730         IMimeSecurity* iface,
02731         const HWND hwndParent,
02732         IMimeBody* pBody,
02733         DWORD* pdwSecType)
02734 {
02735     FIXME("(%p)->(%p, %p, %p): stub\n", iface, hwndParent, pBody, pdwSecType);
02736     return E_NOTIMPL;
02737 }
02738 
02739 static HRESULT WINAPI MimeSecurity_GetCertData(
02740         IMimeSecurity* iface,
02741         const PCX509CERT pX509Cert,
02742         const CERTDATAID dataid,
02743         LPPROPVARIANT pValue)
02744 {
02745     FIXME("(%p)->(%p, %x, %p): stub\n", iface, pX509Cert, dataid, pValue);
02746     return E_NOTIMPL;
02747 }
02748 
02749 
02750 static const IMimeSecurityVtbl MimeSecurityVtbl =
02751 {
02752     MimeSecurity_QueryInterface,
02753     MimeSecurity_AddRef,
02754     MimeSecurity_Release,
02755     MimeSecurity_InitNew,
02756     MimeSecurity_CheckInit,
02757     MimeSecurity_EncodeMessage,
02758     MimeSecurity_EncodeBody,
02759     MimeSecurity_DecodeMessage,
02760     MimeSecurity_DecodeBody,
02761     MimeSecurity_EnumCertificates,
02762     MimeSecurity_GetCertificateName,
02763     MimeSecurity_GetMessageType,
02764     MimeSecurity_GetCertData
02765 };
02766 
02767 HRESULT MimeSecurity_create(IUnknown *outer, void **obj)
02768 {
02769     MimeSecurity *This;
02770 
02771     *obj = NULL;
02772 
02773     if (outer) return CLASS_E_NOAGGREGATION;
02774 
02775     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
02776     if (!This) return E_OUTOFMEMORY;
02777 
02778     This->lpVtbl = &MimeSecurityVtbl;
02779     This->refs = 1;
02780 
02781     *obj = &This->lpVtbl;
02782     return S_OK;
02783 }
02784 
02785 /***********************************************************************
02786  *              MimeOleCreateSecurity (INETCOMM.@)
02787  */
02788 HRESULT WINAPI MimeOleCreateSecurity(IMimeSecurity **ppSecurity)
02789 {
02790     return MimeSecurity_create(NULL, (void **)ppSecurity);
02791 }
02792 
02793 typedef struct
02794 {
02795     IMimeAllocatorVtbl *lpVtbl;
02796 } MimeAllocator;
02797 
02798 static HRESULT WINAPI MimeAlloc_QueryInterface(
02799         IMimeAllocator* iface,
02800         REFIID riid,
02801         void **obj)
02802 {
02803     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), obj);
02804 
02805     if (IsEqualIID(riid, &IID_IUnknown) ||
02806         IsEqualIID(riid, &IID_IMalloc) ||
02807         IsEqualIID(riid, &IID_IMimeAllocator))
02808     {
02809         *obj = iface;
02810         IUnknown_AddRef(iface);
02811         return S_OK;
02812     }
02813 
02814     FIXME("no interface for %s\n", debugstr_guid(riid));
02815     *obj = NULL;
02816     return E_NOINTERFACE;
02817 }
02818 
02819 static ULONG WINAPI MimeAlloc_AddRef(
02820         IMimeAllocator* iface)
02821 {
02822     return 2;
02823 }
02824 
02825 static ULONG WINAPI MimeAlloc_Release(
02826         IMimeAllocator* iface)
02827 {
02828     return 1;
02829 }
02830 
02831 static LPVOID WINAPI MimeAlloc_Alloc(
02832         IMimeAllocator* iface,
02833         ULONG cb)
02834 {
02835     return CoTaskMemAlloc(cb);
02836 }
02837 
02838 static LPVOID WINAPI MimeAlloc_Realloc(
02839         IMimeAllocator* iface,
02840         LPVOID pv,
02841         ULONG cb)
02842 {
02843     return CoTaskMemRealloc(pv, cb);
02844 }
02845 
02846 static void WINAPI MimeAlloc_Free(
02847         IMimeAllocator* iface,
02848         LPVOID pv)
02849 {
02850     CoTaskMemFree(pv);
02851 }
02852 
02853 static ULONG WINAPI MimeAlloc_GetSize(
02854         IMimeAllocator* iface,
02855         LPVOID pv)
02856 {
02857     FIXME("stub\n");
02858     return 0;
02859 }
02860 
02861 static int WINAPI MimeAlloc_DidAlloc(
02862         IMimeAllocator* iface,
02863         LPVOID pv)
02864 {
02865     FIXME("stub\n");
02866     return 0;
02867 }
02868 
02869 static void WINAPI MimeAlloc_HeapMinimize(
02870         IMimeAllocator* iface)
02871 {
02872     FIXME("stub\n");
02873     return;
02874 }
02875 
02876 static HRESULT WINAPI MimeAlloc_FreeParamInfoArray(
02877         IMimeAllocator* iface,
02878         ULONG cParams,
02879         LPMIMEPARAMINFO prgParam,
02880         boolean fFreeArray)
02881 {
02882     ULONG i;
02883     TRACE("(%p)->(%d, %p, %d)\n", iface, cParams, prgParam, fFreeArray);
02884 
02885     for(i = 0; i < cParams; i++)
02886     {
02887         IMimeAllocator_Free(iface, prgParam[i].pszName);
02888         IMimeAllocator_Free(iface, prgParam[i].pszData);
02889     }
02890     if(fFreeArray) IMimeAllocator_Free(iface, prgParam);
02891     return S_OK;
02892 }
02893 
02894 static HRESULT WINAPI MimeAlloc_FreeAddressList(
02895         IMimeAllocator* iface,
02896         LPADDRESSLIST pList)
02897 {
02898     FIXME("stub\n");
02899     return E_NOTIMPL;
02900 }
02901 
02902 static HRESULT WINAPI MimeAlloc_FreeAddressProps(
02903         IMimeAllocator* iface,
02904         LPADDRESSPROPS pAddress)
02905 {
02906     FIXME("stub\n");
02907     return E_NOTIMPL;
02908 }
02909 
02910 static HRESULT WINAPI MimeAlloc_ReleaseObjects(
02911         IMimeAllocator* iface,
02912         ULONG cObjects,
02913         IUnknown **prgpUnknown,
02914         boolean fFreeArray)
02915 {
02916     FIXME("stub\n");
02917     return E_NOTIMPL;
02918 }
02919 
02920 
02921 static HRESULT WINAPI MimeAlloc_FreeEnumHeaderRowArray(
02922         IMimeAllocator* iface,
02923         ULONG cRows,
02924         LPENUMHEADERROW prgRow,
02925         boolean fFreeArray)
02926 {
02927     FIXME("stub\n");
02928     return E_NOTIMPL;
02929 }
02930 
02931 static HRESULT WINAPI MimeAlloc_FreeEnumPropertyArray(
02932         IMimeAllocator* iface,
02933         ULONG cProps,
02934         LPENUMPROPERTY prgProp,
02935         boolean fFreeArray)
02936 {
02937     FIXME("stub\n");
02938     return E_NOTIMPL;
02939 }
02940 
02941 static HRESULT WINAPI MimeAlloc_FreeThumbprint(
02942         IMimeAllocator* iface,
02943         THUMBBLOB *pthumbprint)
02944 {
02945     FIXME("stub\n");
02946     return E_NOTIMPL;
02947 }
02948 
02949 
02950 static HRESULT WINAPI MimeAlloc_PropVariantClear(
02951         IMimeAllocator* iface,
02952         LPPROPVARIANT pProp)
02953 {
02954     FIXME("stub\n");
02955     return E_NOTIMPL;
02956 }
02957 
02958 static IMimeAllocatorVtbl mime_alloc_vtbl =
02959 {
02960     MimeAlloc_QueryInterface,
02961     MimeAlloc_AddRef,
02962     MimeAlloc_Release,
02963     MimeAlloc_Alloc,
02964     MimeAlloc_Realloc,
02965     MimeAlloc_Free,
02966     MimeAlloc_GetSize,
02967     MimeAlloc_DidAlloc,
02968     MimeAlloc_HeapMinimize,
02969     MimeAlloc_FreeParamInfoArray,
02970     MimeAlloc_FreeAddressList,
02971     MimeAlloc_FreeAddressProps,
02972     MimeAlloc_ReleaseObjects,
02973     MimeAlloc_FreeEnumHeaderRowArray,
02974     MimeAlloc_FreeEnumPropertyArray,
02975     MimeAlloc_FreeThumbprint,
02976     MimeAlloc_PropVariantClear
02977 };
02978 
02979 static MimeAllocator mime_allocator =
02980 {
02981     &mime_alloc_vtbl
02982 };
02983 
02984 HRESULT MimeAllocator_create(IUnknown *outer, void **obj)
02985 {
02986     if(outer) return CLASS_E_NOAGGREGATION;
02987 
02988     *obj = &mime_allocator;
02989     return S_OK;
02990 }
02991 
02992 HRESULT WINAPI MimeOleGetAllocator(IMimeAllocator **alloc)
02993 {
02994     return MimeAllocator_create(NULL, (void**)alloc);
02995 }
02996 
02997 HRESULT VirtualStream_create(IUnknown *outer, void **obj)
02998 {
02999     FIXME("(%p, %p)\n", outer, obj);
03000 
03001     *obj = NULL;
03002     if (outer) return CLASS_E_NOAGGREGATION;
03003 
03004     return MimeOleCreateVirtualStream((IStream **)obj);
03005 }

Generated on Thu May 24 2012 04:24:28 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.