Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmimeintl.c
Go to the documentation of this file.
00001 /* 00002 * MIME OLE International interface 00003 * 00004 * Copyright 2008 Huw Davies for CodeWeavers 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #define COBJMACROS 00022 #define NONAMELESSUNION 00023 00024 #include <stdarg.h> 00025 #include <stdio.h> 00026 00027 #include "windef.h" 00028 #include "winbase.h" 00029 #include "winuser.h" 00030 #include "winnls.h" 00031 #include "objbase.h" 00032 #include "ole2.h" 00033 #include "mimeole.h" 00034 #include "mlang.h" 00035 00036 #include "wine/list.h" 00037 #include "wine/unicode.h" 00038 #include "wine/debug.h" 00039 00040 #include "inetcomm_private.h" 00041 00042 WINE_DEFAULT_DEBUG_CHANNEL(inetcomm); 00043 00044 typedef struct 00045 { 00046 struct list entry; 00047 INETCSETINFO cs_info; 00048 } charset_entry; 00049 00050 typedef struct 00051 { 00052 IMimeInternational IMimeInternational_iface; 00053 LONG refs; 00054 CRITICAL_SECTION cs; 00055 00056 struct list charsets; 00057 LONG next_charset_handle; 00058 HCHARSET default_charset; 00059 } internat_impl; 00060 00061 static inline internat_impl *impl_from_IMimeInternational(IMimeInternational *iface) 00062 { 00063 return CONTAINING_RECORD(iface, internat_impl, IMimeInternational_iface); 00064 } 00065 00066 static inline HRESULT get_mlang(IMultiLanguage **ml) 00067 { 00068 return CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, 00069 &IID_IMultiLanguage, (void **)ml); 00070 } 00071 00072 static HRESULT WINAPI MimeInternat_QueryInterface( IMimeInternational *iface, REFIID riid, LPVOID *ppobj ) 00073 { 00074 if (IsEqualGUID(riid, &IID_IUnknown) || 00075 IsEqualGUID(riid, &IID_IMimeInternational)) 00076 { 00077 IMimeInternational_AddRef( iface ); 00078 *ppobj = iface; 00079 return S_OK; 00080 } 00081 00082 FIXME("interface %s not implemented\n", debugstr_guid(riid)); 00083 return E_NOINTERFACE; 00084 } 00085 00086 static ULONG WINAPI MimeInternat_AddRef( IMimeInternational *iface ) 00087 { 00088 internat_impl *This = impl_from_IMimeInternational( iface ); 00089 return InterlockedIncrement(&This->refs); 00090 } 00091 00092 static ULONG WINAPI MimeInternat_Release( IMimeInternational *iface ) 00093 { 00094 internat_impl *This = impl_from_IMimeInternational( iface ); 00095 ULONG refs; 00096 00097 refs = InterlockedDecrement(&This->refs); 00098 if (!refs) 00099 { 00100 charset_entry *charset, *cursor2; 00101 00102 LIST_FOR_EACH_ENTRY_SAFE(charset, cursor2, &This->charsets, charset_entry, entry) 00103 { 00104 list_remove(&charset->entry); 00105 HeapFree(GetProcessHeap(), 0, charset); 00106 } 00107 This->cs.DebugInfo->Spare[0] = 0; 00108 DeleteCriticalSection(&This->cs); 00109 HeapFree(GetProcessHeap(), 0, This); 00110 } 00111 00112 return refs; 00113 } 00114 00115 static HRESULT WINAPI MimeInternat_SetDefaultCharset(IMimeInternational *iface, HCHARSET hCharset) 00116 { 00117 internat_impl *This = impl_from_IMimeInternational( iface ); 00118 00119 TRACE("(%p)->(%p)\n", iface, hCharset); 00120 00121 if(hCharset == NULL) return E_INVALIDARG; 00122 /* FIXME check hCharset is valid */ 00123 00124 InterlockedExchangePointer(&This->default_charset, hCharset); 00125 00126 return S_OK; 00127 } 00128 00129 static HRESULT WINAPI MimeInternat_GetDefaultCharset(IMimeInternational *iface, LPHCHARSET phCharset) 00130 { 00131 internat_impl *This = impl_from_IMimeInternational( iface ); 00132 HRESULT hr = S_OK; 00133 00134 TRACE("(%p)->(%p)\n", iface, phCharset); 00135 00136 if(This->default_charset == NULL) 00137 { 00138 HCHARSET hcs; 00139 hr = IMimeInternational_GetCodePageCharset(iface, GetACP(), CHARSET_BODY, &hcs); 00140 if(SUCCEEDED(hr)) 00141 InterlockedCompareExchangePointer(&This->default_charset, hcs, NULL); 00142 } 00143 *phCharset = This->default_charset; 00144 00145 return hr; 00146 } 00147 00148 static HRESULT mlang_getcodepageinfo(UINT cp, MIMECPINFO *mlang_cp_info) 00149 { 00150 HRESULT hr; 00151 IMultiLanguage *ml; 00152 00153 hr = get_mlang(&ml); 00154 00155 if(SUCCEEDED(hr)) 00156 { 00157 hr = IMultiLanguage_GetCodePageInfo(ml, cp, mlang_cp_info); 00158 IMultiLanguage_Release(ml); 00159 } 00160 return hr; 00161 } 00162 00163 static HRESULT WINAPI MimeInternat_GetCodePageCharset(IMimeInternational *iface, CODEPAGEID cpiCodePage, 00164 CHARSETTYPE ctCsetType, 00165 LPHCHARSET phCharset) 00166 { 00167 HRESULT hr; 00168 MIMECPINFO mlang_cp_info; 00169 00170 TRACE("(%p)->(%d, %d, %p)\n", iface, cpiCodePage, ctCsetType, phCharset); 00171 00172 *phCharset = NULL; 00173 00174 hr = mlang_getcodepageinfo(cpiCodePage, &mlang_cp_info); 00175 if(SUCCEEDED(hr)) 00176 { 00177 const WCHAR *charset_nameW = NULL; 00178 char *charset_name; 00179 DWORD len; 00180 00181 switch(ctCsetType) 00182 { 00183 case CHARSET_BODY: 00184 charset_nameW = mlang_cp_info.wszBodyCharset; 00185 break; 00186 case CHARSET_HEADER: 00187 charset_nameW = mlang_cp_info.wszHeaderCharset; 00188 break; 00189 case CHARSET_WEB: 00190 charset_nameW = mlang_cp_info.wszWebCharset; 00191 break; 00192 default: 00193 return MIME_E_INVALID_CHARSET_TYPE; 00194 } 00195 len = WideCharToMultiByte(CP_ACP, 0, charset_nameW, -1, NULL, 0, NULL, NULL); 00196 charset_name = HeapAlloc(GetProcessHeap(), 0, len); 00197 WideCharToMultiByte(CP_ACP, 0, charset_nameW, -1, charset_name, len, NULL, NULL); 00198 hr = IMimeInternational_FindCharset(iface, charset_name, phCharset); 00199 HeapFree(GetProcessHeap(), 0, charset_name); 00200 } 00201 return hr; 00202 } 00203 00204 static HRESULT mlang_getcsetinfo(const char *charset, MIMECSETINFO *mlang_info) 00205 { 00206 DWORD len = MultiByteToWideChar(CP_ACP, 0, charset, -1, NULL, 0); 00207 BSTR bstr = SysAllocStringLen(NULL, len - 1); 00208 HRESULT hr; 00209 IMultiLanguage *ml; 00210 00211 MultiByteToWideChar(CP_ACP, 0, charset, -1, bstr, len); 00212 00213 hr = get_mlang(&ml); 00214 00215 if(SUCCEEDED(hr)) 00216 { 00217 hr = IMultiLanguage_GetCharsetInfo(ml, bstr, mlang_info); 00218 IMultiLanguage_Release(ml); 00219 } 00220 SysFreeString(bstr); 00221 if(FAILED(hr)) hr = MIME_E_NOT_FOUND; 00222 return hr; 00223 } 00224 00225 static HCHARSET add_charset(struct list *list, MIMECSETINFO *mlang_info, HCHARSET handle) 00226 { 00227 charset_entry *charset = HeapAlloc(GetProcessHeap(), 0, sizeof(*charset)); 00228 00229 WideCharToMultiByte(CP_ACP, 0, mlang_info->wszCharset, -1, 00230 charset->cs_info.szName, sizeof(charset->cs_info.szName), NULL, NULL); 00231 charset->cs_info.cpiWindows = mlang_info->uiCodePage; 00232 charset->cs_info.cpiInternet = mlang_info->uiInternetEncoding; 00233 charset->cs_info.hCharset = handle; 00234 charset->cs_info.dwReserved1 = 0; 00235 list_add_head(list, &charset->entry); 00236 00237 return charset->cs_info.hCharset; 00238 } 00239 00240 static HRESULT WINAPI MimeInternat_FindCharset(IMimeInternational *iface, LPCSTR pszCharset, 00241 LPHCHARSET phCharset) 00242 { 00243 internat_impl *This = impl_from_IMimeInternational( iface ); 00244 HRESULT hr = MIME_E_NOT_FOUND; 00245 charset_entry *charset; 00246 00247 TRACE("(%p)->(%s, %p)\n", iface, debugstr_a(pszCharset), phCharset); 00248 00249 *phCharset = NULL; 00250 00251 EnterCriticalSection(&This->cs); 00252 00253 LIST_FOR_EACH_ENTRY(charset, &This->charsets, charset_entry, entry) 00254 { 00255 if(!lstrcmpiA(charset->cs_info.szName, pszCharset)) 00256 { 00257 *phCharset = charset->cs_info.hCharset; 00258 hr = S_OK; 00259 break; 00260 } 00261 } 00262 00263 if(hr == MIME_E_NOT_FOUND) 00264 { 00265 MIMECSETINFO mlang_info; 00266 00267 LeaveCriticalSection(&This->cs); 00268 hr = mlang_getcsetinfo(pszCharset, &mlang_info); 00269 EnterCriticalSection(&This->cs); 00270 00271 if(SUCCEEDED(hr)) 00272 *phCharset = add_charset(&This->charsets, &mlang_info, 00273 UlongToHandle(InterlockedIncrement(&This->next_charset_handle))); 00274 } 00275 00276 LeaveCriticalSection(&This->cs); 00277 return hr; 00278 } 00279 00280 static HRESULT WINAPI MimeInternat_GetCharsetInfo(IMimeInternational *iface, HCHARSET hCharset, 00281 LPINETCSETINFO pCsetInfo) 00282 { 00283 internat_impl *This = impl_from_IMimeInternational( iface ); 00284 HRESULT hr = MIME_E_INVALID_HANDLE; 00285 charset_entry *charset; 00286 00287 TRACE("(%p)->(%p, %p)\n", iface, hCharset, pCsetInfo); 00288 00289 EnterCriticalSection(&This->cs); 00290 00291 LIST_FOR_EACH_ENTRY(charset, &This->charsets, charset_entry, entry) 00292 { 00293 if(charset->cs_info.hCharset == hCharset) 00294 { 00295 *pCsetInfo = charset->cs_info; 00296 hr = S_OK; 00297 break; 00298 } 00299 } 00300 00301 LeaveCriticalSection(&This->cs); 00302 00303 return hr; 00304 } 00305 00306 static HRESULT WINAPI MimeInternat_GetCodePageInfo(IMimeInternational *iface, CODEPAGEID cpiCodePage, 00307 LPCODEPAGEINFO pCodePageInfo) 00308 { 00309 FIXME("stub\n"); 00310 return E_NOTIMPL; 00311 } 00312 00313 static HRESULT WINAPI MimeInternat_CanConvertCodePages(IMimeInternational *iface, CODEPAGEID cpiSource, 00314 CODEPAGEID cpiDest) 00315 { 00316 HRESULT hr; 00317 IMultiLanguage *ml; 00318 00319 TRACE("(%p)->(%d, %d)\n", iface, cpiSource, cpiDest); 00320 00321 /* Could call mlang.IsConvertINetStringAvailable() to avoid the COM overhead if need be. */ 00322 00323 hr = get_mlang(&ml); 00324 if(SUCCEEDED(hr)) 00325 { 00326 hr = IMultiLanguage_IsConvertible(ml, cpiSource, cpiDest); 00327 IMultiLanguage_Release(ml); 00328 } 00329 00330 return hr; 00331 } 00332 00333 static HRESULT WINAPI MimeInternat_DecodeHeader(IMimeInternational *iface, HCHARSET hCharset, 00334 LPCSTR pszData, 00335 LPPROPVARIANT pDecoded, 00336 LPRFC1522INFO pRfc1522Info) 00337 { 00338 FIXME("stub\n"); 00339 return E_NOTIMPL; 00340 } 00341 00342 static HRESULT WINAPI MimeInternat_EncodeHeader(IMimeInternational *iface, HCHARSET hCharset, 00343 LPPROPVARIANT pData, 00344 LPSTR *ppszEncoded, 00345 LPRFC1522INFO pRfc1522Info) 00346 { 00347 FIXME("stub\n"); 00348 return E_NOTIMPL; 00349 } 00350 00351 static HRESULT WINAPI MimeInternat_ConvertBuffer(IMimeInternational *iface, CODEPAGEID cpiSource, 00352 CODEPAGEID cpiDest, LPBLOB pIn, LPBLOB pOut, 00353 ULONG *pcbRead) 00354 { 00355 HRESULT hr; 00356 IMultiLanguage *ml; 00357 00358 TRACE("(%p)->(%d, %d, %p, %p, %p)\n", iface, cpiSource, cpiDest, pIn, pOut, pcbRead); 00359 00360 *pcbRead = 0; 00361 pOut->cbSize = 0; 00362 00363 /* Could call mlang.ConvertINetString() to avoid the COM overhead if need be. */ 00364 00365 hr = get_mlang(&ml); 00366 if(SUCCEEDED(hr)) 00367 { 00368 DWORD mode = 0; 00369 UINT in_size = pIn->cbSize, out_size; 00370 00371 hr = IMultiLanguage_ConvertString(ml, &mode, cpiSource, cpiDest, pIn->pBlobData, &in_size, 00372 NULL, &out_size); 00373 if(hr == S_OK) /* S_FALSE means the conversion could not be performed */ 00374 { 00375 pOut->pBlobData = CoTaskMemAlloc(out_size); 00376 if(!pOut->pBlobData) 00377 hr = E_OUTOFMEMORY; 00378 else 00379 { 00380 mode = 0; 00381 in_size = pIn->cbSize; 00382 hr = IMultiLanguage_ConvertString(ml, &mode, cpiSource, cpiDest, pIn->pBlobData, &in_size, 00383 pOut->pBlobData, &out_size); 00384 00385 if(hr == S_OK) 00386 { 00387 *pcbRead = in_size; 00388 pOut->cbSize = out_size; 00389 } 00390 else 00391 CoTaskMemFree(pOut->pBlobData); 00392 } 00393 } 00394 IMultiLanguage_Release(ml); 00395 } 00396 00397 return hr; 00398 } 00399 00400 static HRESULT WINAPI MimeInternat_ConvertString(IMimeInternational *iface, CODEPAGEID cpiSource, 00401 CODEPAGEID cpiDest, LPPROPVARIANT pIn, 00402 LPPROPVARIANT pOut) 00403 { 00404 HRESULT hr; 00405 int src_len; 00406 IMultiLanguage *ml; 00407 00408 TRACE("(%p)->(%d, %d, %p %p)\n", iface, cpiSource, cpiDest, pIn, pOut); 00409 00410 switch(pIn->vt) 00411 { 00412 case VT_LPSTR: 00413 if(cpiSource == CP_UNICODE) cpiSource = GetACP(); 00414 src_len = strlen(pIn->u.pszVal); 00415 break; 00416 case VT_LPWSTR: 00417 cpiSource = CP_UNICODE; 00418 src_len = strlenW(pIn->u.pwszVal) * sizeof(WCHAR); 00419 break; 00420 default: 00421 return E_INVALIDARG; 00422 } 00423 00424 hr = get_mlang(&ml); 00425 if(SUCCEEDED(hr)) 00426 { 00427 DWORD mode = 0; 00428 UINT in_size = src_len, out_size; 00429 00430 hr = IMultiLanguage_ConvertString(ml, &mode, cpiSource, cpiDest, (BYTE*)pIn->u.pszVal, &in_size, 00431 NULL, &out_size); 00432 if(hr == S_OK) /* S_FALSE means the conversion could not be performed */ 00433 { 00434 out_size += (cpiDest == CP_UNICODE) ? sizeof(WCHAR) : sizeof(char); 00435 00436 pOut->u.pszVal = CoTaskMemAlloc(out_size); 00437 if(!pOut->u.pszVal) 00438 hr = E_OUTOFMEMORY; 00439 else 00440 { 00441 mode = 0; 00442 in_size = src_len; 00443 hr = IMultiLanguage_ConvertString(ml, &mode, cpiSource, cpiDest, (BYTE*)pIn->u.pszVal, &in_size, 00444 (BYTE*)pOut->u.pszVal, &out_size); 00445 00446 if(hr == S_OK) 00447 { 00448 if(cpiDest == CP_UNICODE) 00449 { 00450 pOut->u.pwszVal[out_size / sizeof(WCHAR)] = 0; 00451 pOut->vt = VT_LPWSTR; 00452 } 00453 else 00454 { 00455 pOut->u.pszVal[out_size] = '\0'; 00456 pOut->vt = VT_LPSTR; 00457 } 00458 } 00459 else 00460 CoTaskMemFree(pOut->u.pszVal); 00461 } 00462 } 00463 IMultiLanguage_Release(ml); 00464 } 00465 return hr; 00466 } 00467 00468 static HRESULT WINAPI MimeInternat_MLANG_ConvertInetReset(IMimeInternational *iface) 00469 { 00470 FIXME("stub\n"); 00471 return E_NOTIMPL; 00472 } 00473 00474 static HRESULT WINAPI MimeInternat_MLANG_ConvertInetString(IMimeInternational *iface, CODEPAGEID cpiSource, 00475 CODEPAGEID cpiDest, 00476 LPCSTR pSource, 00477 int *pnSizeOfSource, 00478 LPSTR pDestination, 00479 int *pnDstSize) 00480 { 00481 FIXME("stub\n"); 00482 return E_NOTIMPL; 00483 } 00484 00485 static HRESULT WINAPI MimeInternat_Rfc1522Decode(IMimeInternational *iface, LPCSTR pszValue, 00486 LPSTR pszCharset, 00487 ULONG cchmax, 00488 LPSTR *ppszDecoded) 00489 { 00490 FIXME("stub\n"); 00491 return E_NOTIMPL; 00492 } 00493 00494 static HRESULT WINAPI MimeInternat_Rfc1522Encode(IMimeInternational *iface, LPCSTR pszValue, 00495 HCHARSET hCharset, 00496 LPSTR *ppszEncoded) 00497 { 00498 FIXME("stub\n"); 00499 return E_NOTIMPL; 00500 } 00501 00502 static IMimeInternationalVtbl mime_internat_vtbl = 00503 { 00504 MimeInternat_QueryInterface, 00505 MimeInternat_AddRef, 00506 MimeInternat_Release, 00507 MimeInternat_SetDefaultCharset, 00508 MimeInternat_GetDefaultCharset, 00509 MimeInternat_GetCodePageCharset, 00510 MimeInternat_FindCharset, 00511 MimeInternat_GetCharsetInfo, 00512 MimeInternat_GetCodePageInfo, 00513 MimeInternat_CanConvertCodePages, 00514 MimeInternat_DecodeHeader, 00515 MimeInternat_EncodeHeader, 00516 MimeInternat_ConvertBuffer, 00517 MimeInternat_ConvertString, 00518 MimeInternat_MLANG_ConvertInetReset, 00519 MimeInternat_MLANG_ConvertInetString, 00520 MimeInternat_Rfc1522Decode, 00521 MimeInternat_Rfc1522Encode 00522 }; 00523 00524 static internat_impl *global_internat; 00525 00526 HRESULT MimeInternational_Construct(IMimeInternational **internat) 00527 { 00528 global_internat = HeapAlloc(GetProcessHeap(), 0, sizeof(*global_internat)); 00529 global_internat->IMimeInternational_iface.lpVtbl = &mime_internat_vtbl; 00530 global_internat->refs = 0; 00531 InitializeCriticalSection(&global_internat->cs); 00532 global_internat->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": global_internat.cs"); 00533 00534 list_init(&global_internat->charsets); 00535 global_internat->next_charset_handle = 0; 00536 global_internat->default_charset = NULL; 00537 00538 *internat = &global_internat->IMimeInternational_iface; 00539 00540 IMimeInternational_AddRef(*internat); 00541 return S_OK; 00542 } 00543 00544 HRESULT WINAPI MimeOleGetInternat(IMimeInternational **internat) 00545 { 00546 TRACE("(%p)\n", internat); 00547 00548 *internat = &global_internat->IMimeInternational_iface; 00549 IMimeInternational_AddRef(*internat); 00550 return S_OK; 00551 } 00552 00553 HRESULT WINAPI MimeOleFindCharset(LPCSTR name, LPHCHARSET charset) 00554 { 00555 IMimeInternational *internat; 00556 HRESULT hr; 00557 00558 TRACE("(%s, %p)\n", debugstr_a(name), charset); 00559 00560 hr = MimeOleGetInternat(&internat); 00561 if(SUCCEEDED(hr)) 00562 { 00563 hr = IMimeInternational_FindCharset(internat, name, charset); 00564 IMimeInternational_Release(internat); 00565 } 00566 return hr; 00567 } 00568 00569 HRESULT WINAPI MimeOleGetCharsetInfo(HCHARSET hCharset, LPINETCSETINFO pCsetInfo) 00570 { 00571 IMimeInternational *internat; 00572 HRESULT hr; 00573 00574 TRACE("(%p, %p)\n", hCharset, pCsetInfo); 00575 00576 hr = MimeOleGetInternat(&internat); 00577 if(SUCCEEDED(hr)) 00578 { 00579 hr = IMimeInternational_GetCharsetInfo(internat, hCharset, pCsetInfo); 00580 IMimeInternational_Release(internat); 00581 } 00582 return hr; 00583 } 00584 00585 HRESULT WINAPI MimeOleGetDefaultCharset(LPHCHARSET charset) 00586 { 00587 IMimeInternational *internat; 00588 HRESULT hr; 00589 00590 TRACE("(%p)\n", charset); 00591 00592 hr = MimeOleGetInternat(&internat); 00593 if(SUCCEEDED(hr)) 00594 { 00595 hr = IMimeInternational_GetDefaultCharset(internat, charset); 00596 IMimeInternational_Release(internat); 00597 } 00598 return hr; 00599 } Generated on Fri May 25 2012 04:22:07 for ReactOS by
1.7.6.1
|