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
21 #define WIN32_NO_STATUS
23 #define COM_NO_WINDOWS_H
26 #define NONAMELESSUNION
33 //#include "winuser.h"
35 //#include "objbase.h"
40 #include <wine/list.h>
41 #include <wine/unicode.h>
42 #include <wine/debug.h>
44 #include "inetcomm_private.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(inetcomm
);
56 IMimeInternational IMimeInternational_iface
;
61 LONG next_charset_handle
;
62 HCHARSET default_charset
;
65 static inline internat_impl
*impl_from_IMimeInternational(IMimeInternational
*iface
)
67 return CONTAINING_RECORD(iface
, internat_impl
, IMimeInternational_iface
);
70 static inline HRESULT
get_mlang(IMultiLanguage
**ml
)
72 return CoCreateInstance(&CLSID_CMultiLanguage
, NULL
, CLSCTX_INPROC_SERVER
| CLSCTX_INPROC_HANDLER
,
73 &IID_IMultiLanguage
, (void **)ml
);
76 static HRESULT WINAPI
MimeInternat_QueryInterface( IMimeInternational
*iface
, REFIID riid
, LPVOID
*ppobj
)
78 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
79 IsEqualGUID(riid
, &IID_IMimeInternational
))
81 IMimeInternational_AddRef( iface
);
86 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
90 static ULONG WINAPI
MimeInternat_AddRef( IMimeInternational
*iface
)
92 internat_impl
*This
= impl_from_IMimeInternational( iface
);
93 return InterlockedIncrement(&This
->refs
);
96 static ULONG WINAPI
MimeInternat_Release( IMimeInternational
*iface
)
98 internat_impl
*This
= impl_from_IMimeInternational( iface
);
101 refs
= InterlockedDecrement(&This
->refs
);
104 charset_entry
*charset
, *cursor2
;
106 LIST_FOR_EACH_ENTRY_SAFE(charset
, cursor2
, &This
->charsets
, charset_entry
, entry
)
108 list_remove(&charset
->entry
);
109 HeapFree(GetProcessHeap(), 0, charset
);
111 This
->cs
.DebugInfo
->Spare
[0] = 0;
112 DeleteCriticalSection(&This
->cs
);
113 HeapFree(GetProcessHeap(), 0, This
);
119 static HRESULT WINAPI
MimeInternat_SetDefaultCharset(IMimeInternational
*iface
, HCHARSET hCharset
)
121 internat_impl
*This
= impl_from_IMimeInternational( iface
);
123 TRACE("(%p)->(%p)\n", iface
, hCharset
);
125 if(hCharset
== NULL
) return E_INVALIDARG
;
126 /* FIXME check hCharset is valid */
128 InterlockedExchangePointer(&This
->default_charset
, hCharset
);
133 static HRESULT WINAPI
MimeInternat_GetDefaultCharset(IMimeInternational
*iface
, LPHCHARSET phCharset
)
135 internat_impl
*This
= impl_from_IMimeInternational( iface
);
138 TRACE("(%p)->(%p)\n", iface
, phCharset
);
140 if(This
->default_charset
== NULL
)
143 hr
= IMimeInternational_GetCodePageCharset(iface
, GetACP(), CHARSET_BODY
, &hcs
);
145 InterlockedCompareExchangePointer(&This
->default_charset
, hcs
, NULL
);
147 *phCharset
= This
->default_charset
;
152 static HRESULT
mlang_getcodepageinfo(UINT cp
, MIMECPINFO
*mlang_cp_info
)
161 hr
= IMultiLanguage_GetCodePageInfo(ml
, cp
, mlang_cp_info
);
162 IMultiLanguage_Release(ml
);
167 static HRESULT WINAPI
MimeInternat_GetCodePageCharset(IMimeInternational
*iface
, CODEPAGEID cpiCodePage
,
168 CHARSETTYPE ctCsetType
,
169 LPHCHARSET phCharset
)
172 MIMECPINFO mlang_cp_info
;
174 TRACE("(%p)->(%d, %d, %p)\n", iface
, cpiCodePage
, ctCsetType
, phCharset
);
178 hr
= mlang_getcodepageinfo(cpiCodePage
, &mlang_cp_info
);
181 const WCHAR
*charset_nameW
= NULL
;
188 charset_nameW
= mlang_cp_info
.wszBodyCharset
;
191 charset_nameW
= mlang_cp_info
.wszHeaderCharset
;
194 charset_nameW
= mlang_cp_info
.wszWebCharset
;
197 return MIME_E_INVALID_CHARSET_TYPE
;
199 len
= WideCharToMultiByte(CP_ACP
, 0, charset_nameW
, -1, NULL
, 0, NULL
, NULL
);
200 charset_name
= HeapAlloc(GetProcessHeap(), 0, len
);
201 WideCharToMultiByte(CP_ACP
, 0, charset_nameW
, -1, charset_name
, len
, NULL
, NULL
);
202 hr
= IMimeInternational_FindCharset(iface
, charset_name
, phCharset
);
203 HeapFree(GetProcessHeap(), 0, charset_name
);
208 static HRESULT
mlang_getcsetinfo(const char *charset
, MIMECSETINFO
*mlang_info
)
210 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, charset
, -1, NULL
, 0);
211 BSTR bstr
= SysAllocStringLen(NULL
, len
- 1);
215 MultiByteToWideChar(CP_ACP
, 0, charset
, -1, bstr
, len
);
221 hr
= IMultiLanguage_GetCharsetInfo(ml
, bstr
, mlang_info
);
222 IMultiLanguage_Release(ml
);
225 if(FAILED(hr
)) hr
= MIME_E_NOT_FOUND
;
229 static HCHARSET
add_charset(struct list
*list
, MIMECSETINFO
*mlang_info
, HCHARSET handle
)
231 charset_entry
*charset
= HeapAlloc(GetProcessHeap(), 0, sizeof(*charset
));
233 WideCharToMultiByte(CP_ACP
, 0, mlang_info
->wszCharset
, -1,
234 charset
->cs_info
.szName
, sizeof(charset
->cs_info
.szName
), NULL
, NULL
);
235 charset
->cs_info
.cpiWindows
= mlang_info
->uiCodePage
;
236 charset
->cs_info
.cpiInternet
= mlang_info
->uiInternetEncoding
;
237 charset
->cs_info
.hCharset
= handle
;
238 charset
->cs_info
.dwReserved1
= 0;
239 list_add_head(list
, &charset
->entry
);
241 return charset
->cs_info
.hCharset
;
244 static HRESULT WINAPI
MimeInternat_FindCharset(IMimeInternational
*iface
, LPCSTR pszCharset
,
245 LPHCHARSET phCharset
)
247 internat_impl
*This
= impl_from_IMimeInternational( iface
);
248 HRESULT hr
= MIME_E_NOT_FOUND
;
249 charset_entry
*charset
;
251 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_a(pszCharset
), phCharset
);
255 EnterCriticalSection(&This
->cs
);
257 LIST_FOR_EACH_ENTRY(charset
, &This
->charsets
, charset_entry
, entry
)
259 if(!lstrcmpiA(charset
->cs_info
.szName
, pszCharset
))
261 *phCharset
= charset
->cs_info
.hCharset
;
267 if(hr
== MIME_E_NOT_FOUND
)
269 MIMECSETINFO mlang_info
;
271 LeaveCriticalSection(&This
->cs
);
272 hr
= mlang_getcsetinfo(pszCharset
, &mlang_info
);
273 EnterCriticalSection(&This
->cs
);
276 *phCharset
= add_charset(&This
->charsets
, &mlang_info
,
277 UlongToHandle(InterlockedIncrement(&This
->next_charset_handle
)));
280 LeaveCriticalSection(&This
->cs
);
284 static HRESULT WINAPI
MimeInternat_GetCharsetInfo(IMimeInternational
*iface
, HCHARSET hCharset
,
285 LPINETCSETINFO pCsetInfo
)
287 internat_impl
*This
= impl_from_IMimeInternational( iface
);
288 HRESULT hr
= MIME_E_INVALID_HANDLE
;
289 charset_entry
*charset
;
291 TRACE("(%p)->(%p, %p)\n", iface
, hCharset
, pCsetInfo
);
293 EnterCriticalSection(&This
->cs
);
295 LIST_FOR_EACH_ENTRY(charset
, &This
->charsets
, charset_entry
, entry
)
297 if(charset
->cs_info
.hCharset
== hCharset
)
299 *pCsetInfo
= charset
->cs_info
;
305 LeaveCriticalSection(&This
->cs
);
310 static HRESULT WINAPI
MimeInternat_GetCodePageInfo(IMimeInternational
*iface
, CODEPAGEID cpiCodePage
,
311 LPCODEPAGEINFO pCodePageInfo
)
317 static HRESULT WINAPI
MimeInternat_CanConvertCodePages(IMimeInternational
*iface
, CODEPAGEID cpiSource
,
323 TRACE("(%p)->(%d, %d)\n", iface
, cpiSource
, cpiDest
);
325 /* Could call mlang.IsConvertINetStringAvailable() to avoid the COM overhead if need be. */
330 hr
= IMultiLanguage_IsConvertible(ml
, cpiSource
, cpiDest
);
331 IMultiLanguage_Release(ml
);
337 static HRESULT WINAPI
MimeInternat_DecodeHeader(IMimeInternational
*iface
, HCHARSET hCharset
,
339 LPPROPVARIANT pDecoded
,
340 LPRFC1522INFO pRfc1522Info
)
346 static HRESULT WINAPI
MimeInternat_EncodeHeader(IMimeInternational
*iface
, HCHARSET hCharset
,
349 LPRFC1522INFO pRfc1522Info
)
355 static HRESULT WINAPI
MimeInternat_ConvertBuffer(IMimeInternational
*iface
, CODEPAGEID cpiSource
,
356 CODEPAGEID cpiDest
, LPBLOB pIn
, LPBLOB pOut
,
362 TRACE("(%p)->(%d, %d, %p, %p, %p)\n", iface
, cpiSource
, cpiDest
, pIn
, pOut
, pcbRead
);
367 /* Could call mlang.ConvertINetString() to avoid the COM overhead if need be. */
373 UINT in_size
= pIn
->cbSize
, out_size
;
375 hr
= IMultiLanguage_ConvertString(ml
, &mode
, cpiSource
, cpiDest
, pIn
->pBlobData
, &in_size
,
377 if(hr
== S_OK
) /* S_FALSE means the conversion could not be performed */
379 pOut
->pBlobData
= CoTaskMemAlloc(out_size
);
385 in_size
= pIn
->cbSize
;
386 hr
= IMultiLanguage_ConvertString(ml
, &mode
, cpiSource
, cpiDest
, pIn
->pBlobData
, &in_size
,
387 pOut
->pBlobData
, &out_size
);
392 pOut
->cbSize
= out_size
;
395 CoTaskMemFree(pOut
->pBlobData
);
398 IMultiLanguage_Release(ml
);
404 static HRESULT WINAPI
MimeInternat_ConvertString(IMimeInternational
*iface
, CODEPAGEID cpiSource
,
405 CODEPAGEID cpiDest
, LPPROPVARIANT pIn
,
412 TRACE("(%p)->(%d, %d, %p %p)\n", iface
, cpiSource
, cpiDest
, pIn
, pOut
);
417 if(cpiSource
== CP_UNICODE
) cpiSource
= GetACP();
418 src_len
= strlen(pIn
->u
.pszVal
);
421 cpiSource
= CP_UNICODE
;
422 src_len
= strlenW(pIn
->u
.pwszVal
) * sizeof(WCHAR
);
432 UINT in_size
= src_len
, out_size
;
434 hr
= IMultiLanguage_ConvertString(ml
, &mode
, cpiSource
, cpiDest
, (BYTE
*)pIn
->u
.pszVal
, &in_size
,
436 if(hr
== S_OK
) /* S_FALSE means the conversion could not be performed */
438 out_size
+= (cpiDest
== CP_UNICODE
) ? sizeof(WCHAR
) : sizeof(char);
440 pOut
->u
.pszVal
= CoTaskMemAlloc(out_size
);
447 hr
= IMultiLanguage_ConvertString(ml
, &mode
, cpiSource
, cpiDest
, (BYTE
*)pIn
->u
.pszVal
, &in_size
,
448 (BYTE
*)pOut
->u
.pszVal
, &out_size
);
452 if(cpiDest
== CP_UNICODE
)
454 pOut
->u
.pwszVal
[out_size
/ sizeof(WCHAR
)] = 0;
455 pOut
->vt
= VT_LPWSTR
;
459 pOut
->u
.pszVal
[out_size
] = '\0';
464 CoTaskMemFree(pOut
->u
.pszVal
);
467 IMultiLanguage_Release(ml
);
472 static HRESULT WINAPI
MimeInternat_MLANG_ConvertInetReset(IMimeInternational
*iface
)
478 static HRESULT WINAPI
MimeInternat_MLANG_ConvertInetString(IMimeInternational
*iface
, CODEPAGEID cpiSource
,
489 static HRESULT WINAPI
MimeInternat_Rfc1522Decode(IMimeInternational
*iface
, LPCSTR pszValue
,
498 static HRESULT WINAPI
MimeInternat_Rfc1522Encode(IMimeInternational
*iface
, LPCSTR pszValue
,
506 static IMimeInternationalVtbl mime_internat_vtbl
=
508 MimeInternat_QueryInterface
,
510 MimeInternat_Release
,
511 MimeInternat_SetDefaultCharset
,
512 MimeInternat_GetDefaultCharset
,
513 MimeInternat_GetCodePageCharset
,
514 MimeInternat_FindCharset
,
515 MimeInternat_GetCharsetInfo
,
516 MimeInternat_GetCodePageInfo
,
517 MimeInternat_CanConvertCodePages
,
518 MimeInternat_DecodeHeader
,
519 MimeInternat_EncodeHeader
,
520 MimeInternat_ConvertBuffer
,
521 MimeInternat_ConvertString
,
522 MimeInternat_MLANG_ConvertInetReset
,
523 MimeInternat_MLANG_ConvertInetString
,
524 MimeInternat_Rfc1522Decode
,
525 MimeInternat_Rfc1522Encode
528 static internat_impl
*global_internat
;
530 HRESULT
MimeInternational_Construct(IMimeInternational
**internat
)
532 global_internat
= HeapAlloc(GetProcessHeap(), 0, sizeof(*global_internat
));
533 global_internat
->IMimeInternational_iface
.lpVtbl
= &mime_internat_vtbl
;
534 global_internat
->refs
= 0;
535 InitializeCriticalSection(&global_internat
->cs
);
536 global_internat
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": global_internat.cs");
538 list_init(&global_internat
->charsets
);
539 global_internat
->next_charset_handle
= 0;
540 global_internat
->default_charset
= NULL
;
542 *internat
= &global_internat
->IMimeInternational_iface
;
544 IMimeInternational_AddRef(*internat
);
548 HRESULT WINAPI
MimeOleGetInternat(IMimeInternational
**internat
)
550 TRACE("(%p)\n", internat
);
552 *internat
= &global_internat
->IMimeInternational_iface
;
553 IMimeInternational_AddRef(*internat
);
557 HRESULT WINAPI
MimeOleFindCharset(LPCSTR name
, LPHCHARSET charset
)
559 IMimeInternational
*internat
;
562 TRACE("(%s, %p)\n", debugstr_a(name
), charset
);
564 hr
= MimeOleGetInternat(&internat
);
567 hr
= IMimeInternational_FindCharset(internat
, name
, charset
);
568 IMimeInternational_Release(internat
);
573 HRESULT WINAPI
MimeOleGetCharsetInfo(HCHARSET hCharset
, LPINETCSETINFO pCsetInfo
)
575 IMimeInternational
*internat
;
578 TRACE("(%p, %p)\n", hCharset
, pCsetInfo
);
580 hr
= MimeOleGetInternat(&internat
);
583 hr
= IMimeInternational_GetCharsetInfo(internat
, hCharset
, pCsetInfo
);
584 IMimeInternational_Release(internat
);
589 HRESULT WINAPI
MimeOleGetDefaultCharset(LPHCHARSET charset
)
591 IMimeInternational
*internat
;
594 TRACE("(%p)\n", charset
);
596 hr
= MimeOleGetInternat(&internat
);
599 hr
= IMimeInternational_GetDefaultCharset(internat
, charset
);
600 IMimeInternational_Release(internat
);