xref: /reactos/dll/win32/mlang/mlang.c (revision be08d69b)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  *    MLANG Class Factory
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * Copyright 2002 Lionel Ulmer
5c2c66affSColin Finck  * Copyright 2003,2004 Mike McCormack
6c2c66affSColin Finck  * Copyright 2004,2005 Dmitry Timoshkov
7c2c66affSColin Finck  * Copyright 2009 Detlef Riekenberg
8c2c66affSColin Finck  *
9c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
10c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
11c2c66affSColin Finck  * License as published by the Free Software Foundation; either
12c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
13c2c66affSColin Finck  *
14c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
15c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17c2c66affSColin Finck  * Lesser General Public License for more details.
18c2c66affSColin Finck  *
19c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
20c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
21c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22c2c66affSColin Finck  */
23c2c66affSColin Finck 
24c2c66affSColin Finck 
25c2c66affSColin Finck #include <stdarg.h>
262c523eefSAmine Khaldi #include <stdio.h>
27c2c66affSColin Finck 
28c2c66affSColin Finck #define COBJMACROS
29c2c66affSColin Finck 
302c523eefSAmine Khaldi #include "windef.h"
312c523eefSAmine Khaldi #include "winbase.h"
322c523eefSAmine Khaldi #include "wingdi.h"
332c523eefSAmine Khaldi #include "winuser.h"
342c523eefSAmine Khaldi #include "ole2.h"
352c523eefSAmine Khaldi #include "objbase.h"
362c523eefSAmine Khaldi #include "rpcproxy.h"
372c523eefSAmine Khaldi #include "mlang.h"
382c523eefSAmine Khaldi #include "mimeole.h"
39c2c66affSColin Finck 
402c523eefSAmine Khaldi #include "wine/debug.h"
412c523eefSAmine Khaldi #include "wine/list.h"
42c2c66affSColin Finck 
43c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(mlang);
44c2c66affSColin Finck 
452c523eefSAmine Khaldi #include "initguid.h"
46c2c66affSColin Finck 
47c2c66affSColin Finck static HRESULT MultiLanguage_create(IUnknown *pUnkOuter, LPVOID *ppObj);
48c2c66affSColin Finck static HRESULT MLangConvertCharset_create(IUnknown *outer, void **obj);
49c2c66affSColin Finck static HRESULT EnumRfc1766_create(LANGID LangId, IEnumRfc1766 **ppEnum);
50c2c66affSColin Finck 
51c2c66affSColin Finck static HINSTANCE instance;
52c2c66affSColin Finck static DWORD MLANG_tls_index; /* to store various per thead data */
53c2c66affSColin Finck 
54c2c66affSColin Finck /* FIXME:
55c2c66affSColin Finck  * Under what circumstances HKEY_CLASSES_ROOT\MIME\Database\Codepage and
56c2c66affSColin Finck  * HKEY_CLASSES_ROOT\MIME\Database\Charset are used?
57c2c66affSColin Finck  */
58c2c66affSColin Finck 
59c2c66affSColin Finck typedef struct
60c2c66affSColin Finck {
61c2c66affSColin Finck     const char *description;
62c2c66affSColin Finck     UINT cp;
63c2c66affSColin Finck     DWORD flags;
64c2c66affSColin Finck     const char *web_charset;
65c2c66affSColin Finck     const char *header_charset;
66c2c66affSColin Finck     const char *body_charset;
67c2c66affSColin Finck     const WCHAR *alias;
68c2c66affSColin Finck } MIME_CP_INFO;
69c2c66affSColin Finck 
70c2c66affSColin Finck /* These data are based on the codepage info in libs/unicode/cpmap.pl */
71c2c66affSColin Finck /* FIXME: Add 28604 (Celtic), 28606 (Balkan) */
72c2c66affSColin Finck 
73c2c66affSColin Finck static const MIME_CP_INFO arabic_cp[] =
74c2c66affSColin Finck {
75c2c66affSColin Finck     { "Arabic (864)",
76c2c66affSColin Finck       864, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
77c2c66affSColin Finck            MIMECONTF_MIME_LATEST,
78c2c66affSColin Finck       "ibm864", "ibm864", "ibm864" },
79c2c66affSColin Finck     { "Arabic (1006)",
80c2c66affSColin Finck       1006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
81c2c66affSColin Finck             MIMECONTF_MIME_LATEST,
82c2c66affSColin Finck       "ibm1006", "ibm1006", "ibm1006" },
83c2c66affSColin Finck     { "Arabic (Windows)",
84c2c66affSColin Finck       1256, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
85c2c66affSColin Finck             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
86c2c66affSColin Finck             MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
87c2c66affSColin Finck       "windows-1256", "windows-1256", "windows-1256" },
88c2c66affSColin Finck     { "Arabic (ISO)",
89c2c66affSColin Finck       28596, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
90c2c66affSColin Finck              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
91c2c66affSColin Finck              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
92c2c66affSColin Finck              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
93c2c66affSColin Finck       "iso-8859-6", "iso-8859-6", "iso-8859-6" }
94c2c66affSColin Finck };
95c2c66affSColin Finck static const MIME_CP_INFO baltic_cp[] =
96c2c66affSColin Finck {
97c2c66affSColin Finck     { "Baltic (DOS)",
98c2c66affSColin Finck       775, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
99c2c66affSColin Finck            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
100c2c66affSColin Finck       "ibm775", "ibm775", "ibm775" },
101c2c66affSColin Finck     { "Baltic (Windows)",
102c2c66affSColin Finck       1257, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
103c2c66affSColin Finck             MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
104c2c66affSColin Finck             MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
105c2c66affSColin Finck             MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
106c2c66affSColin Finck       "windows-1257", "windows-1257", "windows-1257" },
107c2c66affSColin Finck     { "Baltic (ISO)",
108c2c66affSColin Finck       28594, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
109c2c66affSColin Finck              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
110c2c66affSColin Finck              MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
111c2c66affSColin Finck              MIMECONTF_MIME_LATEST,
112c2c66affSColin Finck       "iso-8859-4", "iso-8859-4", "iso-8859-4" },
113c2c66affSColin Finck     { "Estonian (ISO)",
114c2c66affSColin Finck       28603, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
115c2c66affSColin Finck              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
116c2c66affSColin Finck       "iso-8859-13", "iso-8859-13", "iso-8859-13" }
117c2c66affSColin Finck };
118c2c66affSColin Finck static const MIME_CP_INFO chinese_simplified_cp[] =
119c2c66affSColin Finck {
1205e2c163fSAmine Khaldi     { "Chinese Simplified (Auto-Select)",
1215e2c163fSAmine Khaldi       50936, MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
1225e2c163fSAmine Khaldi              MIMECONTF_MIME_LATEST,
1235e2c163fSAmine Khaldi       "_autodetect_chs", "_autodetect_chs", "_autodetect_chs" },
124c2c66affSColin Finck     { "Chinese Simplified (GB2312)",
125c2c66affSColin Finck       936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
1265e2c163fSAmine Khaldi            MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID |
127c2c66affSColin Finck            MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
128c2c66affSColin Finck            MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
129c2c66affSColin Finck       "gb2312", "gb2312", "gb2312" },
1305e2c163fSAmine Khaldi     { "Chinese Simplified (GB2312-80)",
1315e2c163fSAmine Khaldi       20936, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
1325e2c163fSAmine Khaldi              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
1335e2c163fSAmine Khaldi       "x-cp20936", "x-cp20936", "x-cp20936" },
1345e2c163fSAmine Khaldi     { "Chinese Simplified (HZ)",
1355e2c163fSAmine Khaldi       52936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
1365e2c163fSAmine Khaldi              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
1375e2c163fSAmine Khaldi              MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
1385e2c163fSAmine Khaldi              MIMECONTF_MIME_LATEST,
1395e2c163fSAmine Khaldi       "hz-gb-2312", "hz-gb-2312", "hz-gb-2312" },
1405e2c163fSAmine Khaldi     { "Chinese Simplified (GB18030)",
1415e2c163fSAmine Khaldi       54936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
1425e2c163fSAmine Khaldi              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
1435e2c163fSAmine Khaldi              MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
1445e2c163fSAmine Khaldi              MIMECONTF_MIME_LATEST,
1455e2c163fSAmine Khaldi       "GB18030", "GB18030", "GB18030" },
146c2c66affSColin Finck     { "Chinese Simplified (GBK)",
147c2c66affSColin Finck       936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
148c2c66affSColin Finck            MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
149c2c66affSColin Finck            MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
150c2c66affSColin Finck            MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
151c2c66affSColin Finck       "gbk", "gbk", "gbk" }
152c2c66affSColin Finck };
153c2c66affSColin Finck static const MIME_CP_INFO chinese_traditional_cp[] =
154c2c66affSColin Finck {
1555e2c163fSAmine Khaldi     { "Chinese Traditional (Auto-Select)",
1565e2c163fSAmine Khaldi       50950, MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
1575e2c163fSAmine Khaldi              MIMECONTF_MIME_LATEST,
1585e2c163fSAmine Khaldi       "_autodetect_cht", "_autodetect_cht", "_autodetect_cht" },
159c2c66affSColin Finck     { "Chinese Traditional (Big5)",
160c2c66affSColin Finck       950, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
161c2c66affSColin Finck            MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
1625e2c163fSAmine Khaldi            MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
163c2c66affSColin Finck            MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
1645e2c163fSAmine Khaldi       "big5", "big5", "big5" },
1655e2c163fSAmine Khaldi     { "Chinese Traditional (CNS)",
1665e2c163fSAmine Khaldi       20000, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
1675e2c163fSAmine Khaldi              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
1685e2c163fSAmine Khaldi       "x-Chinese-CNS", "x-Chinese-CNS", "x-Chinese-CNS" }
169c2c66affSColin Finck };
170c2c66affSColin Finck static const MIME_CP_INFO central_european_cp[] =
171c2c66affSColin Finck {
172c2c66affSColin Finck     { "Central European (DOS)",
173c2c66affSColin Finck       852, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
174c2c66affSColin Finck            MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
175c2c66affSColin Finck            MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
176c2c66affSColin Finck       "ibm852", "ibm852", "ibm852" },
177c2c66affSColin Finck     { "Central European (Windows)",
178c2c66affSColin Finck       1250, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
179c2c66affSColin Finck             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
180c2c66affSColin Finck             MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
181c2c66affSColin Finck             MIMECONTF_MIME_LATEST,
182c2c66affSColin Finck       "windows-1250", "windows-1250", "windows-1250" },
183c2c66affSColin Finck     { "Central European (Mac)",
184c2c66affSColin Finck       10029, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
185c2c66affSColin Finck              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
186c2c66affSColin Finck       "x-mac-ce", "x-mac-ce", "x-mac-ce" },
187c2c66affSColin Finck     { "Central European (ISO)",
188c2c66affSColin Finck       28592, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
189c2c66affSColin Finck              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
190c2c66affSColin Finck              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
191c2c66affSColin Finck              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
192c2c66affSColin Finck       "iso-8859-2", "iso-8859-2", "iso-8859-2" }
193c2c66affSColin Finck };
194c2c66affSColin Finck static const MIME_CP_INFO cyrillic_cp[] =
195c2c66affSColin Finck {
196c2c66affSColin Finck     { "OEM Cyrillic",
197c2c66affSColin Finck       855, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
198c2c66affSColin Finck            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
199c2c66affSColin Finck       "ibm855", "ibm855", "ibm855" },
200c2c66affSColin Finck     { "Cyrillic (DOS)",
201c2c66affSColin Finck       866, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
202c2c66affSColin Finck            MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
203c2c66affSColin Finck            MIMECONTF_MIME_LATEST,
204c2c66affSColin Finck       "cp866", "cp866", "cp866" },
205c2c66affSColin Finck #if 0 /* Windows has 20866 as an official code page for KOI8-R */
206c2c66affSColin Finck     { "Cyrillic (KOI8-R)",
207c2c66affSColin Finck       878, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
208c2c66affSColin Finck            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
209c2c66affSColin Finck       "koi8-r", "koi8-r", "koi8-r" },
210c2c66affSColin Finck #endif
211c2c66affSColin Finck     { "Cyrillic (Windows)",
212c2c66affSColin Finck       1251, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
213c2c66affSColin Finck             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
214c2c66affSColin Finck             MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
215c2c66affSColin Finck       "windows-1251", "windows-1251", "windows-1251" },
216c2c66affSColin Finck     { "Cyrillic (Mac)",
217c2c66affSColin Finck       10007, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
218c2c66affSColin Finck              MIMECONTF_MIME_LATEST,
219c2c66affSColin Finck       "x-mac-cyrillic", "x-mac-cyrillic", "x-mac-cyrillic" },
220c2c66affSColin Finck     { "Cyrillic (KOI8-R)",
221c2c66affSColin Finck       20866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
222c2c66affSColin Finck              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
223c2c66affSColin Finck              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
224c2c66affSColin Finck              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
225c2c66affSColin Finck       "koi8-r", "koi8-r", "koi8-r" },
226c2c66affSColin Finck     { "Cyrillic (KOI8-U)",
227c2c66affSColin Finck       21866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
228c2c66affSColin Finck              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
229c2c66affSColin Finck              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
230c2c66affSColin Finck              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
231c2c66affSColin Finck       "koi8-u", "koi8-u", "koi8-u" },
232c2c66affSColin Finck     { "Cyrillic (ISO)",
233c2c66affSColin Finck       28595, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
234c2c66affSColin Finck              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
235c2c66affSColin Finck              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
236c2c66affSColin Finck              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
237c2c66affSColin Finck       "iso-8859-5", "iso-8859-5", "iso-8859-5" }
238c2c66affSColin Finck };
239c2c66affSColin Finck static const MIME_CP_INFO greek_cp[] =
240c2c66affSColin Finck {
241c2c66affSColin Finck     { "Greek (DOS)",
242c2c66affSColin Finck       737, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
243c2c66affSColin Finck            MIMECONTF_MIME_LATEST,
244c2c66affSColin Finck       "ibm737", "ibm737", "ibm737" },
245c2c66affSColin Finck     { "Greek, Modern (DOS)",
246c2c66affSColin Finck       869, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
247c2c66affSColin Finck            MIMECONTF_MIME_LATEST,
248c2c66affSColin Finck       "ibm869", "ibm869", "ibm869" },
249c2c66affSColin Finck     { "IBM EBCDIC (Greek Modern)",
250c2c66affSColin Finck       875, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
251c2c66affSColin Finck            MIMECONTF_MIME_LATEST,
252c2c66affSColin Finck       "cp875", "cp875", "cp875" },
253c2c66affSColin Finck     { "Greek (Windows)",
254c2c66affSColin Finck       1253, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
255c2c66affSColin Finck             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
256c2c66affSColin Finck             MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
257c2c66affSColin Finck       "windows-1253", "windows-1253", "windows-1253" },
258c2c66affSColin Finck     { "Greek (Mac)",
259c2c66affSColin Finck       10006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
260c2c66affSColin Finck              MIMECONTF_MIME_LATEST,
261c2c66affSColin Finck       "x-mac-greek", "x-mac-greek", "x-mac-greek" },
262c2c66affSColin Finck     { "Greek (ISO)",
263c2c66affSColin Finck       28597, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
264c2c66affSColin Finck              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
265c2c66affSColin Finck              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
266c2c66affSColin Finck              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
267c2c66affSColin Finck       "iso-8859-7", "iso-8859-7", "iso-8859-7" }
268c2c66affSColin Finck };
269c2c66affSColin Finck static const MIME_CP_INFO hebrew_cp[] =
270c2c66affSColin Finck {
271c2c66affSColin Finck     { "Hebrew (424)",
272c2c66affSColin Finck       424, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
273c2c66affSColin Finck            MIMECONTF_MIME_LATEST,
274c2c66affSColin Finck       "ibm424", "ibm424", "ibm424" },
275c2c66affSColin Finck     { "Hebrew (856)",
276c2c66affSColin Finck       856, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
277c2c66affSColin Finck            MIMECONTF_MIME_LATEST,
278c2c66affSColin Finck       "cp856", "cp856", "cp856" },
279c2c66affSColin Finck     { "Hebrew (DOS)",
280c2c66affSColin Finck       862, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
281c2c66affSColin Finck            MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
282c2c66affSColin Finck            MIMECONTF_MIME_LATEST,
283c2c66affSColin Finck       "dos-862", "dos-862", "dos-862" },
284c2c66affSColin Finck     { "Hebrew (Windows)",
285c2c66affSColin Finck       1255, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
286c2c66affSColin Finck             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
287c2c66affSColin Finck             MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
288c2c66affSColin Finck       "windows-1255", "windows-1255", "windows-1255" },
289c2c66affSColin Finck     { "Hebrew (ISO-Visual)",
290c2c66affSColin Finck       28598, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
291c2c66affSColin Finck              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
292c2c66affSColin Finck              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
293c2c66affSColin Finck       "iso-8859-8", "iso-8859-8", "iso-8859-8" }
294c2c66affSColin Finck };
295c2c66affSColin Finck static const MIME_CP_INFO japanese_cp[] =
296c2c66affSColin Finck {
297c2c66affSColin Finck     { "Japanese (Auto-Select)",
298c2c66affSColin Finck       50932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
299c2c66affSColin Finck              MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
300c2c66affSColin Finck              MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
301c2c66affSColin Finck       "_autodetect", "_autodetect", "_autodetect" },
302c2c66affSColin Finck     { "Japanese (EUC)",
303c2c66affSColin Finck       51932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
304c2c66affSColin Finck              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
305c2c66affSColin Finck              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
306c2c66affSColin Finck              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
307c2c66affSColin Finck       "euc-jp", "euc-jp", "euc-jp" },
308c2c66affSColin Finck     { "Japanese (JIS)",
309c2c66affSColin Finck       50220, MIMECONTF_IMPORT | MIMECONTF_MAILNEWS | MIMECONTF_EXPORT |
310c2c66affSColin Finck              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID_NLS |
311c2c66affSColin Finck              MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST |
312c2c66affSColin Finck              MIMECONTF_MIME_IE4,
313c2c66affSColin Finck       "iso-2022-jp","iso-2022-jp","iso-2022-jp"},
314c2c66affSColin Finck     { "Japanese (JIS 0208-1990 and 0212-1990)",
315c2c66affSColin Finck       20932, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
316c2c66affSColin Finck              MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
317c2c66affSColin Finck       "EUC-JP","EUC-JP","EUC-JP"},
318c2c66affSColin Finck     { "Japanese (JIS-Allow 1 byte Kana)",
319c2c66affSColin Finck       50221, MIMECONTF_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_SAVABLE_BROWSER |
320c2c66affSColin Finck              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID_NLS |
321c2c66affSColin Finck              MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
322c2c66affSColin Finck       "csISO2022JP","iso-2022-jp","iso-2022-jp"},
323c2c66affSColin Finck     { "Japanese (JIS-Allow 1 byte Kana - SO/SI)",
324c2c66affSColin Finck       50222, MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_VALID |
325c2c66affSColin Finck              MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
326c2c66affSColin Finck       "iso-2022-jp","iso-2022-jp","iso-2022-jp"},
327c2c66affSColin Finck     { "Japanese (Mac)",
328c2c66affSColin Finck       10001, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
329c2c66affSColin Finck              MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
330c2c66affSColin Finck       "x-mac-japanese","x-mac-japanese","x-mac-japanese"},
331c2c66affSColin Finck     { "Japanese (Shift-JIS)",
332c2c66affSColin Finck       932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
333c2c66affSColin Finck            MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
334c2c66affSColin Finck            MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
335c2c66affSColin Finck            MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
336c2c66affSColin Finck       "shift_jis", "iso-2022-jp", "iso-2022-jp" }
337c2c66affSColin Finck };
338c2c66affSColin Finck static const MIME_CP_INFO korean_cp[] =
339c2c66affSColin Finck {
340c2c66affSColin Finck     { "Korean",
341c2c66affSColin Finck       949, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
342c2c66affSColin Finck            MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
343c2c66affSColin Finck            MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
344c2c66affSColin Finck            MIMECONTF_MIME_LATEST,
345c2c66affSColin Finck       "ks_c_5601-1987", "ks_c_5601-1987", "ks_c_5601-1987" }
346c2c66affSColin Finck };
347c2c66affSColin Finck static const MIME_CP_INFO thai_cp[] =
348c2c66affSColin Finck {
349c2c66affSColin Finck     { "Thai (Windows)",
350c2c66affSColin Finck       874, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_MIME_LATEST,
351c2c66affSColin Finck       "ibm-thai", "ibm-thai", "ibm-thai" }
352c2c66affSColin Finck };
353c2c66affSColin Finck static const MIME_CP_INFO turkish_cp[] =
354c2c66affSColin Finck {
355c2c66affSColin Finck     { "Turkish (DOS)",
356c2c66affSColin Finck       857, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
357c2c66affSColin Finck            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
358c2c66affSColin Finck       "ibm857", "ibm857", "ibm857" },
359c2c66affSColin Finck     { "IBM EBCDIC (Turkish Latin-5)",
360c2c66affSColin Finck       1026, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
361c2c66affSColin Finck             MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
362c2c66affSColin Finck       "ibm1026", "ibm1026", "ibm1026" },
363c2c66affSColin Finck     { "Turkish (Windows)",
364c2c66affSColin Finck       1254, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
365c2c66affSColin Finck             MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
366c2c66affSColin Finck             MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
367c2c66affSColin Finck             MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
368c2c66affSColin Finck       "windows-1254", "windows-1254", "windows-1254" },
369c2c66affSColin Finck     { "Turkish (Mac)",
370c2c66affSColin Finck       10081, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
371c2c66affSColin Finck              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
372c2c66affSColin Finck       "x-mac-turkish", "x-mac-turkish", "x-mac-turkish" },
373c2c66affSColin Finck     { "Latin 3 (ISO)",
374c2c66affSColin Finck       28593, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
375c2c66affSColin Finck              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
376c2c66affSColin Finck              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
377c2c66affSColin Finck       "iso-8859-3", "iso-8859-3", "iso-8859-3" },
378c2c66affSColin Finck     { "Turkish (ISO)",
379c2c66affSColin Finck       28599, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
380c2c66affSColin Finck              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
381c2c66affSColin Finck              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
382c2c66affSColin Finck              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
383c2c66affSColin Finck       "iso-8859-9", "iso-8859-9", "iso-8859-9" }
384c2c66affSColin Finck };
385c2c66affSColin Finck static const MIME_CP_INFO vietnamese_cp[] =
386c2c66affSColin Finck {
387c2c66affSColin Finck     { "Vietnamese (Windows)",
388c2c66affSColin Finck       1258, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
389c2c66affSColin Finck             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
390c2c66affSColin Finck             MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
391c2c66affSColin Finck             MIMECONTF_MIME_LATEST,
392c2c66affSColin Finck       "windows-1258", "windows-1258", "windows-1258" }
393c2c66affSColin Finck };
394c2c66affSColin Finck 
395c2c66affSColin Finck static const WCHAR asciiW[] = {'a','s','c','i','i',0};
396c2c66affSColin Finck 
397c2c66affSColin Finck static const MIME_CP_INFO western_cp[] =
398c2c66affSColin Finck {
399c2c66affSColin Finck     { "IBM EBCDIC (US-Canada)",
400c2c66affSColin Finck       37, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
401c2c66affSColin Finck           MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
402c2c66affSColin Finck       "ibm037", "ibm037", "ibm037" },
403c2c66affSColin Finck     { "OEM United States",
404c2c66affSColin Finck       437, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
405c2c66affSColin Finck            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
406c2c66affSColin Finck       "ibm437", "ibm437", "ibm437" },
407c2c66affSColin Finck     { "IBM EBCDIC (International)",
408c2c66affSColin Finck       500, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
409c2c66affSColin Finck            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
410c2c66affSColin Finck       "ibm500", "ibm500", "ibm500" },
411c2c66affSColin Finck     { "Western European (DOS)",
412c2c66affSColin Finck       850, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
413c2c66affSColin Finck            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
414c2c66affSColin Finck       "ibm850", "ibm850", "ibm850" },
415c2c66affSColin Finck     { "Portuguese (DOS)",
416c2c66affSColin Finck       860, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
417c2c66affSColin Finck            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
418c2c66affSColin Finck       "ibm860", "ibm860", "ibm860" },
419c2c66affSColin Finck     { "Icelandic (DOS)",
420c2c66affSColin Finck       861, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
421c2c66affSColin Finck            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
422c2c66affSColin Finck       "ibm861", "ibm861", "ibm861" },
423c2c66affSColin Finck     { "French Canadian (DOS)",
424c2c66affSColin Finck       863, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
425c2c66affSColin Finck            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
426c2c66affSColin Finck       "ibm863", "ibm863", "ibm863" },
427c2c66affSColin Finck     { "Nordic (DOS)",
428c2c66affSColin Finck       865, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
429c2c66affSColin Finck            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
430c2c66affSColin Finck       "ibm865", "ibm865", "ibm865" },
431c2c66affSColin Finck     { "Western European (Windows)",
432c2c66affSColin Finck       1252, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
433c2c66affSColin Finck             MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
434c2c66affSColin Finck             MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
435c2c66affSColin Finck             MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
436c2c66affSColin Finck       "windows-1252", "windows-1252", "iso-8859-1" },
437c2c66affSColin Finck     { "Western European (Mac)",
438c2c66affSColin Finck       10000, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
439c2c66affSColin Finck              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
440c2c66affSColin Finck       "macintosh", "macintosh", "macintosh" },
441c2c66affSColin Finck     { "Icelandic (Mac)",
442c2c66affSColin Finck       10079, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
443c2c66affSColin Finck              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
444c2c66affSColin Finck       "x-mac-icelandic", "x-mac-icelandic", "x-mac-icelandic" },
445c2c66affSColin Finck     { "US-ASCII",
446c2c66affSColin Finck       20127, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT | MIMECONTF_EXPORT |
447c2c66affSColin Finck              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID |
448c2c66affSColin Finck              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
449c2c66affSColin Finck       "us-ascii", "us-ascii", "us-ascii", asciiW },
450c2c66affSColin Finck     { "Western European (ISO)",
451c2c66affSColin Finck       28591, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
452c2c66affSColin Finck              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
453c2c66affSColin Finck              MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
454c2c66affSColin Finck              MIMECONTF_MIME_LATEST,
455c2c66affSColin Finck       "iso-8859-1", "iso-8859-1", "iso-8859-1" },
456c2c66affSColin Finck     { "Latin 9 (ISO)",
457c2c66affSColin Finck       28605, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
458c2c66affSColin Finck              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
459c2c66affSColin Finck              MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
460c2c66affSColin Finck              MIMECONTF_MIME_LATEST,
461c2c66affSColin Finck       "iso-8859-15", "iso-8859-15", "iso-8859-15" }
462c2c66affSColin Finck };
463c2c66affSColin Finck static const MIME_CP_INFO unicode_cp[] =
464c2c66affSColin Finck {
465c2c66affSColin Finck     { "Unicode",
466c2c66affSColin Finck       CP_UNICODE, MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
467c2c66affSColin Finck                   MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
468c2c66affSColin Finck                   MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
469c2c66affSColin Finck                   MIMECONTF_MIME_LATEST,
470c2c66affSColin Finck       "unicode", "unicode", "unicode" },
471c2c66affSColin Finck     { "Unicode (UTF-7)",
472c2c66affSColin Finck       CP_UTF7, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
473c2c66affSColin Finck                MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
474c2c66affSColin Finck                MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
475c2c66affSColin Finck       "utf-7", "utf-7", "utf-7" },
476c2c66affSColin Finck     { "Unicode (UTF-8)",
477c2c66affSColin Finck       CP_UTF8, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
478c2c66affSColin Finck                MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
479c2c66affSColin Finck                MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
480c2c66affSColin Finck                MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
481c2c66affSColin Finck       "utf-8", "utf-8", "utf-8" }
482c2c66affSColin Finck };
483c2c66affSColin Finck 
484c2c66affSColin Finck static const struct mlang_data
485c2c66affSColin Finck {
486c2c66affSColin Finck     const char *description;
487c2c66affSColin Finck     UINT family_codepage;
488c2c66affSColin Finck     UINT number_of_cp;
489c2c66affSColin Finck     const MIME_CP_INFO *mime_cp_info;
490c2c66affSColin Finck     const char *fixed_font;
491c2c66affSColin Finck     const char *proportional_font;
492c2c66affSColin Finck     SCRIPT_ID sid;
493c2c66affSColin Finck } mlang_data[] =
494c2c66affSColin Finck {
495ccc3eeaeSAmine Khaldi     { "Arabic", 1256, ARRAY_SIZE(arabic_cp), arabic_cp,
4965e2c163fSAmine Khaldi       "Simplified Arabic Fixed","Simplified Arabic", sidArabic },
497ccc3eeaeSAmine Khaldi     { "Baltic",  1257, ARRAY_SIZE(baltic_cp), baltic_cp,
4985e2c163fSAmine Khaldi       "Courier New","Arial", sidAsciiLatin },
499ccc3eeaeSAmine Khaldi     { "Chinese Simplified", 936, ARRAY_SIZE(chinese_simplified_cp), chinese_simplified_cp,
5005e2c163fSAmine Khaldi       "Simsun","Simsun", sidHan },
501ccc3eeaeSAmine Khaldi     { "Chinese Traditional", 950, ARRAY_SIZE(chinese_traditional_cp), chinese_traditional_cp,
5025e2c163fSAmine Khaldi       "MingLiu","New MingLiu", sidBopomofo },
503ccc3eeaeSAmine Khaldi     { "Central European", 1250, ARRAY_SIZE(central_european_cp), central_european_cp,
5045e2c163fSAmine Khaldi       "Courier New","Arial", sidAsciiLatin },
505ccc3eeaeSAmine Khaldi     { "Cyrillic", 1251, ARRAY_SIZE(cyrillic_cp), cyrillic_cp,
5065e2c163fSAmine Khaldi       "Courier New","Arial", sidCyrillic },
507ccc3eeaeSAmine Khaldi     { "Greek", 1253, ARRAY_SIZE(greek_cp), greek_cp,
5085e2c163fSAmine Khaldi       "Courier New","Arial", sidGreek },
509ccc3eeaeSAmine Khaldi     { "Hebrew", 1255, ARRAY_SIZE(hebrew_cp), hebrew_cp,
5105e2c163fSAmine Khaldi       "Miriam Fixed","David", sidHebrew },
511ccc3eeaeSAmine Khaldi     { "Japanese", 932, ARRAY_SIZE(japanese_cp), japanese_cp,
512c2c66affSColin Finck       "MS Gothic","MS PGothic", sidKana },
513ccc3eeaeSAmine Khaldi     { "Korean", 949, ARRAY_SIZE(korean_cp), korean_cp,
5145e2c163fSAmine Khaldi       "GulimChe","Gulim", sidHangul },
515ccc3eeaeSAmine Khaldi     { "Thai", 874, ARRAY_SIZE(thai_cp), thai_cp,
5165e2c163fSAmine Khaldi       "Tahoma","Tahoma", sidThai },
517ccc3eeaeSAmine Khaldi     { "Turkish", 1254, ARRAY_SIZE(turkish_cp), turkish_cp,
5185e2c163fSAmine Khaldi       "Courier New","Arial", sidAsciiLatin },
519ccc3eeaeSAmine Khaldi     { "Vietnamese", 1258, ARRAY_SIZE(vietnamese_cp), vietnamese_cp,
5205e2c163fSAmine Khaldi       "Courier New","Arial", sidAsciiLatin },
521ccc3eeaeSAmine Khaldi     { "Western European", 1252, ARRAY_SIZE(western_cp), western_cp,
5225e2c163fSAmine Khaldi       "Courier New","Arial", sidAsciiLatin },
523ccc3eeaeSAmine Khaldi     { "Unicode", CP_UNICODE, ARRAY_SIZE(unicode_cp), unicode_cp,
5245e2c163fSAmine Khaldi       "Courier New","Arial" }
525c2c66affSColin Finck };
526c2c66affSColin Finck 
5275e2c163fSAmine Khaldi struct font_list
5285e2c163fSAmine Khaldi {
5295e2c163fSAmine Khaldi     struct list list_entry;
5305e2c163fSAmine Khaldi     HFONT base_font;
5315e2c163fSAmine Khaldi     HFONT font;
5325e2c163fSAmine Khaldi     UINT charset;
5335e2c163fSAmine Khaldi };
5345e2c163fSAmine Khaldi 
5355e2c163fSAmine Khaldi static struct list font_cache = LIST_INIT(font_cache);
5365e2c163fSAmine Khaldi static CRITICAL_SECTION font_cache_critical;
5375e2c163fSAmine Khaldi static CRITICAL_SECTION_DEBUG font_cache_critical_debug =
5385e2c163fSAmine Khaldi {
5395e2c163fSAmine Khaldi     0, 0, &font_cache_critical,
5405e2c163fSAmine Khaldi     { &font_cache_critical_debug.ProcessLocksList, &font_cache_critical_debug.ProcessLocksList },
5415e2c163fSAmine Khaldi     0, 0, { (DWORD_PTR)(__FILE__ ": font_cache_critical") }
5425e2c163fSAmine Khaldi };
5435e2c163fSAmine Khaldi static CRITICAL_SECTION font_cache_critical = { &font_cache_critical_debug, -1, 0, 0, 0, 0 };
5445e2c163fSAmine Khaldi 
545c2c66affSColin Finck static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info);
546c2c66affSColin Finck 
547c2c66affSColin Finck static LONG dll_count;
548c2c66affSColin Finck 
549c2c66affSColin Finck /*
550c2c66affSColin Finck  * Japanese Detection and Conversion Functions
551c2c66affSColin Finck  */
552c2c66affSColin Finck 
553c2c66affSColin Finck #define HANKATA(A)  ((A >= 161) && (A <= 223))
554c2c66affSColin Finck #define ISEUC(A)    ((A >= 161) && (A <= 254))
555c2c66affSColin Finck #define NOTEUC(A,B) (((A >= 129) && (A <= 159)) && ((B >= 64) && (B <= 160)))
556c2c66affSColin Finck #define SJIS1(A)    (((A >= 129) && (A <= 159)) || ((A >= 224) && (A <= 239)))
557c2c66affSColin Finck #define SJIS2(A)    ((A >= 64) && (A <= 252))
558c2c66affSColin Finck #define ISMARU(A)   ((A >= 202) && (A <= 206))
559c2c66affSColin Finck #define ISNIGORI(A) (((A >= 182) && (A <= 196)) || ((A >= 202) && (A <= 206)))
560c2c66affSColin Finck 
DetectJapaneseCode(LPCSTR input,DWORD count)561c2c66affSColin Finck static UINT DetectJapaneseCode(LPCSTR input, DWORD count)
562c2c66affSColin Finck {
563c2c66affSColin Finck     UINT code = 0;
564c2c66affSColin Finck     DWORD i = 0;
565c2c66affSColin Finck     unsigned char c1,c2;
566c2c66affSColin Finck 
567c2c66affSColin Finck     while ((code == 0 || code == 51932) && i < count)
568c2c66affSColin Finck     {
569c2c66affSColin Finck         c1 = input[i];
570c2c66affSColin Finck         if (c1 == 0x1b /* ESC */)
571c2c66affSColin Finck         {
572c2c66affSColin Finck             i++;
573c2c66affSColin Finck             if (i >= count)
574c2c66affSColin Finck                 return code;
575c2c66affSColin Finck             c1 = input[i];
576c2c66affSColin Finck             if (c1 == '$')
577c2c66affSColin Finck             {
578c2c66affSColin Finck                 i++;
579c2c66affSColin Finck                 if (i >= count)
580c2c66affSColin Finck                     return code;
581c2c66affSColin Finck                 c1 = input[i];
582c2c66affSColin Finck                 if (c1 =='B' || c1 == '@')
583c2c66affSColin Finck                     code = 50220;
584c2c66affSColin Finck             }
585c2c66affSColin Finck             if (c1 == 'K')
586c2c66affSColin Finck                 code = 50220;
587c2c66affSColin Finck         }
588c2c66affSColin Finck         else if (c1 >= 129)
589c2c66affSColin Finck         {
590c2c66affSColin Finck             i++;
591c2c66affSColin Finck             if (i >= count)
592c2c66affSColin Finck                 return code;
593c2c66affSColin Finck             c2 = input[i];
594c2c66affSColin Finck             if NOTEUC(c1,c2)
595c2c66affSColin Finck                 code = 932;
596c2c66affSColin Finck             else if (ISEUC(c1) && ISEUC(c2))
597c2c66affSColin Finck                 code = 51932;
598c2c66affSColin Finck             else if (((c1 == 142)) && HANKATA(c2))
599c2c66affSColin Finck                 code = 51932;
600c2c66affSColin Finck         }
601c2c66affSColin Finck         i++;
602c2c66affSColin Finck     }
603c2c66affSColin Finck     return code;
604c2c66affSColin Finck }
605c2c66affSColin Finck 
jis2sjis(unsigned char * p1,unsigned char * p2)606c2c66affSColin Finck static inline void jis2sjis(unsigned char *p1, unsigned char *p2)
607c2c66affSColin Finck {
608c2c66affSColin Finck     unsigned char c1 = *p1;
609c2c66affSColin Finck     unsigned char c2 = *p2;
610c2c66affSColin Finck     int row = c1 < 95 ? 112 : 176;
611c2c66affSColin Finck     int cell = c1 % 2 ? 31 + (c2 > 95) : 126;
612c2c66affSColin Finck 
613c2c66affSColin Finck     *p1 = ((c1 + 1) >> 1) + row;
614c2c66affSColin Finck     *p2 = c2 + cell;
615c2c66affSColin Finck }
616c2c66affSColin Finck 
sjis2jis(unsigned char * p1,unsigned char * p2)617c2c66affSColin Finck static inline void sjis2jis(unsigned char *p1, unsigned char *p2)
618c2c66affSColin Finck {
619c2c66affSColin Finck     unsigned char c1 = *p1;
620c2c66affSColin Finck     unsigned char c2 = *p2;
621c2c66affSColin Finck     int shift = c2 < 159;
622c2c66affSColin Finck     int row = c1 < 160 ? 112 : 176;
623c2c66affSColin Finck     int cell = shift ? (31 + (c2 > 127)): 126;
624c2c66affSColin Finck 
625c2c66affSColin Finck     *p1 = ((c1 - row) << 1) - shift;
626c2c66affSColin Finck     *p2 -= cell;
627c2c66affSColin Finck }
628c2c66affSColin Finck 
han2zen(unsigned char * p1,unsigned char * p2)629c2c66affSColin Finck static int han2zen(unsigned char *p1, unsigned char *p2)
630c2c66affSColin Finck {
631c2c66affSColin Finck     BOOL maru = FALSE;
632c2c66affSColin Finck     BOOL nigori = FALSE;
633c2c66affSColin Finck     static const unsigned char char1[] = {129,129,129,129,129,131,131,131,131,
634c2c66affSColin Finck         131,131,131,131,131,131,129,131,131,131,131,131,131,131,131,131,131,
635c2c66affSColin Finck         131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
636c2c66affSColin Finck         131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
637c2c66affSColin Finck         131,129,129 };
638c2c66affSColin Finck     static const unsigned char char2[] = {66,117,118,65,69,146,64,66,68,70,
639c2c66affSColin Finck         72,131,133,135,98,91,65,67,69,71,73,74,76,78,80,82,84,86,88,90,92,94,
640c2c66affSColin Finck         96,99,101,103,105,106,107,108,109,110,113,116,119,122,125,126,128,
641c2c66affSColin Finck         129,130,132,134,136,137,138,139,140,141,143,147,74,75};
642c2c66affSColin Finck 
643c2c66affSColin Finck     if (( *p2 == 222) && ((ISNIGORI(*p1) || (*p1 == 179))))
644c2c66affSColin Finck             nigori = TRUE;
645c2c66affSColin Finck     else if ((*p2 == 223) && (ISMARU(*p1)))
646c2c66affSColin Finck             maru = TRUE;
647c2c66affSColin Finck 
648c2c66affSColin Finck     if (*p1 >= 161 && *p1 <= 223)
649c2c66affSColin Finck     {
650c2c66affSColin Finck         unsigned char index = *p1 - 161;
651c2c66affSColin Finck         *p1 = char1[index];
652c2c66affSColin Finck         *p2 = char2[index];
653c2c66affSColin Finck     }
654c2c66affSColin Finck 
655c2c66affSColin Finck     if (maru || nigori)
656c2c66affSColin Finck     {
657c2c66affSColin Finck         if (nigori)
658c2c66affSColin Finck         {
659c2c66affSColin Finck             if (((*p2 >= 74) && (*p2 <= 103)) || ((*p2 >= 110) && (*p2 <= 122)))
660c2c66affSColin Finck                 (*p2)++;
661c2c66affSColin Finck             else if ((*p1 == 131) && (*p2 == 69))
662c2c66affSColin Finck                 *p2 = 148;
663c2c66affSColin Finck         }
664c2c66affSColin Finck         else if ((maru) && ((*p2 >= 110) && (*p2 <= 122)))
665c2c66affSColin Finck             *p2+= 2;
666c2c66affSColin Finck 
667c2c66affSColin Finck         return 1;
668c2c66affSColin Finck     }
669c2c66affSColin Finck 
670c2c66affSColin Finck     return 0;
671c2c66affSColin Finck }
672c2c66affSColin Finck 
673c2c66affSColin Finck 
ConvertJIS2SJIS(LPCSTR input,DWORD count,LPSTR output)674c2c66affSColin Finck static UINT ConvertJIS2SJIS(LPCSTR input, DWORD count, LPSTR output)
675c2c66affSColin Finck {
676c2c66affSColin Finck     DWORD i = 0;
677c2c66affSColin Finck     int j = 0;
678c2c66affSColin Finck     unsigned char p2,p;
679c2c66affSColin Finck     BOOL shifted = FALSE;
680c2c66affSColin Finck 
681c2c66affSColin Finck     while (i < count)
682c2c66affSColin Finck     {
683c2c66affSColin Finck         p = input[i];
684c2c66affSColin Finck         if (p == 0x1b /* ESC */)
685c2c66affSColin Finck         {
686c2c66affSColin Finck             i++;
687c2c66affSColin Finck             if (i >= count)
688c2c66affSColin Finck                 return 0;
689c2c66affSColin Finck             p2 = input[i];
690c2c66affSColin Finck             if (p2 == '$' || p2 =='(')
691c2c66affSColin Finck                 i++;
692c2c66affSColin Finck             if (p2 == 'K' || p2 =='$')
693c2c66affSColin Finck                 shifted = TRUE;
694c2c66affSColin Finck             else
695c2c66affSColin Finck                 shifted = FALSE;
696c2c66affSColin Finck         }
697c2c66affSColin Finck         else
698c2c66affSColin Finck         {
699c2c66affSColin Finck             if (shifted)
700c2c66affSColin Finck             {
701c2c66affSColin Finck                 i++;
702c2c66affSColin Finck                 if (i >= count)
703c2c66affSColin Finck                     return 0;
704c2c66affSColin Finck                 p2 = input[i];
705c2c66affSColin Finck                 jis2sjis(&p,&p2);
706c2c66affSColin Finck                 output[j++]=p;
707c2c66affSColin Finck                 output[j++]=p2;
708c2c66affSColin Finck             }
709c2c66affSColin Finck             else
710c2c66affSColin Finck             {
711c2c66affSColin Finck                 output[j++] = p;
712c2c66affSColin Finck             }
713c2c66affSColin Finck         }
714c2c66affSColin Finck         i++;
715c2c66affSColin Finck     }
716c2c66affSColin Finck     return j;
717c2c66affSColin Finck }
718c2c66affSColin Finck 
exit_shift(LPSTR out,int c)719c2c66affSColin Finck static inline int exit_shift(LPSTR out, int c)
720c2c66affSColin Finck {
721c2c66affSColin Finck     if (out)
722c2c66affSColin Finck     {
723c2c66affSColin Finck         out[c] = 0x1b;
724c2c66affSColin Finck         out[c+1] = '(';
725c2c66affSColin Finck         out[c+2] = 'B';
726c2c66affSColin Finck     }
727c2c66affSColin Finck     return 3;
728c2c66affSColin Finck }
729c2c66affSColin Finck 
enter_shift(LPSTR out,int c)730c2c66affSColin Finck static inline int enter_shift(LPSTR out, int c)
731c2c66affSColin Finck {
732c2c66affSColin Finck     if (out)
733c2c66affSColin Finck     {
734c2c66affSColin Finck         out[c] = 0x1b;
735c2c66affSColin Finck         out[c+1] = '$';
736c2c66affSColin Finck         out[c+2] = 'B';
737c2c66affSColin Finck     }
738c2c66affSColin Finck     return 3;
739c2c66affSColin Finck }
740c2c66affSColin Finck 
741c2c66affSColin Finck 
ConvertSJIS2JIS(LPCSTR input,DWORD count,LPSTR output)742c2c66affSColin Finck static UINT ConvertSJIS2JIS(LPCSTR input, DWORD count, LPSTR output)
743c2c66affSColin Finck {
744c2c66affSColin Finck     DWORD i = 0;
745c2c66affSColin Finck     int j = 0;
746c2c66affSColin Finck     unsigned char p2,p;
747c2c66affSColin Finck     BOOL shifted = FALSE;
748c2c66affSColin Finck 
749c2c66affSColin Finck     while (i < count)
750c2c66affSColin Finck     {
751c2c66affSColin Finck         p = input[i] & 0xff;
752c2c66affSColin Finck         if (p == 10 || p == 13) /* NL and CR */
753c2c66affSColin Finck         {
754c2c66affSColin Finck             if (shifted)
755c2c66affSColin Finck             {
756c2c66affSColin Finck                 shifted = FALSE;
757c2c66affSColin Finck                 j += exit_shift(output,j);
758c2c66affSColin Finck             }
759c2c66affSColin Finck             if (output)
760c2c66affSColin Finck                 output[j++] = p;
761c2c66affSColin Finck             else
762c2c66affSColin Finck                 j++;
763c2c66affSColin Finck         }
764c2c66affSColin Finck         else
765c2c66affSColin Finck         {
766c2c66affSColin Finck             if (SJIS1(p))
767c2c66affSColin Finck             {
768c2c66affSColin Finck                 i++;
769c2c66affSColin Finck                 if (i >= count)
770c2c66affSColin Finck                     return 0;
771c2c66affSColin Finck                 p2 = input[i] & 0xff;
772c2c66affSColin Finck                 if (SJIS2(p2))
773c2c66affSColin Finck                 {
774c2c66affSColin Finck                     sjis2jis(&p,&p2);
775c2c66affSColin Finck                     if (!shifted)
776c2c66affSColin Finck                     {
777c2c66affSColin Finck                         shifted = TRUE;
778c2c66affSColin Finck                         j+=enter_shift(output,j);
779c2c66affSColin Finck                     }
780c2c66affSColin Finck                 }
781c2c66affSColin Finck 
782c2c66affSColin Finck                 if (output)
783c2c66affSColin Finck                 {
784c2c66affSColin Finck                     output[j++]=p;
785c2c66affSColin Finck                     output[j++]=p2;
786c2c66affSColin Finck                 }
787c2c66affSColin Finck                 else
788c2c66affSColin Finck                     j+=2;
789c2c66affSColin Finck             }
790c2c66affSColin Finck             else
791c2c66affSColin Finck             {
792c2c66affSColin Finck                 if (HANKATA(p))
793c2c66affSColin Finck                 {
794c2c66affSColin Finck                     if ((i+1) >= count)
795c2c66affSColin Finck                         return 0;
796c2c66affSColin Finck                     p2 = input[i+1] & 0xff;
797c2c66affSColin Finck                     i+=han2zen(&p,&p2);
798c2c66affSColin Finck                     sjis2jis(&p,&p2);
799c2c66affSColin Finck                     if (!shifted)
800c2c66affSColin Finck                     {
801c2c66affSColin Finck                         shifted = TRUE;
802c2c66affSColin Finck                         j+=enter_shift(output,j);
803c2c66affSColin Finck                     }
804c2c66affSColin Finck                     if (output)
805c2c66affSColin Finck                     {
806c2c66affSColin Finck                         output[j++]=p;
807c2c66affSColin Finck                         output[j++]=p2;
808c2c66affSColin Finck                     }
809c2c66affSColin Finck                     else
810c2c66affSColin Finck                         j+=2;
811c2c66affSColin Finck                 }
812c2c66affSColin Finck                 else
813c2c66affSColin Finck                 {
814c2c66affSColin Finck                     if (shifted)
815c2c66affSColin Finck                     {
816c2c66affSColin Finck                         shifted = FALSE;
817c2c66affSColin Finck                         j += exit_shift(output,j);
818c2c66affSColin Finck                     }
819c2c66affSColin Finck                     if (output)
820c2c66affSColin Finck                         output[j++]=p;
821c2c66affSColin Finck                     else
822c2c66affSColin Finck                         j++;
823c2c66affSColin Finck                 }
824c2c66affSColin Finck             }
825c2c66affSColin Finck         }
826c2c66affSColin Finck         i++;
827c2c66affSColin Finck     }
828c2c66affSColin Finck     if (shifted)
829c2c66affSColin Finck         j += exit_shift(output,j);
830c2c66affSColin Finck     return j;
831c2c66affSColin Finck }
832c2c66affSColin Finck 
ConvertJISJapaneseToUnicode(LPCSTR input,DWORD count,LPWSTR output,DWORD out_count)833c2c66affSColin Finck static UINT ConvertJISJapaneseToUnicode(LPCSTR input, DWORD count,
834c2c66affSColin Finck                                         LPWSTR output, DWORD out_count)
835c2c66affSColin Finck {
836c2c66affSColin Finck     CHAR *sjis_string;
837c2c66affSColin Finck     UINT rc = 0;
838c2c66affSColin Finck     sjis_string = HeapAlloc(GetProcessHeap(),0,count);
839c2c66affSColin Finck     rc = ConvertJIS2SJIS(input,count,sjis_string);
840c2c66affSColin Finck     if (rc)
841c2c66affSColin Finck     {
842c2c66affSColin Finck         TRACE("%s\n",debugstr_an(sjis_string,rc));
843c2c66affSColin Finck         if (output)
844c2c66affSColin Finck             rc = MultiByteToWideChar(932,0,sjis_string,rc,output,out_count);
845c2c66affSColin Finck         else
846c2c66affSColin Finck             rc = MultiByteToWideChar(932,0,sjis_string,rc,0,0);
847c2c66affSColin Finck     }
848c2c66affSColin Finck     HeapFree(GetProcessHeap(),0,sjis_string);
849c2c66affSColin Finck     return rc;
850c2c66affSColin Finck 
851c2c66affSColin Finck }
852c2c66affSColin Finck 
ConvertUnknownJapaneseToUnicode(LPCSTR input,DWORD count,LPWSTR output,DWORD out_count)853c2c66affSColin Finck static UINT ConvertUnknownJapaneseToUnicode(LPCSTR input, DWORD count,
854c2c66affSColin Finck                                             LPWSTR output, DWORD out_count)
855c2c66affSColin Finck {
856c2c66affSColin Finck     CHAR *sjis_string;
857c2c66affSColin Finck     UINT rc = 0;
858c2c66affSColin Finck     int code = DetectJapaneseCode(input,count);
859c2c66affSColin Finck     TRACE("Japanese code %i\n",code);
860c2c66affSColin Finck 
861c2c66affSColin Finck     switch (code)
862c2c66affSColin Finck     {
863c2c66affSColin Finck     case 0:
864c2c66affSColin Finck         if (output)
865c2c66affSColin Finck             rc = MultiByteToWideChar(CP_ACP,0,input,count,output,out_count);
866c2c66affSColin Finck         else
867c2c66affSColin Finck             rc = MultiByteToWideChar(CP_ACP,0,input,count,0,0);
868c2c66affSColin Finck         break;
869c2c66affSColin Finck 
870c2c66affSColin Finck     case 932:
871c2c66affSColin Finck         if (output)
872c2c66affSColin Finck             rc = MultiByteToWideChar(932,0,input,count,output,out_count);
873c2c66affSColin Finck         else
874c2c66affSColin Finck             rc = MultiByteToWideChar(932,0,input,count,0,0);
875c2c66affSColin Finck         break;
876c2c66affSColin Finck 
877c2c66affSColin Finck     case 51932:
878c2c66affSColin Finck         if (output)
879c2c66affSColin Finck             rc = MultiByteToWideChar(20932,0,input,count,output,out_count);
880c2c66affSColin Finck         else
881c2c66affSColin Finck             rc = MultiByteToWideChar(20932,0,input,count,0,0);
882c2c66affSColin Finck         break;
883c2c66affSColin Finck 
884c2c66affSColin Finck     case 50220:
885c2c66affSColin Finck         sjis_string = HeapAlloc(GetProcessHeap(),0,count);
886c2c66affSColin Finck         rc = ConvertJIS2SJIS(input,count,sjis_string);
887c2c66affSColin Finck         if (rc)
888c2c66affSColin Finck         {
889c2c66affSColin Finck             TRACE("%s\n",debugstr_an(sjis_string,rc));
890c2c66affSColin Finck             if (output)
891c2c66affSColin Finck                 rc = MultiByteToWideChar(932,0,sjis_string,rc,output,out_count);
892c2c66affSColin Finck             else
893c2c66affSColin Finck                 rc = MultiByteToWideChar(932,0,sjis_string,rc,0,0);
894c2c66affSColin Finck         }
895c2c66affSColin Finck         HeapFree(GetProcessHeap(),0,sjis_string);
896c2c66affSColin Finck         break;
897c2c66affSColin Finck     }
898c2c66affSColin Finck     return rc;
899c2c66affSColin Finck }
900c2c66affSColin Finck 
ConvertJapaneseUnicodeToJIS(LPCWSTR input,DWORD count,LPSTR output,DWORD out_count)901c2c66affSColin Finck static UINT ConvertJapaneseUnicodeToJIS(LPCWSTR input, DWORD count,
902c2c66affSColin Finck                                         LPSTR output, DWORD out_count)
903c2c66affSColin Finck {
904c2c66affSColin Finck     CHAR *sjis_string;
905c2c66affSColin Finck     INT len;
906c2c66affSColin Finck     UINT rc = 0;
907c2c66affSColin Finck 
908c2c66affSColin Finck     len = WideCharToMultiByte(932,0,input,count,0,0,NULL,NULL);
909c2c66affSColin Finck     sjis_string = HeapAlloc(GetProcessHeap(),0,len);
910c2c66affSColin Finck     WideCharToMultiByte(932,0,input,count,sjis_string,len,NULL,NULL);
911c2c66affSColin Finck     TRACE("%s\n",debugstr_an(sjis_string,len));
912c2c66affSColin Finck 
913c2c66affSColin Finck     rc = ConvertSJIS2JIS(sjis_string, len, NULL);
914c2c66affSColin Finck     if (out_count >= rc)
915c2c66affSColin Finck     {
916c2c66affSColin Finck         ConvertSJIS2JIS(sjis_string, len, output);
917c2c66affSColin Finck     }
918c2c66affSColin Finck     HeapFree(GetProcessHeap(),0,sjis_string);
919c2c66affSColin Finck     return rc;
920c2c66affSColin Finck 
921c2c66affSColin Finck }
922c2c66affSColin Finck 
923c2c66affSColin Finck /*
924c2c66affSColin Finck  * Dll lifetime tracking declaration
925c2c66affSColin Finck  */
LockModule(void)926c2c66affSColin Finck static void LockModule(void)
927c2c66affSColin Finck {
928c2c66affSColin Finck     InterlockedIncrement(&dll_count);
929c2c66affSColin Finck }
930c2c66affSColin Finck 
UnlockModule(void)931c2c66affSColin Finck static void UnlockModule(void)
932c2c66affSColin Finck {
933c2c66affSColin Finck     InterlockedDecrement(&dll_count);
934c2c66affSColin Finck }
935c2c66affSColin Finck 
DllMain(HINSTANCE hInstDLL,DWORD fdwReason,LPVOID lpv)936c2c66affSColin Finck BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
937c2c66affSColin Finck {
938c2c66affSColin Finck     switch(fdwReason) {
939c2c66affSColin Finck         case DLL_PROCESS_ATTACH:
940c2c66affSColin Finck             instance = hInstDLL;
941c2c66affSColin Finck             MLANG_tls_index = TlsAlloc();
942c2c66affSColin Finck             DisableThreadLibraryCalls(hInstDLL);
943c2c66affSColin Finck 	    break;
944c2c66affSColin Finck 	case DLL_PROCESS_DETACH:
945c2c66affSColin Finck             if (lpv) break;
946c2c66affSColin Finck             TlsFree(MLANG_tls_index);
947c2c66affSColin Finck 	    break;
948c2c66affSColin Finck     }
949c2c66affSColin Finck     return TRUE;
950c2c66affSColin Finck }
951c2c66affSColin Finck 
ConvertINetMultiByteToUnicode(LPDWORD pdwMode,DWORD dwEncoding,LPCSTR pSrcStr,LPINT pcSrcSize,LPWSTR pDstStr,LPINT pcDstSize)952c2c66affSColin Finck HRESULT WINAPI ConvertINetMultiByteToUnicode(
953c2c66affSColin Finck     LPDWORD pdwMode,
954c2c66affSColin Finck     DWORD dwEncoding,
955c2c66affSColin Finck     LPCSTR pSrcStr,
956c2c66affSColin Finck     LPINT pcSrcSize,
957c2c66affSColin Finck     LPWSTR pDstStr,
958c2c66affSColin Finck     LPINT pcDstSize)
959c2c66affSColin Finck {
960c2c66affSColin Finck     INT src_len = -1;
961c2c66affSColin Finck 
962c2c66affSColin Finck     TRACE("%p %d %s %p %p %p\n", pdwMode, dwEncoding,
963c2c66affSColin Finck           debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
964c2c66affSColin Finck 
965c2c66affSColin Finck     if (!pcDstSize)
966c2c66affSColin Finck         return E_FAIL;
967c2c66affSColin Finck 
968c2c66affSColin Finck     if (!pcSrcSize)
969c2c66affSColin Finck         pcSrcSize = &src_len;
970c2c66affSColin Finck 
971c2c66affSColin Finck     if (!*pcSrcSize)
972c2c66affSColin Finck     {
973c2c66affSColin Finck         *pcDstSize = 0;
974c2c66affSColin Finck         return S_OK;
975c2c66affSColin Finck     }
976c2c66affSColin Finck 
977c2c66affSColin Finck     /* forwarding euc-jp to EUC-JP */
978c2c66affSColin Finck     if (dwEncoding == 51932)
979c2c66affSColin Finck         dwEncoding = 20932;
980c2c66affSColin Finck 
981c2c66affSColin Finck     switch (dwEncoding)
982c2c66affSColin Finck     {
983c2c66affSColin Finck     case CP_UNICODE:
984c2c66affSColin Finck         if (*pcSrcSize == -1)
985c2c66affSColin Finck             *pcSrcSize = lstrlenW((LPCWSTR)pSrcStr);
986c2c66affSColin Finck         *pcDstSize = min(*pcSrcSize, *pcDstSize);
987c2c66affSColin Finck         *pcSrcSize *= sizeof(WCHAR);
988c2c66affSColin Finck         if (pDstStr)
989c2c66affSColin Finck             memmove(pDstStr, pSrcStr, *pcDstSize * sizeof(WCHAR));
990c2c66affSColin Finck         break;
991c2c66affSColin Finck 
992c2c66affSColin Finck     case 50220:
993c2c66affSColin Finck     case 50221:
994c2c66affSColin Finck     case 50222:
995c2c66affSColin Finck         *pcDstSize = ConvertJISJapaneseToUnicode(pSrcStr,*pcSrcSize,pDstStr,*pcDstSize);
996c2c66affSColin Finck         break;
997c2c66affSColin Finck     case 50932:
998c2c66affSColin Finck         *pcDstSize = ConvertUnknownJapaneseToUnicode(pSrcStr,*pcSrcSize,pDstStr,*pcDstSize);
999c2c66affSColin Finck         break;
1000c2c66affSColin Finck 
1001c2c66affSColin Finck     default:
1002c2c66affSColin Finck         if (*pcSrcSize == -1)
1003c2c66affSColin Finck             *pcSrcSize = lstrlenA(pSrcStr);
1004c2c66affSColin Finck 
1005c2c66affSColin Finck         if (pDstStr)
1006c2c66affSColin Finck             *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, pDstStr, *pcDstSize);
1007c2c66affSColin Finck         else
1008c2c66affSColin Finck             *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, NULL, 0);
1009c2c66affSColin Finck         break;
1010c2c66affSColin Finck     }
1011c2c66affSColin Finck 
1012c2c66affSColin Finck     if (!*pcDstSize)
1013c2c66affSColin Finck         return E_FAIL;
1014c2c66affSColin Finck 
1015c2c66affSColin Finck     return S_OK;
1016c2c66affSColin Finck }
1017c2c66affSColin Finck 
ConvertINetUnicodeToMultiByte(LPDWORD pdwMode,DWORD dwEncoding,LPCWSTR pSrcStr,LPINT pcSrcSize,LPSTR pDstStr,LPINT pcDstSize)1018c2c66affSColin Finck HRESULT WINAPI ConvertINetUnicodeToMultiByte(
1019c2c66affSColin Finck     LPDWORD pdwMode,
1020c2c66affSColin Finck     DWORD dwEncoding,
1021c2c66affSColin Finck     LPCWSTR pSrcStr,
1022c2c66affSColin Finck     LPINT pcSrcSize,
1023c2c66affSColin Finck     LPSTR pDstStr,
1024c2c66affSColin Finck     LPINT pcDstSize)
1025c2c66affSColin Finck {
1026c2c66affSColin Finck     INT destsz, size;
1027c2c66affSColin Finck     INT src_len = -1;
1028c2c66affSColin Finck 
1029c2c66affSColin Finck     TRACE("%p %d %s %p %p %p\n", pdwMode, dwEncoding,
1030c2c66affSColin Finck           debugstr_w(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
1031c2c66affSColin Finck 
1032c2c66affSColin Finck     if (!pcDstSize)
1033c2c66affSColin Finck         return S_OK;
1034c2c66affSColin Finck 
1035c2c66affSColin Finck     if (!pcSrcSize)
1036c2c66affSColin Finck         pcSrcSize = &src_len;
1037c2c66affSColin Finck 
1038c2c66affSColin Finck     destsz = (pDstStr) ? *pcDstSize : 0;
1039c2c66affSColin Finck     *pcDstSize = 0;
1040c2c66affSColin Finck 
1041c2c66affSColin Finck     if (!pSrcStr || !*pcSrcSize)
1042c2c66affSColin Finck         return S_OK;
1043c2c66affSColin Finck 
1044c2c66affSColin Finck     if (*pcSrcSize == -1)
1045c2c66affSColin Finck         *pcSrcSize = lstrlenW(pSrcStr);
1046c2c66affSColin Finck 
1047c2c66affSColin Finck     /* forwarding euc-jp to EUC-JP */
1048c2c66affSColin Finck     if (dwEncoding == 51932)
1049c2c66affSColin Finck         dwEncoding = 20932;
1050c2c66affSColin Finck 
1051c2c66affSColin Finck     if (dwEncoding == CP_UNICODE)
1052c2c66affSColin Finck     {
1053c2c66affSColin Finck         if (*pcSrcSize == -1)
1054c2c66affSColin Finck             *pcSrcSize = lstrlenW(pSrcStr);
1055c2c66affSColin Finck 
1056c2c66affSColin Finck         size = min(*pcSrcSize, destsz) * sizeof(WCHAR);
1057c2c66affSColin Finck         if (pDstStr)
1058c2c66affSColin Finck             memmove(pDstStr, pSrcStr, size);
1059c2c66affSColin Finck 
1060c2c66affSColin Finck         if (size >= destsz)
1061c2c66affSColin Finck             goto fail;
1062c2c66affSColin Finck     }
1063c2c66affSColin Finck     else if (dwEncoding == 50220 || dwEncoding == 50221 || dwEncoding == 50222)
1064c2c66affSColin Finck     {
1065c2c66affSColin Finck         size = ConvertJapaneseUnicodeToJIS(pSrcStr, *pcSrcSize, NULL, 0);
1066c2c66affSColin Finck         if (!size)
1067c2c66affSColin Finck             goto fail;
1068c2c66affSColin Finck 
1069c2c66affSColin Finck         if (pDstStr)
1070c2c66affSColin Finck         {
1071c2c66affSColin Finck             size = ConvertJapaneseUnicodeToJIS(pSrcStr, *pcSrcSize, pDstStr,
1072c2c66affSColin Finck                                                destsz);
1073c2c66affSColin Finck             if (!size)
1074c2c66affSColin Finck                 goto fail;
1075c2c66affSColin Finck         }
1076c2c66affSColin Finck 
1077c2c66affSColin Finck     }
1078c2c66affSColin Finck     else
1079c2c66affSColin Finck     {
1080c2c66affSColin Finck         size = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize,
1081c2c66affSColin Finck                                    NULL, 0, NULL, NULL);
1082c2c66affSColin Finck         if (!size)
1083c2c66affSColin Finck             goto fail;
1084c2c66affSColin Finck 
1085c2c66affSColin Finck         if (pDstStr)
1086c2c66affSColin Finck         {
1087c2c66affSColin Finck             size = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize,
1088c2c66affSColin Finck                                        pDstStr, destsz, NULL, NULL);
1089c2c66affSColin Finck             if (!size)
1090c2c66affSColin Finck                 goto fail;
1091c2c66affSColin Finck         }
1092c2c66affSColin Finck     }
1093c2c66affSColin Finck 
1094c2c66affSColin Finck     *pcDstSize = size;
1095c2c66affSColin Finck     return S_OK;
1096c2c66affSColin Finck 
1097c2c66affSColin Finck fail:
1098c2c66affSColin Finck     *pcSrcSize = 0;
1099c2c66affSColin Finck     *pcDstSize = 0;
1100c2c66affSColin Finck     return E_FAIL;
1101c2c66affSColin Finck }
1102c2c66affSColin Finck 
ConvertINetString(LPDWORD pdwMode,DWORD dwSrcEncoding,DWORD dwDstEncoding,LPCSTR pSrcStr,LPINT pcSrcSize,LPSTR pDstStr,LPINT pcDstSize)1103c2c66affSColin Finck HRESULT WINAPI ConvertINetString(
1104c2c66affSColin Finck     LPDWORD pdwMode,
1105c2c66affSColin Finck     DWORD dwSrcEncoding,
1106c2c66affSColin Finck     DWORD dwDstEncoding,
1107c2c66affSColin Finck     LPCSTR pSrcStr,
1108c2c66affSColin Finck     LPINT pcSrcSize,
1109c2c66affSColin Finck     LPSTR pDstStr,
1110c2c66affSColin Finck     LPINT pcDstSize
1111c2c66affSColin Finck )
1112c2c66affSColin Finck {
1113c2c66affSColin Finck     TRACE("%p %d %d %s %p %p %p\n", pdwMode, dwSrcEncoding, dwDstEncoding,
1114c2c66affSColin Finck           debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
1115c2c66affSColin Finck 
1116c2c66affSColin Finck     if (dwSrcEncoding == CP_UNICODE)
1117c2c66affSColin Finck     {
1118c2c66affSColin Finck         INT cSrcSizeW;
1119c2c66affSColin Finck         if (pcSrcSize && *pcSrcSize != -1)
1120c2c66affSColin Finck         {
1121c2c66affSColin Finck             cSrcSizeW = *pcSrcSize / sizeof(WCHAR);
1122c2c66affSColin Finck             pcSrcSize = &cSrcSizeW;
1123c2c66affSColin Finck         }
1124c2c66affSColin Finck         return ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, (LPCWSTR)pSrcStr, pcSrcSize, pDstStr, pcDstSize);
1125c2c66affSColin Finck     }
1126c2c66affSColin Finck     else if (dwDstEncoding == CP_UNICODE)
1127c2c66affSColin Finck     {
1128c2c66affSColin Finck         HRESULT hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, (LPWSTR)pDstStr, pcDstSize);
1129c2c66affSColin Finck         *pcDstSize *= sizeof(WCHAR);
1130c2c66affSColin Finck         return hr;
1131c2c66affSColin Finck     }
1132c2c66affSColin Finck     else
1133c2c66affSColin Finck     {
1134c2c66affSColin Finck         INT cDstSizeW;
1135c2c66affSColin Finck         LPWSTR pDstStrW;
1136c2c66affSColin Finck         HRESULT hr;
1137c2c66affSColin Finck 
1138c2c66affSColin Finck         TRACE("convert %s from %d to %d\n", debugstr_a(pSrcStr), dwSrcEncoding, dwDstEncoding);
1139c2c66affSColin Finck 
1140c2c66affSColin Finck         hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, NULL, &cDstSizeW);
1141c2c66affSColin Finck         if (hr != S_OK)
1142c2c66affSColin Finck             return hr;
1143c2c66affSColin Finck 
1144c2c66affSColin Finck         pDstStrW = HeapAlloc(GetProcessHeap(), 0, cDstSizeW * sizeof(WCHAR));
1145c2c66affSColin Finck         hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, pDstStrW, &cDstSizeW);
1146c2c66affSColin Finck         if (hr == S_OK)
1147c2c66affSColin Finck             hr = ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, pDstStrW, &cDstSizeW, pDstStr, pcDstSize);
1148c2c66affSColin Finck 
1149c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, pDstStrW);
1150c2c66affSColin Finck         return hr;
1151c2c66affSColin Finck     }
1152c2c66affSColin Finck }
1153c2c66affSColin Finck 
GetFamilyCodePage(UINT uiCodePage,UINT * puiFamilyCodePage)1154c2c66affSColin Finck static HRESULT GetFamilyCodePage(
1155c2c66affSColin Finck     UINT uiCodePage,
1156c2c66affSColin Finck     UINT* puiFamilyCodePage)
1157c2c66affSColin Finck {
1158c2c66affSColin Finck     UINT i, n;
1159c2c66affSColin Finck 
1160c2c66affSColin Finck     TRACE("%u %p\n", uiCodePage, puiFamilyCodePage);
1161c2c66affSColin Finck 
1162c2c66affSColin Finck     if (!puiFamilyCodePage) return S_FALSE;
1163c2c66affSColin Finck 
1164ccc3eeaeSAmine Khaldi     for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
1165c2c66affSColin Finck     {
1166c2c66affSColin Finck         for (n = 0; n < mlang_data[i].number_of_cp; n++)
1167c2c66affSColin Finck         {
1168c2c66affSColin Finck             if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
1169c2c66affSColin Finck             {
1170c2c66affSColin Finck                 *puiFamilyCodePage = mlang_data[i].family_codepage;
1171c2c66affSColin Finck                 return S_OK;
1172c2c66affSColin Finck             }
1173c2c66affSColin Finck         }
1174c2c66affSColin Finck     }
1175c2c66affSColin Finck 
1176c2c66affSColin Finck     return S_FALSE;
1177c2c66affSColin Finck }
1178c2c66affSColin Finck 
IsConvertINetStringAvailable(DWORD dwSrcEncoding,DWORD dwDstEncoding)1179c2c66affSColin Finck HRESULT WINAPI IsConvertINetStringAvailable(
1180c2c66affSColin Finck     DWORD dwSrcEncoding,
1181c2c66affSColin Finck     DWORD dwDstEncoding)
1182c2c66affSColin Finck {
1183c2c66affSColin Finck     UINT src_family, dst_family;
1184c2c66affSColin Finck 
1185c2c66affSColin Finck     TRACE("%d %d\n", dwSrcEncoding, dwDstEncoding);
1186c2c66affSColin Finck 
1187c2c66affSColin Finck     if (GetFamilyCodePage(dwSrcEncoding, &src_family) != S_OK ||
1188c2c66affSColin Finck         GetFamilyCodePage(dwDstEncoding, &dst_family) != S_OK)
1189c2c66affSColin Finck         return S_FALSE;
1190c2c66affSColin Finck 
1191c2c66affSColin Finck     if (src_family == dst_family) return S_OK;
1192c2c66affSColin Finck 
1193c2c66affSColin Finck     /* we can convert any codepage to/from unicode */
1194c2c66affSColin Finck     if (src_family == CP_UNICODE || dst_family == CP_UNICODE) return S_OK;
1195c2c66affSColin Finck 
1196c2c66affSColin Finck     return S_FALSE;
1197c2c66affSColin Finck }
1198c2c66affSColin Finck 
lcid_to_rfc1766A(LCID lcid,LPSTR rfc1766,INT len)1199c2c66affSColin Finck static inline HRESULT lcid_to_rfc1766A( LCID lcid, LPSTR rfc1766, INT len )
1200c2c66affSColin Finck {
1201c2c66affSColin Finck     CHAR buffer[MAX_RFC1766_NAME];
1202c2c66affSColin Finck     INT n = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, buffer, MAX_RFC1766_NAME);
1203c2c66affSColin Finck     INT i;
1204c2c66affSColin Finck 
1205c2c66affSColin Finck     if (n)
1206c2c66affSColin Finck     {
1207c2c66affSColin Finck         i = PRIMARYLANGID(lcid);
1208c2c66affSColin Finck         if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
1209c2c66affSColin Finck             (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
1210c2c66affSColin Finck             (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
1211c2c66affSColin Finck 
1212c2c66affSColin Finck             buffer[n - 1] = '-';
1213c2c66affSColin Finck             i = GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, MAX_RFC1766_NAME - n);
1214c2c66affSColin Finck             if (!i)
1215c2c66affSColin Finck                 buffer[n - 1] = '\0';
1216c2c66affSColin Finck         }
1217c2c66affSColin Finck         else
1218c2c66affSColin Finck             i = 0;
1219c2c66affSColin Finck 
1220c2c66affSColin Finck         LCMapStringA( LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len );
1221c2c66affSColin Finck         return ((n + i) > len) ? E_INVALIDARG : S_OK;
1222c2c66affSColin Finck     }
1223c2c66affSColin Finck     return E_FAIL;
1224c2c66affSColin Finck }
1225c2c66affSColin Finck 
lcid_to_rfc1766W(LCID lcid,LPWSTR rfc1766,INT len)1226c2c66affSColin Finck static inline HRESULT lcid_to_rfc1766W( LCID lcid, LPWSTR rfc1766, INT len )
1227c2c66affSColin Finck {
1228c2c66affSColin Finck     WCHAR buffer[MAX_RFC1766_NAME];
1229c2c66affSColin Finck     INT n = GetLocaleInfoW(lcid, LOCALE_SISO639LANGNAME, buffer, MAX_RFC1766_NAME);
1230c2c66affSColin Finck     INT i;
1231c2c66affSColin Finck 
1232c2c66affSColin Finck     if (n)
1233c2c66affSColin Finck     {
1234c2c66affSColin Finck         i = PRIMARYLANGID(lcid);
1235c2c66affSColin Finck         if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
1236c2c66affSColin Finck             (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
1237c2c66affSColin Finck             (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
1238c2c66affSColin Finck 
1239c2c66affSColin Finck             buffer[n - 1] = '-';
1240c2c66affSColin Finck             i = GetLocaleInfoW(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, MAX_RFC1766_NAME - n);
1241c2c66affSColin Finck             if (!i)
1242c2c66affSColin Finck                 buffer[n - 1] = '\0';
1243c2c66affSColin Finck         }
1244c2c66affSColin Finck         else
1245c2c66affSColin Finck             i = 0;
1246c2c66affSColin Finck 
1247c2c66affSColin Finck         LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len);
1248c2c66affSColin Finck         return ((n + i) > len) ? E_INVALIDARG : S_OK;
1249c2c66affSColin Finck     }
1250c2c66affSColin Finck     return E_FAIL;
1251c2c66affSColin Finck }
1252c2c66affSColin Finck 
LcidToRfc1766A(LCID lcid,LPSTR pszRfc1766,INT nChar)1253c2c66affSColin Finck HRESULT WINAPI LcidToRfc1766A(
1254c2c66affSColin Finck     LCID lcid,
1255c2c66affSColin Finck     LPSTR pszRfc1766,
1256c2c66affSColin Finck     INT nChar)
1257c2c66affSColin Finck {
1258c2c66affSColin Finck     TRACE("%04x %p %u\n", lcid, pszRfc1766, nChar);
1259c2c66affSColin Finck     if (!pszRfc1766)
1260c2c66affSColin Finck         return E_INVALIDARG;
1261c2c66affSColin Finck 
1262c2c66affSColin Finck     return lcid_to_rfc1766A(lcid, pszRfc1766, nChar);
1263c2c66affSColin Finck }
1264c2c66affSColin Finck 
LcidToRfc1766W(LCID lcid,LPWSTR pszRfc1766,INT nChar)1265c2c66affSColin Finck HRESULT WINAPI LcidToRfc1766W(
1266c2c66affSColin Finck     LCID lcid,
1267c2c66affSColin Finck     LPWSTR pszRfc1766,
1268c2c66affSColin Finck     INT nChar)
1269c2c66affSColin Finck {
1270c2c66affSColin Finck     TRACE("%04x %p %u\n", lcid, pszRfc1766, nChar);
1271c2c66affSColin Finck     if (!pszRfc1766)
1272c2c66affSColin Finck         return E_INVALIDARG;
1273c2c66affSColin Finck 
1274c2c66affSColin Finck     return lcid_to_rfc1766W(lcid, pszRfc1766, nChar);
1275c2c66affSColin Finck }
1276c2c66affSColin Finck 
lcid_from_rfc1766(IEnumRfc1766 * iface,LCID * lcid,LPCWSTR rfc1766)1277c2c66affSColin Finck static HRESULT lcid_from_rfc1766(IEnumRfc1766 *iface, LCID *lcid, LPCWSTR rfc1766)
1278c2c66affSColin Finck {
1279c2c66affSColin Finck     RFC1766INFO info;
1280c2c66affSColin Finck     ULONG num;
1281c2c66affSColin Finck 
1282c2c66affSColin Finck     while (IEnumRfc1766_Next(iface, 1, &info, &num) == S_OK)
1283c2c66affSColin Finck     {
1284853d6414SAmine Khaldi         if (!wcsicmp(info.wszRfc1766, rfc1766))
1285c2c66affSColin Finck         {
1286c2c66affSColin Finck             *lcid = info.lcid;
1287c2c66affSColin Finck             return S_OK;
1288c2c66affSColin Finck         }
1289853d6414SAmine Khaldi         if (lstrlenW(rfc1766) == 2 && !memcmp(info.wszRfc1766, rfc1766, 2 * sizeof(WCHAR)))
1290c2c66affSColin Finck         {
1291c2c66affSColin Finck             *lcid = PRIMARYLANGID(info.lcid);
1292c2c66affSColin Finck             return S_OK;
1293c2c66affSColin Finck         }
1294c2c66affSColin Finck     }
1295c2c66affSColin Finck 
1296c2c66affSColin Finck     return E_FAIL;
1297c2c66affSColin Finck }
1298c2c66affSColin Finck 
Rfc1766ToLcidW(LCID * pLocale,LPCWSTR pszRfc1766)1299c2c66affSColin Finck HRESULT WINAPI Rfc1766ToLcidW(LCID *pLocale, LPCWSTR pszRfc1766)
1300c2c66affSColin Finck {
1301c2c66affSColin Finck     IEnumRfc1766 *enumrfc1766;
1302c2c66affSColin Finck     HRESULT hr;
1303c2c66affSColin Finck 
1304c2c66affSColin Finck     TRACE("(%p, %s)\n", pLocale, debugstr_w(pszRfc1766));
1305c2c66affSColin Finck 
1306c2c66affSColin Finck     if (!pLocale || !pszRfc1766)
1307c2c66affSColin Finck         return E_INVALIDARG;
1308c2c66affSColin Finck 
1309c2c66affSColin Finck     hr = EnumRfc1766_create(0, &enumrfc1766);
1310c2c66affSColin Finck     if (FAILED(hr))
1311c2c66affSColin Finck         return hr;
1312c2c66affSColin Finck 
1313c2c66affSColin Finck     hr = lcid_from_rfc1766(enumrfc1766, pLocale, pszRfc1766);
1314c2c66affSColin Finck     IEnumRfc1766_Release(enumrfc1766);
1315c2c66affSColin Finck 
1316c2c66affSColin Finck     return hr;
1317c2c66affSColin Finck }
1318c2c66affSColin Finck 
Rfc1766ToLcidA(LCID * lcid,LPCSTR rfc1766A)1319c2c66affSColin Finck HRESULT WINAPI Rfc1766ToLcidA(LCID *lcid, LPCSTR rfc1766A)
1320c2c66affSColin Finck {
1321c2c66affSColin Finck     WCHAR rfc1766W[MAX_RFC1766_NAME + 1];
1322c2c66affSColin Finck 
1323c2c66affSColin Finck     if (!rfc1766A)
1324c2c66affSColin Finck         return E_INVALIDARG;
1325c2c66affSColin Finck 
1326c2c66affSColin Finck     MultiByteToWideChar(CP_ACP, 0, rfc1766A, -1, rfc1766W, MAX_RFC1766_NAME);
1327c2c66affSColin Finck     rfc1766W[MAX_RFC1766_NAME] = 0;
1328c2c66affSColin Finck 
1329c2c66affSColin Finck     return Rfc1766ToLcidW(lcid, rfc1766W);
1330c2c66affSColin Finck }
1331c2c66affSColin Finck 
map_font(HDC hdc,DWORD codepages,HFONT src_font,HFONT * dst_font)13325e2c163fSAmine Khaldi static HRESULT map_font(HDC hdc, DWORD codepages, HFONT src_font, HFONT *dst_font)
13335e2c163fSAmine Khaldi {
13345e2c163fSAmine Khaldi     struct font_list *font_list_entry;
13355e2c163fSAmine Khaldi     CHARSETINFO charset_info;
13365e2c163fSAmine Khaldi     HFONT new_font, old_font;
13375e2c163fSAmine Khaldi     LOGFONTW font_attr;
13385e2c163fSAmine Khaldi     DWORD mask, Csb[2];
13395e2c163fSAmine Khaldi     BOOL found_cached;
13405e2c163fSAmine Khaldi     UINT charset;
13415e2c163fSAmine Khaldi     BOOL ret;
13425e2c163fSAmine Khaldi     UINT i;
13435e2c163fSAmine Khaldi 
13445e2c163fSAmine Khaldi     if (hdc == NULL || src_font == NULL) return E_FAIL;
13455e2c163fSAmine Khaldi 
13465e2c163fSAmine Khaldi     for (i = 0; i < 32; i++)
13475e2c163fSAmine Khaldi     {
13485e2c163fSAmine Khaldi         mask = (DWORD)(1 << i);
13495e2c163fSAmine Khaldi         if (codepages & mask)
13505e2c163fSAmine Khaldi         {
13515e2c163fSAmine Khaldi             Csb[0] = mask;
13525e2c163fSAmine Khaldi             Csb[1] = 0x0;
13535e2c163fSAmine Khaldi             ret = TranslateCharsetInfo(Csb, &charset_info, TCI_SRCFONTSIG);
13545e2c163fSAmine Khaldi             if (!ret) continue;
13555e2c163fSAmine Khaldi 
13565e2c163fSAmine Khaldi             /* use cached font if possible */
13575e2c163fSAmine Khaldi             found_cached = FALSE;
13585e2c163fSAmine Khaldi             EnterCriticalSection(&font_cache_critical);
13595e2c163fSAmine Khaldi             LIST_FOR_EACH_ENTRY(font_list_entry, &font_cache, struct font_list, list_entry)
13605e2c163fSAmine Khaldi             {
13615e2c163fSAmine Khaldi                 if (font_list_entry->charset == charset_info.ciCharset &&
13625e2c163fSAmine Khaldi                     font_list_entry->base_font == src_font)
13635e2c163fSAmine Khaldi                 {
13645e2c163fSAmine Khaldi                     if (dst_font != NULL)
13655e2c163fSAmine Khaldi                         *dst_font = font_list_entry->font;
13665e2c163fSAmine Khaldi                     found_cached = TRUE;
13675e2c163fSAmine Khaldi                 }
13685e2c163fSAmine Khaldi             }
13695e2c163fSAmine Khaldi             LeaveCriticalSection(&font_cache_critical);
13705e2c163fSAmine Khaldi             if (found_cached) return S_OK;
13715e2c163fSAmine Khaldi 
13725e2c163fSAmine Khaldi             GetObjectW(src_font, sizeof(font_attr), &font_attr);
13735e2c163fSAmine Khaldi             font_attr.lfCharSet = (BYTE)charset_info.ciCharset;
13745e2c163fSAmine Khaldi             font_attr.lfWidth = 0;
13755e2c163fSAmine Khaldi             font_attr.lfFaceName[0] = 0;
13765e2c163fSAmine Khaldi             new_font = CreateFontIndirectW(&font_attr);
13775e2c163fSAmine Khaldi             if (new_font == NULL) continue;
13785e2c163fSAmine Khaldi 
13795e2c163fSAmine Khaldi             old_font = SelectObject(hdc, new_font);
13805e2c163fSAmine Khaldi             charset = GetTextCharset(hdc);
13815e2c163fSAmine Khaldi             SelectObject(hdc, old_font);
13825e2c163fSAmine Khaldi             if (charset == charset_info.ciCharset)
13835e2c163fSAmine Khaldi             {
13845e2c163fSAmine Khaldi                 font_list_entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*font_list_entry));
13855e2c163fSAmine Khaldi                 if (font_list_entry == NULL) return E_OUTOFMEMORY;
13865e2c163fSAmine Khaldi 
13875e2c163fSAmine Khaldi                 font_list_entry->base_font = src_font;
13885e2c163fSAmine Khaldi                 font_list_entry->font = new_font;
13895e2c163fSAmine Khaldi                 font_list_entry->charset = charset;
13905e2c163fSAmine Khaldi 
13915e2c163fSAmine Khaldi                 EnterCriticalSection(&font_cache_critical);
13925e2c163fSAmine Khaldi                 list_add_tail(&font_cache, &font_list_entry->list_entry);
13935e2c163fSAmine Khaldi                 LeaveCriticalSection(&font_cache_critical);
13945e2c163fSAmine Khaldi 
13955e2c163fSAmine Khaldi                 if (dst_font != NULL)
13965e2c163fSAmine Khaldi                     *dst_font = new_font;
13975e2c163fSAmine Khaldi                 return S_OK;
13985e2c163fSAmine Khaldi             }
13995e2c163fSAmine Khaldi         }
14005e2c163fSAmine Khaldi     }
14015e2c163fSAmine Khaldi 
14025e2c163fSAmine Khaldi     return E_FAIL;
14035e2c163fSAmine Khaldi }
14045e2c163fSAmine Khaldi 
release_font(HFONT font)14055e2c163fSAmine Khaldi static HRESULT release_font(HFONT font)
14065e2c163fSAmine Khaldi {
14075e2c163fSAmine Khaldi     struct font_list *font_list_entry;
14085e2c163fSAmine Khaldi     HRESULT hr;
14095e2c163fSAmine Khaldi 
14105e2c163fSAmine Khaldi     hr = E_FAIL;
14115e2c163fSAmine Khaldi     EnterCriticalSection(&font_cache_critical);
14125e2c163fSAmine Khaldi     LIST_FOR_EACH_ENTRY(font_list_entry, &font_cache, struct font_list, list_entry)
14135e2c163fSAmine Khaldi     {
14145e2c163fSAmine Khaldi         if (font_list_entry->font == font)
14155e2c163fSAmine Khaldi         {
14165e2c163fSAmine Khaldi             list_remove(&font_list_entry->list_entry);
14175e2c163fSAmine Khaldi             DeleteObject(font);
14185e2c163fSAmine Khaldi             HeapFree(GetProcessHeap(), 0, font_list_entry);
14195e2c163fSAmine Khaldi             hr = S_OK;
14205e2c163fSAmine Khaldi             break;
14215e2c163fSAmine Khaldi         }
14225e2c163fSAmine Khaldi     }
14235e2c163fSAmine Khaldi     LeaveCriticalSection(&font_cache_critical);
14245e2c163fSAmine Khaldi 
14255e2c163fSAmine Khaldi     return hr;
14265e2c163fSAmine Khaldi }
14275e2c163fSAmine Khaldi 
clear_font_cache(void)14285e2c163fSAmine Khaldi static HRESULT clear_font_cache(void)
14295e2c163fSAmine Khaldi {
14305e2c163fSAmine Khaldi     struct font_list *font_list_entry;
14315e2c163fSAmine Khaldi     struct font_list *font_list_entry2;
14325e2c163fSAmine Khaldi 
14335e2c163fSAmine Khaldi     EnterCriticalSection(&font_cache_critical);
14345e2c163fSAmine Khaldi     LIST_FOR_EACH_ENTRY_SAFE(font_list_entry, font_list_entry2, &font_cache, struct font_list, list_entry)
14355e2c163fSAmine Khaldi     {
14365e2c163fSAmine Khaldi         list_remove(&font_list_entry->list_entry);
14375e2c163fSAmine Khaldi         DeleteObject(font_list_entry->font);
14385e2c163fSAmine Khaldi         HeapFree(GetProcessHeap(), 0, font_list_entry);
14395e2c163fSAmine Khaldi     }
14405e2c163fSAmine Khaldi     LeaveCriticalSection(&font_cache_critical);
14415e2c163fSAmine Khaldi 
14425e2c163fSAmine Khaldi     return S_OK;
14435e2c163fSAmine Khaldi }
14445e2c163fSAmine Khaldi 
1445c2c66affSColin Finck /******************************************************************************
1446c2c66affSColin Finck  * MLANG ClassFactory
1447c2c66affSColin Finck  */
1448c2c66affSColin Finck typedef struct {
1449c2c66affSColin Finck     IClassFactory IClassFactory_iface;
1450c2c66affSColin Finck     LONG ref;
1451c2c66affSColin Finck     HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
1452c2c66affSColin Finck } IClassFactoryImpl;
1453c2c66affSColin Finck 
impl_from_IClassFactory(IClassFactory * iface)1454c2c66affSColin Finck static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
1455c2c66affSColin Finck {
1456c2c66affSColin Finck     return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
1457c2c66affSColin Finck }
1458c2c66affSColin Finck 
1459c2c66affSColin Finck struct object_creation_info
1460c2c66affSColin Finck {
1461c2c66affSColin Finck     const CLSID *clsid;
1462c2c66affSColin Finck     LPCSTR szClassName;
1463c2c66affSColin Finck     HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
1464c2c66affSColin Finck };
1465c2c66affSColin Finck 
1466c2c66affSColin Finck static const struct object_creation_info object_creation[] =
1467c2c66affSColin Finck {
1468c2c66affSColin Finck     { &CLSID_CMultiLanguage, "CLSID_CMultiLanguage", MultiLanguage_create },
1469c2c66affSColin Finck     { &CLSID_CMLangConvertCharset, "CLSID_CMLangConvertCharset", MLangConvertCharset_create }
1470c2c66affSColin Finck };
1471c2c66affSColin Finck 
MLANGCF_QueryInterface(IClassFactory * iface,REFIID riid,void ** ppobj)1472c2c66affSColin Finck static HRESULT WINAPI MLANGCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj)
1473c2c66affSColin Finck {
1474c2c66affSColin Finck     TRACE("%s\n", debugstr_guid(riid) );
1475c2c66affSColin Finck 
1476c2c66affSColin Finck     if (IsEqualGUID(riid, &IID_IUnknown)
1477c2c66affSColin Finck 	|| IsEqualGUID(riid, &IID_IClassFactory))
1478c2c66affSColin Finck     {
1479c2c66affSColin Finck 	IClassFactory_AddRef(iface);
1480c2c66affSColin Finck         *ppobj = iface;
1481c2c66affSColin Finck 	return S_OK;
1482c2c66affSColin Finck     }
1483c2c66affSColin Finck 
1484c2c66affSColin Finck     *ppobj = NULL;
1485c2c66affSColin Finck     WARN("(%p)->(%s,%p), not found\n", iface, debugstr_guid(riid), ppobj);
1486c2c66affSColin Finck     return E_NOINTERFACE;
1487c2c66affSColin Finck }
1488c2c66affSColin Finck 
MLANGCF_AddRef(IClassFactory * iface)1489c2c66affSColin Finck static ULONG WINAPI MLANGCF_AddRef(IClassFactory *iface)
1490c2c66affSColin Finck {
1491c2c66affSColin Finck     IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1492c2c66affSColin Finck     return InterlockedIncrement(&This->ref);
1493c2c66affSColin Finck }
1494c2c66affSColin Finck 
MLANGCF_Release(IClassFactory * iface)1495c2c66affSColin Finck static ULONG WINAPI MLANGCF_Release(IClassFactory *iface)
1496c2c66affSColin Finck {
1497c2c66affSColin Finck     IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1498c2c66affSColin Finck     ULONG ref = InterlockedDecrement(&This->ref);
1499c2c66affSColin Finck 
1500c2c66affSColin Finck     if (ref == 0)
1501c2c66affSColin Finck     {
1502c2c66affSColin Finck         TRACE("Destroying %p\n", This);
1503c2c66affSColin Finck 	HeapFree(GetProcessHeap(), 0, This);
1504c2c66affSColin Finck     }
1505c2c66affSColin Finck 
1506c2c66affSColin Finck     return ref;
1507c2c66affSColin Finck }
1508c2c66affSColin Finck 
MLANGCF_CreateInstance(IClassFactory * iface,IUnknown * pOuter,REFIID riid,void ** ppobj)1509c2c66affSColin Finck static HRESULT WINAPI MLANGCF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
1510c2c66affSColin Finck         REFIID riid, void **ppobj)
1511c2c66affSColin Finck {
1512c2c66affSColin Finck     IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1513c2c66affSColin Finck     HRESULT hres;
1514c2c66affSColin Finck     LPUNKNOWN punk;
1515c2c66affSColin Finck 
1516c2c66affSColin Finck     TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
1517c2c66affSColin Finck 
1518c2c66affSColin Finck     *ppobj = NULL;
1519c2c66affSColin Finck     hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk);
1520c2c66affSColin Finck     if (SUCCEEDED(hres)) {
1521c2c66affSColin Finck         hres = IUnknown_QueryInterface(punk, riid, ppobj);
1522c2c66affSColin Finck         IUnknown_Release(punk);
1523c2c66affSColin Finck     }
1524c2c66affSColin Finck     TRACE("returning (%p) -> %x\n", *ppobj, hres);
1525c2c66affSColin Finck     return hres;
1526c2c66affSColin Finck }
1527c2c66affSColin Finck 
MLANGCF_LockServer(IClassFactory * iface,BOOL dolock)1528c2c66affSColin Finck static HRESULT WINAPI MLANGCF_LockServer(IClassFactory *iface, BOOL dolock)
1529c2c66affSColin Finck {
1530c2c66affSColin Finck     if (dolock)
1531c2c66affSColin Finck         LockModule();
1532c2c66affSColin Finck     else
1533c2c66affSColin Finck         UnlockModule();
1534c2c66affSColin Finck 
1535c2c66affSColin Finck     return S_OK;
1536c2c66affSColin Finck }
1537c2c66affSColin Finck 
1538c2c66affSColin Finck static const IClassFactoryVtbl MLANGCF_Vtbl =
1539c2c66affSColin Finck {
1540c2c66affSColin Finck     MLANGCF_QueryInterface,
1541c2c66affSColin Finck     MLANGCF_AddRef,
1542c2c66affSColin Finck     MLANGCF_Release,
1543c2c66affSColin Finck     MLANGCF_CreateInstance,
1544c2c66affSColin Finck     MLANGCF_LockServer
1545c2c66affSColin Finck };
1546c2c66affSColin Finck 
1547c2c66affSColin Finck /******************************************************************
1548c2c66affSColin Finck  *		DllGetClassObject (MLANG.@)
1549c2c66affSColin Finck  */
DllGetClassObject(REFCLSID rclsid,REFIID iid,LPVOID * ppv)1550c2c66affSColin Finck HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
1551c2c66affSColin Finck {
1552c2c66affSColin Finck     unsigned int i;
1553c2c66affSColin Finck     IClassFactoryImpl *factory;
1554c2c66affSColin Finck 
1555c2c66affSColin Finck     TRACE("%s %s %p\n",debugstr_guid(rclsid), debugstr_guid(iid), ppv);
1556c2c66affSColin Finck 
1557c2c66affSColin Finck     if ( !IsEqualGUID( &IID_IClassFactory, iid )
1558c2c66affSColin Finck 	 && ! IsEqualGUID( &IID_IUnknown, iid) )
1559c2c66affSColin Finck 	return E_NOINTERFACE;
1560c2c66affSColin Finck 
1561ccc3eeaeSAmine Khaldi     for (i = 0; i < ARRAY_SIZE(object_creation); i++)
1562c2c66affSColin Finck     {
1563c2c66affSColin Finck 	if (IsEqualGUID(object_creation[i].clsid, rclsid))
1564c2c66affSColin Finck 	    break;
1565c2c66affSColin Finck     }
1566c2c66affSColin Finck 
1567ccc3eeaeSAmine Khaldi     if (i == ARRAY_SIZE(object_creation))
1568c2c66affSColin Finck     {
1569c2c66affSColin Finck 	FIXME("%s: no class found.\n", debugstr_guid(rclsid));
1570c2c66affSColin Finck 	return CLASS_E_CLASSNOTAVAILABLE;
1571c2c66affSColin Finck     }
1572c2c66affSColin Finck 
1573c2c66affSColin Finck     TRACE("Creating a class factory for %s\n",object_creation[i].szClassName);
1574c2c66affSColin Finck 
1575c2c66affSColin Finck     factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));
1576c2c66affSColin Finck     if (factory == NULL) return E_OUTOFMEMORY;
1577c2c66affSColin Finck 
1578c2c66affSColin Finck     factory->IClassFactory_iface.lpVtbl = &MLANGCF_Vtbl;
1579c2c66affSColin Finck     factory->ref = 1;
1580c2c66affSColin Finck 
1581c2c66affSColin Finck     factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
1582c2c66affSColin Finck 
1583c2c66affSColin Finck     *ppv = &factory->IClassFactory_iface;
1584c2c66affSColin Finck 
1585c2c66affSColin Finck     TRACE("(%p) <- %p\n", ppv, &factory->IClassFactory_iface);
1586c2c66affSColin Finck 
1587c2c66affSColin Finck     return S_OK;
1588c2c66affSColin Finck }
1589c2c66affSColin Finck 
1590c2c66affSColin Finck 
1591c2c66affSColin Finck /******************************************************************************/
1592c2c66affSColin Finck 
1593c2c66affSColin Finck typedef struct tagMLang_impl
1594c2c66affSColin Finck {
1595c2c66affSColin Finck     IMLangFontLink IMLangFontLink_iface;
1596c2c66affSColin Finck     IMultiLanguage IMultiLanguage_iface;
1597c2c66affSColin Finck     IMultiLanguage3 IMultiLanguage3_iface;
1598c2c66affSColin Finck     IMLangFontLink2 IMLangFontLink2_iface;
1599c2c66affSColin Finck     IMLangLineBreakConsole IMLangLineBreakConsole_iface;
1600c2c66affSColin Finck     LONG ref;
1601c2c66affSColin Finck     DWORD total_cp, total_scripts;
1602c2c66affSColin Finck } MLang_impl;
1603c2c66affSColin Finck 
1604c2c66affSColin Finck /******************************************************************************/
1605c2c66affSColin Finck 
1606c2c66affSColin Finck typedef struct tagEnumCodePage_impl
1607c2c66affSColin Finck {
1608c2c66affSColin Finck     IEnumCodePage IEnumCodePage_iface;
1609c2c66affSColin Finck     LONG ref;
1610c2c66affSColin Finck     MIMECPINFO *cpinfo;
1611c2c66affSColin Finck     DWORD total, pos;
1612c2c66affSColin Finck } EnumCodePage_impl;
1613c2c66affSColin Finck 
impl_from_IEnumCodePage(IEnumCodePage * iface)1614c2c66affSColin Finck static inline EnumCodePage_impl *impl_from_IEnumCodePage( IEnumCodePage *iface )
1615c2c66affSColin Finck {
1616c2c66affSColin Finck     return CONTAINING_RECORD( iface, EnumCodePage_impl, IEnumCodePage_iface );
1617c2c66affSColin Finck }
1618c2c66affSColin Finck 
fnIEnumCodePage_QueryInterface(IEnumCodePage * iface,REFIID riid,void ** ppvObject)1619c2c66affSColin Finck static HRESULT WINAPI fnIEnumCodePage_QueryInterface(
1620c2c66affSColin Finck         IEnumCodePage* iface,
1621c2c66affSColin Finck         REFIID riid,
1622c2c66affSColin Finck         void** ppvObject)
1623c2c66affSColin Finck {
1624c2c66affSColin Finck     EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1625c2c66affSColin Finck 
1626c2c66affSColin Finck     TRACE("%p -> %s\n", This, debugstr_guid(riid) );
1627c2c66affSColin Finck 
1628c2c66affSColin Finck     if (IsEqualGUID(riid, &IID_IUnknown)
1629c2c66affSColin Finck 	|| IsEqualGUID(riid, &IID_IEnumCodePage))
1630c2c66affSColin Finck     {
1631c2c66affSColin Finck 	IEnumCodePage_AddRef(iface);
1632c2c66affSColin Finck         TRACE("Returning IID_IEnumCodePage %p ref = %d\n", This, This->ref);
1633c2c66affSColin Finck 	*ppvObject = &This->IEnumCodePage_iface;
1634c2c66affSColin Finck         return S_OK;
1635c2c66affSColin Finck     }
1636c2c66affSColin Finck 
1637c2c66affSColin Finck     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1638c2c66affSColin Finck     return E_NOINTERFACE;
1639c2c66affSColin Finck }
1640c2c66affSColin Finck 
fnIEnumCodePage_AddRef(IEnumCodePage * iface)1641c2c66affSColin Finck static ULONG WINAPI fnIEnumCodePage_AddRef(
1642c2c66affSColin Finck         IEnumCodePage* iface)
1643c2c66affSColin Finck {
1644c2c66affSColin Finck     EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1645c2c66affSColin Finck     return InterlockedIncrement(&This->ref);
1646c2c66affSColin Finck }
1647c2c66affSColin Finck 
fnIEnumCodePage_Release(IEnumCodePage * iface)1648c2c66affSColin Finck static ULONG WINAPI fnIEnumCodePage_Release(
1649c2c66affSColin Finck         IEnumCodePage* iface)
1650c2c66affSColin Finck {
1651c2c66affSColin Finck     EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1652c2c66affSColin Finck     ULONG ref = InterlockedDecrement(&This->ref);
1653c2c66affSColin Finck 
1654c2c66affSColin Finck     TRACE("%p ref = %d\n", This, ref);
1655c2c66affSColin Finck     if (ref == 0)
1656c2c66affSColin Finck     {
1657c2c66affSColin Finck         TRACE("Destroying %p\n", This);
1658c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, This->cpinfo);
1659c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, This);
1660c2c66affSColin Finck     }
1661c2c66affSColin Finck 
1662c2c66affSColin Finck     return ref;
1663c2c66affSColin Finck }
1664c2c66affSColin Finck 
fnIEnumCodePage_Clone(IEnumCodePage * iface,IEnumCodePage ** ppEnum)1665c2c66affSColin Finck static HRESULT WINAPI fnIEnumCodePage_Clone(
1666c2c66affSColin Finck         IEnumCodePage* iface,
1667c2c66affSColin Finck         IEnumCodePage** ppEnum)
1668c2c66affSColin Finck {
1669c2c66affSColin Finck     EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1670c2c66affSColin Finck     FIXME("%p %p\n", This, ppEnum);
1671c2c66affSColin Finck     return E_NOTIMPL;
1672c2c66affSColin Finck }
1673c2c66affSColin Finck 
fnIEnumCodePage_Next(IEnumCodePage * iface,ULONG celt,PMIMECPINFO rgelt,ULONG * pceltFetched)1674c2c66affSColin Finck static  HRESULT WINAPI fnIEnumCodePage_Next(
1675c2c66affSColin Finck         IEnumCodePage* iface,
1676c2c66affSColin Finck         ULONG celt,
1677c2c66affSColin Finck         PMIMECPINFO rgelt,
1678c2c66affSColin Finck         ULONG* pceltFetched)
1679c2c66affSColin Finck {
1680c2c66affSColin Finck     ULONG i;
1681c2c66affSColin Finck     EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1682c2c66affSColin Finck 
1683c2c66affSColin Finck     TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
1684c2c66affSColin Finck 
1685c2c66affSColin Finck     if (!pceltFetched) return S_FALSE;
1686c2c66affSColin Finck     *pceltFetched = 0;
1687c2c66affSColin Finck 
1688c2c66affSColin Finck     if (!rgelt) return S_FALSE;
1689c2c66affSColin Finck 
1690c2c66affSColin Finck     if (This->pos + celt > This->total)
1691c2c66affSColin Finck         celt = This->total - This->pos;
1692c2c66affSColin Finck 
1693c2c66affSColin Finck     if (!celt) return S_FALSE;
1694c2c66affSColin Finck 
1695c2c66affSColin Finck     memcpy(rgelt, This->cpinfo + This->pos, celt * sizeof(MIMECPINFO));
1696c2c66affSColin Finck     *pceltFetched = celt;
1697c2c66affSColin Finck     This->pos += celt;
1698c2c66affSColin Finck 
1699c2c66affSColin Finck     for (i = 0; i < celt; i++)
1700c2c66affSColin Finck     {
1701c2c66affSColin Finck         TRACE("#%u: %08x %u %u %s %s %s %s %s %s %d\n",
1702c2c66affSColin Finck               i, rgelt[i].dwFlags, rgelt[i].uiCodePage,
1703c2c66affSColin Finck               rgelt[i].uiFamilyCodePage,
1704c2c66affSColin Finck               wine_dbgstr_w(rgelt[i].wszDescription),
1705c2c66affSColin Finck               wine_dbgstr_w(rgelt[i].wszWebCharset),
1706c2c66affSColin Finck               wine_dbgstr_w(rgelt[i].wszHeaderCharset),
1707c2c66affSColin Finck               wine_dbgstr_w(rgelt[i].wszBodyCharset),
1708c2c66affSColin Finck               wine_dbgstr_w(rgelt[i].wszFixedWidthFont),
1709c2c66affSColin Finck               wine_dbgstr_w(rgelt[i].wszProportionalFont),
1710c2c66affSColin Finck               rgelt[i].bGDICharset);
1711c2c66affSColin Finck     }
1712c2c66affSColin Finck     return S_OK;
1713c2c66affSColin Finck }
1714c2c66affSColin Finck 
fnIEnumCodePage_Reset(IEnumCodePage * iface)1715c2c66affSColin Finck static HRESULT WINAPI fnIEnumCodePage_Reset(
1716c2c66affSColin Finck         IEnumCodePage* iface)
1717c2c66affSColin Finck {
1718c2c66affSColin Finck     EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1719c2c66affSColin Finck 
1720c2c66affSColin Finck     TRACE("%p\n", This);
1721c2c66affSColin Finck 
1722c2c66affSColin Finck     This->pos = 0;
1723c2c66affSColin Finck     return S_OK;
1724c2c66affSColin Finck }
1725c2c66affSColin Finck 
fnIEnumCodePage_Skip(IEnumCodePage * iface,ULONG celt)1726c2c66affSColin Finck static  HRESULT WINAPI fnIEnumCodePage_Skip(
1727c2c66affSColin Finck         IEnumCodePage* iface,
1728c2c66affSColin Finck         ULONG celt)
1729c2c66affSColin Finck {
1730c2c66affSColin Finck     EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1731c2c66affSColin Finck 
1732c2c66affSColin Finck     TRACE("%p %u\n", This, celt);
1733c2c66affSColin Finck 
1734c2c66affSColin Finck     if (celt >= This->total) return S_FALSE;
1735c2c66affSColin Finck 
1736c2c66affSColin Finck     This->pos += celt;
1737c2c66affSColin Finck     return S_OK;
1738c2c66affSColin Finck }
1739c2c66affSColin Finck 
1740c2c66affSColin Finck static const IEnumCodePageVtbl IEnumCodePage_vtbl =
1741c2c66affSColin Finck {
1742c2c66affSColin Finck     fnIEnumCodePage_QueryInterface,
1743c2c66affSColin Finck     fnIEnumCodePage_AddRef,
1744c2c66affSColin Finck     fnIEnumCodePage_Release,
1745c2c66affSColin Finck     fnIEnumCodePage_Clone,
1746c2c66affSColin Finck     fnIEnumCodePage_Next,
1747c2c66affSColin Finck     fnIEnumCodePage_Reset,
1748c2c66affSColin Finck     fnIEnumCodePage_Skip
1749c2c66affSColin Finck };
1750c2c66affSColin Finck 
EnumCodePage_create(MLang_impl * mlang,DWORD grfFlags,LANGID LangId,IEnumCodePage ** ppEnumCodePage)1751c2c66affSColin Finck static HRESULT EnumCodePage_create( MLang_impl* mlang, DWORD grfFlags,
1752c2c66affSColin Finck                      LANGID LangId, IEnumCodePage** ppEnumCodePage )
1753c2c66affSColin Finck {
1754c2c66affSColin Finck     EnumCodePage_impl *ecp;
1755c2c66affSColin Finck     MIMECPINFO *cpinfo;
1756c2c66affSColin Finck     UINT i, n;
1757c2c66affSColin Finck 
1758c2c66affSColin Finck     TRACE("%p, %08x, %04x, %p\n", mlang, grfFlags, LangId, ppEnumCodePage);
1759c2c66affSColin Finck 
1760c2c66affSColin Finck     if (!grfFlags) /* enumerate internal data base of encodings */
1761c2c66affSColin Finck         grfFlags = MIMECONTF_MIME_LATEST;
1762c2c66affSColin Finck 
1763c2c66affSColin Finck     ecp = HeapAlloc( GetProcessHeap(), 0, sizeof (EnumCodePage_impl) );
1764c2c66affSColin Finck     ecp->IEnumCodePage_iface.lpVtbl = &IEnumCodePage_vtbl;
1765c2c66affSColin Finck     ecp->ref = 1;
1766c2c66affSColin Finck     ecp->pos = 0;
1767c2c66affSColin Finck     ecp->total = 0;
1768ccc3eeaeSAmine Khaldi     for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
1769c2c66affSColin Finck     {
1770c2c66affSColin Finck         for (n = 0; n < mlang_data[i].number_of_cp; n++)
1771c2c66affSColin Finck         {
1772c2c66affSColin Finck             if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
1773c2c66affSColin Finck                 ecp->total++;
1774c2c66affSColin Finck         }
1775c2c66affSColin Finck     }
1776c2c66affSColin Finck 
1777c2c66affSColin Finck     ecp->cpinfo = HeapAlloc(GetProcessHeap(), 0,
1778c2c66affSColin Finck                             sizeof(MIMECPINFO) * ecp->total);
1779c2c66affSColin Finck     cpinfo = ecp->cpinfo;
1780c2c66affSColin Finck 
1781ccc3eeaeSAmine Khaldi     for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
1782c2c66affSColin Finck     {
1783c2c66affSColin Finck         for (n = 0; n < mlang_data[i].number_of_cp; n++)
1784c2c66affSColin Finck         {
1785c2c66affSColin Finck             if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
1786c2c66affSColin Finck                 fill_cp_info(&mlang_data[i], n, cpinfo++);
1787c2c66affSColin Finck         }
1788c2c66affSColin Finck     }
1789c2c66affSColin Finck 
1790c2c66affSColin Finck     TRACE("enumerated %d codepages with flags %08x\n", ecp->total, grfFlags);
1791c2c66affSColin Finck 
1792c2c66affSColin Finck     *ppEnumCodePage = &ecp->IEnumCodePage_iface;
1793c2c66affSColin Finck 
1794c2c66affSColin Finck     return S_OK;
1795c2c66affSColin Finck }
1796c2c66affSColin Finck 
1797c2c66affSColin Finck /******************************************************************************/
1798c2c66affSColin Finck 
1799c2c66affSColin Finck typedef struct tagEnumScript_impl
1800c2c66affSColin Finck {
1801c2c66affSColin Finck     IEnumScript IEnumScript_iface;
1802c2c66affSColin Finck     LONG ref;
1803c2c66affSColin Finck     SCRIPTINFO *script_info;
1804c2c66affSColin Finck     DWORD total, pos;
1805c2c66affSColin Finck } EnumScript_impl;
1806c2c66affSColin Finck 
impl_from_IEnumScript(IEnumScript * iface)1807c2c66affSColin Finck static inline EnumScript_impl *impl_from_IEnumScript( IEnumScript *iface )
1808c2c66affSColin Finck {
1809c2c66affSColin Finck     return CONTAINING_RECORD( iface, EnumScript_impl, IEnumScript_iface );
1810c2c66affSColin Finck }
1811c2c66affSColin Finck 
fnIEnumScript_QueryInterface(IEnumScript * iface,REFIID riid,void ** ppvObject)1812c2c66affSColin Finck static HRESULT WINAPI fnIEnumScript_QueryInterface(
1813c2c66affSColin Finck         IEnumScript* iface,
1814c2c66affSColin Finck         REFIID riid,
1815c2c66affSColin Finck         void** ppvObject)
1816c2c66affSColin Finck {
1817c2c66affSColin Finck     EnumScript_impl *This = impl_from_IEnumScript( iface );
1818c2c66affSColin Finck 
1819c2c66affSColin Finck     TRACE("%p -> %s\n", This, debugstr_guid(riid) );
1820c2c66affSColin Finck 
1821c2c66affSColin Finck     if (IsEqualGUID(riid, &IID_IUnknown)
1822c2c66affSColin Finck         || IsEqualGUID(riid, &IID_IEnumScript))
1823c2c66affSColin Finck     {
1824c2c66affSColin Finck         IEnumScript_AddRef(iface);
1825c2c66affSColin Finck         TRACE("Returning IID_IEnumScript %p ref = %d\n", This, This->ref);
1826c2c66affSColin Finck         *ppvObject = &This->IEnumScript_iface;
1827c2c66affSColin Finck         return S_OK;
1828c2c66affSColin Finck     }
1829c2c66affSColin Finck 
1830c2c66affSColin Finck     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1831c2c66affSColin Finck     return E_NOINTERFACE;
1832c2c66affSColin Finck }
1833c2c66affSColin Finck 
fnIEnumScript_AddRef(IEnumScript * iface)1834c2c66affSColin Finck static ULONG WINAPI fnIEnumScript_AddRef(
1835c2c66affSColin Finck         IEnumScript* iface)
1836c2c66affSColin Finck {
1837c2c66affSColin Finck     EnumScript_impl *This = impl_from_IEnumScript( iface );
1838c2c66affSColin Finck     return InterlockedIncrement(&This->ref);
1839c2c66affSColin Finck }
1840c2c66affSColin Finck 
fnIEnumScript_Release(IEnumScript * iface)1841c2c66affSColin Finck static ULONG WINAPI fnIEnumScript_Release(
1842c2c66affSColin Finck         IEnumScript* iface)
1843c2c66affSColin Finck {
1844c2c66affSColin Finck     EnumScript_impl *This = impl_from_IEnumScript( iface );
1845c2c66affSColin Finck     ULONG ref = InterlockedDecrement(&This->ref);
1846c2c66affSColin Finck 
1847c2c66affSColin Finck     TRACE("%p ref = %d\n", This, ref);
1848c2c66affSColin Finck     if (ref == 0)
1849c2c66affSColin Finck     {
1850c2c66affSColin Finck         TRACE("Destroying %p\n", This);
1851c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, This->script_info);
1852c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, This);
1853c2c66affSColin Finck     }
1854c2c66affSColin Finck 
1855c2c66affSColin Finck     return ref;
1856c2c66affSColin Finck }
1857c2c66affSColin Finck 
fnIEnumScript_Clone(IEnumScript * iface,IEnumScript ** ppEnum)1858c2c66affSColin Finck static HRESULT WINAPI fnIEnumScript_Clone(
1859c2c66affSColin Finck         IEnumScript* iface,
1860c2c66affSColin Finck         IEnumScript** ppEnum)
1861c2c66affSColin Finck {
1862c2c66affSColin Finck     EnumScript_impl *This = impl_from_IEnumScript( iface );
1863c2c66affSColin Finck     FIXME("%p %p: stub!\n", This, ppEnum);
1864c2c66affSColin Finck     return E_NOTIMPL;
1865c2c66affSColin Finck }
1866c2c66affSColin Finck 
fnIEnumScript_Next(IEnumScript * iface,ULONG celt,PSCRIPTINFO rgelt,ULONG * pceltFetched)1867c2c66affSColin Finck static  HRESULT WINAPI fnIEnumScript_Next(
1868c2c66affSColin Finck         IEnumScript* iface,
1869c2c66affSColin Finck         ULONG celt,
1870c2c66affSColin Finck         PSCRIPTINFO rgelt,
1871c2c66affSColin Finck         ULONG* pceltFetched)
1872c2c66affSColin Finck {
1873c2c66affSColin Finck     EnumScript_impl *This = impl_from_IEnumScript( iface );
1874c2c66affSColin Finck 
1875c2c66affSColin Finck     TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
1876c2c66affSColin Finck 
1877c2c66affSColin Finck     if (!pceltFetched || !rgelt) return E_FAIL;
1878c2c66affSColin Finck 
1879c2c66affSColin Finck     *pceltFetched = 0;
1880c2c66affSColin Finck 
1881c2c66affSColin Finck     if (This->pos + celt > This->total)
1882c2c66affSColin Finck         celt = This->total - This->pos;
1883c2c66affSColin Finck 
1884c2c66affSColin Finck     if (!celt) return S_FALSE;
1885c2c66affSColin Finck 
1886c2c66affSColin Finck     memcpy(rgelt, This->script_info + This->pos, celt * sizeof(SCRIPTINFO));
1887c2c66affSColin Finck     *pceltFetched = celt;
1888c2c66affSColin Finck     This->pos += celt;
1889c2c66affSColin Finck 
1890c2c66affSColin Finck     return S_OK;
1891c2c66affSColin Finck }
1892c2c66affSColin Finck 
fnIEnumScript_Reset(IEnumScript * iface)1893c2c66affSColin Finck static HRESULT WINAPI fnIEnumScript_Reset(
1894c2c66affSColin Finck         IEnumScript* iface)
1895c2c66affSColin Finck {
1896c2c66affSColin Finck     EnumScript_impl *This = impl_from_IEnumScript( iface );
1897c2c66affSColin Finck 
1898c2c66affSColin Finck     TRACE("%p\n", This);
1899c2c66affSColin Finck 
1900c2c66affSColin Finck     This->pos = 0;
1901c2c66affSColin Finck     return S_OK;
1902c2c66affSColin Finck }
1903c2c66affSColin Finck 
fnIEnumScript_Skip(IEnumScript * iface,ULONG celt)1904c2c66affSColin Finck static  HRESULT WINAPI fnIEnumScript_Skip(
1905c2c66affSColin Finck         IEnumScript* iface,
1906c2c66affSColin Finck         ULONG celt)
1907c2c66affSColin Finck {
1908c2c66affSColin Finck     EnumScript_impl *This = impl_from_IEnumScript( iface );
1909c2c66affSColin Finck 
1910c2c66affSColin Finck     TRACE("%p %u\n", This, celt);
1911c2c66affSColin Finck 
1912c2c66affSColin Finck     if (celt >= This->total) return S_FALSE;
1913c2c66affSColin Finck 
1914c2c66affSColin Finck     This->pos += celt;
1915c2c66affSColin Finck     return S_OK;
1916c2c66affSColin Finck }
1917c2c66affSColin Finck 
1918c2c66affSColin Finck static const IEnumScriptVtbl IEnumScript_vtbl =
1919c2c66affSColin Finck {
1920c2c66affSColin Finck     fnIEnumScript_QueryInterface,
1921c2c66affSColin Finck     fnIEnumScript_AddRef,
1922c2c66affSColin Finck     fnIEnumScript_Release,
1923c2c66affSColin Finck     fnIEnumScript_Clone,
1924c2c66affSColin Finck     fnIEnumScript_Next,
1925c2c66affSColin Finck     fnIEnumScript_Reset,
1926c2c66affSColin Finck     fnIEnumScript_Skip
1927c2c66affSColin Finck };
1928c2c66affSColin Finck 
EnumScript_create(MLang_impl * mlang,DWORD dwFlags,LANGID LangId,IEnumScript ** ppEnumScript)1929c2c66affSColin Finck static HRESULT EnumScript_create( MLang_impl* mlang, DWORD dwFlags,
1930c2c66affSColin Finck                      LANGID LangId, IEnumScript** ppEnumScript )
1931c2c66affSColin Finck {
1932c2c66affSColin Finck     EnumScript_impl *es;
1933c2c66affSColin Finck     UINT i;
1934c2c66affSColin Finck 
1935c2c66affSColin Finck     TRACE("%p, %08x, %04x, %p\n", mlang, dwFlags, LangId, ppEnumScript);
1936c2c66affSColin Finck 
1937c2c66affSColin Finck     if (!dwFlags) /* enumerate all available scripts */
1938c2c66affSColin Finck         dwFlags = SCRIPTCONTF_SCRIPT_USER | SCRIPTCONTF_SCRIPT_HIDE | SCRIPTCONTF_SCRIPT_SYSTEM;
1939c2c66affSColin Finck 
1940c2c66affSColin Finck     es = HeapAlloc( GetProcessHeap(), 0, sizeof (EnumScript_impl) );
1941c2c66affSColin Finck     es->IEnumScript_iface.lpVtbl = &IEnumScript_vtbl;
1942c2c66affSColin Finck     es->ref = 1;
1943c2c66affSColin Finck     es->pos = 0;
1944c2c66affSColin Finck     /* do not enumerate unicode flavours */
1945ccc3eeaeSAmine Khaldi     es->total = ARRAY_SIZE(mlang_data) - 1;
1946c2c66affSColin Finck     es->script_info = HeapAlloc(GetProcessHeap(), 0, sizeof(SCRIPTINFO) * es->total);
1947c2c66affSColin Finck 
1948c2c66affSColin Finck     for (i = 0; i < es->total; i++)
1949c2c66affSColin Finck     {
1950c2c66affSColin Finck         es->script_info[i].ScriptId = i;
1951c2c66affSColin Finck         es->script_info[i].uiCodePage = mlang_data[i].family_codepage;
1952c2c66affSColin Finck         MultiByteToWideChar(CP_ACP, 0, mlang_data[i].description, -1,
1953c2c66affSColin Finck             es->script_info[i].wszDescription, MAX_SCRIPT_NAME);
1954c2c66affSColin Finck         MultiByteToWideChar(CP_ACP, 0, mlang_data[i].fixed_font, -1,
1955c2c66affSColin Finck             es->script_info[i].wszFixedWidthFont, MAX_MIMEFACE_NAME);
1956c2c66affSColin Finck         MultiByteToWideChar(CP_ACP, 0, mlang_data[i].proportional_font, -1,
1957c2c66affSColin Finck             es->script_info[i].wszProportionalFont, MAX_MIMEFACE_NAME);
1958c2c66affSColin Finck     }
1959c2c66affSColin Finck 
1960c2c66affSColin Finck     TRACE("enumerated %d scripts with flags %08x\n", es->total, dwFlags);
1961c2c66affSColin Finck 
1962c2c66affSColin Finck     *ppEnumScript = &es->IEnumScript_iface;
1963c2c66affSColin Finck 
1964c2c66affSColin Finck     return S_OK;
1965c2c66affSColin Finck }
1966c2c66affSColin Finck 
1967c2c66affSColin Finck /******************************************************************************/
1968c2c66affSColin Finck 
impl_from_IMLangFontLink(IMLangFontLink * iface)1969c2c66affSColin Finck static inline MLang_impl *impl_from_IMLangFontLink( IMLangFontLink *iface )
1970c2c66affSColin Finck {
1971c2c66affSColin Finck     return CONTAINING_RECORD( iface, MLang_impl, IMLangFontLink_iface );
1972c2c66affSColin Finck }
1973c2c66affSColin Finck 
fnIMLangFontLink_QueryInterface(IMLangFontLink * iface,REFIID riid,void ** ppvObject)1974c2c66affSColin Finck static HRESULT WINAPI fnIMLangFontLink_QueryInterface(
1975c2c66affSColin Finck         IMLangFontLink* iface,
1976c2c66affSColin Finck         REFIID riid,
1977c2c66affSColin Finck         void** ppvObject)
1978c2c66affSColin Finck {
1979c2c66affSColin Finck     MLang_impl *This = impl_from_IMLangFontLink( iface );
1980c2c66affSColin Finck     return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
1981c2c66affSColin Finck }
1982c2c66affSColin Finck 
fnIMLangFontLink_AddRef(IMLangFontLink * iface)1983c2c66affSColin Finck static ULONG WINAPI fnIMLangFontLink_AddRef(
1984c2c66affSColin Finck         IMLangFontLink* iface)
1985c2c66affSColin Finck {
1986c2c66affSColin Finck     MLang_impl *This = impl_from_IMLangFontLink( iface );
1987c2c66affSColin Finck     return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
1988c2c66affSColin Finck }
1989c2c66affSColin Finck 
fnIMLangFontLink_Release(IMLangFontLink * iface)1990c2c66affSColin Finck static ULONG WINAPI fnIMLangFontLink_Release(
1991c2c66affSColin Finck         IMLangFontLink* iface)
1992c2c66affSColin Finck {
1993c2c66affSColin Finck     MLang_impl *This = impl_from_IMLangFontLink( iface );
1994c2c66affSColin Finck     return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
1995c2c66affSColin Finck }
1996c2c66affSColin Finck 
fnIMLangFontLink_GetCharCodePages(IMLangFontLink * iface,WCHAR ch_src,DWORD * codepages)1997c2c66affSColin Finck static HRESULT WINAPI fnIMLangFontLink_GetCharCodePages(
1998c2c66affSColin Finck         IMLangFontLink* iface,
1999c2c66affSColin Finck         WCHAR ch_src,
2000c2c66affSColin Finck         DWORD* codepages)
2001c2c66affSColin Finck {
2002c2c66affSColin Finck     MLang_impl *This = impl_from_IMLangFontLink( iface );
2003c2c66affSColin Finck     return IMLangFontLink2_GetCharCodePages(&This->IMLangFontLink2_iface, ch_src, codepages);
2004c2c66affSColin Finck }
2005c2c66affSColin Finck 
fnIMLangFontLink_GetStrCodePages(IMLangFontLink * iface,const WCHAR * src,LONG src_len,DWORD priority_cp,DWORD * codepages,LONG * ret_len)2006c2c66affSColin Finck static HRESULT WINAPI fnIMLangFontLink_GetStrCodePages(
2007c2c66affSColin Finck         IMLangFontLink* iface,
2008c2c66affSColin Finck         const WCHAR* src,
2009c2c66affSColin Finck         LONG src_len,
2010c2c66affSColin Finck         DWORD priority_cp,
2011c2c66affSColin Finck         DWORD* codepages,
2012c2c66affSColin Finck         LONG* ret_len)
2013c2c66affSColin Finck {
2014c2c66affSColin Finck     MLang_impl *This = impl_from_IMLangFontLink( iface );
2015c2c66affSColin Finck     return IMLangFontLink2_GetStrCodePages(&This->IMLangFontLink2_iface, src, src_len, priority_cp,
2016c2c66affSColin Finck         codepages, ret_len);
2017c2c66affSColin Finck }
2018c2c66affSColin Finck 
fnIMLangFontLink_CodePageToCodePages(IMLangFontLink * iface,UINT codepage,DWORD * codepages)2019c2c66affSColin Finck static HRESULT WINAPI fnIMLangFontLink_CodePageToCodePages(
2020c2c66affSColin Finck         IMLangFontLink* iface,
2021c2c66affSColin Finck         UINT codepage,
2022c2c66affSColin Finck         DWORD* codepages)
2023c2c66affSColin Finck {
2024c2c66affSColin Finck     MLang_impl *This = impl_from_IMLangFontLink( iface );
2025c2c66affSColin Finck     return IMLangFontLink2_CodePageToCodePages(&This->IMLangFontLink2_iface, codepage, codepages);
2026c2c66affSColin Finck }
2027c2c66affSColin Finck 
fnIMLangFontLink_CodePagesToCodePage(IMLangFontLink * iface,DWORD codepages,UINT def_codepage,UINT * codepage)2028c2c66affSColin Finck static HRESULT WINAPI fnIMLangFontLink_CodePagesToCodePage(
2029c2c66affSColin Finck         IMLangFontLink* iface,
2030c2c66affSColin Finck         DWORD codepages,
2031c2c66affSColin Finck         UINT def_codepage,
2032c2c66affSColin Finck         UINT* codepage)
2033c2c66affSColin Finck {
2034c2c66affSColin Finck     MLang_impl *This = impl_from_IMLangFontLink(iface);
2035c2c66affSColin Finck     return IMLangFontLink2_CodePagesToCodePage(&This->IMLangFontLink2_iface, codepages,
2036c2c66affSColin Finck         def_codepage, codepage);
2037c2c66affSColin Finck }
2038c2c66affSColin Finck 
fnIMLangFontLink_GetFontCodePages(IMLangFontLink * iface,HDC hdc,HFONT hfont,DWORD * codepages)2039c2c66affSColin Finck static HRESULT WINAPI fnIMLangFontLink_GetFontCodePages(
2040c2c66affSColin Finck         IMLangFontLink* iface,
2041c2c66affSColin Finck         HDC hdc,
2042c2c66affSColin Finck         HFONT hfont,
2043c2c66affSColin Finck         DWORD* codepages)
2044c2c66affSColin Finck {
2045c2c66affSColin Finck     MLang_impl *This = impl_from_IMLangFontLink(iface);
2046c2c66affSColin Finck     return IMLangFontLink2_GetFontCodePages(&This->IMLangFontLink2_iface, hdc, hfont, codepages);
2047c2c66affSColin Finck }
2048c2c66affSColin Finck 
fnIMLangFontLink_MapFont(IMLangFontLink * iface,HDC hDC,DWORD dwCodePages,HFONT hSrcFont,HFONT * phDestFont)2049c2c66affSColin Finck static HRESULT WINAPI fnIMLangFontLink_MapFont(
2050c2c66affSColin Finck         IMLangFontLink* iface,
2051c2c66affSColin Finck         HDC hDC,
2052c2c66affSColin Finck         DWORD dwCodePages,
2053c2c66affSColin Finck         HFONT hSrcFont,
2054c2c66affSColin Finck         HFONT* phDestFont)
2055c2c66affSColin Finck {
20565e2c163fSAmine Khaldi     TRACE("(%p)->%p %08x %p %p\n",iface, hDC, dwCodePages, hSrcFont, phDestFont);
20575e2c163fSAmine Khaldi 
20585e2c163fSAmine Khaldi     return map_font(hDC, dwCodePages, hSrcFont, phDestFont);
2059c2c66affSColin Finck }
2060c2c66affSColin Finck 
fnIMLangFontLink_ReleaseFont(IMLangFontLink * iface,HFONT hFont)2061c2c66affSColin Finck static HRESULT WINAPI fnIMLangFontLink_ReleaseFont(
2062c2c66affSColin Finck         IMLangFontLink* iface,
2063c2c66affSColin Finck         HFONT hFont)
2064c2c66affSColin Finck {
20655e2c163fSAmine Khaldi     TRACE("(%p)->%p\n",iface, hFont);
20665e2c163fSAmine Khaldi 
20675e2c163fSAmine Khaldi     return release_font(hFont);
2068c2c66affSColin Finck }
2069c2c66affSColin Finck 
fnIMLangFontLink_ResetFontMapping(IMLangFontLink * iface)2070c2c66affSColin Finck static HRESULT WINAPI fnIMLangFontLink_ResetFontMapping(
2071c2c66affSColin Finck         IMLangFontLink* iface)
2072c2c66affSColin Finck {
20735e2c163fSAmine Khaldi     TRACE("(%p)\n",iface);
20745e2c163fSAmine Khaldi 
20755e2c163fSAmine Khaldi     return clear_font_cache();
2076c2c66affSColin Finck }
2077c2c66affSColin Finck 
2078c2c66affSColin Finck 
2079c2c66affSColin Finck static const IMLangFontLinkVtbl IMLangFontLink_vtbl =
2080c2c66affSColin Finck {
2081c2c66affSColin Finck     fnIMLangFontLink_QueryInterface,
2082c2c66affSColin Finck     fnIMLangFontLink_AddRef,
2083c2c66affSColin Finck     fnIMLangFontLink_Release,
2084c2c66affSColin Finck     fnIMLangFontLink_GetCharCodePages,
2085c2c66affSColin Finck     fnIMLangFontLink_GetStrCodePages,
2086c2c66affSColin Finck     fnIMLangFontLink_CodePageToCodePages,
2087c2c66affSColin Finck     fnIMLangFontLink_CodePagesToCodePage,
2088c2c66affSColin Finck     fnIMLangFontLink_GetFontCodePages,
2089c2c66affSColin Finck     fnIMLangFontLink_MapFont,
2090c2c66affSColin Finck     fnIMLangFontLink_ReleaseFont,
2091c2c66affSColin Finck     fnIMLangFontLink_ResetFontMapping,
2092c2c66affSColin Finck };
2093c2c66affSColin Finck 
2094c2c66affSColin Finck /******************************************************************************/
2095c2c66affSColin Finck 
impl_from_IMultiLanguage(IMultiLanguage * iface)2096c2c66affSColin Finck static inline MLang_impl *impl_from_IMultiLanguage( IMultiLanguage *iface )
2097c2c66affSColin Finck {
2098c2c66affSColin Finck     return CONTAINING_RECORD( iface, MLang_impl, IMultiLanguage_iface );
2099c2c66affSColin Finck }
2100c2c66affSColin Finck 
fnIMultiLanguage_QueryInterface(IMultiLanguage * iface,REFIID riid,void ** obj)2101c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage_QueryInterface(
2102c2c66affSColin Finck     IMultiLanguage* iface,
2103c2c66affSColin Finck     REFIID riid,
2104c2c66affSColin Finck     void** obj)
2105c2c66affSColin Finck {
2106c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage( iface );
2107c2c66affSColin Finck     return IMultiLanguage3_QueryInterface(&This->IMultiLanguage3_iface, riid, obj);
2108c2c66affSColin Finck }
2109c2c66affSColin Finck 
fnIMultiLanguage_AddRef(IMultiLanguage * iface)2110c2c66affSColin Finck static ULONG WINAPI fnIMultiLanguage_AddRef( IMultiLanguage* iface )
2111c2c66affSColin Finck {
2112c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage( iface );
2113c2c66affSColin Finck     return IMultiLanguage3_AddRef(&This->IMultiLanguage3_iface);
2114c2c66affSColin Finck }
2115c2c66affSColin Finck 
fnIMultiLanguage_Release(IMultiLanguage * iface)2116c2c66affSColin Finck static ULONG WINAPI fnIMultiLanguage_Release( IMultiLanguage* iface )
2117c2c66affSColin Finck {
2118c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage( iface );
2119c2c66affSColin Finck     return IMultiLanguage3_Release(&This->IMultiLanguage3_iface);
2120c2c66affSColin Finck }
2121c2c66affSColin Finck 
fnIMultiLanguage_GetNumberOfCodePageInfo(IMultiLanguage * iface,UINT * cp)2122c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage_GetNumberOfCodePageInfo(
2123c2c66affSColin Finck     IMultiLanguage* iface,
2124c2c66affSColin Finck     UINT* cp)
2125c2c66affSColin Finck {
2126c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage( iface );
2127c2c66affSColin Finck     TRACE("(%p, %p)\n", This, cp);
2128c2c66affSColin Finck     return IMultiLanguage3_GetNumberOfCodePageInfo(&This->IMultiLanguage3_iface, cp);
2129c2c66affSColin Finck }
2130c2c66affSColin Finck 
fnIMultiLanguage_GetCodePageInfo(IMultiLanguage * iface,UINT uiCodePage,PMIMECPINFO pCodePageInfo)2131c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage_GetCodePageInfo(
2132c2c66affSColin Finck     IMultiLanguage* iface,
2133c2c66affSColin Finck     UINT uiCodePage,
2134c2c66affSColin Finck     PMIMECPINFO pCodePageInfo)
2135c2c66affSColin Finck {
2136c2c66affSColin Finck     UINT i, n;
2137c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage( iface );
2138c2c66affSColin Finck 
2139c2c66affSColin Finck     TRACE("%p, %u, %p\n", This, uiCodePage, pCodePageInfo);
2140c2c66affSColin Finck 
2141ccc3eeaeSAmine Khaldi     for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2142c2c66affSColin Finck     {
2143c2c66affSColin Finck         for (n = 0; n < mlang_data[i].number_of_cp; n++)
2144c2c66affSColin Finck         {
2145c2c66affSColin Finck             if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
2146c2c66affSColin Finck             {
2147c2c66affSColin Finck                 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
2148c2c66affSColin Finck                 return S_OK;
2149c2c66affSColin Finck             }
2150c2c66affSColin Finck         }
2151c2c66affSColin Finck     }
2152c2c66affSColin Finck 
2153c2c66affSColin Finck     return S_FALSE;
2154c2c66affSColin Finck }
2155c2c66affSColin Finck 
fnIMultiLanguage_GetFamilyCodePage(IMultiLanguage * iface,UINT cp,UINT * family_cp)2156c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage_GetFamilyCodePage(
2157c2c66affSColin Finck     IMultiLanguage* iface,
2158c2c66affSColin Finck     UINT cp,
2159c2c66affSColin Finck     UINT* family_cp)
2160c2c66affSColin Finck {
2161c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage( iface );
2162c2c66affSColin Finck     return IMultiLanguage3_GetFamilyCodePage(&This->IMultiLanguage3_iface, cp, family_cp);
2163c2c66affSColin Finck }
2164c2c66affSColin Finck 
fnIMultiLanguage_EnumCodePages(IMultiLanguage * iface,DWORD grfFlags,IEnumCodePage ** ppEnumCodePage)2165c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage_EnumCodePages(
2166c2c66affSColin Finck     IMultiLanguage* iface,
2167c2c66affSColin Finck     DWORD grfFlags,
2168c2c66affSColin Finck     IEnumCodePage** ppEnumCodePage)
2169c2c66affSColin Finck {
2170c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage( iface );
2171c2c66affSColin Finck 
2172c2c66affSColin Finck     TRACE("%p %08x %p\n", This, grfFlags, ppEnumCodePage);
2173c2c66affSColin Finck 
2174c2c66affSColin Finck     return EnumCodePage_create( This, grfFlags, 0, ppEnumCodePage );
2175c2c66affSColin Finck }
2176c2c66affSColin Finck 
fnIMultiLanguage_GetCharsetInfo(IMultiLanguage * iface,BSTR Charset,PMIMECSETINFO pCharsetInfo)2177c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage_GetCharsetInfo(
2178c2c66affSColin Finck     IMultiLanguage* iface,
2179c2c66affSColin Finck     BSTR Charset,
2180c2c66affSColin Finck     PMIMECSETINFO pCharsetInfo)
2181c2c66affSColin Finck {
2182c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage( iface );
2183c2c66affSColin Finck     return IMultiLanguage3_GetCharsetInfo( &This->IMultiLanguage3_iface, Charset, pCharsetInfo );
2184c2c66affSColin Finck }
2185c2c66affSColin Finck 
fnIMultiLanguage_IsConvertible(IMultiLanguage * iface,DWORD src_enc,DWORD dst_enc)2186c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage_IsConvertible(
2187c2c66affSColin Finck     IMultiLanguage* iface,
2188c2c66affSColin Finck     DWORD src_enc,
2189c2c66affSColin Finck     DWORD dst_enc)
2190c2c66affSColin Finck {
2191c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage( iface );
2192c2c66affSColin Finck     return IMultiLanguage3_IsConvertible(&This->IMultiLanguage3_iface, src_enc, dst_enc);
2193c2c66affSColin Finck }
2194c2c66affSColin Finck 
fnIMultiLanguage_ConvertString(IMultiLanguage * iface,DWORD * mode,DWORD src_enc,DWORD dst_enc,BYTE * src,UINT * src_size,BYTE * dest,UINT * dest_size)2195c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage_ConvertString(
2196c2c66affSColin Finck     IMultiLanguage* iface,
2197c2c66affSColin Finck     DWORD* mode,
2198c2c66affSColin Finck     DWORD src_enc,
2199c2c66affSColin Finck     DWORD dst_enc,
2200c2c66affSColin Finck     BYTE* src,
2201c2c66affSColin Finck     UINT* src_size,
2202c2c66affSColin Finck     BYTE* dest,
2203c2c66affSColin Finck     UINT* dest_size)
2204c2c66affSColin Finck {
2205c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage( iface );
2206c2c66affSColin Finck     return IMultiLanguage3_ConvertString(&This->IMultiLanguage3_iface, mode, src_enc,
2207c2c66affSColin Finck         dst_enc, src, src_size, dest, dest_size);
2208c2c66affSColin Finck }
2209c2c66affSColin Finck 
fnIMultiLanguage_ConvertStringToUnicode(IMultiLanguage * iface,DWORD * mode,DWORD src_enc,CHAR * src,UINT * src_size,WCHAR * dest,UINT * dest_size)2210c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage_ConvertStringToUnicode(
2211c2c66affSColin Finck     IMultiLanguage* iface,
2212c2c66affSColin Finck     DWORD* mode,
2213c2c66affSColin Finck     DWORD src_enc,
2214c2c66affSColin Finck     CHAR* src,
2215c2c66affSColin Finck     UINT* src_size,
2216c2c66affSColin Finck     WCHAR* dest,
2217c2c66affSColin Finck     UINT* dest_size)
2218c2c66affSColin Finck {
2219c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage( iface );
2220c2c66affSColin Finck     return IMultiLanguage3_ConvertStringToUnicode(&This->IMultiLanguage3_iface,
2221c2c66affSColin Finck         mode, src_enc, src, src_size, dest, dest_size);
2222c2c66affSColin Finck }
2223c2c66affSColin Finck 
fnIMultiLanguage_ConvertStringFromUnicode(IMultiLanguage * iface,DWORD * mode,DWORD encoding,WCHAR * src,UINT * src_size,CHAR * dest,UINT * dest_size)2224c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage_ConvertStringFromUnicode(
2225c2c66affSColin Finck     IMultiLanguage* iface,
2226c2c66affSColin Finck     DWORD* mode,
2227c2c66affSColin Finck     DWORD encoding,
2228c2c66affSColin Finck     WCHAR* src,
2229c2c66affSColin Finck     UINT* src_size,
2230c2c66affSColin Finck     CHAR* dest,
2231c2c66affSColin Finck     UINT* dest_size)
2232c2c66affSColin Finck {
2233c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage(iface);
2234c2c66affSColin Finck     return IMultiLanguage3_ConvertStringFromUnicode(&This->IMultiLanguage3_iface,
2235c2c66affSColin Finck         mode, encoding, src, src_size, dest, dest_size);
2236c2c66affSColin Finck }
2237c2c66affSColin Finck 
fnIMultiLanguage_ConvertStringReset(IMultiLanguage * iface)2238c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage_ConvertStringReset(
2239c2c66affSColin Finck     IMultiLanguage* iface)
2240c2c66affSColin Finck {
2241c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage( iface );
2242c2c66affSColin Finck     return IMultiLanguage3_ConvertStringReset(&This->IMultiLanguage3_iface);
2243c2c66affSColin Finck }
2244c2c66affSColin Finck 
fnIMultiLanguage_GetRfc1766FromLcid(IMultiLanguage * iface,LCID lcid,BSTR * pbstrRfc1766)2245c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage_GetRfc1766FromLcid(
2246c2c66affSColin Finck     IMultiLanguage* iface,
2247c2c66affSColin Finck     LCID lcid,
2248c2c66affSColin Finck     BSTR* pbstrRfc1766)
2249c2c66affSColin Finck {
2250c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage(iface);
2251c2c66affSColin Finck     return IMultiLanguage3_GetRfc1766FromLcid(&This->IMultiLanguage3_iface, lcid, pbstrRfc1766);
2252c2c66affSColin Finck }
2253c2c66affSColin Finck 
fnIMultiLanguage_GetLcidFromRfc1766(IMultiLanguage * iface,LCID * locale,BSTR rfc1766)2254c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage_GetLcidFromRfc1766(
2255c2c66affSColin Finck     IMultiLanguage* iface,
2256c2c66affSColin Finck     LCID* locale,
2257c2c66affSColin Finck     BSTR rfc1766)
2258c2c66affSColin Finck {
2259c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage(iface);
2260c2c66affSColin Finck     return IMultiLanguage3_GetLcidFromRfc1766(&This->IMultiLanguage3_iface, locale, rfc1766);
2261c2c66affSColin Finck }
2262c2c66affSColin Finck 
2263c2c66affSColin Finck /******************************************************************************/
2264c2c66affSColin Finck 
2265c2c66affSColin Finck typedef struct tagEnumRfc1766_impl
2266c2c66affSColin Finck {
2267c2c66affSColin Finck     IEnumRfc1766 IEnumRfc1766_iface;
2268c2c66affSColin Finck     LONG ref;
2269c2c66affSColin Finck     RFC1766INFO *info;
2270c2c66affSColin Finck     DWORD total, pos;
2271c2c66affSColin Finck } EnumRfc1766_impl;
2272c2c66affSColin Finck 
impl_from_IEnumRfc1766(IEnumRfc1766 * iface)2273c2c66affSColin Finck static inline EnumRfc1766_impl *impl_from_IEnumRfc1766( IEnumRfc1766 *iface )
2274c2c66affSColin Finck {
2275c2c66affSColin Finck     return CONTAINING_RECORD( iface, EnumRfc1766_impl, IEnumRfc1766_iface );
2276c2c66affSColin Finck }
2277c2c66affSColin Finck 
fnIEnumRfc1766_QueryInterface(IEnumRfc1766 * iface,REFIID riid,void ** ppvObject)2278c2c66affSColin Finck static HRESULT WINAPI fnIEnumRfc1766_QueryInterface(
2279c2c66affSColin Finck         IEnumRfc1766 *iface,
2280c2c66affSColin Finck         REFIID riid,
2281c2c66affSColin Finck         void** ppvObject)
2282c2c66affSColin Finck {
2283c2c66affSColin Finck     EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2284c2c66affSColin Finck 
2285c2c66affSColin Finck     TRACE("%p -> %s\n", This, debugstr_guid(riid) );
2286c2c66affSColin Finck 
2287c2c66affSColin Finck     if (IsEqualGUID(riid, &IID_IUnknown)
2288c2c66affSColin Finck         || IsEqualGUID(riid, &IID_IEnumRfc1766))
2289c2c66affSColin Finck     {
2290c2c66affSColin Finck         IEnumRfc1766_AddRef(iface);
2291c2c66affSColin Finck         TRACE("Returning IID_IEnumRfc1766 %p ref = %d\n", This, This->ref);
2292c2c66affSColin Finck         *ppvObject = &This->IEnumRfc1766_iface;
2293c2c66affSColin Finck         return S_OK;
2294c2c66affSColin Finck     }
2295c2c66affSColin Finck 
2296c2c66affSColin Finck     WARN("(%p) -> (%s,%p), not found\n",This,debugstr_guid(riid),ppvObject);
2297c2c66affSColin Finck     return E_NOINTERFACE;
2298c2c66affSColin Finck }
2299c2c66affSColin Finck 
fnIEnumRfc1766_AddRef(IEnumRfc1766 * iface)2300c2c66affSColin Finck static ULONG WINAPI fnIEnumRfc1766_AddRef(
2301c2c66affSColin Finck         IEnumRfc1766 *iface)
2302c2c66affSColin Finck {
2303c2c66affSColin Finck     EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2304c2c66affSColin Finck     return InterlockedIncrement(&This->ref);
2305c2c66affSColin Finck }
2306c2c66affSColin Finck 
fnIEnumRfc1766_Release(IEnumRfc1766 * iface)2307c2c66affSColin Finck static ULONG WINAPI fnIEnumRfc1766_Release(
2308c2c66affSColin Finck         IEnumRfc1766 *iface)
2309c2c66affSColin Finck {
2310c2c66affSColin Finck     EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2311c2c66affSColin Finck     ULONG ref = InterlockedDecrement(&This->ref);
2312c2c66affSColin Finck 
2313c2c66affSColin Finck     TRACE("%p ref = %d\n", This, ref);
2314c2c66affSColin Finck     if (ref == 0)
2315c2c66affSColin Finck     {
2316c2c66affSColin Finck         TRACE("Destroying %p\n", This);
2317c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, This->info);
2318c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, This);
2319c2c66affSColin Finck     }
2320c2c66affSColin Finck     return ref;
2321c2c66affSColin Finck }
2322c2c66affSColin Finck 
fnIEnumRfc1766_Clone(IEnumRfc1766 * iface,IEnumRfc1766 ** ppEnum)2323c2c66affSColin Finck static HRESULT WINAPI fnIEnumRfc1766_Clone(
2324c2c66affSColin Finck         IEnumRfc1766 *iface,
2325c2c66affSColin Finck         IEnumRfc1766 **ppEnum)
2326c2c66affSColin Finck {
2327c2c66affSColin Finck     EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2328c2c66affSColin Finck 
2329c2c66affSColin Finck     FIXME("%p %p\n", This, ppEnum);
2330c2c66affSColin Finck     return E_NOTIMPL;
2331c2c66affSColin Finck }
2332c2c66affSColin Finck 
fnIEnumRfc1766_Next(IEnumRfc1766 * iface,ULONG celt,PRFC1766INFO rgelt,ULONG * pceltFetched)2333c2c66affSColin Finck static  HRESULT WINAPI fnIEnumRfc1766_Next(
2334c2c66affSColin Finck         IEnumRfc1766 *iface,
2335c2c66affSColin Finck         ULONG celt,
2336c2c66affSColin Finck         PRFC1766INFO rgelt,
2337c2c66affSColin Finck         ULONG *pceltFetched)
2338c2c66affSColin Finck {
2339c2c66affSColin Finck     ULONG i;
2340c2c66affSColin Finck     EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2341c2c66affSColin Finck 
2342c2c66affSColin Finck     TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
2343c2c66affSColin Finck 
2344c2c66affSColin Finck     if (!pceltFetched) return S_FALSE;
2345c2c66affSColin Finck     *pceltFetched = 0;
2346c2c66affSColin Finck 
2347c2c66affSColin Finck     if (!rgelt) return S_FALSE;
2348c2c66affSColin Finck 
2349c2c66affSColin Finck     if (This->pos + celt > This->total)
2350c2c66affSColin Finck         celt = This->total - This->pos;
2351c2c66affSColin Finck 
2352c2c66affSColin Finck     if (!celt) return S_FALSE;
2353c2c66affSColin Finck 
2354c2c66affSColin Finck     memcpy(rgelt, This->info + This->pos, celt * sizeof(RFC1766INFO));
2355c2c66affSColin Finck     *pceltFetched = celt;
2356c2c66affSColin Finck     This->pos += celt;
2357c2c66affSColin Finck 
2358c2c66affSColin Finck     for (i = 0; i < celt; i++)
2359c2c66affSColin Finck     {
2360c2c66affSColin Finck         TRACE("#%u: %08x %s %s\n",
2361c2c66affSColin Finck               i, rgelt[i].lcid,
2362c2c66affSColin Finck               wine_dbgstr_w(rgelt[i].wszRfc1766),
2363c2c66affSColin Finck               wine_dbgstr_w(rgelt[i].wszLocaleName));
2364c2c66affSColin Finck     }
2365c2c66affSColin Finck     return S_OK;
2366c2c66affSColin Finck }
2367c2c66affSColin Finck 
fnIEnumRfc1766_Reset(IEnumRfc1766 * iface)2368c2c66affSColin Finck static HRESULT WINAPI fnIEnumRfc1766_Reset(
2369c2c66affSColin Finck         IEnumRfc1766 *iface)
2370c2c66affSColin Finck {
2371c2c66affSColin Finck     EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2372c2c66affSColin Finck 
2373c2c66affSColin Finck     TRACE("%p\n", This);
2374c2c66affSColin Finck 
2375c2c66affSColin Finck     This->pos = 0;
2376c2c66affSColin Finck     return S_OK;
2377c2c66affSColin Finck }
2378c2c66affSColin Finck 
fnIEnumRfc1766_Skip(IEnumRfc1766 * iface,ULONG celt)2379c2c66affSColin Finck static  HRESULT WINAPI fnIEnumRfc1766_Skip(
2380c2c66affSColin Finck         IEnumRfc1766 *iface,
2381c2c66affSColin Finck         ULONG celt)
2382c2c66affSColin Finck {
2383c2c66affSColin Finck     EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2384c2c66affSColin Finck 
2385c2c66affSColin Finck     TRACE("%p %u\n", This, celt);
2386c2c66affSColin Finck 
2387c2c66affSColin Finck     if (celt >= This->total) return S_FALSE;
2388c2c66affSColin Finck 
2389c2c66affSColin Finck     This->pos += celt;
2390c2c66affSColin Finck     return S_OK;
2391c2c66affSColin Finck }
2392c2c66affSColin Finck 
2393c2c66affSColin Finck static const IEnumRfc1766Vtbl IEnumRfc1766_vtbl =
2394c2c66affSColin Finck {
2395c2c66affSColin Finck     fnIEnumRfc1766_QueryInterface,
2396c2c66affSColin Finck     fnIEnumRfc1766_AddRef,
2397c2c66affSColin Finck     fnIEnumRfc1766_Release,
2398c2c66affSColin Finck     fnIEnumRfc1766_Clone,
2399c2c66affSColin Finck     fnIEnumRfc1766_Next,
2400c2c66affSColin Finck     fnIEnumRfc1766_Reset,
2401c2c66affSColin Finck     fnIEnumRfc1766_Skip
2402c2c66affSColin Finck };
2403c2c66affSColin Finck 
2404c2c66affSColin Finck struct enum_locales_data
2405c2c66affSColin Finck {
2406c2c66affSColin Finck     RFC1766INFO *info;
2407c2c66affSColin Finck     DWORD total, allocated;
2408c2c66affSColin Finck };
2409c2c66affSColin Finck 
enum_locales_proc(LPWSTR locale)2410c2c66affSColin Finck static BOOL CALLBACK enum_locales_proc(LPWSTR locale)
2411c2c66affSColin Finck {
2412c2c66affSColin Finck     WCHAR *end;
2413c2c66affSColin Finck     struct enum_locales_data *data = TlsGetValue(MLANG_tls_index);
2414c2c66affSColin Finck     RFC1766INFO *info;
2415c2c66affSColin Finck 
2416c2c66affSColin Finck     TRACE("%s\n", debugstr_w(locale));
2417c2c66affSColin Finck 
2418c2c66affSColin Finck     if (data->total >= data->allocated)
2419c2c66affSColin Finck     {
2420c2c66affSColin Finck         data->allocated += 32;
2421c2c66affSColin Finck         data->info = HeapReAlloc(GetProcessHeap(), 0, data->info, data->allocated * sizeof(RFC1766INFO));
2422c2c66affSColin Finck         if (!data->info) return FALSE;
2423c2c66affSColin Finck     }
2424c2c66affSColin Finck 
2425c2c66affSColin Finck     info = &data->info[data->total];
2426c2c66affSColin Finck 
2427853d6414SAmine Khaldi     info->lcid = wcstol(locale, &end, 16);
2428c2c66affSColin Finck     if (*end) /* invalid number */
2429c2c66affSColin Finck         return FALSE;
2430c2c66affSColin Finck 
2431c2c66affSColin Finck     info->wszRfc1766[0] = 0;
2432c2c66affSColin Finck     lcid_to_rfc1766W( info->lcid, info->wszRfc1766, MAX_RFC1766_NAME );
2433c2c66affSColin Finck 
2434c2c66affSColin Finck     info->wszLocaleName[0] = 0;
2435c2c66affSColin Finck     GetLocaleInfoW(info->lcid, LOCALE_SLANGUAGE, info->wszLocaleName, MAX_LOCALE_NAME);
2436c2c66affSColin Finck     TRACE("ISO639: %s SLANGUAGE: %s\n", wine_dbgstr_w(info->wszRfc1766), wine_dbgstr_w(info->wszLocaleName));
2437c2c66affSColin Finck 
2438c2c66affSColin Finck     data->total++;
2439c2c66affSColin Finck 
2440c2c66affSColin Finck     return TRUE;
2441c2c66affSColin Finck }
2442c2c66affSColin Finck 
EnumRfc1766_create(LANGID LangId,IEnumRfc1766 ** ppEnum)2443c2c66affSColin Finck static HRESULT EnumRfc1766_create(LANGID LangId, IEnumRfc1766 **ppEnum)
2444c2c66affSColin Finck {
2445c2c66affSColin Finck     EnumRfc1766_impl *rfc;
2446c2c66affSColin Finck     struct enum_locales_data data;
2447c2c66affSColin Finck 
2448c2c66affSColin Finck     TRACE("%04x, %p\n", LangId, ppEnum);
2449c2c66affSColin Finck 
2450c2c66affSColin Finck     rfc = HeapAlloc( GetProcessHeap(), 0, sizeof(EnumRfc1766_impl) );
2451c2c66affSColin Finck     rfc->IEnumRfc1766_iface.lpVtbl = &IEnumRfc1766_vtbl;
2452c2c66affSColin Finck     rfc->ref = 1;
2453c2c66affSColin Finck     rfc->pos = 0;
2454c2c66affSColin Finck     rfc->total = 0;
2455c2c66affSColin Finck 
2456c2c66affSColin Finck     data.total = 0;
2457c2c66affSColin Finck     data.allocated = 160;
2458c2c66affSColin Finck     data.info = HeapAlloc(GetProcessHeap(), 0, data.allocated * sizeof(RFC1766INFO));
2459c2c66affSColin Finck     if (!data.info)
2460c2c66affSColin Finck     {
2461c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, rfc);
2462c2c66affSColin Finck         return E_OUTOFMEMORY;
2463c2c66affSColin Finck     }
2464c2c66affSColin Finck 
2465c2c66affSColin Finck     TlsSetValue(MLANG_tls_index, &data);
2466c2c66affSColin Finck     EnumSystemLocalesW(enum_locales_proc, 0/*LOCALE_SUPPORTED*/);
2467c2c66affSColin Finck     TlsSetValue(MLANG_tls_index, NULL);
2468c2c66affSColin Finck 
2469c2c66affSColin Finck     TRACE("enumerated %d rfc1766 structures\n", data.total);
2470c2c66affSColin Finck 
2471c2c66affSColin Finck     if (!data.total)
2472c2c66affSColin Finck     {
2473c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, data.info);
2474c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, rfc);
2475c2c66affSColin Finck         return E_FAIL;
2476c2c66affSColin Finck     }
2477c2c66affSColin Finck 
2478c2c66affSColin Finck     rfc->info = data.info;
2479c2c66affSColin Finck     rfc->total = data.total;
2480c2c66affSColin Finck 
2481c2c66affSColin Finck     *ppEnum = &rfc->IEnumRfc1766_iface;
2482c2c66affSColin Finck     return S_OK;
2483c2c66affSColin Finck }
2484c2c66affSColin Finck 
fnIMultiLanguage_EnumRfc1766(IMultiLanguage * iface,IEnumRfc1766 ** ppEnumRfc1766)2485c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage_EnumRfc1766(
2486c2c66affSColin Finck     IMultiLanguage *iface,
2487c2c66affSColin Finck     IEnumRfc1766 **ppEnumRfc1766)
2488c2c66affSColin Finck {
2489c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage( iface );
2490c2c66affSColin Finck 
2491c2c66affSColin Finck     TRACE("%p %p\n", This, ppEnumRfc1766);
2492c2c66affSColin Finck 
2493c2c66affSColin Finck     return EnumRfc1766_create(0, ppEnumRfc1766);
2494c2c66affSColin Finck }
2495c2c66affSColin Finck 
2496c2c66affSColin Finck /******************************************************************************/
2497c2c66affSColin Finck 
fnIMultiLanguage_GetRfc1766Info(IMultiLanguage * iface,LCID Locale,PRFC1766INFO pRfc1766Info)2498c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage_GetRfc1766Info(
2499c2c66affSColin Finck     IMultiLanguage* iface,
2500c2c66affSColin Finck     LCID Locale,
2501c2c66affSColin Finck     PRFC1766INFO pRfc1766Info)
2502c2c66affSColin Finck {
2503c2c66affSColin Finck     LCTYPE type = LOCALE_SLANGUAGE;
2504c2c66affSColin Finck 
2505c2c66affSColin Finck     TRACE("(%p, 0x%04x, %p)\n", iface, Locale, pRfc1766Info);
2506c2c66affSColin Finck 
2507c2c66affSColin Finck     if (!pRfc1766Info)
2508c2c66affSColin Finck         return E_INVALIDARG;
2509c2c66affSColin Finck 
2510c2c66affSColin Finck     if ((PRIMARYLANGID(Locale) == LANG_ENGLISH) ||
2511c2c66affSColin Finck         (PRIMARYLANGID(Locale) == LANG_CHINESE) ||
2512c2c66affSColin Finck         (PRIMARYLANGID(Locale) == LANG_ARABIC)) {
2513c2c66affSColin Finck 
2514c2c66affSColin Finck         if (!SUBLANGID(Locale))
2515c2c66affSColin Finck             type = LOCALE_SENGLANGUAGE; /* suppress country */
2516c2c66affSColin Finck     }
2517c2c66affSColin Finck     else
2518c2c66affSColin Finck     {
2519c2c66affSColin Finck         if (!SUBLANGID(Locale)) {
2520c2c66affSColin Finck             TRACE("SUBLANGID missing in 0x%04x\n", Locale);
2521c2c66affSColin Finck             return E_FAIL;
2522c2c66affSColin Finck         }
2523c2c66affSColin Finck     }
2524c2c66affSColin Finck 
2525c2c66affSColin Finck     pRfc1766Info->lcid = Locale;
2526c2c66affSColin Finck     pRfc1766Info->wszRfc1766[0] = 0;
2527c2c66affSColin Finck     pRfc1766Info->wszLocaleName[0] = 0;
2528c2c66affSColin Finck 
2529c2c66affSColin Finck     if ((!lcid_to_rfc1766W(Locale, pRfc1766Info->wszRfc1766, MAX_RFC1766_NAME)) &&
2530c2c66affSColin Finck         (GetLocaleInfoW(Locale, type, pRfc1766Info->wszLocaleName, MAX_LOCALE_NAME) > 0))
2531c2c66affSColin Finck             return S_OK;
2532c2c66affSColin Finck 
2533c2c66affSColin Finck     /* Locale not supported */
2534c2c66affSColin Finck     return E_INVALIDARG;
2535c2c66affSColin Finck }
2536c2c66affSColin Finck 
fnIMultiLanguage_CreateConvertCharset(IMultiLanguage * iface,UINT src_cp,UINT dst_cp,DWORD prop,IMLangConvertCharset ** convert_charset)2537c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage_CreateConvertCharset(
2538c2c66affSColin Finck     IMultiLanguage* iface,
2539c2c66affSColin Finck     UINT src_cp,
2540c2c66affSColin Finck     UINT dst_cp,
2541c2c66affSColin Finck     DWORD prop,
2542c2c66affSColin Finck     IMLangConvertCharset** convert_charset)
2543c2c66affSColin Finck {
2544c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage(iface);
2545c2c66affSColin Finck     return IMultiLanguage3_CreateConvertCharset(&This->IMultiLanguage3_iface, src_cp, dst_cp, prop, convert_charset);
2546c2c66affSColin Finck }
2547c2c66affSColin Finck 
2548c2c66affSColin Finck static const IMultiLanguageVtbl IMultiLanguage_vtbl =
2549c2c66affSColin Finck {
2550c2c66affSColin Finck     fnIMultiLanguage_QueryInterface,
2551c2c66affSColin Finck     fnIMultiLanguage_AddRef,
2552c2c66affSColin Finck     fnIMultiLanguage_Release,
2553c2c66affSColin Finck     fnIMultiLanguage_GetNumberOfCodePageInfo,
2554c2c66affSColin Finck     fnIMultiLanguage_GetCodePageInfo,
2555c2c66affSColin Finck     fnIMultiLanguage_GetFamilyCodePage,
2556c2c66affSColin Finck     fnIMultiLanguage_EnumCodePages,
2557c2c66affSColin Finck     fnIMultiLanguage_GetCharsetInfo,
2558c2c66affSColin Finck     fnIMultiLanguage_IsConvertible,
2559c2c66affSColin Finck     fnIMultiLanguage_ConvertString,
2560c2c66affSColin Finck     fnIMultiLanguage_ConvertStringToUnicode,
2561c2c66affSColin Finck     fnIMultiLanguage_ConvertStringFromUnicode,
2562c2c66affSColin Finck     fnIMultiLanguage_ConvertStringReset,
2563c2c66affSColin Finck     fnIMultiLanguage_GetRfc1766FromLcid,
2564c2c66affSColin Finck     fnIMultiLanguage_GetLcidFromRfc1766,
2565c2c66affSColin Finck     fnIMultiLanguage_EnumRfc1766,
2566c2c66affSColin Finck     fnIMultiLanguage_GetRfc1766Info,
2567c2c66affSColin Finck     fnIMultiLanguage_CreateConvertCharset,
2568c2c66affSColin Finck };
2569c2c66affSColin Finck 
2570c2c66affSColin Finck 
2571c2c66affSColin Finck /******************************************************************************/
2572c2c66affSColin Finck 
impl_from_IMultiLanguage3(IMultiLanguage3 * iface)2573c2c66affSColin Finck static inline MLang_impl *impl_from_IMultiLanguage3( IMultiLanguage3 *iface )
2574c2c66affSColin Finck {
2575c2c66affSColin Finck     return CONTAINING_RECORD( iface, MLang_impl, IMultiLanguage3_iface );
2576c2c66affSColin Finck }
2577c2c66affSColin Finck 
fnIMultiLanguage3_QueryInterface(IMultiLanguage3 * iface,REFIID riid,void ** obj)2578c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_QueryInterface(
2579c2c66affSColin Finck     IMultiLanguage3* iface,
2580c2c66affSColin Finck     REFIID riid,
2581c2c66affSColin Finck     void** obj)
2582c2c66affSColin Finck {
2583c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage3( iface );
2584c2c66affSColin Finck 
2585c2c66affSColin Finck     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
2586c2c66affSColin Finck 
2587c2c66affSColin Finck     if (IsEqualGUID(riid, &IID_IUnknown) ||
2588c2c66affSColin Finck         IsEqualGUID(riid, &IID_IMultiLanguage))
2589c2c66affSColin Finck     {
2590c2c66affSColin Finck         *obj = &This->IMultiLanguage_iface;
2591c2c66affSColin Finck     }
2592c2c66affSColin Finck     else if (IsEqualGUID(riid, &IID_IMLangCodePages) ||
2593c2c66affSColin Finck              IsEqualGUID(riid, &IID_IMLangFontLink))
2594c2c66affSColin Finck     {
2595c2c66affSColin Finck         *obj = &This->IMLangFontLink_iface;
2596c2c66affSColin Finck     }
2597c2c66affSColin Finck     else if (IsEqualGUID(riid, &IID_IMLangFontLink2))
2598c2c66affSColin Finck     {
2599c2c66affSColin Finck         *obj = &This->IMLangFontLink2_iface;
2600c2c66affSColin Finck     }
2601c2c66affSColin Finck     else if (IsEqualGUID(riid, &IID_IMultiLanguage2) ||
2602c2c66affSColin Finck              IsEqualGUID(riid, &IID_IMultiLanguage3))
2603c2c66affSColin Finck     {
2604c2c66affSColin Finck         *obj = &This->IMultiLanguage3_iface;
2605c2c66affSColin Finck     }
2606c2c66affSColin Finck     else if (IsEqualGUID(riid, &IID_IMLangLineBreakConsole))
2607c2c66affSColin Finck     {
2608c2c66affSColin Finck         *obj = &This->IMLangLineBreakConsole_iface;
2609c2c66affSColin Finck     }
2610c2c66affSColin Finck     else
2611c2c66affSColin Finck     {
2612c2c66affSColin Finck         WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), obj);
2613c2c66affSColin Finck         *obj = NULL;
2614c2c66affSColin Finck         return E_NOINTERFACE;
2615c2c66affSColin Finck     }
2616c2c66affSColin Finck 
2617c2c66affSColin Finck     IMultiLanguage3_AddRef(iface);
2618c2c66affSColin Finck     return S_OK;
2619c2c66affSColin Finck }
2620c2c66affSColin Finck 
fnIMultiLanguage3_AddRef(IMultiLanguage3 * iface)2621c2c66affSColin Finck static ULONG WINAPI fnIMultiLanguage3_AddRef( IMultiLanguage3* iface )
2622c2c66affSColin Finck {
2623c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage3( iface );
2624c2c66affSColin Finck     return InterlockedIncrement(&This->ref);
2625c2c66affSColin Finck }
2626c2c66affSColin Finck 
fnIMultiLanguage3_Release(IMultiLanguage3 * iface)2627c2c66affSColin Finck static ULONG WINAPI fnIMultiLanguage3_Release( IMultiLanguage3* iface )
2628c2c66affSColin Finck {
2629c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage3( iface );
2630c2c66affSColin Finck     ULONG ref = InterlockedDecrement(&This->ref);
2631c2c66affSColin Finck 
2632c2c66affSColin Finck     TRACE("(%p)->(%d)\n", This, ref);
2633c2c66affSColin Finck     if (ref == 0)
2634c2c66affSColin Finck     {
2635c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, This);
2636c2c66affSColin Finck         UnlockModule();
2637c2c66affSColin Finck     }
2638c2c66affSColin Finck 
2639c2c66affSColin Finck     return ref;
2640c2c66affSColin Finck }
2641c2c66affSColin Finck 
fnIMultiLanguage3_GetNumberOfCodePageInfo(IMultiLanguage3 * iface,UINT * pcCodePage)2642c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_GetNumberOfCodePageInfo(
2643c2c66affSColin Finck     IMultiLanguage3* iface,
2644c2c66affSColin Finck     UINT* pcCodePage)
2645c2c66affSColin Finck {
2646c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage3( iface );
2647c2c66affSColin Finck 
2648c2c66affSColin Finck     TRACE("%p, %p\n", This, pcCodePage);
2649c2c66affSColin Finck 
2650c2c66affSColin Finck     if (!pcCodePage) return E_INVALIDARG;
2651c2c66affSColin Finck 
2652c2c66affSColin Finck     *pcCodePage = This->total_cp;
2653c2c66affSColin Finck     return S_OK;
2654c2c66affSColin Finck }
2655c2c66affSColin Finck 
fill_cp_info(const struct mlang_data * ml_data,UINT index,MIMECPINFO * mime_cp_info)2656c2c66affSColin Finck static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info)
2657c2c66affSColin Finck {
2658c2c66affSColin Finck     CHARSETINFO csi;
2659c2c66affSColin Finck 
2660c2c66affSColin Finck     if (TranslateCharsetInfo((DWORD*)(DWORD_PTR)ml_data->family_codepage, &csi,
2661c2c66affSColin Finck                              TCI_SRCCODEPAGE))
2662c2c66affSColin Finck         mime_cp_info->bGDICharset = csi.ciCharset;
2663c2c66affSColin Finck     else
2664c2c66affSColin Finck         mime_cp_info->bGDICharset = DEFAULT_CHARSET;
2665c2c66affSColin Finck 
2666c2c66affSColin Finck     mime_cp_info->dwFlags = ml_data->mime_cp_info[index].flags;
2667c2c66affSColin Finck     mime_cp_info->uiCodePage = ml_data->mime_cp_info[index].cp;
2668c2c66affSColin Finck     mime_cp_info->uiFamilyCodePage = ml_data->family_codepage;
2669c2c66affSColin Finck     MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].description, -1,
2670ccc3eeaeSAmine Khaldi                         mime_cp_info->wszDescription, ARRAY_SIZE(mime_cp_info->wszDescription));
2671c2c66affSColin Finck     MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].web_charset, -1,
2672ccc3eeaeSAmine Khaldi                         mime_cp_info->wszWebCharset, ARRAY_SIZE(mime_cp_info->wszWebCharset));
2673c2c66affSColin Finck     MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].header_charset, -1,
2674ccc3eeaeSAmine Khaldi                         mime_cp_info->wszHeaderCharset, ARRAY_SIZE(mime_cp_info->wszHeaderCharset));
2675c2c66affSColin Finck     MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].body_charset, -1,
2676ccc3eeaeSAmine Khaldi                         mime_cp_info->wszBodyCharset, ARRAY_SIZE(mime_cp_info->wszBodyCharset));
2677c2c66affSColin Finck 
2678c2c66affSColin Finck     MultiByteToWideChar(CP_ACP, 0, ml_data->fixed_font, -1,
2679ccc3eeaeSAmine Khaldi         mime_cp_info->wszFixedWidthFont, ARRAY_SIZE(mime_cp_info->wszFixedWidthFont));
2680c2c66affSColin Finck     MultiByteToWideChar(CP_ACP, 0, ml_data->proportional_font, -1,
2681ccc3eeaeSAmine Khaldi         mime_cp_info->wszProportionalFont, ARRAY_SIZE(mime_cp_info->wszProportionalFont));
2682c2c66affSColin Finck 
2683c2c66affSColin Finck     TRACE("%08x %u %u %s %s %s %s %s %s %d\n",
2684c2c66affSColin Finck           mime_cp_info->dwFlags, mime_cp_info->uiCodePage,
2685c2c66affSColin Finck           mime_cp_info->uiFamilyCodePage,
2686c2c66affSColin Finck           wine_dbgstr_w(mime_cp_info->wszDescription),
2687c2c66affSColin Finck           wine_dbgstr_w(mime_cp_info->wszWebCharset),
2688c2c66affSColin Finck           wine_dbgstr_w(mime_cp_info->wszHeaderCharset),
2689c2c66affSColin Finck           wine_dbgstr_w(mime_cp_info->wszBodyCharset),
2690c2c66affSColin Finck           wine_dbgstr_w(mime_cp_info->wszFixedWidthFont),
2691c2c66affSColin Finck           wine_dbgstr_w(mime_cp_info->wszProportionalFont),
2692c2c66affSColin Finck           mime_cp_info->bGDICharset);
2693c2c66affSColin Finck }
2694c2c66affSColin Finck 
fnIMultiLanguage3_GetCodePageInfo(IMultiLanguage3 * iface,UINT uiCodePage,LANGID LangId,PMIMECPINFO pCodePageInfo)2695c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_GetCodePageInfo(
2696c2c66affSColin Finck     IMultiLanguage3* iface,
2697c2c66affSColin Finck     UINT uiCodePage,
2698c2c66affSColin Finck     LANGID LangId,
2699c2c66affSColin Finck     PMIMECPINFO pCodePageInfo)
2700c2c66affSColin Finck {
2701c2c66affSColin Finck     UINT i, n;
2702c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage3( iface );
2703c2c66affSColin Finck 
2704c2c66affSColin Finck     TRACE("%p, %u, %04x, %p\n", This, uiCodePage, LangId, pCodePageInfo);
2705c2c66affSColin Finck 
2706ccc3eeaeSAmine Khaldi     for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2707c2c66affSColin Finck     {
2708c2c66affSColin Finck         for (n = 0; n < mlang_data[i].number_of_cp; n++)
2709c2c66affSColin Finck         {
2710c2c66affSColin Finck             if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
2711c2c66affSColin Finck             {
2712c2c66affSColin Finck                 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
2713c2c66affSColin Finck                 return S_OK;
2714c2c66affSColin Finck             }
2715c2c66affSColin Finck         }
2716c2c66affSColin Finck     }
2717c2c66affSColin Finck 
2718c2c66affSColin Finck     return S_FALSE;
2719c2c66affSColin Finck }
2720c2c66affSColin Finck 
fnIMultiLanguage3_GetFamilyCodePage(IMultiLanguage3 * iface,UINT uiCodePage,UINT * puiFamilyCodePage)2721c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_GetFamilyCodePage(
2722c2c66affSColin Finck     IMultiLanguage3* iface,
2723c2c66affSColin Finck     UINT uiCodePage,
2724c2c66affSColin Finck     UINT* puiFamilyCodePage)
2725c2c66affSColin Finck {
2726c2c66affSColin Finck     return GetFamilyCodePage(uiCodePage, puiFamilyCodePage);
2727c2c66affSColin Finck }
2728c2c66affSColin Finck 
fnIMultiLanguage3_EnumCodePages(IMultiLanguage3 * iface,DWORD grfFlags,LANGID LangId,IEnumCodePage ** ppEnumCodePage)2729c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_EnumCodePages(
2730c2c66affSColin Finck     IMultiLanguage3* iface,
2731c2c66affSColin Finck     DWORD grfFlags,
2732c2c66affSColin Finck     LANGID LangId,
2733c2c66affSColin Finck     IEnumCodePage** ppEnumCodePage)
2734c2c66affSColin Finck {
2735c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage3( iface );
2736c2c66affSColin Finck 
2737c2c66affSColin Finck     TRACE("%p %08x %04x %p\n", This, grfFlags, LangId, ppEnumCodePage);
2738c2c66affSColin Finck 
2739c2c66affSColin Finck     return EnumCodePage_create( This, grfFlags, LangId, ppEnumCodePage );
2740c2c66affSColin Finck }
2741c2c66affSColin Finck 
fnIMultiLanguage3_GetCharsetInfo(IMultiLanguage3 * iface,BSTR Charset,PMIMECSETINFO pCharsetInfo)2742c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_GetCharsetInfo(
2743c2c66affSColin Finck     IMultiLanguage3* iface,
2744c2c66affSColin Finck     BSTR Charset,
2745c2c66affSColin Finck     PMIMECSETINFO pCharsetInfo)
2746c2c66affSColin Finck {
2747c2c66affSColin Finck     UINT i, n;
2748c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage3( iface );
2749c2c66affSColin Finck 
2750c2c66affSColin Finck     TRACE("%p %s %p\n", This, debugstr_w(Charset), pCharsetInfo);
2751c2c66affSColin Finck 
2752c2c66affSColin Finck     if (!pCharsetInfo) return E_FAIL;
2753c2c66affSColin Finck 
2754ccc3eeaeSAmine Khaldi     for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2755c2c66affSColin Finck     {
2756c2c66affSColin Finck         for (n = 0; n < mlang_data[i].number_of_cp; n++)
2757c2c66affSColin Finck         {
2758c2c66affSColin Finck             WCHAR csetW[MAX_MIMECSET_NAME];
2759c2c66affSColin Finck 
2760c2c66affSColin Finck             MultiByteToWideChar(CP_ACP, 0, mlang_data[i].mime_cp_info[n].web_charset, -1, csetW, MAX_MIMECSET_NAME);
2761c2c66affSColin Finck             if (!lstrcmpiW(Charset, csetW))
2762c2c66affSColin Finck             {
2763c2c66affSColin Finck                 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2764c2c66affSColin Finck                 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2765853d6414SAmine Khaldi                 lstrcpyW(pCharsetInfo->wszCharset, csetW);
2766c2c66affSColin Finck                 return S_OK;
2767c2c66affSColin Finck             }
2768c2c66affSColin Finck             if (mlang_data[i].mime_cp_info[n].alias && !lstrcmpiW(Charset, mlang_data[i].mime_cp_info[n].alias))
2769c2c66affSColin Finck             {
2770c2c66affSColin Finck                 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2771c2c66affSColin Finck                 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2772853d6414SAmine Khaldi                 lstrcpyW(pCharsetInfo->wszCharset, mlang_data[i].mime_cp_info[n].alias);
2773c2c66affSColin Finck                 return S_OK;
2774c2c66affSColin Finck             }
2775c2c66affSColin Finck         }
2776c2c66affSColin Finck     }
2777c2c66affSColin Finck 
2778c2c66affSColin Finck     /* FIXME:
2779c2c66affSColin Finck      * Since we do not support charsets like iso-2022-jp and do not have
2780c2c66affSColin Finck      * them in our database as a primary (web_charset) encoding this loop
2781c2c66affSColin Finck      * does an attempt to 'approximate' charset name by header_charset.
2782c2c66affSColin Finck      */
2783ccc3eeaeSAmine Khaldi     for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2784c2c66affSColin Finck     {
2785c2c66affSColin Finck         for (n = 0; n < mlang_data[i].number_of_cp; n++)
2786c2c66affSColin Finck         {
2787c2c66affSColin Finck             WCHAR csetW[MAX_MIMECSET_NAME];
2788c2c66affSColin Finck 
2789c2c66affSColin Finck             MultiByteToWideChar(CP_ACP, 0, mlang_data[i].mime_cp_info[n].header_charset, -1, csetW, MAX_MIMECSET_NAME);
2790c2c66affSColin Finck             if (!lstrcmpiW(Charset, csetW))
2791c2c66affSColin Finck             {
2792c2c66affSColin Finck                 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2793c2c66affSColin Finck                 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2794853d6414SAmine Khaldi                 lstrcpyW(pCharsetInfo->wszCharset, csetW);
2795c2c66affSColin Finck                 return S_OK;
2796c2c66affSColin Finck             }
2797c2c66affSColin Finck         }
2798c2c66affSColin Finck     }
2799c2c66affSColin Finck 
2800c2c66affSColin Finck     return E_FAIL;
2801c2c66affSColin Finck }
2802c2c66affSColin Finck 
fnIMultiLanguage3_IsConvertible(IMultiLanguage3 * iface,DWORD dwSrcEncoding,DWORD dwDstEncoding)2803c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_IsConvertible(
2804c2c66affSColin Finck     IMultiLanguage3* iface,
2805c2c66affSColin Finck     DWORD dwSrcEncoding,
2806c2c66affSColin Finck     DWORD dwDstEncoding)
2807c2c66affSColin Finck {
2808c2c66affSColin Finck     return IsConvertINetStringAvailable(dwSrcEncoding, dwDstEncoding);
2809c2c66affSColin Finck }
2810c2c66affSColin Finck 
fnIMultiLanguage3_ConvertString(IMultiLanguage3 * iface,DWORD * pdwMode,DWORD dwSrcEncoding,DWORD dwDstEncoding,BYTE * pSrcStr,UINT * pcSrcSize,BYTE * pDstStr,UINT * pcDstSize)2811c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_ConvertString(
2812c2c66affSColin Finck     IMultiLanguage3* iface,
2813c2c66affSColin Finck     DWORD* pdwMode,
2814c2c66affSColin Finck     DWORD dwSrcEncoding,
2815c2c66affSColin Finck     DWORD dwDstEncoding,
2816c2c66affSColin Finck     BYTE* pSrcStr,
2817c2c66affSColin Finck     UINT* pcSrcSize,
2818c2c66affSColin Finck     BYTE* pDstStr,
2819c2c66affSColin Finck     UINT* pcDstSize)
2820c2c66affSColin Finck {
2821c2c66affSColin Finck     return ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding,
2822c2c66affSColin Finck         (LPCSTR)pSrcStr, (LPINT)pcSrcSize, (LPSTR)pDstStr, (LPINT)pcDstSize);
2823c2c66affSColin Finck }
2824c2c66affSColin Finck 
fnIMultiLanguage3_ConvertStringToUnicode(IMultiLanguage3 * iface,DWORD * pdwMode,DWORD dwEncoding,CHAR * pSrcStr,UINT * pcSrcSize,WCHAR * pDstStr,UINT * pcDstSize)2825c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_ConvertStringToUnicode(
2826c2c66affSColin Finck     IMultiLanguage3* iface,
2827c2c66affSColin Finck     DWORD* pdwMode,
2828c2c66affSColin Finck     DWORD dwEncoding,
2829c2c66affSColin Finck     CHAR* pSrcStr,
2830c2c66affSColin Finck     UINT* pcSrcSize,
2831c2c66affSColin Finck     WCHAR* pDstStr,
2832c2c66affSColin Finck     UINT* pcDstSize)
2833c2c66affSColin Finck {
2834c2c66affSColin Finck     return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
2835c2c66affSColin Finck         pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2836c2c66affSColin Finck }
2837c2c66affSColin Finck 
fnIMultiLanguage3_ConvertStringFromUnicode(IMultiLanguage3 * iface,DWORD * pdwMode,DWORD dwEncoding,WCHAR * pSrcStr,UINT * pcSrcSize,CHAR * pDstStr,UINT * pcDstSize)2838c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_ConvertStringFromUnicode(
2839c2c66affSColin Finck     IMultiLanguage3* iface,
2840c2c66affSColin Finck     DWORD* pdwMode,
2841c2c66affSColin Finck     DWORD dwEncoding,
2842c2c66affSColin Finck     WCHAR* pSrcStr,
2843c2c66affSColin Finck     UINT* pcSrcSize,
2844c2c66affSColin Finck     CHAR* pDstStr,
2845c2c66affSColin Finck     UINT* pcDstSize)
2846c2c66affSColin Finck {
2847c2c66affSColin Finck     return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
2848c2c66affSColin Finck         pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2849c2c66affSColin Finck }
2850c2c66affSColin Finck 
fnIMultiLanguage3_ConvertStringReset(IMultiLanguage3 * iface)2851c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_ConvertStringReset(
2852c2c66affSColin Finck     IMultiLanguage3* iface)
2853c2c66affSColin Finck {
2854c2c66affSColin Finck     FIXME("\n");
2855c2c66affSColin Finck     return E_NOTIMPL;
2856c2c66affSColin Finck }
2857c2c66affSColin Finck 
fnIMultiLanguage3_GetRfc1766FromLcid(IMultiLanguage3 * iface,LCID lcid,BSTR * pbstrRfc1766)2858c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_GetRfc1766FromLcid(
2859c2c66affSColin Finck     IMultiLanguage3* iface,
2860c2c66affSColin Finck     LCID lcid,
2861c2c66affSColin Finck     BSTR* pbstrRfc1766)
2862c2c66affSColin Finck {
2863c2c66affSColin Finck     WCHAR buf[MAX_RFC1766_NAME];
2864c2c66affSColin Finck 
2865c2c66affSColin Finck     TRACE("%p %04x %p\n", iface, lcid, pbstrRfc1766);
2866c2c66affSColin Finck     if (!pbstrRfc1766)
2867c2c66affSColin Finck         return E_INVALIDARG;
2868c2c66affSColin Finck 
2869c2c66affSColin Finck     if (!lcid_to_rfc1766W( lcid, buf, MAX_RFC1766_NAME ))
2870c2c66affSColin Finck     {
2871c2c66affSColin Finck         *pbstrRfc1766 = SysAllocString( buf );
2872c2c66affSColin Finck         return S_OK;
2873c2c66affSColin Finck     }
2874c2c66affSColin Finck     return E_FAIL;
2875c2c66affSColin Finck }
2876c2c66affSColin Finck 
fnIMultiLanguage3_GetLcidFromRfc1766(IMultiLanguage3 * iface,LCID * pLocale,BSTR bstrRfc1766)2877c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_GetLcidFromRfc1766(
2878c2c66affSColin Finck     IMultiLanguage3* iface,
2879c2c66affSColin Finck     LCID* pLocale,
2880c2c66affSColin Finck     BSTR bstrRfc1766)
2881c2c66affSColin Finck {
2882c2c66affSColin Finck     HRESULT hr;
2883c2c66affSColin Finck     IEnumRfc1766 *rfc1766;
2884c2c66affSColin Finck 
2885c2c66affSColin Finck     TRACE("%p %p %s\n", iface, pLocale, debugstr_w(bstrRfc1766));
2886c2c66affSColin Finck 
2887c2c66affSColin Finck     if (!pLocale || !bstrRfc1766)
2888c2c66affSColin Finck         return E_INVALIDARG;
2889c2c66affSColin Finck 
2890c2c66affSColin Finck     hr = IMultiLanguage3_EnumRfc1766(iface, 0, &rfc1766);
2891c2c66affSColin Finck     if (FAILED(hr))
2892c2c66affSColin Finck         return hr;
2893c2c66affSColin Finck 
2894c2c66affSColin Finck     hr = lcid_from_rfc1766(rfc1766, pLocale, bstrRfc1766);
2895c2c66affSColin Finck 
2896c2c66affSColin Finck     IEnumRfc1766_Release(rfc1766);
2897c2c66affSColin Finck     return hr;
2898c2c66affSColin Finck }
2899c2c66affSColin Finck 
fnIMultiLanguage3_EnumRfc1766(IMultiLanguage3 * iface,LANGID LangId,IEnumRfc1766 ** ppEnumRfc1766)2900c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_EnumRfc1766(
2901c2c66affSColin Finck     IMultiLanguage3* iface,
2902c2c66affSColin Finck     LANGID LangId,
2903c2c66affSColin Finck     IEnumRfc1766** ppEnumRfc1766)
2904c2c66affSColin Finck {
2905c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage3( iface );
2906c2c66affSColin Finck 
2907c2c66affSColin Finck     TRACE("%p %p\n", This, ppEnumRfc1766);
2908c2c66affSColin Finck 
2909c2c66affSColin Finck     return EnumRfc1766_create(LangId, ppEnumRfc1766);
2910c2c66affSColin Finck }
2911c2c66affSColin Finck 
fnIMultiLanguage3_GetRfc1766Info(IMultiLanguage3 * iface,LCID Locale,LANGID LangId,PRFC1766INFO pRfc1766Info)2912c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_GetRfc1766Info(
2913c2c66affSColin Finck     IMultiLanguage3* iface,
2914c2c66affSColin Finck     LCID Locale,
2915c2c66affSColin Finck     LANGID LangId,
2916c2c66affSColin Finck     PRFC1766INFO pRfc1766Info)
2917c2c66affSColin Finck {
2918c2c66affSColin Finck     static LANGID last_lang = -1;
2919c2c66affSColin Finck     LCTYPE type = LOCALE_SLANGUAGE;
2920c2c66affSColin Finck 
2921c2c66affSColin Finck     TRACE("(%p, 0x%04x, 0x%04x, %p)\n", iface, Locale, LangId, pRfc1766Info);
2922c2c66affSColin Finck 
2923c2c66affSColin Finck     if (!pRfc1766Info)
2924c2c66affSColin Finck         return E_INVALIDARG;
2925c2c66affSColin Finck 
2926c2c66affSColin Finck     if ((PRIMARYLANGID(Locale) == LANG_ENGLISH) ||
2927c2c66affSColin Finck         (PRIMARYLANGID(Locale) == LANG_CHINESE) ||
2928c2c66affSColin Finck         (PRIMARYLANGID(Locale) == LANG_ARABIC)) {
2929c2c66affSColin Finck 
2930c2c66affSColin Finck         if (!SUBLANGID(Locale))
2931c2c66affSColin Finck             type = LOCALE_SENGLANGUAGE; /* suppress country */
2932c2c66affSColin Finck     }
2933c2c66affSColin Finck     else
2934c2c66affSColin Finck     {
2935c2c66affSColin Finck         if (!SUBLANGID(Locale)) {
2936c2c66affSColin Finck             TRACE("SUBLANGID missing in 0x%04x\n", Locale);
2937c2c66affSColin Finck             return E_FAIL;
2938c2c66affSColin Finck         }
2939c2c66affSColin Finck     }
2940c2c66affSColin Finck 
2941c2c66affSColin Finck     pRfc1766Info->lcid = Locale;
2942c2c66affSColin Finck     pRfc1766Info->wszRfc1766[0] = 0;
2943c2c66affSColin Finck     pRfc1766Info->wszLocaleName[0] = 0;
2944c2c66affSColin Finck 
2945c2c66affSColin Finck     if ((PRIMARYLANGID(LangId) != LANG_ENGLISH) &&
2946c2c66affSColin Finck         (last_lang != LangId)) {
2947c2c66affSColin Finck         FIXME("Only English names supported (requested: 0x%04x)\n", LangId);
2948c2c66affSColin Finck         last_lang = LangId;
2949c2c66affSColin Finck     }
2950c2c66affSColin Finck 
2951c2c66affSColin Finck     if ((!lcid_to_rfc1766W(Locale, pRfc1766Info->wszRfc1766, MAX_RFC1766_NAME)) &&
2952c2c66affSColin Finck         (GetLocaleInfoW(Locale, type, pRfc1766Info->wszLocaleName, MAX_LOCALE_NAME) > 0))
2953c2c66affSColin Finck             return S_OK;
2954c2c66affSColin Finck 
2955c2c66affSColin Finck     /* Locale not supported */
2956c2c66affSColin Finck     return E_INVALIDARG;
2957c2c66affSColin Finck }
2958c2c66affSColin Finck 
fnIMultiLanguage3_CreateConvertCharset(IMultiLanguage3 * iface,UINT src_cp,UINT dst_cp,DWORD prop,IMLangConvertCharset ** convert_charset)2959c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_CreateConvertCharset(
2960c2c66affSColin Finck     IMultiLanguage3* iface,
2961c2c66affSColin Finck     UINT src_cp,
2962c2c66affSColin Finck     UINT dst_cp,
2963c2c66affSColin Finck     DWORD prop,
2964c2c66affSColin Finck     IMLangConvertCharset** convert_charset)
2965c2c66affSColin Finck {
2966c2c66affSColin Finck     HRESULT hr;
2967c2c66affSColin Finck 
2968c2c66affSColin Finck     TRACE("(%u %u 0x%08x %p)\n", src_cp, dst_cp, prop, convert_charset);
2969c2c66affSColin Finck 
2970c2c66affSColin Finck     hr = MLangConvertCharset_create(NULL, (void**)convert_charset);
2971c2c66affSColin Finck     if (FAILED(hr)) return hr;
2972c2c66affSColin Finck 
2973c2c66affSColin Finck     return IMLangConvertCharset_Initialize(*convert_charset, src_cp, dst_cp, prop);
2974c2c66affSColin Finck }
2975c2c66affSColin Finck 
fnIMultiLanguage3_ConvertStringInIStream(IMultiLanguage3 * iface,DWORD * pdwMode,DWORD dwFlag,WCHAR * lpFallBack,DWORD dwSrcEncoding,DWORD dwDstEncoding,IStream * pstmIn,IStream * pstmOut)2976c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_ConvertStringInIStream(
2977c2c66affSColin Finck     IMultiLanguage3* iface,
2978c2c66affSColin Finck     DWORD* pdwMode,
2979c2c66affSColin Finck     DWORD dwFlag,
2980c2c66affSColin Finck     WCHAR* lpFallBack,
2981c2c66affSColin Finck     DWORD dwSrcEncoding,
2982c2c66affSColin Finck     DWORD dwDstEncoding,
2983c2c66affSColin Finck     IStream* pstmIn,
2984c2c66affSColin Finck     IStream* pstmOut)
2985c2c66affSColin Finck {
2986c2c66affSColin Finck     char *src, *dst = NULL;
2987c2c66affSColin Finck     INT srclen, dstlen;
2988c2c66affSColin Finck     STATSTG stat;
2989c2c66affSColin Finck     HRESULT hr;
2990c2c66affSColin Finck 
2991c2c66affSColin Finck     TRACE("%p %0x8 %s %u %u %p %p\n",
2992c2c66affSColin Finck           pdwMode, dwFlag, debugstr_w(lpFallBack), dwSrcEncoding, dwDstEncoding, pstmIn, pstmOut);
2993c2c66affSColin Finck 
2994c2c66affSColin Finck     FIXME("dwFlag and lpFallBack not handled\n");
2995c2c66affSColin Finck 
2996c2c66affSColin Finck     hr = IStream_Stat(pstmIn, &stat, STATFLAG_NONAME);
2997c2c66affSColin Finck     if (FAILED(hr)) return hr;
2998c2c66affSColin Finck 
2999c2c66affSColin Finck     if (stat.cbSize.QuadPart > MAXLONG) return E_INVALIDARG;
3000c2c66affSColin Finck     if (!(src = HeapAlloc(GetProcessHeap(), 0, stat.cbSize.QuadPart))) return E_OUTOFMEMORY;
3001c2c66affSColin Finck 
3002c2c66affSColin Finck     hr = IStream_Read(pstmIn, src, stat.cbSize.QuadPart, (ULONG *)&srclen);
3003c2c66affSColin Finck     if (FAILED(hr)) goto exit;
3004c2c66affSColin Finck 
3005c2c66affSColin Finck     hr = ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding, src, &srclen, NULL, &dstlen);
3006c2c66affSColin Finck     if (FAILED(hr)) goto exit;
3007c2c66affSColin Finck 
3008c2c66affSColin Finck     if (!(dst = HeapAlloc(GetProcessHeap(), 0, dstlen)))
3009c2c66affSColin Finck     {
3010c2c66affSColin Finck         hr = E_OUTOFMEMORY;
3011c2c66affSColin Finck         goto exit;
3012c2c66affSColin Finck     }
3013c2c66affSColin Finck     hr = ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding, src, &srclen, dst, &dstlen);
3014c2c66affSColin Finck     if (FAILED(hr)) goto exit;
3015c2c66affSColin Finck 
3016c2c66affSColin Finck     hr = IStream_Write(pstmOut, dst, dstlen, NULL);
3017c2c66affSColin Finck 
3018c2c66affSColin Finck exit:
3019c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, src);
3020c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, dst);
3021c2c66affSColin Finck     return hr;
3022c2c66affSColin Finck }
3023c2c66affSColin Finck 
fnIMultiLanguage3_ConvertStringToUnicodeEx(IMultiLanguage3 * iface,DWORD * pdwMode,DWORD dwEncoding,CHAR * pSrcStr,UINT * pcSrcSize,WCHAR * pDstStr,UINT * pcDstSize,DWORD dwFlag,WCHAR * lpFallBack)3024c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_ConvertStringToUnicodeEx(
3025c2c66affSColin Finck     IMultiLanguage3* iface,
3026c2c66affSColin Finck     DWORD* pdwMode,
3027c2c66affSColin Finck     DWORD dwEncoding,
3028c2c66affSColin Finck     CHAR* pSrcStr,
3029c2c66affSColin Finck     UINT* pcSrcSize,
3030c2c66affSColin Finck     WCHAR* pDstStr,
3031c2c66affSColin Finck     UINT* pcDstSize,
3032c2c66affSColin Finck     DWORD dwFlag,
3033c2c66affSColin Finck     WCHAR* lpFallBack)
3034c2c66affSColin Finck {
3035c2c66affSColin Finck     if (dwFlag || lpFallBack)
3036c2c66affSColin Finck         FIXME("Ignoring dwFlag (0x%x/%d) and lpFallBack (%p)\n",
3037c2c66affSColin Finck                 dwFlag, dwFlag, lpFallBack);
3038c2c66affSColin Finck 
3039c2c66affSColin Finck     return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
3040c2c66affSColin Finck         pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
3041c2c66affSColin Finck }
3042c2c66affSColin Finck 
3043c2c66affSColin Finck /*****************************************************************************
3044c2c66affSColin Finck  * MultiLanguage2::ConvertStringToUnicodeEx
3045c2c66affSColin Finck  *
3046c2c66affSColin Finck  * Translates the multibyte string from the specified code page to Unicode.
3047c2c66affSColin Finck  *
3048c2c66affSColin Finck  * PARAMS
3049c2c66affSColin Finck  *   see ConvertStringToUnicode
3050c2c66affSColin Finck  *   dwFlag
3051c2c66affSColin Finck  *   lpFallBack if dwFlag contains MLCONVCHARF_USEDEFCHAR, lpFallBack string used
3052c2c66affSColin Finck  *              instead unconvertible characters.
3053c2c66affSColin Finck  *
3054c2c66affSColin Finck  * RETURNS
3055c2c66affSColin Finck  *   S_OK     Success.
3056c2c66affSColin Finck  *   S_FALSE  The conversion is not supported.
3057c2c66affSColin Finck  *   E_FAIL   Some error has occurred.
3058c2c66affSColin Finck  *
3059c2c66affSColin Finck  * TODO: handle dwFlag and lpFallBack
3060c2c66affSColin Finck */
fnIMultiLanguage3_ConvertStringFromUnicodeEx(IMultiLanguage3 * This,DWORD * pdwMode,DWORD dwEncoding,WCHAR * pSrcStr,UINT * pcSrcSize,CHAR * pDstStr,UINT * pcDstSize,DWORD dwFlag,WCHAR * lpFallBack)3061c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_ConvertStringFromUnicodeEx(
3062c2c66affSColin Finck     IMultiLanguage3* This,
3063c2c66affSColin Finck     DWORD* pdwMode,
3064c2c66affSColin Finck     DWORD dwEncoding,
3065c2c66affSColin Finck     WCHAR* pSrcStr,
3066c2c66affSColin Finck     UINT* pcSrcSize,
3067c2c66affSColin Finck     CHAR* pDstStr,
3068c2c66affSColin Finck     UINT* pcDstSize,
3069c2c66affSColin Finck     DWORD dwFlag,
3070c2c66affSColin Finck     WCHAR* lpFallBack)
3071c2c66affSColin Finck {
3072c2c66affSColin Finck     FIXME("\n");
3073c2c66affSColin Finck     return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
3074c2c66affSColin Finck         pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
3075c2c66affSColin Finck }
3076c2c66affSColin Finck 
fnIMultiLanguage3_DetectCodepageInIStream(IMultiLanguage3 * iface,DWORD dwFlag,DWORD dwPrefWinCodePage,IStream * pstmIn,DetectEncodingInfo * lpEncoding,INT * pnScores)3077c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_DetectCodepageInIStream(
3078c2c66affSColin Finck     IMultiLanguage3* iface,
3079c2c66affSColin Finck     DWORD dwFlag,
3080c2c66affSColin Finck     DWORD dwPrefWinCodePage,
3081c2c66affSColin Finck     IStream* pstmIn,
3082c2c66affSColin Finck     DetectEncodingInfo* lpEncoding,
3083c2c66affSColin Finck     INT* pnScores)
3084c2c66affSColin Finck {
3085c2c66affSColin Finck     FIXME("\n");
3086c2c66affSColin Finck     return E_NOTIMPL;
3087c2c66affSColin Finck }
3088c2c66affSColin Finck 
fnIMultiLanguage3_DetectInputCodepage(IMultiLanguage3 * iface,DWORD dwFlag,DWORD dwPrefWinCodePage,CHAR * pSrcStr,INT * pcSrcSize,DetectEncodingInfo * lpEncoding,INT * pnScores)3089c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_DetectInputCodepage(
3090c2c66affSColin Finck     IMultiLanguage3* iface,
3091c2c66affSColin Finck     DWORD dwFlag,
3092c2c66affSColin Finck     DWORD dwPrefWinCodePage,
3093c2c66affSColin Finck     CHAR* pSrcStr,
3094c2c66affSColin Finck     INT* pcSrcSize,
3095c2c66affSColin Finck     DetectEncodingInfo* lpEncoding,
3096c2c66affSColin Finck     INT* pnScores)
3097c2c66affSColin Finck {
3098c2c66affSColin Finck     FIXME("\n");
3099c2c66affSColin Finck     return E_NOTIMPL;
3100c2c66affSColin Finck }
3101c2c66affSColin Finck 
fnIMultiLanguage3_ValidateCodePage(IMultiLanguage3 * iface,UINT uiCodePage,HWND hwnd)3102c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_ValidateCodePage(
3103c2c66affSColin Finck     IMultiLanguage3* iface,
3104c2c66affSColin Finck     UINT uiCodePage,
3105c2c66affSColin Finck     HWND hwnd)
3106c2c66affSColin Finck {
3107c2c66affSColin Finck     return IMultiLanguage3_ValidateCodePageEx(iface,uiCodePage,hwnd,0);
3108c2c66affSColin Finck }
3109c2c66affSColin Finck 
fnIMultiLanguage3_GetCodePageDescription(IMultiLanguage3 * iface,UINT uiCodePage,LCID lcid,LPWSTR lpWideCharStr,int cchWideChar)3110c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_GetCodePageDescription(
3111c2c66affSColin Finck     IMultiLanguage3* iface,
3112c2c66affSColin Finck     UINT uiCodePage,
3113c2c66affSColin Finck     LCID lcid,
3114c2c66affSColin Finck     LPWSTR lpWideCharStr,
3115c2c66affSColin Finck     int cchWideChar)
3116c2c66affSColin Finck {
3117c2c66affSColin Finck     /* Find first instance */
3118c2c66affSColin Finck     unsigned int i,n;
3119c2c66affSColin Finck 
3120c2c66affSColin Finck     TRACE ("%u, %04x, %p, %d\n", uiCodePage, lcid, lpWideCharStr, cchWideChar);
3121ccc3eeaeSAmine Khaldi     for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3122c2c66affSColin Finck     {
3123c2c66affSColin Finck         for (n = 0; n < mlang_data[i].number_of_cp; n++)
3124c2c66affSColin Finck         {
3125c2c66affSColin Finck             if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
3126c2c66affSColin Finck             {
3127c2c66affSColin Finck                 MultiByteToWideChar(CP_ACP, 0,
3128c2c66affSColin Finck                                     mlang_data[i].mime_cp_info[n].description,
3129c2c66affSColin Finck                                     -1, lpWideCharStr, cchWideChar);
3130c2c66affSColin Finck                 return S_OK;
3131c2c66affSColin Finck             }
3132c2c66affSColin Finck         }
3133c2c66affSColin Finck     }
3134c2c66affSColin Finck 
3135c2c66affSColin Finck     return S_FALSE;
3136c2c66affSColin Finck }
3137c2c66affSColin Finck 
fnIMultiLanguage3_IsCodePageInstallable(IMultiLanguage3 * iface,UINT uiCodePage)3138c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_IsCodePageInstallable(
3139c2c66affSColin Finck     IMultiLanguage3* iface,
3140c2c66affSColin Finck     UINT uiCodePage)
3141c2c66affSColin Finck {
3142c2c66affSColin Finck     TRACE("%u\n", uiCodePage);
3143c2c66affSColin Finck 
3144c2c66affSColin Finck     /* FIXME: the installable set is usually larger than the set of valid codepages */
3145c2c66affSColin Finck     return IMultiLanguage3_ValidateCodePageEx(iface, uiCodePage, NULL, CPIOD_PEEK);
3146c2c66affSColin Finck }
3147c2c66affSColin Finck 
fnIMultiLanguage3_SetMimeDBSource(IMultiLanguage3 * iface,MIMECONTF dwSource)3148c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_SetMimeDBSource(
3149c2c66affSColin Finck     IMultiLanguage3* iface,
3150c2c66affSColin Finck     MIMECONTF dwSource)
3151c2c66affSColin Finck {
3152c2c66affSColin Finck     FIXME("0x%08x\n", dwSource);
3153c2c66affSColin Finck     return S_OK;
3154c2c66affSColin Finck }
3155c2c66affSColin Finck 
fnIMultiLanguage3_GetNumberOfScripts(IMultiLanguage3 * iface,UINT * pnScripts)3156c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_GetNumberOfScripts(
3157c2c66affSColin Finck     IMultiLanguage3* iface,
3158c2c66affSColin Finck     UINT* pnScripts)
3159c2c66affSColin Finck {
3160c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage3( iface );
3161c2c66affSColin Finck 
3162c2c66affSColin Finck     TRACE("%p %p\n", This, pnScripts);
3163c2c66affSColin Finck 
3164c2c66affSColin Finck     if (!pnScripts) return S_FALSE;
3165c2c66affSColin Finck 
3166c2c66affSColin Finck     *pnScripts = This->total_scripts;
3167c2c66affSColin Finck     return S_OK;
3168c2c66affSColin Finck }
3169c2c66affSColin Finck 
fnIMultiLanguage3_EnumScripts(IMultiLanguage3 * iface,DWORD dwFlags,LANGID LangId,IEnumScript ** ppEnumScript)3170c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_EnumScripts(
3171c2c66affSColin Finck     IMultiLanguage3* iface,
3172c2c66affSColin Finck     DWORD dwFlags,
3173c2c66affSColin Finck     LANGID LangId,
3174c2c66affSColin Finck     IEnumScript** ppEnumScript)
3175c2c66affSColin Finck {
3176c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage3( iface );
3177c2c66affSColin Finck 
3178c2c66affSColin Finck     TRACE("%p %08x %04x %p\n", This, dwFlags, LangId, ppEnumScript);
3179c2c66affSColin Finck 
3180c2c66affSColin Finck     return EnumScript_create( This, dwFlags, LangId, ppEnumScript );
3181c2c66affSColin Finck }
3182c2c66affSColin Finck 
fnIMultiLanguage3_ValidateCodePageEx(IMultiLanguage3 * iface,UINT uiCodePage,HWND hwnd,DWORD dwfIODControl)3183c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_ValidateCodePageEx(
3184c2c66affSColin Finck     IMultiLanguage3* iface,
3185c2c66affSColin Finck     UINT uiCodePage,
3186c2c66affSColin Finck     HWND hwnd,
3187c2c66affSColin Finck     DWORD dwfIODControl)
3188c2c66affSColin Finck {
3189c2c66affSColin Finck     unsigned int i;
3190c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage3( iface );
3191c2c66affSColin Finck 
3192c2c66affSColin Finck     TRACE("%p %u %p %08x\n", This, uiCodePage, hwnd, dwfIODControl);
3193c2c66affSColin Finck 
3194c2c66affSColin Finck     /* quick check for kernel32 supported code pages */
3195c2c66affSColin Finck     if (IsValidCodePage(uiCodePage))
3196c2c66affSColin Finck         return S_OK;
3197c2c66affSColin Finck 
3198c2c66affSColin Finck     /* check for mlang supported code pages */
3199ccc3eeaeSAmine Khaldi     for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3200c2c66affSColin Finck     {
3201c2c66affSColin Finck         UINT n;
3202c2c66affSColin Finck         for (n = 0; n < mlang_data[i].number_of_cp; n++)
3203c2c66affSColin Finck         {
3204c2c66affSColin Finck             if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
3205c2c66affSColin Finck                 return S_OK;
3206c2c66affSColin Finck         }
3207c2c66affSColin Finck     }
3208c2c66affSColin Finck 
3209c2c66affSColin Finck     if (dwfIODControl != CPIOD_PEEK)
3210c2c66affSColin Finck         FIXME("Request to install codepage language pack not handled\n");
3211c2c66affSColin Finck 
3212c2c66affSColin Finck     return S_FALSE;
3213c2c66affSColin Finck }
3214c2c66affSColin Finck 
fnIMultiLanguage3_DetectOutboundCodePage(IMultiLanguage3 * iface,DWORD dwFlags,LPCWSTR lpWideCharStr,UINT cchWideChar,UINT * puiPreferredCodePages,UINT nPreferredCodePages,UINT * puiDetectedCodePages,UINT * pnDetectedCodePages,WCHAR * lpSpecialChar)3215c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_DetectOutboundCodePage(
3216c2c66affSColin Finck     IMultiLanguage3 *iface,
3217c2c66affSColin Finck     DWORD dwFlags,
3218c2c66affSColin Finck     LPCWSTR lpWideCharStr,
3219c2c66affSColin Finck     UINT cchWideChar,
3220c2c66affSColin Finck     UINT *puiPreferredCodePages,
3221c2c66affSColin Finck     UINT nPreferredCodePages,
3222c2c66affSColin Finck     UINT *puiDetectedCodePages,
3223c2c66affSColin Finck     UINT *pnDetectedCodePages,
3224c2c66affSColin Finck     WCHAR *lpSpecialChar)
3225c2c66affSColin Finck {
3226c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage3( iface );
3227c2c66affSColin Finck 
3228c2c66affSColin Finck     FIXME("(%p)->(%08x %s %p %u %p %p(%u) %s)\n", This, dwFlags, debugstr_w(lpWideCharStr),
3229c2c66affSColin Finck           puiPreferredCodePages, nPreferredCodePages, puiDetectedCodePages,
3230c2c66affSColin Finck           pnDetectedCodePages, pnDetectedCodePages ? *pnDetectedCodePages : 0,
3231c2c66affSColin Finck           debugstr_w(lpSpecialChar));
3232c2c66affSColin Finck 
3233c2c66affSColin Finck     if (!puiDetectedCodePages || !pnDetectedCodePages || !*pnDetectedCodePages)
3234c2c66affSColin Finck         return E_INVALIDARG;
3235c2c66affSColin Finck 
3236c2c66affSColin Finck     puiDetectedCodePages[0] = CP_UTF8;
3237c2c66affSColin Finck     *pnDetectedCodePages = 1;
3238c2c66affSColin Finck     return S_OK;
3239c2c66affSColin Finck }
3240c2c66affSColin Finck 
fnIMultiLanguage3_DetectOutboundCodePageInIStream(IMultiLanguage3 * iface,DWORD dwFlags,IStream * pStrIn,UINT * puiPreferredCodePages,UINT nPreferredCodePages,UINT * puiDetectedCodePages,UINT * pnDetectedCodePages,WCHAR * lpSpecialChar)3241c2c66affSColin Finck static HRESULT WINAPI fnIMultiLanguage3_DetectOutboundCodePageInIStream(
3242c2c66affSColin Finck     IMultiLanguage3 *iface,
3243c2c66affSColin Finck     DWORD dwFlags,
3244c2c66affSColin Finck     IStream *pStrIn,
3245c2c66affSColin Finck     UINT *puiPreferredCodePages,
3246c2c66affSColin Finck     UINT nPreferredCodePages,
3247c2c66affSColin Finck     UINT *puiDetectedCodePages,
3248c2c66affSColin Finck     UINT *pnDetectedCodePages,
3249c2c66affSColin Finck     WCHAR *lpSpecialChar)
3250c2c66affSColin Finck {
3251c2c66affSColin Finck     MLang_impl *This = impl_from_IMultiLanguage3( iface );
3252c2c66affSColin Finck 
3253c2c66affSColin Finck     FIXME("(%p)->(%08x %p %p %u %p %p(%u) %s)\n", This, dwFlags, pStrIn,
3254c2c66affSColin Finck           puiPreferredCodePages, nPreferredCodePages, puiDetectedCodePages,
3255c2c66affSColin Finck           pnDetectedCodePages, pnDetectedCodePages ? *pnDetectedCodePages : 0,
3256c2c66affSColin Finck           debugstr_w(lpSpecialChar));
3257c2c66affSColin Finck 
3258c2c66affSColin Finck     if (!puiDetectedCodePages || !pnDetectedCodePages || !*pnDetectedCodePages)
3259c2c66affSColin Finck         return E_INVALIDARG;
3260c2c66affSColin Finck 
3261c2c66affSColin Finck     puiDetectedCodePages[0] = CP_UTF8;
3262c2c66affSColin Finck     *pnDetectedCodePages = 1;
3263c2c66affSColin Finck     return S_OK;
3264c2c66affSColin Finck }
3265c2c66affSColin Finck 
3266c2c66affSColin Finck static const IMultiLanguage3Vtbl IMultiLanguage3_vtbl =
3267c2c66affSColin Finck {
3268c2c66affSColin Finck     fnIMultiLanguage3_QueryInterface,
3269c2c66affSColin Finck     fnIMultiLanguage3_AddRef,
3270c2c66affSColin Finck     fnIMultiLanguage3_Release,
3271c2c66affSColin Finck     fnIMultiLanguage3_GetNumberOfCodePageInfo,
3272c2c66affSColin Finck     fnIMultiLanguage3_GetCodePageInfo,
3273c2c66affSColin Finck     fnIMultiLanguage3_GetFamilyCodePage,
3274c2c66affSColin Finck     fnIMultiLanguage3_EnumCodePages,
3275c2c66affSColin Finck     fnIMultiLanguage3_GetCharsetInfo,
3276c2c66affSColin Finck     fnIMultiLanguage3_IsConvertible,
3277c2c66affSColin Finck     fnIMultiLanguage3_ConvertString,
3278c2c66affSColin Finck     fnIMultiLanguage3_ConvertStringToUnicode,
3279c2c66affSColin Finck     fnIMultiLanguage3_ConvertStringFromUnicode,
3280c2c66affSColin Finck     fnIMultiLanguage3_ConvertStringReset,
3281c2c66affSColin Finck     fnIMultiLanguage3_GetRfc1766FromLcid,
3282c2c66affSColin Finck     fnIMultiLanguage3_GetLcidFromRfc1766,
3283c2c66affSColin Finck     fnIMultiLanguage3_EnumRfc1766,
3284c2c66affSColin Finck     fnIMultiLanguage3_GetRfc1766Info,
3285c2c66affSColin Finck     fnIMultiLanguage3_CreateConvertCharset,
3286c2c66affSColin Finck     fnIMultiLanguage3_ConvertStringInIStream,
3287c2c66affSColin Finck     fnIMultiLanguage3_ConvertStringToUnicodeEx,
3288c2c66affSColin Finck     fnIMultiLanguage3_ConvertStringFromUnicodeEx,
3289c2c66affSColin Finck     fnIMultiLanguage3_DetectCodepageInIStream,
3290c2c66affSColin Finck     fnIMultiLanguage3_DetectInputCodepage,
3291c2c66affSColin Finck     fnIMultiLanguage3_ValidateCodePage,
3292c2c66affSColin Finck     fnIMultiLanguage3_GetCodePageDescription,
3293c2c66affSColin Finck     fnIMultiLanguage3_IsCodePageInstallable,
3294c2c66affSColin Finck     fnIMultiLanguage3_SetMimeDBSource,
3295c2c66affSColin Finck     fnIMultiLanguage3_GetNumberOfScripts,
3296c2c66affSColin Finck     fnIMultiLanguage3_EnumScripts,
3297c2c66affSColin Finck     fnIMultiLanguage3_ValidateCodePageEx,
3298c2c66affSColin Finck     fnIMultiLanguage3_DetectOutboundCodePage,
3299c2c66affSColin Finck     fnIMultiLanguage3_DetectOutboundCodePageInIStream
3300c2c66affSColin Finck };
3301c2c66affSColin Finck 
3302c2c66affSColin Finck /******************************************************************************/
3303c2c66affSColin Finck 
impl_from_IMLangFontLink2(IMLangFontLink2 * iface)3304c2c66affSColin Finck static inline MLang_impl *impl_from_IMLangFontLink2( IMLangFontLink2 *iface )
3305c2c66affSColin Finck {
3306c2c66affSColin Finck     return CONTAINING_RECORD( iface, MLang_impl, IMLangFontLink2_iface );
3307c2c66affSColin Finck }
3308c2c66affSColin Finck 
fnIMLangFontLink2_QueryInterface(IMLangFontLink2 * iface,REFIID riid,void ** ppvObject)3309c2c66affSColin Finck static HRESULT WINAPI fnIMLangFontLink2_QueryInterface(
3310c2c66affSColin Finck     IMLangFontLink2 * iface,
3311c2c66affSColin Finck     REFIID riid,
3312c2c66affSColin Finck     void** ppvObject)
3313c2c66affSColin Finck {
3314c2c66affSColin Finck     MLang_impl *This = impl_from_IMLangFontLink2( iface );
3315c2c66affSColin Finck     return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
3316c2c66affSColin Finck }
3317c2c66affSColin Finck 
fnIMLangFontLink2_AddRef(IMLangFontLink2 * iface)3318c2c66affSColin Finck static ULONG WINAPI fnIMLangFontLink2_AddRef( IMLangFontLink2* iface )
3319c2c66affSColin Finck {
3320c2c66affSColin Finck     MLang_impl *This = impl_from_IMLangFontLink2( iface );
3321c2c66affSColin Finck     return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
3322c2c66affSColin Finck }
3323c2c66affSColin Finck 
fnIMLangFontLink2_Release(IMLangFontLink2 * iface)3324c2c66affSColin Finck static ULONG WINAPI fnIMLangFontLink2_Release( IMLangFontLink2* iface )
3325c2c66affSColin Finck {
3326c2c66affSColin Finck     MLang_impl *This = impl_from_IMLangFontLink2( iface );
3327c2c66affSColin Finck     return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
3328c2c66affSColin Finck }
3329c2c66affSColin Finck 
fnIMLangFontLink2_GetCharCodePages(IMLangFontLink2 * iface,WCHAR ch_src,DWORD * ret_codepages)3330c2c66affSColin Finck static HRESULT WINAPI fnIMLangFontLink2_GetCharCodePages( IMLangFontLink2* iface,
3331c2c66affSColin Finck         WCHAR ch_src, DWORD *ret_codepages)
3332c2c66affSColin Finck {
3333c2c66affSColin Finck     MLang_impl *This = impl_from_IMLangFontLink2(iface);
3334c2c66affSColin Finck     unsigned int i;
3335c2c66affSColin Finck 
3336c2c66affSColin Finck     TRACE("(%p)->(%s %p)\n", This, debugstr_wn(&ch_src, 1), ret_codepages);
3337c2c66affSColin Finck 
3338c2c66affSColin Finck     *ret_codepages = 0;
3339c2c66affSColin Finck 
3340ccc3eeaeSAmine Khaldi     for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3341c2c66affSColin Finck     {
3342c2c66affSColin Finck         BOOL used_dc;
3343c2c66affSColin Finck         CHAR buf;
3344c2c66affSColin Finck 
3345c2c66affSColin Finck         WideCharToMultiByte(mlang_data[i].family_codepage, WC_NO_BEST_FIT_CHARS,
3346c2c66affSColin Finck             &ch_src, 1, &buf, 1, NULL, &used_dc);
3347c2c66affSColin Finck 
3348c2c66affSColin Finck         /* If default char is not used, current codepage include the given symbol */
3349c2c66affSColin Finck         if (!used_dc)
3350c2c66affSColin Finck         {
3351c2c66affSColin Finck             DWORD codepages;
3352c2c66affSColin Finck 
3353c2c66affSColin Finck             IMLangFontLink2_CodePageToCodePages(iface,
3354c2c66affSColin Finck                 mlang_data[i].family_codepage, &codepages);
3355c2c66affSColin Finck             *ret_codepages |= codepages;
3356c2c66affSColin Finck         }
3357c2c66affSColin Finck     }
3358c2c66affSColin Finck     return S_OK;
3359c2c66affSColin Finck }
3360c2c66affSColin Finck 
fnIMLangFontLink2_GetStrCodePages(IMLangFontLink2 * iface,const WCHAR * src,LONG src_len,DWORD priority_cp,DWORD * codepages,LONG * ret_len)3361c2c66affSColin Finck static HRESULT WINAPI fnIMLangFontLink2_GetStrCodePages( IMLangFontLink2* iface,
3362c2c66affSColin Finck         const WCHAR *src, LONG src_len, DWORD priority_cp,
3363c2c66affSColin Finck         DWORD *codepages, LONG *ret_len)
3364c2c66affSColin Finck {
3365c2c66affSColin Finck     MLang_impl *This = impl_from_IMLangFontLink2(iface);
3366c2c66affSColin Finck     LONG i;
3367c2c66affSColin Finck     DWORD cps = 0;
3368c2c66affSColin Finck 
3369c2c66affSColin Finck     TRACE("(%p)->(%s:%d %x %p %p)\n", This, debugstr_wn(src, src_len), src_len, priority_cp,
3370c2c66affSColin Finck         codepages, ret_len);
3371c2c66affSColin Finck 
3372c2c66affSColin Finck     if (codepages) *codepages = 0;
3373c2c66affSColin Finck     if (ret_len) *ret_len = 0;
3374c2c66affSColin Finck 
3375c2c66affSColin Finck     if (!src || !src_len || src_len < 0)
3376c2c66affSColin Finck         return E_INVALIDARG;
3377c2c66affSColin Finck 
3378c2c66affSColin Finck     for (i = 0; i < src_len; i++)
3379c2c66affSColin Finck     {
3380c2c66affSColin Finck         DWORD cp;
3381c2c66affSColin Finck         HRESULT ret;
3382c2c66affSColin Finck 
3383c2c66affSColin Finck         ret = IMLangFontLink2_GetCharCodePages(iface, src[i], &cp);
3384c2c66affSColin Finck         if (ret != S_OK) return E_FAIL;
3385c2c66affSColin Finck 
3386c2c66affSColin Finck         if (!cps) cps = cp;
3387c2c66affSColin Finck         else cps &= cp;
3388c2c66affSColin Finck 
3389c2c66affSColin Finck         /* FIXME: not tested */
3390c2c66affSColin Finck         if (priority_cp & cps) break;
3391c2c66affSColin Finck     }
3392c2c66affSColin Finck 
3393c2c66affSColin Finck     if (codepages) *codepages = cps;
3394c2c66affSColin Finck     if (ret_len) *ret_len = min( i + 1, src_len );
3395c2c66affSColin Finck     return S_OK;
3396c2c66affSColin Finck }
3397c2c66affSColin Finck 
fnIMLangFontLink2_CodePageToCodePages(IMLangFontLink2 * iface,UINT codepage,DWORD * codepages)3398c2c66affSColin Finck static HRESULT WINAPI fnIMLangFontLink2_CodePageToCodePages(IMLangFontLink2* iface,
3399c2c66affSColin Finck         UINT codepage,
3400c2c66affSColin Finck         DWORD *codepages)
3401c2c66affSColin Finck {
3402c2c66affSColin Finck     MLang_impl *This = impl_from_IMLangFontLink2(iface);
3403c2c66affSColin Finck     CHARSETINFO cs;
3404c2c66affSColin Finck     BOOL rc;
3405c2c66affSColin Finck 
3406c2c66affSColin Finck     TRACE("(%p)->(%u %p)\n", This, codepage, codepages);
3407c2c66affSColin Finck 
3408c2c66affSColin Finck     rc = TranslateCharsetInfo((DWORD*)(DWORD_PTR)codepage, &cs, TCI_SRCCODEPAGE);
3409c2c66affSColin Finck     if (rc)
3410c2c66affSColin Finck     {
3411c2c66affSColin Finck         *codepages = cs.fs.fsCsb[0];
3412c2c66affSColin Finck         TRACE("resulting codepages 0x%x\n", *codepages);
3413c2c66affSColin Finck         return S_OK;
3414c2c66affSColin Finck     }
3415c2c66affSColin Finck 
3416c2c66affSColin Finck     TRACE("codepage not found\n");
3417c2c66affSColin Finck     *codepages = 0;
3418c2c66affSColin Finck     return E_FAIL;
3419c2c66affSColin Finck }
3420c2c66affSColin Finck 
fnIMLangFontLink2_CodePagesToCodePage(IMLangFontLink2 * iface,DWORD codepages,UINT def_codepage,UINT * codepage)3421c2c66affSColin Finck static HRESULT WINAPI fnIMLangFontLink2_CodePagesToCodePage(IMLangFontLink2* iface,
3422c2c66affSColin Finck         DWORD codepages, UINT def_codepage, UINT *codepage)
3423c2c66affSColin Finck {
3424c2c66affSColin Finck     MLang_impl *This = impl_from_IMLangFontLink2(iface);
3425c2c66affSColin Finck     DWORD mask = 0;
3426c2c66affSColin Finck     CHARSETINFO cs;
3427c2c66affSColin Finck     BOOL rc;
3428c2c66affSColin Finck     UINT i;
3429c2c66affSColin Finck 
3430c2c66affSColin Finck     TRACE("(%p)->(0x%x %u %p)\n", This, codepages, def_codepage, codepage);
3431c2c66affSColin Finck 
3432c2c66affSColin Finck     *codepage = 0;
3433c2c66affSColin Finck 
3434c2c66affSColin Finck     rc = TranslateCharsetInfo((DWORD*)(DWORD_PTR)def_codepage, &cs, TCI_SRCCODEPAGE);
3435c2c66affSColin Finck     if (rc && (codepages & cs.fs.fsCsb[0]))
3436c2c66affSColin Finck     {
3437c2c66affSColin Finck         TRACE("Found Default Codepage\n");
3438c2c66affSColin Finck         *codepage = def_codepage;
3439c2c66affSColin Finck         return S_OK;
3440c2c66affSColin Finck     }
3441c2c66affSColin Finck 
3442c2c66affSColin Finck     for (i = 0; i < 32; i++)
3443c2c66affSColin Finck     {
3444c2c66affSColin Finck         mask = 1 << i;
3445c2c66affSColin Finck         if (codepages & mask)
3446c2c66affSColin Finck         {
3447c2c66affSColin Finck             DWORD Csb[2];
3448c2c66affSColin Finck             Csb[0] = mask;
3449c2c66affSColin Finck             Csb[1] = 0x0;
3450c2c66affSColin Finck             rc = TranslateCharsetInfo(Csb, &cs, TCI_SRCFONTSIG);
3451c2c66affSColin Finck             if (!rc)
3452c2c66affSColin Finck                 continue;
3453c2c66affSColin Finck 
3454c2c66affSColin Finck             TRACE("Falling back to least significant found CodePage %u\n",
3455c2c66affSColin Finck                     cs.ciACP);
3456c2c66affSColin Finck             *codepage = cs.ciACP;
3457c2c66affSColin Finck             return S_OK;
3458c2c66affSColin Finck         }
3459c2c66affSColin Finck     }
3460c2c66affSColin Finck 
3461c2c66affSColin Finck     TRACE("no codepage found\n");
3462c2c66affSColin Finck     return E_FAIL;
3463c2c66affSColin Finck }
3464c2c66affSColin Finck 
fnIMLangFontLink2_GetFontCodePages(IMLangFontLink2 * iface,HDC hdc,HFONT hfont,DWORD * codepages)3465c2c66affSColin Finck static HRESULT WINAPI fnIMLangFontLink2_GetFontCodePages(IMLangFontLink2 *iface,
3466c2c66affSColin Finck         HDC hdc, HFONT hfont, DWORD *codepages)
3467c2c66affSColin Finck {
3468c2c66affSColin Finck     MLang_impl *This = impl_from_IMLangFontLink2(iface);
3469c2c66affSColin Finck     FONTSIGNATURE fontsig;
3470c2c66affSColin Finck     HFONT old_font;
3471c2c66affSColin Finck 
3472c2c66affSColin Finck     TRACE("(%p)->(%p %p %p)\n", This, hdc, hfont, codepages);
3473c2c66affSColin Finck 
3474c2c66affSColin Finck     old_font = SelectObject(hdc, hfont);
3475c2c66affSColin Finck     GetTextCharsetInfo(hdc, &fontsig, 0);
3476c2c66affSColin Finck     SelectObject(hdc, old_font);
3477c2c66affSColin Finck 
3478c2c66affSColin Finck     *codepages = fontsig.fsCsb[0];
3479c2c66affSColin Finck     TRACE("ret 0x%x\n", fontsig.fsCsb[0]);
3480c2c66affSColin Finck 
3481c2c66affSColin Finck     return S_OK;
3482c2c66affSColin Finck }
3483c2c66affSColin Finck 
fnIMLangFontLink2_ReleaseFont(IMLangFontLink2 * This,HFONT hFont)3484c2c66affSColin Finck static HRESULT WINAPI fnIMLangFontLink2_ReleaseFont(IMLangFontLink2* This,
3485c2c66affSColin Finck         HFONT hFont)
3486c2c66affSColin Finck {
34875e2c163fSAmine Khaldi     TRACE("(%p)->%p\n",This, hFont);
34885e2c163fSAmine Khaldi 
34895e2c163fSAmine Khaldi     return release_font(hFont);
3490c2c66affSColin Finck }
3491c2c66affSColin Finck 
fnIMLangFontLink2_ResetFontMapping(IMLangFontLink2 * This)3492c2c66affSColin Finck static HRESULT WINAPI fnIMLangFontLink2_ResetFontMapping(IMLangFontLink2* This)
3493c2c66affSColin Finck {
34945e2c163fSAmine Khaldi     TRACE("(%p)\n",This);
34955e2c163fSAmine Khaldi 
34965e2c163fSAmine Khaldi     return clear_font_cache();
3497c2c66affSColin Finck }
3498c2c66affSColin Finck 
fnIMLangFontLink2_MapFont(IMLangFontLink2 * This,HDC hDC,DWORD dwCodePages,WCHAR chSrc,HFONT * pFont)3499c2c66affSColin Finck static HRESULT WINAPI fnIMLangFontLink2_MapFont(IMLangFontLink2* This,
3500c2c66affSColin Finck         HDC hDC, DWORD dwCodePages, WCHAR chSrc, HFONT *pFont)
3501c2c66affSColin Finck {
35025e2c163fSAmine Khaldi     HFONT old_font;
35035e2c163fSAmine Khaldi 
35045e2c163fSAmine Khaldi     TRACE("(%p)->%p %08x %04x %p\n",This, hDC, dwCodePages, chSrc, pFont);
35055e2c163fSAmine Khaldi 
35065e2c163fSAmine Khaldi     if (!hDC) return E_FAIL;
35075e2c163fSAmine Khaldi 
35085e2c163fSAmine Khaldi     if (dwCodePages != 0)
35095e2c163fSAmine Khaldi     {
35105e2c163fSAmine Khaldi         old_font = GetCurrentObject(hDC, OBJ_FONT);
35115e2c163fSAmine Khaldi         return map_font(hDC, dwCodePages, old_font, pFont);
35125e2c163fSAmine Khaldi     }
35135e2c163fSAmine Khaldi     else
35145e2c163fSAmine Khaldi     {
35155e2c163fSAmine Khaldi         if (pFont == NULL) return E_INVALIDARG;
35165e2c163fSAmine Khaldi         FIXME("the situation where dwCodepages is set to zero is not implemented\n");
35175e2c163fSAmine Khaldi         return E_FAIL;
35185e2c163fSAmine Khaldi     }
3519c2c66affSColin Finck }
3520c2c66affSColin Finck 
fnIMLangFontLink2_GetFontUnicodeRanges(IMLangFontLink2 * This,HDC hDC,UINT * puiRanges,UNICODERANGE * pUranges)3521c2c66affSColin Finck static HRESULT WINAPI fnIMLangFontLink2_GetFontUnicodeRanges(IMLangFontLink2* This,
3522c2c66affSColin Finck         HDC hDC, UINT *puiRanges, UNICODERANGE *pUranges)
3523c2c66affSColin Finck {
3524c2c66affSColin Finck     DWORD size;
3525c2c66affSColin Finck     GLYPHSET *gs;
3526c2c66affSColin Finck 
3527c2c66affSColin Finck     TRACE("(%p)->%p %p %p\n", This, hDC, puiRanges, pUranges);
3528c2c66affSColin Finck 
3529c2c66affSColin Finck     if (!puiRanges) return E_INVALIDARG;
3530c2c66affSColin Finck     if (!(size = GetFontUnicodeRanges(hDC, NULL))) return E_FAIL;
3531c2c66affSColin Finck     if (!(gs = HeapAlloc(GetProcessHeap(), 0, size))) return E_OUTOFMEMORY;
3532c2c66affSColin Finck 
3533c2c66affSColin Finck     GetFontUnicodeRanges(hDC, gs);
3534c2c66affSColin Finck     *puiRanges = gs->cRanges;
3535c2c66affSColin Finck     if (pUranges)
3536c2c66affSColin Finck     {
3537c2c66affSColin Finck         UINT i;
3538c2c66affSColin Finck         for (i = 0; i < gs->cRanges; i++)
3539c2c66affSColin Finck         {
3540c2c66affSColin Finck             if (i >= *puiRanges) break;
3541c2c66affSColin Finck             pUranges[i].wcFrom = gs->ranges[i].wcLow;
3542c2c66affSColin Finck             pUranges[i].wcTo   = gs->ranges[i].wcLow + gs->ranges[i].cGlyphs;
3543c2c66affSColin Finck         }
3544c2c66affSColin Finck         *puiRanges = i;
3545c2c66affSColin Finck     }
3546c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, gs);
3547c2c66affSColin Finck     return S_OK;
3548c2c66affSColin Finck }
3549c2c66affSColin Finck 
fnIMLangFontLink2_GetScriptFontInfo(IMLangFontLink2 * This,SCRIPT_ID sid,DWORD dwFlags,UINT * puiFonts,SCRIPTFONTINFO * pScriptFont)3550c2c66affSColin Finck static HRESULT WINAPI fnIMLangFontLink2_GetScriptFontInfo(IMLangFontLink2* This,
3551c2c66affSColin Finck         SCRIPT_ID sid, DWORD dwFlags, UINT *puiFonts,
3552c2c66affSColin Finck         SCRIPTFONTINFO *pScriptFont)
3553c2c66affSColin Finck {
3554c2c66affSColin Finck     UINT i, j;
3555c2c66affSColin Finck 
3556c2c66affSColin Finck     TRACE("(%p)->%u %x %p %p\n", This, sid, dwFlags, puiFonts, pScriptFont);
3557c2c66affSColin Finck 
3558c2c66affSColin Finck     if (!dwFlags) dwFlags = SCRIPTCONTF_PROPORTIONAL_FONT;
3559c2c66affSColin Finck 
3560ccc3eeaeSAmine Khaldi     for (i = 0, j = 0; i < ARRAY_SIZE(mlang_data); i++)
3561c2c66affSColin Finck     {
3562c2c66affSColin Finck         if (sid == mlang_data[i].sid)
3563c2c66affSColin Finck         {
3564c2c66affSColin Finck             if (pScriptFont)
3565c2c66affSColin Finck             {
3566c2c66affSColin Finck                 if (j >= *puiFonts) break;
3567c2c66affSColin Finck 
3568*be08d69bSSerge Gautherie                 pScriptFont[j].scripts = (SCRIPT_IDS)1 << mlang_data[i].sid;
3569c2c66affSColin Finck                 if (dwFlags == SCRIPTCONTF_FIXED_FONT)
3570c2c66affSColin Finck                 {
3571c2c66affSColin Finck                     MultiByteToWideChar(CP_ACP, 0, mlang_data[i].fixed_font, -1,
3572c2c66affSColin Finck                         pScriptFont[j].wszFont, MAX_MIMEFACE_NAME);
3573c2c66affSColin Finck                 }
3574c2c66affSColin Finck                 else if (dwFlags == SCRIPTCONTF_PROPORTIONAL_FONT)
3575c2c66affSColin Finck                 {
3576c2c66affSColin Finck                     MultiByteToWideChar(CP_ACP, 0, mlang_data[i].proportional_font, -1,
3577c2c66affSColin Finck                         pScriptFont[j].wszFont, MAX_MIMEFACE_NAME);
3578c2c66affSColin Finck                 }
3579c2c66affSColin Finck             }
3580c2c66affSColin Finck             j++;
3581c2c66affSColin Finck         }
3582c2c66affSColin Finck     }
3583c2c66affSColin Finck     *puiFonts = j;
3584c2c66affSColin Finck     return S_OK;
3585c2c66affSColin Finck }
3586c2c66affSColin Finck 
fnIMLangFontLink2_CodePageToScriptID(IMLangFontLink2 * This,UINT uiCodePage,SCRIPT_ID * pSid)3587c2c66affSColin Finck static HRESULT WINAPI fnIMLangFontLink2_CodePageToScriptID(IMLangFontLink2* This,
3588c2c66affSColin Finck         UINT uiCodePage, SCRIPT_ID *pSid)
3589c2c66affSColin Finck {
3590c2c66affSColin Finck     UINT i;
3591c2c66affSColin Finck 
3592c2c66affSColin Finck     TRACE("(%p)->%i %p\n", This, uiCodePage, pSid);
3593c2c66affSColin Finck 
3594c2c66affSColin Finck     if (uiCodePage == CP_UNICODE) return E_FAIL;
3595c2c66affSColin Finck 
3596ccc3eeaeSAmine Khaldi     for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3597c2c66affSColin Finck     {
3598c2c66affSColin Finck         if (uiCodePage == mlang_data[i].family_codepage)
3599c2c66affSColin Finck         {
3600c2c66affSColin Finck             if (pSid) *pSid = mlang_data[i].sid;
3601c2c66affSColin Finck             return S_OK;
3602c2c66affSColin Finck         }
3603c2c66affSColin Finck     }
3604c2c66affSColin Finck     return E_FAIL;
3605c2c66affSColin Finck }
3606c2c66affSColin Finck 
3607c2c66affSColin Finck static const IMLangFontLink2Vtbl IMLangFontLink2_vtbl =
3608c2c66affSColin Finck {
3609c2c66affSColin Finck     fnIMLangFontLink2_QueryInterface,
3610c2c66affSColin Finck     fnIMLangFontLink2_AddRef,
3611c2c66affSColin Finck     fnIMLangFontLink2_Release,
3612c2c66affSColin Finck     fnIMLangFontLink2_GetCharCodePages,
3613c2c66affSColin Finck     fnIMLangFontLink2_GetStrCodePages,
3614c2c66affSColin Finck     fnIMLangFontLink2_CodePageToCodePages,
3615c2c66affSColin Finck     fnIMLangFontLink2_CodePagesToCodePage,
3616c2c66affSColin Finck     fnIMLangFontLink2_GetFontCodePages,
3617c2c66affSColin Finck     fnIMLangFontLink2_ReleaseFont,
3618c2c66affSColin Finck     fnIMLangFontLink2_ResetFontMapping,
3619c2c66affSColin Finck     fnIMLangFontLink2_MapFont,
3620c2c66affSColin Finck     fnIMLangFontLink2_GetFontUnicodeRanges,
3621c2c66affSColin Finck     fnIMLangFontLink2_GetScriptFontInfo,
3622c2c66affSColin Finck     fnIMLangFontLink2_CodePageToScriptID
3623c2c66affSColin Finck };
3624c2c66affSColin Finck 
3625c2c66affSColin Finck /******************************************************************************/
3626c2c66affSColin Finck 
impl_from_IMLangLineBreakConsole(IMLangLineBreakConsole * iface)3627c2c66affSColin Finck static inline MLang_impl *impl_from_IMLangLineBreakConsole( IMLangLineBreakConsole *iface )
3628c2c66affSColin Finck {
3629c2c66affSColin Finck     return CONTAINING_RECORD( iface, MLang_impl, IMLangLineBreakConsole_iface );
3630c2c66affSColin Finck }
3631c2c66affSColin Finck 
fnIMLangLineBreakConsole_QueryInterface(IMLangLineBreakConsole * iface,REFIID riid,void ** ppvObject)3632c2c66affSColin Finck static HRESULT WINAPI fnIMLangLineBreakConsole_QueryInterface(
3633c2c66affSColin Finck     IMLangLineBreakConsole* iface,
3634c2c66affSColin Finck     REFIID riid,
3635c2c66affSColin Finck     void** ppvObject)
3636c2c66affSColin Finck {
3637c2c66affSColin Finck     MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3638c2c66affSColin Finck     return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
3639c2c66affSColin Finck }
3640c2c66affSColin Finck 
fnIMLangLineBreakConsole_AddRef(IMLangLineBreakConsole * iface)3641c2c66affSColin Finck static ULONG WINAPI fnIMLangLineBreakConsole_AddRef(
3642c2c66affSColin Finck     IMLangLineBreakConsole* iface )
3643c2c66affSColin Finck {
3644c2c66affSColin Finck     MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3645c2c66affSColin Finck     return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
3646c2c66affSColin Finck }
3647c2c66affSColin Finck 
fnIMLangLineBreakConsole_Release(IMLangLineBreakConsole * iface)3648c2c66affSColin Finck static ULONG WINAPI fnIMLangLineBreakConsole_Release(
3649c2c66affSColin Finck     IMLangLineBreakConsole* iface )
3650c2c66affSColin Finck {
3651c2c66affSColin Finck     MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3652c2c66affSColin Finck     return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
3653c2c66affSColin Finck }
3654c2c66affSColin Finck 
fnIMLangLineBreakConsole_BreakLineML(IMLangLineBreakConsole * iface,IMLangString * pSrcMLStr,LONG lSrcPos,LONG lSrcLen,LONG cMinColumns,LONG cMaxColumns,LONG * plLineLen,LONG * plSkipLen)3655c2c66affSColin Finck static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineML(
3656c2c66affSColin Finck     IMLangLineBreakConsole* iface,
3657c2c66affSColin Finck     IMLangString* pSrcMLStr,
3658c2c66affSColin Finck     LONG lSrcPos,
3659c2c66affSColin Finck     LONG lSrcLen,
3660c2c66affSColin Finck     LONG cMinColumns,
3661c2c66affSColin Finck     LONG cMaxColumns,
3662c2c66affSColin Finck     LONG* plLineLen,
3663c2c66affSColin Finck     LONG* plSkipLen)
3664c2c66affSColin Finck {
3665c2c66affSColin Finck     FIXME("(%p)->%p %i %i %i %i %p %p\n", iface, pSrcMLStr, lSrcPos, lSrcLen, cMinColumns, cMaxColumns, plLineLen, plSkipLen);
3666c2c66affSColin Finck     return E_NOTIMPL;
3667c2c66affSColin Finck }
3668c2c66affSColin Finck 
fnIMLangLineBreakConsole_BreakLineW(IMLangLineBreakConsole * iface,LCID locale,const WCHAR * pszSrc,LONG cchSrc,LONG cMaxColumns,LONG * pcchLine,LONG * pcchSkip)3669c2c66affSColin Finck static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineW(
3670c2c66affSColin Finck     IMLangLineBreakConsole* iface,
3671c2c66affSColin Finck     LCID locale,
3672c2c66affSColin Finck     const WCHAR* pszSrc,
3673c2c66affSColin Finck     LONG cchSrc,
3674c2c66affSColin Finck     LONG cMaxColumns,
3675c2c66affSColin Finck     LONG* pcchLine,
3676c2c66affSColin Finck     LONG* pcchSkip )
3677c2c66affSColin Finck {
3678c2c66affSColin Finck     FIXME("(%p)->%i %s %i %i %p %p\n", iface, locale, debugstr_wn(pszSrc,cchSrc), cchSrc, cMaxColumns, pcchLine, pcchSkip);
3679c2c66affSColin Finck 
3680c2c66affSColin Finck     *pcchLine = cchSrc;
3681c2c66affSColin Finck     *pcchSkip = 0;
3682c2c66affSColin Finck     return S_OK;
3683c2c66affSColin Finck }
3684c2c66affSColin Finck 
fnIMLangLineBreakConsole_BreakLineA(IMLangLineBreakConsole * iface,LCID locale,UINT uCodePage,const CHAR * pszSrc,LONG cchSrc,LONG cMaxColumns,LONG * pcchLine,LONG * pcchSkip)3685c2c66affSColin Finck static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineA(
3686c2c66affSColin Finck     IMLangLineBreakConsole* iface,
3687c2c66affSColin Finck     LCID locale,
3688c2c66affSColin Finck     UINT uCodePage,
3689c2c66affSColin Finck     const CHAR* pszSrc,
3690c2c66affSColin Finck     LONG cchSrc,
3691c2c66affSColin Finck     LONG cMaxColumns,
3692c2c66affSColin Finck     LONG* pcchLine,
3693c2c66affSColin Finck     LONG* pcchSkip)
3694c2c66affSColin Finck {
3695c2c66affSColin Finck     LONG i, line = cchSrc, skip = 0;
3696c2c66affSColin Finck 
3697c2c66affSColin Finck     FIXME("(%p)->%i %i %s %i %i %p %p\n", iface, locale, uCodePage, debugstr_an(pszSrc,cchSrc), cchSrc, cMaxColumns, pcchLine, pcchSkip);
3698c2c66affSColin Finck 
3699c2c66affSColin Finck     if (uCodePage == CP_USASCII && cchSrc > cMaxColumns)
3700c2c66affSColin Finck     {
3701c2c66affSColin Finck         for (line = cMaxColumns, i = cMaxColumns - 1; i >= 0; i--)
3702c2c66affSColin Finck         {
3703c2c66affSColin Finck             if (pszSrc[i] == ' ')
3704c2c66affSColin Finck             {
3705c2c66affSColin Finck                 while (i >= 0 && pszSrc[i] == ' ')
3706c2c66affSColin Finck                 {
3707c2c66affSColin Finck                     i--;
3708c2c66affSColin Finck                     line--;
3709c2c66affSColin Finck                     skip++;
3710c2c66affSColin Finck                 }
3711c2c66affSColin Finck                 break;
3712c2c66affSColin Finck             }
3713c2c66affSColin Finck         }
3714c2c66affSColin Finck     }
3715c2c66affSColin Finck     *pcchLine = line;
3716c2c66affSColin Finck     *pcchSkip = skip;
3717c2c66affSColin Finck     return S_OK;
3718c2c66affSColin Finck }
3719c2c66affSColin Finck 
3720c2c66affSColin Finck static const IMLangLineBreakConsoleVtbl IMLangLineBreakConsole_vtbl =
3721c2c66affSColin Finck {
3722c2c66affSColin Finck     fnIMLangLineBreakConsole_QueryInterface,
3723c2c66affSColin Finck     fnIMLangLineBreakConsole_AddRef,
3724c2c66affSColin Finck     fnIMLangLineBreakConsole_Release,
3725c2c66affSColin Finck     fnIMLangLineBreakConsole_BreakLineML,
3726c2c66affSColin Finck     fnIMLangLineBreakConsole_BreakLineW,
3727c2c66affSColin Finck     fnIMLangLineBreakConsole_BreakLineA
3728c2c66affSColin Finck };
3729c2c66affSColin Finck 
3730c2c66affSColin Finck struct convert_charset {
3731c2c66affSColin Finck     IMLangConvertCharset IMLangConvertCharset_iface;
3732c2c66affSColin Finck     LONG ref;
3733c2c66affSColin Finck 
3734c2c66affSColin Finck     UINT src_cp;
3735c2c66affSColin Finck     UINT dst_cp;
3736c2c66affSColin Finck };
3737c2c66affSColin Finck 
impl_from_IMLangConvertCharset(IMLangConvertCharset * iface)3738c2c66affSColin Finck static inline struct convert_charset *impl_from_IMLangConvertCharset(IMLangConvertCharset *iface)
3739c2c66affSColin Finck {
3740c2c66affSColin Finck     return CONTAINING_RECORD(iface, struct convert_charset, IMLangConvertCharset_iface);
3741c2c66affSColin Finck }
3742c2c66affSColin Finck 
MLangConvertCharset_QueryInterface(IMLangConvertCharset * iface,REFIID riid,void ** obj)3743c2c66affSColin Finck static HRESULT WINAPI MLangConvertCharset_QueryInterface(IMLangConvertCharset *iface, REFIID riid, void **obj)
3744c2c66affSColin Finck {
3745c2c66affSColin Finck     struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3746c2c66affSColin Finck 
3747c2c66affSColin Finck     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
3748c2c66affSColin Finck 
3749c2c66affSColin Finck     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMLangConvertCharset))
3750c2c66affSColin Finck     {
3751c2c66affSColin Finck         *obj = &This->IMLangConvertCharset_iface;
3752c2c66affSColin Finck         IMLangConvertCharset_AddRef(iface);
3753c2c66affSColin Finck         return S_OK;
3754c2c66affSColin Finck     }
3755c2c66affSColin Finck 
3756c2c66affSColin Finck     *obj = NULL;
3757c2c66affSColin Finck     return E_NOINTERFACE;
3758c2c66affSColin Finck }
3759c2c66affSColin Finck 
MLangConvertCharset_AddRef(IMLangConvertCharset * iface)3760c2c66affSColin Finck static ULONG WINAPI MLangConvertCharset_AddRef(IMLangConvertCharset *iface)
3761c2c66affSColin Finck {
3762c2c66affSColin Finck     struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3763c2c66affSColin Finck     ULONG ref = InterlockedIncrement(&This->ref);
3764c2c66affSColin Finck     TRACE("(%p)->(%u)\n", This, ref);
3765c2c66affSColin Finck     return ref;
3766c2c66affSColin Finck }
3767c2c66affSColin Finck 
MLangConvertCharset_Release(IMLangConvertCharset * iface)3768c2c66affSColin Finck static ULONG WINAPI MLangConvertCharset_Release(IMLangConvertCharset *iface)
3769c2c66affSColin Finck {
3770c2c66affSColin Finck     struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3771c2c66affSColin Finck     ULONG ref = InterlockedDecrement(&This->ref);
3772c2c66affSColin Finck 
3773c2c66affSColin Finck     TRACE("(%p)->(%u)\n", This, ref);
3774c2c66affSColin Finck     if (!ref)
3775c2c66affSColin Finck     {
3776c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, This);
3777c2c66affSColin Finck         UnlockModule();
3778c2c66affSColin Finck     }
3779c2c66affSColin Finck 
3780c2c66affSColin Finck     return ref;
3781c2c66affSColin Finck }
3782c2c66affSColin Finck 
MLangConvertCharset_Initialize(IMLangConvertCharset * iface,UINT src_cp,UINT dst_cp,DWORD prop)3783c2c66affSColin Finck static HRESULT WINAPI MLangConvertCharset_Initialize(IMLangConvertCharset *iface,
3784c2c66affSColin Finck     UINT src_cp, UINT dst_cp, DWORD prop)
3785c2c66affSColin Finck {
3786c2c66affSColin Finck     struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3787c2c66affSColin Finck 
3788c2c66affSColin Finck     TRACE("(%p)->(%u %u 0x%08x)\n", This, src_cp, dst_cp, prop);
3789c2c66affSColin Finck 
3790c2c66affSColin Finck     prop &= ~MLCONVCHARF_USEDEFCHAR;
3791c2c66affSColin Finck     if (prop)
3792c2c66affSColin Finck         FIXME("property 0x%08x not supported\n", prop);
3793c2c66affSColin Finck 
3794c2c66affSColin Finck     This->src_cp = src_cp;
3795c2c66affSColin Finck     This->dst_cp = dst_cp;
3796c2c66affSColin Finck 
3797c2c66affSColin Finck     return S_OK;
3798c2c66affSColin Finck }
3799c2c66affSColin Finck 
MLangConvertCharset_GetSourceCodePage(IMLangConvertCharset * iface,UINT * src_cp)3800c2c66affSColin Finck static HRESULT WINAPI MLangConvertCharset_GetSourceCodePage(IMLangConvertCharset *iface, UINT *src_cp)
3801c2c66affSColin Finck {
3802c2c66affSColin Finck     struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3803c2c66affSColin Finck 
3804c2c66affSColin Finck     TRACE("(%p)->(%p)\n", This, src_cp);
3805c2c66affSColin Finck 
3806c2c66affSColin Finck     if (!src_cp) return E_INVALIDARG;
3807c2c66affSColin Finck     *src_cp = This->src_cp;
3808c2c66affSColin Finck     return S_OK;
3809c2c66affSColin Finck }
3810c2c66affSColin Finck 
MLangConvertCharset_GetDestinationCodePage(IMLangConvertCharset * iface,UINT * dst_cp)3811c2c66affSColin Finck static HRESULT WINAPI MLangConvertCharset_GetDestinationCodePage(IMLangConvertCharset *iface, UINT *dst_cp)
3812c2c66affSColin Finck {
3813c2c66affSColin Finck     struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3814c2c66affSColin Finck 
3815c2c66affSColin Finck     TRACE("(%p)->(%p)\n", This, dst_cp);
3816c2c66affSColin Finck 
3817c2c66affSColin Finck     if (!dst_cp) return E_INVALIDARG;
3818c2c66affSColin Finck     *dst_cp = This->dst_cp;
3819c2c66affSColin Finck     return S_OK;
3820c2c66affSColin Finck }
3821c2c66affSColin Finck 
MLangConvertCharset_GetProperty(IMLangConvertCharset * iface,DWORD * prop)3822c2c66affSColin Finck static HRESULT WINAPI MLangConvertCharset_GetProperty(IMLangConvertCharset *iface, DWORD *prop)
3823c2c66affSColin Finck {
3824c2c66affSColin Finck     struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3825c2c66affSColin Finck     FIXME("(%p)->(%p): stub\n", This, prop);
3826c2c66affSColin Finck     return E_NOTIMPL;
3827c2c66affSColin Finck }
3828c2c66affSColin Finck 
MLangConvertCharset_DoConversion(IMLangConvertCharset * iface,BYTE * src,UINT * src_size,BYTE * dest,UINT * dest_size)3829c2c66affSColin Finck static HRESULT WINAPI MLangConvertCharset_DoConversion(IMLangConvertCharset *iface, BYTE *src,
3830c2c66affSColin Finck     UINT *src_size, BYTE *dest, UINT *dest_size)
3831c2c66affSColin Finck {
3832c2c66affSColin Finck     struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3833c2c66affSColin Finck     FIXME("(%p)->(%p %p %p %p): stub\n", This, src, src_size, dest, dest_size);
3834c2c66affSColin Finck     return E_NOTIMPL;
3835c2c66affSColin Finck }
3836c2c66affSColin Finck 
MLangConvertCharset_DoConversionToUnicode(IMLangConvertCharset * iface,CHAR * src,UINT * src_size,WCHAR * dest,UINT * dest_size)3837c2c66affSColin Finck static HRESULT WINAPI MLangConvertCharset_DoConversionToUnicode(IMLangConvertCharset *iface, CHAR *src,
3838c2c66affSColin Finck     UINT *src_size, WCHAR *dest, UINT *dest_size)
3839c2c66affSColin Finck {
3840c2c66affSColin Finck     struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3841c2c66affSColin Finck     TRACE("(%p)->(%p %p %p %p)\n", This, src, src_size, dest, dest_size);
3842c2c66affSColin Finck     return ConvertINetMultiByteToUnicode(NULL, This->src_cp, src, (INT*)src_size, dest, (INT*)dest_size);
3843c2c66affSColin Finck }
3844c2c66affSColin Finck 
MLangConvertCharset_DoConversionFromUnicode(IMLangConvertCharset * iface,WCHAR * src,UINT * src_size,CHAR * dest,UINT * dest_size)3845c2c66affSColin Finck static HRESULT WINAPI MLangConvertCharset_DoConversionFromUnicode(IMLangConvertCharset *iface,
3846c2c66affSColin Finck     WCHAR *src, UINT *src_size, CHAR *dest, UINT *dest_size)
3847c2c66affSColin Finck {
3848c2c66affSColin Finck     struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3849c2c66affSColin Finck     TRACE("(%p)->(%p %p %p %p)\n", This, src, src_size, dest, dest_size);
3850c2c66affSColin Finck     return ConvertINetUnicodeToMultiByte(NULL, This->dst_cp, src, (INT*)src_size, dest, (INT*)dest_size);
3851c2c66affSColin Finck }
3852c2c66affSColin Finck 
3853c2c66affSColin Finck static const IMLangConvertCharsetVtbl MLangConvertCharsetVtbl =
3854c2c66affSColin Finck {
3855c2c66affSColin Finck     MLangConvertCharset_QueryInterface,
3856c2c66affSColin Finck     MLangConvertCharset_AddRef,
3857c2c66affSColin Finck     MLangConvertCharset_Release,
3858c2c66affSColin Finck     MLangConvertCharset_Initialize,
3859c2c66affSColin Finck     MLangConvertCharset_GetSourceCodePage,
3860c2c66affSColin Finck     MLangConvertCharset_GetDestinationCodePage,
3861c2c66affSColin Finck     MLangConvertCharset_GetProperty,
3862c2c66affSColin Finck     MLangConvertCharset_DoConversion,
3863c2c66affSColin Finck     MLangConvertCharset_DoConversionToUnicode,
3864c2c66affSColin Finck     MLangConvertCharset_DoConversionFromUnicode
3865c2c66affSColin Finck };
3866c2c66affSColin Finck 
MultiLanguage_create(IUnknown * pUnkOuter,LPVOID * ppObj)3867c2c66affSColin Finck static HRESULT MultiLanguage_create(IUnknown *pUnkOuter, LPVOID *ppObj)
3868c2c66affSColin Finck {
3869c2c66affSColin Finck     MLang_impl *mlang;
3870c2c66affSColin Finck     UINT i;
3871c2c66affSColin Finck 
3872c2c66affSColin Finck     TRACE("Creating MultiLanguage object\n");
3873c2c66affSColin Finck 
3874c2c66affSColin Finck     if( pUnkOuter )
3875c2c66affSColin Finck         return CLASS_E_NOAGGREGATION;
3876c2c66affSColin Finck 
3877c2c66affSColin Finck     mlang = HeapAlloc( GetProcessHeap(), 0, sizeof (MLang_impl) );
3878c2c66affSColin Finck     mlang->IMLangFontLink_iface.lpVtbl = &IMLangFontLink_vtbl;
3879c2c66affSColin Finck     mlang->IMultiLanguage_iface.lpVtbl = &IMultiLanguage_vtbl;
3880c2c66affSColin Finck     mlang->IMultiLanguage3_iface.lpVtbl = &IMultiLanguage3_vtbl;
3881c2c66affSColin Finck     mlang->IMLangFontLink2_iface.lpVtbl = &IMLangFontLink2_vtbl;
3882c2c66affSColin Finck     mlang->IMLangLineBreakConsole_iface.lpVtbl = &IMLangLineBreakConsole_vtbl;
3883c2c66affSColin Finck 
3884c2c66affSColin Finck     mlang->total_cp = 0;
3885ccc3eeaeSAmine Khaldi     for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3886c2c66affSColin Finck         mlang->total_cp += mlang_data[i].number_of_cp;
3887c2c66affSColin Finck 
3888c2c66affSColin Finck     /* do not enumerate unicode flavours */
3889ccc3eeaeSAmine Khaldi     mlang->total_scripts = ARRAY_SIZE(mlang_data) - 1;
3890c2c66affSColin Finck 
3891c2c66affSColin Finck     mlang->ref = 1;
3892c2c66affSColin Finck     *ppObj = &mlang->IMultiLanguage_iface;
3893c2c66affSColin Finck     TRACE("returning %p\n", mlang);
3894c2c66affSColin Finck 
3895c2c66affSColin Finck     LockModule();
3896c2c66affSColin Finck 
3897c2c66affSColin Finck     return S_OK;
3898c2c66affSColin Finck }
3899c2c66affSColin Finck 
MLangConvertCharset_create(IUnknown * outer,void ** obj)3900c2c66affSColin Finck static HRESULT MLangConvertCharset_create(IUnknown *outer, void **obj)
3901c2c66affSColin Finck {
3902c2c66affSColin Finck     struct convert_charset *convert;
3903c2c66affSColin Finck 
3904c2c66affSColin Finck     if (outer)
3905c2c66affSColin Finck         return CLASS_E_NOAGGREGATION;
3906c2c66affSColin Finck 
3907c2c66affSColin Finck     *obj = NULL;
3908c2c66affSColin Finck 
3909c2c66affSColin Finck     convert = HeapAlloc(GetProcessHeap(), 0, sizeof(struct convert_charset));
3910c2c66affSColin Finck     if (!convert) return E_OUTOFMEMORY;
3911c2c66affSColin Finck 
3912c2c66affSColin Finck     convert->IMLangConvertCharset_iface.lpVtbl = &MLangConvertCharsetVtbl;
3913c2c66affSColin Finck     convert->ref = 1;
3914c2c66affSColin Finck 
3915c2c66affSColin Finck     *obj = &convert->IMLangConvertCharset_iface;
3916c2c66affSColin Finck 
3917c2c66affSColin Finck     LockModule();
3918c2c66affSColin Finck 
3919c2c66affSColin Finck     return S_OK;
3920c2c66affSColin Finck }
3921c2c66affSColin Finck 
3922c2c66affSColin Finck /******************************************************************************/
3923c2c66affSColin Finck 
DllCanUnloadNow(void)3924c2c66affSColin Finck HRESULT WINAPI DllCanUnloadNow(void)
3925c2c66affSColin Finck {
3926c2c66affSColin Finck     return dll_count == 0 ? S_OK : S_FALSE;
3927c2c66affSColin Finck }
3928c2c66affSColin Finck 
register_codepages(void)3929ccc3eeaeSAmine Khaldi static BOOL register_codepages(void)
3930ccc3eeaeSAmine Khaldi {
3931ccc3eeaeSAmine Khaldi     const struct mlang_data *family;
3932ccc3eeaeSAmine Khaldi     const MIME_CP_INFO *info;
3933ccc3eeaeSAmine Khaldi     HKEY db_key, key;
3934ccc3eeaeSAmine Khaldi     WCHAR buf[32];
3935ccc3eeaeSAmine Khaldi     LSTATUS status;
3936ccc3eeaeSAmine Khaldi 
3937ccc3eeaeSAmine Khaldi     static const WCHAR db_key_nameW[] = {
3938ccc3eeaeSAmine Khaldi         'M','I','M','E',
3939ccc3eeaeSAmine Khaldi         '\\','D','a','t','a','b','a','s','e',
3940ccc3eeaeSAmine Khaldi         '\\','C','o','d','e','p','a','g','e',0};
3941ccc3eeaeSAmine Khaldi     static const WCHAR familyW[] = {'F','a','m','i','l','y',0};
3942ccc3eeaeSAmine Khaldi     static const WCHAR formatW[] = {'%','u',0};
3943ccc3eeaeSAmine Khaldi 
3944ccc3eeaeSAmine Khaldi     status = RegCreateKeyW(HKEY_CLASSES_ROOT, db_key_nameW, &db_key);
3945ccc3eeaeSAmine Khaldi     if (status != ERROR_SUCCESS)
3946ccc3eeaeSAmine Khaldi         return FALSE;
3947ccc3eeaeSAmine Khaldi 
3948ccc3eeaeSAmine Khaldi     for (family = mlang_data; family < mlang_data + ARRAY_SIZE(mlang_data); family++)
3949ccc3eeaeSAmine Khaldi     {
3950ccc3eeaeSAmine Khaldi         for (info = family->mime_cp_info; info < family->mime_cp_info + family->number_of_cp; info++)
3951ccc3eeaeSAmine Khaldi         {
3952853d6414SAmine Khaldi             swprintf(buf, formatW, info->cp);
3953ccc3eeaeSAmine Khaldi             status = RegCreateKeyW(db_key, buf, &key);
3954ccc3eeaeSAmine Khaldi             if (status != ERROR_SUCCESS)
3955ccc3eeaeSAmine Khaldi                 continue;
3956ccc3eeaeSAmine Khaldi 
3957ccc3eeaeSAmine Khaldi             RegSetValueExA(key, "BodyCharset", 0, REG_SZ, (BYTE*)info->body_charset,
3958ccc3eeaeSAmine Khaldi                            strlen(info->body_charset) + 1);
3959ccc3eeaeSAmine Khaldi 
3960ccc3eeaeSAmine Khaldi             if (info->cp == family->family_codepage)
3961ccc3eeaeSAmine Khaldi             {
3962ccc3eeaeSAmine Khaldi                 RegSetValueExA(key, "FixedWidthFont", 0, REG_SZ, (BYTE*)family->fixed_font,
3963ccc3eeaeSAmine Khaldi                                strlen(family->fixed_font) + 1);
3964ccc3eeaeSAmine Khaldi                 RegSetValueExA(key, "ProportionalFont", 0, REG_SZ, (BYTE*)family->proportional_font,
3965ccc3eeaeSAmine Khaldi                                strlen(family->proportional_font) + 1);
3966ccc3eeaeSAmine Khaldi             }
3967ccc3eeaeSAmine Khaldi             else
3968ccc3eeaeSAmine Khaldi             {
3969ccc3eeaeSAmine Khaldi                 RegSetValueExW(key, familyW, 0, REG_DWORD, (BYTE*)&family->family_codepage,
3970ccc3eeaeSAmine Khaldi                                sizeof(family->family_codepage));
3971ccc3eeaeSAmine Khaldi             }
3972ccc3eeaeSAmine Khaldi 
3973ccc3eeaeSAmine Khaldi             RegCloseKey(key);
3974ccc3eeaeSAmine Khaldi         }
3975ccc3eeaeSAmine Khaldi     }
3976ccc3eeaeSAmine Khaldi 
3977ccc3eeaeSAmine Khaldi     RegCloseKey(db_key);
3978ccc3eeaeSAmine Khaldi     return TRUE;
3979ccc3eeaeSAmine Khaldi }
3980c2c66affSColin Finck 
3981c2c66affSColin Finck /***********************************************************************
3982c2c66affSColin Finck  *		DllRegisterServer (MLANG.@)
3983c2c66affSColin Finck  */
DllRegisterServer(void)3984c2c66affSColin Finck HRESULT WINAPI DllRegisterServer(void)
3985c2c66affSColin Finck {
3986ccc3eeaeSAmine Khaldi     if(!register_codepages())
3987ccc3eeaeSAmine Khaldi         return E_FAIL;
3988c2c66affSColin Finck     return __wine_register_resources( instance );
3989c2c66affSColin Finck }
3990c2c66affSColin Finck 
3991c2c66affSColin Finck /***********************************************************************
3992c2c66affSColin Finck  *		DllUnregisterServer (MLANG.@)
3993c2c66affSColin Finck  */
DllUnregisterServer(void)3994c2c66affSColin Finck HRESULT WINAPI DllUnregisterServer(void)
3995c2c66affSColin Finck {
3996c2c66affSColin Finck     return __wine_unregister_resources( instance );
3997c2c66affSColin Finck }
3998c2c66affSColin Finck 
GetGlobalFontLinkObject(void ** unknown)3999c2c66affSColin Finck HRESULT WINAPI GetGlobalFontLinkObject(void **unknown)
4000c2c66affSColin Finck {
4001c2c66affSColin Finck     if (!unknown) return E_INVALIDARG;
4002c2c66affSColin Finck 
4003c2c66affSColin Finck     FIXME("%p: stub\n", unknown);
4004c2c66affSColin Finck 
4005c2c66affSColin Finck     return S_FALSE;
4006c2c66affSColin Finck }
4007