2 * MIME OLE International interface
4 * Copyright 2008 Huw Davies for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define NONAMELESSUNION
36 #include "wine/list.h"
37 #include "wine/debug.h"
39 #include "inetcomm_private.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(inetcomm
);
51 const IMimeInternationalVtbl
*lpVtbl
;
56 LONG next_charset_handle
;
57 HCHARSET default_charset
;
60 static inline internat
*impl_from_IMimeInternational( IMimeInternational
*iface
)
62 return (internat
*)((char*)iface
- FIELD_OFFSET(internat
, lpVtbl
));
65 static inline HRESULT
get_mlang(IMultiLanguage
**ml
)
67 return CoCreateInstance(&CLSID_CMultiLanguage
, NULL
, CLSCTX_INPROC_SERVER
| CLSCTX_INPROC_HANDLER
,
68 &IID_IMultiLanguage
, (void **)ml
);
71 static HRESULT WINAPI
MimeInternat_QueryInterface( IMimeInternational
*iface
, REFIID riid
, LPVOID
*ppobj
)
73 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
74 IsEqualGUID(riid
, &IID_IMimeInternational
))
76 IMimeInternational_AddRef( iface
);
81 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
85 static ULONG WINAPI
MimeInternat_AddRef( IMimeInternational
*iface
)
87 internat
*This
= impl_from_IMimeInternational( iface
);
88 return InterlockedIncrement(&This
->refs
);
91 static ULONG WINAPI
MimeInternat_Release( IMimeInternational
*iface
)
93 internat
*This
= impl_from_IMimeInternational( iface
);
96 refs
= InterlockedDecrement(&This
->refs
);
99 charset_entry
*charset
, *cursor2
;
101 LIST_FOR_EACH_ENTRY_SAFE(charset
, cursor2
, &This
->charsets
, charset_entry
, entry
)
103 list_remove(&charset
->entry
);
104 HeapFree(GetProcessHeap(), 0, charset
);
106 HeapFree(GetProcessHeap(), 0, This
);
112 static HRESULT WINAPI
MimeInternat_SetDefaultCharset(IMimeInternational
*iface
, HCHARSET hCharset
)
114 internat
*This
= impl_from_IMimeInternational( iface
);
116 TRACE("(%p)->(%p)\n", iface
, hCharset
);
118 if(hCharset
== NULL
) return E_INVALIDARG
;
119 /* FIXME check hCharset is valid */
121 InterlockedExchangePointer(&This
->default_charset
, hCharset
);
126 static HRESULT WINAPI
MimeInternat_GetDefaultCharset(IMimeInternational
*iface
, LPHCHARSET phCharset
)
128 internat
*This
= impl_from_IMimeInternational( iface
);
131 TRACE("(%p)->(%p)\n", iface
, phCharset
);
133 if(This
->default_charset
== NULL
)
136 hr
= IMimeInternational_GetCodePageCharset(iface
, GetACP(), CHARSET_BODY
, &hcs
);
138 InterlockedCompareExchangePointer(&This
->default_charset
, hcs
, NULL
);
140 *phCharset
= This
->default_charset
;
145 static HRESULT
mlang_getcodepageinfo(UINT cp
, MIMECPINFO
*mlang_cp_info
)
154 hr
= IMultiLanguage_GetCodePageInfo(ml
, cp
, mlang_cp_info
);
155 IMultiLanguage_Release(ml
);
160 static HRESULT WINAPI
MimeInternat_GetCodePageCharset(IMimeInternational
*iface
, CODEPAGEID cpiCodePage
,
161 CHARSETTYPE ctCsetType
,
162 LPHCHARSET phCharset
)
165 MIMECPINFO mlang_cp_info
;
167 TRACE("(%p)->(%d, %d, %p)\n", iface
, cpiCodePage
, ctCsetType
, phCharset
);
171 hr
= mlang_getcodepageinfo(cpiCodePage
, &mlang_cp_info
);
174 const WCHAR
*charset_nameW
= NULL
;
181 charset_nameW
= mlang_cp_info
.wszBodyCharset
;
184 charset_nameW
= mlang_cp_info
.wszHeaderCharset
;
187 charset_nameW
= mlang_cp_info
.wszWebCharset
;
190 return MIME_E_INVALID_CHARSET_TYPE
;
192 len
= WideCharToMultiByte(CP_ACP
, 0, charset_nameW
, -1, NULL
, 0, NULL
, NULL
);
193 charset_name
= HeapAlloc(GetProcessHeap(), 0, len
);
194 WideCharToMultiByte(CP_ACP
, 0, charset_nameW
, -1, charset_name
, len
, NULL
, NULL
);
195 hr
= IMimeInternational_FindCharset(iface
, charset_name
, phCharset
);
196 HeapFree(GetProcessHeap(), 0, charset_name
);
201 static HRESULT
mlang_getcsetinfo(const char *charset
, MIMECSETINFO
*mlang_info
)
203 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, charset
, -1, NULL
, 0);
204 BSTR bstr
= SysAllocStringLen(NULL
, len
- 1);
208 MultiByteToWideChar(CP_ACP
, 0, charset
, -1, bstr
, len
);
214 hr
= IMultiLanguage_GetCharsetInfo(ml
, bstr
, mlang_info
);
215 IMultiLanguage_Release(ml
);
218 if(FAILED(hr
)) hr
= MIME_E_NOT_FOUND
;
222 static HCHARSET
add_charset(struct list
*list
, MIMECSETINFO
*mlang_info
, HCHARSET handle
)
224 charset_entry
*charset
= HeapAlloc(GetProcessHeap(), 0, sizeof(*charset
));
226 WideCharToMultiByte(CP_ACP
, 0, mlang_info
->wszCharset
, -1,
227 charset
->cs_info
.szName
, sizeof(charset
->cs_info
.szName
), NULL
, NULL
);
228 charset
->cs_info
.cpiWindows
= mlang_info
->uiCodePage
;
229 charset
->cs_info
.cpiInternet
= mlang_info
->uiInternetEncoding
;
230 charset
->cs_info
.hCharset
= handle
;
231 charset
->cs_info
.dwReserved1
= 0;
232 list_add_head(list
, &charset
->entry
);
234 return charset
->cs_info
.hCharset
;
237 static HRESULT WINAPI
MimeInternat_FindCharset(IMimeInternational
*iface
, LPCSTR pszCharset
,
238 LPHCHARSET phCharset
)
240 internat
*This
= impl_from_IMimeInternational( iface
);
241 HRESULT hr
= MIME_E_NOT_FOUND
;
242 charset_entry
*charset
;
244 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_a(pszCharset
), phCharset
);
248 EnterCriticalSection(&This
->cs
);
250 LIST_FOR_EACH_ENTRY(charset
, &This
->charsets
, charset_entry
, entry
)
252 if(!strcmp(charset
->cs_info
.szName
, pszCharset
))
254 *phCharset
= charset
->cs_info
.hCharset
;
260 if(hr
== MIME_E_NOT_FOUND
)
262 MIMECSETINFO mlang_info
;
264 LeaveCriticalSection(&This
->cs
);
265 hr
= mlang_getcsetinfo(pszCharset
, &mlang_info
);
266 EnterCriticalSection(&This
->cs
);
269 *phCharset
= add_charset(&This
->charsets
, &mlang_info
,
270 (HCHARSET
)InterlockedIncrement(&This
->next_charset_handle
));
273 LeaveCriticalSection(&This
->cs
);
277 static HRESULT WINAPI
MimeInternat_GetCharsetInfo(IMimeInternational
*iface
, HCHARSET hCharset
,
278 LPINETCSETINFO pCsetInfo
)
280 internat
*This
= impl_from_IMimeInternational( iface
);
281 HRESULT hr
= MIME_E_INVALID_HANDLE
;
282 charset_entry
*charset
;
284 TRACE("(%p)->(%p, %p)\n", iface
, hCharset
, pCsetInfo
);
286 EnterCriticalSection(&This
->cs
);
288 LIST_FOR_EACH_ENTRY(charset
, &This
->charsets
, charset_entry
, entry
)
290 if(charset
->cs_info
.hCharset
== hCharset
)
292 *pCsetInfo
= charset
->cs_info
;
298 LeaveCriticalSection(&This
->cs
);
303 static HRESULT WINAPI
MimeInternat_GetCodePageInfo(IMimeInternational
*iface
, CODEPAGEID cpiCodePage
,
304 LPCODEPAGEINFO pCodePageInfo
)
310 static HRESULT WINAPI
MimeInternat_CanConvertCodePages(IMimeInternational
*iface
, CODEPAGEID cpiSource
,
316 TRACE("(%p)->(%d, %d)\n", iface
, cpiSource
, cpiDest
);
318 /* Could call mlang.IsConvertINetStringAvailable() to avoid the COM overhead if need be. */
323 hr
= IMultiLanguage_IsConvertible(ml
, cpiSource
, cpiDest
);
324 IMultiLanguage_Release(ml
);
330 static HRESULT WINAPI
MimeInternat_DecodeHeader(IMimeInternational
*iface
, HCHARSET hCharset
,
332 LPPROPVARIANT pDecoded
,
333 LPRFC1522INFO pRfc1522Info
)
339 static HRESULT WINAPI
MimeInternat_EncodeHeader(IMimeInternational
*iface
, HCHARSET hCharset
,
342 LPRFC1522INFO pRfc1522Info
)
348 static HRESULT WINAPI
MimeInternat_ConvertBuffer(IMimeInternational
*iface
, CODEPAGEID cpiSource
,
349 CODEPAGEID cpiDest
, LPBLOB pIn
, LPBLOB pOut
,
355 TRACE("(%p)->(%d, %d, %p, %p, %p)\n", iface
, cpiSource
, cpiDest
, pIn
, pOut
, pcbRead
);
360 /* Could call mlang.ConvertINetString() to avoid the COM overhead if need be. */
366 UINT in_size
= pIn
->cbSize
, out_size
;
368 hr
= IMultiLanguage_ConvertString(ml
, &mode
, cpiSource
, cpiDest
, pIn
->pBlobData
, &in_size
,
370 if(hr
== S_OK
) /* S_FALSE means the conversion could not be performed */
372 pOut
->pBlobData
= CoTaskMemAlloc(out_size
);
378 in_size
= pIn
->cbSize
;
379 hr
= IMultiLanguage_ConvertString(ml
, &mode
, cpiSource
, cpiDest
, pIn
->pBlobData
, &in_size
,
380 pOut
->pBlobData
, &out_size
);
385 pOut
->cbSize
= out_size
;
388 CoTaskMemFree(pOut
->pBlobData
);
391 IMultiLanguage_Release(ml
);
397 static HRESULT WINAPI
MimeInternat_ConvertString(IMimeInternational
*iface
, CODEPAGEID cpiSource
,
406 static HRESULT WINAPI
MimeInternat_MLANG_ConvertInetReset(IMimeInternational
*iface
)
412 static HRESULT WINAPI
MimeInternat_MLANG_ConvertInetString(IMimeInternational
*iface
, CODEPAGEID cpiSource
,
423 static HRESULT WINAPI
MimeInternat_Rfc1522Decode(IMimeInternational
*iface
, LPCSTR pszValue
,
432 static HRESULT WINAPI
MimeInternat_Rfc1522Encode(IMimeInternational
*iface
, LPCSTR pszValue
,
440 static IMimeInternationalVtbl mime_internat_vtbl
=
442 MimeInternat_QueryInterface
,
444 MimeInternat_Release
,
445 MimeInternat_SetDefaultCharset
,
446 MimeInternat_GetDefaultCharset
,
447 MimeInternat_GetCodePageCharset
,
448 MimeInternat_FindCharset
,
449 MimeInternat_GetCharsetInfo
,
450 MimeInternat_GetCodePageInfo
,
451 MimeInternat_CanConvertCodePages
,
452 MimeInternat_DecodeHeader
,
453 MimeInternat_EncodeHeader
,
454 MimeInternat_ConvertBuffer
,
455 MimeInternat_ConvertString
,
456 MimeInternat_MLANG_ConvertInetReset
,
457 MimeInternat_MLANG_ConvertInetString
,
458 MimeInternat_Rfc1522Decode
,
459 MimeInternat_Rfc1522Encode
462 static internat
*global_internat
;
464 HRESULT
MimeInternational_Construct(IMimeInternational
**internat
)
466 global_internat
= HeapAlloc(GetProcessHeap(), 0, sizeof(*global_internat
));
467 global_internat
->lpVtbl
= &mime_internat_vtbl
;
468 global_internat
->refs
= 0;
469 InitializeCriticalSection(&global_internat
->cs
);
471 list_init(&global_internat
->charsets
);
472 global_internat
->next_charset_handle
= 0;
473 global_internat
->default_charset
= NULL
;
475 *internat
= (IMimeInternational
*)&global_internat
->lpVtbl
;
477 IMimeInternational_AddRef(*internat
);
481 HRESULT WINAPI
MimeOleGetInternat(IMimeInternational
**internat
)
483 TRACE("(%p)\n", internat
);
485 *internat
= (IMimeInternational
*)&global_internat
->lpVtbl
;
486 IMimeInternational_AddRef(*internat
);