Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmimeole.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, ¶m->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(¶m->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, ¶m_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
1.7.6.1
|