diff --git a/dlls/inetcomm/Makefile.in b/dlls/inetcomm/Makefile.in index ee03db03f70..171b98d8fd3 100644 --- a/dlls/inetcomm/Makefile.in +++ b/dlls/inetcomm/Makefile.in @@ -4,7 +4,7 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = inetcomm.dll IMPORTLIB = inetcomm -IMPORTS = uuid ole32 ws2_32 user32 advapi32 kernel32 +IMPORTS = uuid oleaut32 ole32 ws2_32 user32 advapi32 kernel32 C_SRCS = \ inetcomm_main.c \ diff --git a/dlls/inetcomm/mimeintl.c b/dlls/inetcomm/mimeintl.c index 6cc1d96f601..a7a8313f56f 100644 --- a/dlls/inetcomm/mimeintl.c +++ b/dlls/inetcomm/mimeintl.c @@ -31,6 +31,7 @@ #include "objbase.h" #include "ole2.h" #include "mimeole.h" +#include "mlang.h" #include "wine/list.h" #include "wine/debug.h" @@ -39,10 +40,20 @@ WINE_DEFAULT_DEBUG_CHANNEL(inetcomm); +typedef struct +{ + struct list entry; + INETCSETINFO cs_info; +} charset_entry; + typedef struct { const IMimeInternationalVtbl *lpVtbl; LONG refs; + CRITICAL_SECTION cs; + + struct list charsets; + LONG next_charset_handle; } internat; static inline internat *impl_from_IMimeInternational( IMimeInternational *iface ) @@ -50,6 +61,12 @@ static inline internat *impl_from_IMimeInternational( IMimeInternational *iface return (internat *)((char*)iface - FIELD_OFFSET(internat, lpVtbl)); } +static inline HRESULT get_mlang(IMultiLanguage **ml) +{ + return CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, + &IID_IMultiLanguage, (void **)ml); +} + static HRESULT WINAPI MimeInternat_QueryInterface( IMimeInternational *iface, REFIID riid, LPVOID *ppobj ) { if (IsEqualGUID(riid, &IID_IUnknown) || @@ -78,6 +95,13 @@ static ULONG WINAPI MimeInternat_Release( IMimeInternational *iface ) refs = InterlockedDecrement(&This->refs); if (!refs) { + charset_entry *charset, *cursor2; + + LIST_FOR_EACH_ENTRY_SAFE(charset, cursor2, &This->charsets, charset_entry, entry) + { + list_remove(&charset->entry); + HeapFree(GetProcessHeap(), 0, charset); + } HeapFree(GetProcessHeap(), 0, This); } @@ -104,11 +128,80 @@ static HRESULT WINAPI MimeInternat_GetCodePageCharset(IMimeInternational *iface, return E_NOTIMPL; } +static HRESULT mlang_getcsetinfo(const char *charset, MIMECSETINFO *mlang_info) +{ + DWORD len = MultiByteToWideChar(CP_ACP, 0, charset, -1, NULL, 0); + BSTR bstr = SysAllocStringLen(NULL, len - 1); + HRESULT hr; + IMultiLanguage *ml; + + MultiByteToWideChar(CP_ACP, 0, charset, -1, bstr, len); + + hr = get_mlang(&ml); + + if(SUCCEEDED(hr)) + { + hr = IMultiLanguage_GetCharsetInfo(ml, bstr, mlang_info); + IMultiLanguage_Release(ml); + } + SysFreeString(bstr); + if(FAILED(hr)) hr = MIME_E_NOT_FOUND; + return hr; +} + +static HCHARSET add_charset(struct list *list, MIMECSETINFO *mlang_info, HCHARSET handle) +{ + charset_entry *charset = HeapAlloc(GetProcessHeap(), 0, sizeof(*charset)); + + WideCharToMultiByte(CP_ACP, 0, mlang_info->wszCharset, -1, + charset->cs_info.szName, sizeof(charset->cs_info.szName), NULL, NULL); + charset->cs_info.cpiWindows = mlang_info->uiCodePage; + charset->cs_info.cpiInternet = mlang_info->uiInternetEncoding; + charset->cs_info.hCharset = handle; + charset->cs_info.dwReserved1 = 0; + list_add_head(list, &charset->entry); + + return charset->cs_info.hCharset; +} + static HRESULT WINAPI MimeInternat_FindCharset(IMimeInternational *iface, LPCSTR pszCharset, LPHCHARSET phCharset) { - FIXME("stub\n"); - return E_NOTIMPL; + internat *This = impl_from_IMimeInternational( iface ); + HRESULT hr = MIME_E_NOT_FOUND; + charset_entry *charset; + + TRACE("(%p)->(%s, %p)\n", iface, debugstr_a(pszCharset), phCharset); + + *phCharset = NULL; + + EnterCriticalSection(&This->cs); + + LIST_FOR_EACH_ENTRY(charset, &This->charsets, charset_entry, entry) + { + if(!strcmp(charset->cs_info.szName, pszCharset)) + { + *phCharset = charset->cs_info.hCharset; + hr = S_OK; + break; + } + } + + if(hr == MIME_E_NOT_FOUND) + { + MIMECSETINFO mlang_info; + + LeaveCriticalSection(&This->cs); + hr = mlang_getcsetinfo(pszCharset, &mlang_info); + EnterCriticalSection(&This->cs); + + if(SUCCEEDED(hr)) + *phCharset = add_charset(&This->charsets, &mlang_info, + (HCHARSET)InterlockedIncrement(&This->next_charset_handle)); + } + + LeaveCriticalSection(&This->cs); + return hr; } static HRESULT WINAPI MimeInternat_GetCharsetInfo(IMimeInternational *iface, HCHARSET hCharset, @@ -224,6 +317,10 @@ HRESULT MimeInternational_Construct(IMimeInternational **internat) global_internat = HeapAlloc(GetProcessHeap(), 0, sizeof(*global_internat)); global_internat->lpVtbl = &mime_internat_vtbl; global_internat->refs = 0; + InitializeCriticalSection(&global_internat->cs); + + list_init(&global_internat->charsets); + global_internat->next_charset_handle = 0; *internat = (IMimeInternational*)&global_internat->lpVtbl;