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

Information | Donate

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

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

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

ReactOS Development > Doxygen

mimeintl.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 doxygen 1.7.6.1

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