Return CLASS_E_NOAGGREGATION if pUnkOuter is non-null.
[wine] / dlls / mlang / mlang.c
1 /*
2  *    MLANG Class Factory
3  *
4  * Copyright 2002 Lionel Ulmer
5  * Copyright 2003,2004 Mike McCormack
6  * Copyright 2004 Dmitry Timoshkov
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24
25 #include <stdarg.h>
26 #include <stdio.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wingdi.h"
31 #include "winuser.h"
32 #include "winnls.h"
33 #include "winreg.h"
34 #include "ole2.h"
35 #include "mlang.h"
36
37 #include "uuids.h"
38
39 #include "wine/unicode.h"
40 #include "wine/debug.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(mlang);
43
44 #include "initguid.h"
45
46 #define CP_UNICODE 1200
47
48 #define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))
49
50 static HRESULT MultiLanguage_create(IUnknown *pUnkOuter, LPVOID *ppObj);
51
52 /* FIXME:
53  * Under what circumstances HKEY_CLASSES_ROOT\MIME\Database\Codepage and
54  * HKEY_CLASSES_ROOT\MIME\Database\Charset are used?
55  */
56
57 typedef struct
58 {
59     UINT cp;
60     DWORD flags;
61     const char *web_charset;
62     const char *header_charset;
63     const char *body_charset;
64 } MIME_CP_INFO;
65
66 /* These data are based on the codepage info in libs/unicode/cpmap.pl */
67 /* FIXME: Add 28604 (Celtic), 28606 (Balkan) */
68
69 static const MIME_CP_INFO arabic_cp[] =
70 {
71     { 864, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
72            MIMECONTF_MIME_LATEST,
73       "ibm864", "ibm864", "ibm864" },
74     { 1006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
75             MIMECONTF_MIME_LATEST,
76       "ibm1006", "ibm1006", "ibm1006" },
77     { 1256, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
78             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
79             MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
80       "windows-1256", "windows-1256", "windows-1256" },
81     { 28596, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
82              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
83              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
84              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
85       "iso-8859-6", "iso-8859-6", "iso-8859-6" }
86 };
87 static const MIME_CP_INFO baltic_cp[] =
88 {
89     { 775, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
90            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
91       "ibm775", "ibm775", "ibm775" },
92     { 1257, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
93             MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
94             MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
95             MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
96       "windows-1257", "windows-1257", "windows-1257" },
97     { 28594, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
98              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
99              MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
100              MIMECONTF_MIME_LATEST,
101       "iso-8859-4", "iso-8859-4", "iso-8859-4" },
102     { 28603, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
103              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
104       "iso-8859-13", "iso-8859-13", "iso-8859-13" }
105 };
106 static const MIME_CP_INFO chinese_simplified_cp[] =
107 {
108     { 936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
109            MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
110            MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
111            MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
112       "gb2312", "gb2312", "gb2312" }
113 };
114 static const MIME_CP_INFO chinese_traditional_cp[] =
115 {
116     { 950, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
117            MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
118            MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
119            MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
120       "big5", "big5", "big5" }
121 };
122 static const MIME_CP_INFO central_european_cp[] =
123 {
124     { 852, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
125            MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
126            MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
127       "ibm852", "ibm852", "ibm852" },
128     { 1250, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
129             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
130             MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
131             MIMECONTF_MIME_LATEST,
132       "windows-1250", "windows-1250", "windows-1250" },
133     { 10029, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
134              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
135       "x-mac-ce", "x-mac-ce", "x-mac-ce" },
136     { 28592, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
137              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
138              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
139              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
140       "iso-8859-2", "iso-8859-2", "iso-8859-2" }
141 };
142 static const MIME_CP_INFO cyrillic_cp[] =
143 {
144     { 855, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
145            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
146       "ibm855", "ibm855", "ibm855" },
147     { 866, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
148            MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
149            MIMECONTF_MIME_LATEST,
150       "cp866", "cp866", "cp866" },
151 #if 0 /* Windows has 20866 as an official code page for KOI8-R */
152     { 878, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
153            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
154       "koi8-r", "koi8-r", "koi8-r" },
155 #endif
156     { 1251, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
157             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
158             MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
159       "windows-1251", "windows-1251", "windows-1251" },
160     { 10007, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
161              MIMECONTF_MIME_LATEST,
162       "x-mac-cyrillic", "x-mac-cyrillic", "x-mac-cyrillic" },
163     { 20866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
164              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
165              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
166              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
167       "koi8-r", "koi8-r", "koi8-r" },
168     { 28595, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
169              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
170              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
171              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
172       "iso-8859-5", "iso-8859-5", "iso-8859-5" }
173 };
174 static const MIME_CP_INFO greek_cp[] =
175 {
176     { 737, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
177            MIMECONTF_MIME_LATEST,
178       "ibm737", "ibm737", "ibm737" },
179     { 869, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
180            MIMECONTF_MIME_LATEST,
181       "ibm869", "ibm869", "ibm869" },
182     { 875, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
183            MIMECONTF_MIME_LATEST,
184       "cp875", "cp875", "cp875" },
185     { 1253, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
186             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
187             MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
188       "windows-1253", "windows-1253", "windows-1253" },
189     { 10006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
190              MIMECONTF_MIME_LATEST,
191       "x-mac-greek", "x-mac-greek", "x-mac-greek" },
192     { 28597, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
193              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
194              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
195              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
196       "iso-8859-7", "iso-8859-7", "iso-8859-7" }
197 };
198 static const MIME_CP_INFO hebrew_cp[] =
199 {
200     { 424, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
201            MIMECONTF_MIME_LATEST,
202       "ibm424", "ibm424", "ibm424" },
203     { 856, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
204            MIMECONTF_MIME_LATEST,
205       "cp856", "cp856", "cp856" },
206     { 862, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
207            MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
208            MIMECONTF_MIME_LATEST,
209       "dos-862", "dos-862", "dos-862" },
210     { 1255, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
211             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
212             MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
213       "windows-1255", "windows-1255", "windows-1255" },
214     { 28598, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
215              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
216              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
217       "iso-8859-8", "iso-8859-8", "iso-8859-8" }
218 };
219 static const MIME_CP_INFO japanese_cp[] =
220 {
221     { 932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
222            MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
223            MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
224            MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
225       "shift_jis", "iso-2022-jp", "iso-2022-jp" },
226     { 20932, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
227              MIMECONTF_MIME_LATEST,
228       "euc-jp", "euc-jp", "euc-jp" }
229 };
230 static const MIME_CP_INFO korean_cp[] =
231 {
232     { 949, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
233            MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
234            MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
235            MIMECONTF_MIME_LATEST,
236       "ks_c_5601-1987", "ks_c_5601-1987", "ks_c_5601-1987" }
237 };
238 static const MIME_CP_INFO thai_cp[] =
239 {
240     { 874, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_MIME_LATEST,
241       "ibm-thai", "ibm-thai", "ibm-thai" }
242 };
243 static const MIME_CP_INFO turkish_cp[] =
244 {
245     { 857, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
246            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
247       "ibm857", "ibm857", "ibm857" },
248     { 1026, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
249             MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
250       "ibm1026", "ibm1026", "ibm1026" },
251     { 1254, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
252             MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
253             MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
254             MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
255       "windows-1254", "windows-1254", "windows-1254" },
256     { 10081, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
257              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
258       "x-mac-turkish", "x-mac-turkish", "x-mac-turkish" },
259     { 28593, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
260              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
261              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
262       "iso-8859-3", "iso-8859-3", "iso-8859-3" },
263     { 28599, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
264              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
265              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
266              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
267       "iso-8859-9", "iso-8859-9", "iso-8859-9" }
268 };
269 static const MIME_CP_INFO vietnamese_cp[] =
270 {
271     { 1258, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
272             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
273             MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
274             MIMECONTF_MIME_LATEST,
275       "windows-1258", "windows-1258", "windows-1258" }
276 };
277 static const MIME_CP_INFO western_cp[] =
278 {
279     { 37, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
280           MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
281       "ibm037", "ibm037", "ibm037" },
282     { 437, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
283            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
284       "ibm437", "ibm437", "ibm437" },
285     { 500, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
286            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
287       "ibm500", "ibm500", "ibm500" },
288     { 850, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
289            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
290       "ibm850", "ibm850", "ibm850" },
291     { 860, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
292            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
293       "ibm860", "ibm860", "ibm860" },
294     { 861, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
295            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
296       "ibm861", "ibm861", "ibm861" },
297     { 863, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
298            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
299       "ibm863", "ibm863", "ibm863" },
300     { 865, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
301            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
302       "ibm865", "ibm865", "ibm865" },
303     { 1252, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
304             MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
305             MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
306             MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
307       "windows-1252", "windows-1252", "iso-8859-1" },
308     { 10000, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
309              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
310       "macintosh", "macintosh", "macintosh" },
311     { 10079, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
312              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
313       "x-mac-icelandic", "x-mac-icelandic", "x-mac-icelandic" },
314     { 28591, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
315              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
316              MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
317              MIMECONTF_MIME_LATEST,
318       "iso-8859-1", "iso-8859-1", "iso-8859-1" },
319     { 28605, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
320              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
321              MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
322              MIMECONTF_MIME_LATEST,
323       "iso-8859-15", "iso-8859-15", "iso-8859-15" }
324 };
325 static const MIME_CP_INFO unicode_cp[] =
326 {
327     { CP_UNICODE, MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
328                   MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
329                   MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
330                   MIMECONTF_MIME_LATEST,
331       "unicode", "unicode", "unicode" },
332     { CP_UTF7, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
333                MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
334                MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
335       "utf-7", "utf-7", "utf-7" },
336     { CP_UTF8, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
337                MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
338                MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
339                MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
340       "utf-8", "utf-8", "utf-8" }
341 };
342
343 static const struct mlang_data
344 {
345     const char *description;
346     UINT family_codepage;
347     UINT number_of_cp;
348     const MIME_CP_INFO *mime_cp_info;
349     const char *fixed_font;
350     const char *proportional_font;
351 } mlang_data[] =
352 {
353     { "Arabic",1256,sizeof(arabic_cp)/sizeof(arabic_cp[0]),arabic_cp,
354       "Courier","Arial" }, /* FIXME */
355     { "Baltic",1257,sizeof(baltic_cp)/sizeof(baltic_cp[0]),baltic_cp,
356       "Courier","Arial" }, /* FIXME */
357     { "Chinese Simplified",936,sizeof(chinese_simplified_cp)/sizeof(chinese_simplified_cp[0]),chinese_simplified_cp,
358       "Courier","Arial" }, /* FIXME */
359     { "Chinese Traditional",950,sizeof(chinese_traditional_cp)/sizeof(chinese_traditional_cp[0]),chinese_traditional_cp,
360       "Courier","Arial" }, /* FIXME */
361     { "Central European",1250,sizeof(central_european_cp)/sizeof(central_european_cp[0]),central_european_cp,
362       "Courier","Arial" }, /* FIXME */
363     { "Cyrillic",1251,sizeof(cyrillic_cp)/sizeof(cyrillic_cp[0]),cyrillic_cp,
364       "Courier","Arial" }, /* FIXME */
365     { "Greek",1253,sizeof(greek_cp)/sizeof(greek_cp[0]),greek_cp,
366       "Courier","Arial" }, /* FIXME */
367     { "Hebrew",1255,sizeof(hebrew_cp)/sizeof(hebrew_cp[0]),hebrew_cp,
368       "Courier","Arial" }, /* FIXME */
369     { "Japanese",932,sizeof(japanese_cp)/sizeof(japanese_cp[0]),japanese_cp,
370       "Courier","Arial" }, /* FIXME */
371     { "Korean",949,sizeof(korean_cp)/sizeof(korean_cp[0]),korean_cp,
372       "Courier","Arial" }, /* FIXME */
373     { "Thai",874,sizeof(thai_cp)/sizeof(thai_cp[0]),thai_cp,
374       "Courier","Arial" }, /* FIXME */
375     { "Turkish",1254,sizeof(turkish_cp)/sizeof(turkish_cp[0]),turkish_cp,
376       "Courier","Arial" }, /* FIXME */
377     { "Vietnamese",1258,sizeof(vietnamese_cp)/sizeof(vietnamese_cp[0]),vietnamese_cp,
378       "Courier","Arial" }, /* FIXME */
379     { "Western European",1252,sizeof(western_cp)/sizeof(western_cp[0]),western_cp,
380       "Courier","Arial" }, /* FIXME */
381     { "Unicode",CP_UNICODE,sizeof(unicode_cp)/sizeof(unicode_cp[0]),unicode_cp,
382       "Courier","Arial" } /* FIXME */
383 };
384
385 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info);
386
387 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
388 {
389     switch(fdwReason) {
390         case DLL_PROCESS_ATTACH:
391             DisableThreadLibraryCalls(hInstDLL);
392             break;
393         case DLL_PROCESS_DETACH:
394             break;
395     }
396     return TRUE;
397 }
398
399 HRESULT WINAPI ConvertINetMultiByteToUnicode(
400     LPDWORD pdwMode,
401     DWORD dwEncoding,
402     LPCSTR pSrcStr,
403     LPINT pcSrcSize,
404     LPWSTR pDstStr,
405     LPINT pcDstSize)
406 {
407     INT src_len = -1;
408
409     TRACE("%p %ld %s %p %p %p\n", pdwMode, dwEncoding,
410           debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
411
412     if (!pcDstSize)
413         return E_FAIL;
414
415     if (!pcSrcSize)
416         pcSrcSize = &src_len;
417
418     if (!*pcSrcSize)
419     {
420         *pcDstSize = 0;
421         return S_OK;
422     }
423
424     switch (dwEncoding)
425     {
426     case CP_UNICODE:
427         if (*pcSrcSize == -1)
428             *pcSrcSize = lstrlenW((LPCWSTR)pSrcStr);
429         *pcDstSize = min(*pcSrcSize, *pcDstSize);
430         *pcSrcSize *= sizeof(WCHAR);
431         if (pDstStr)
432             memmove(pDstStr, pSrcStr, *pcDstSize * sizeof(WCHAR));
433         break;
434
435     default:
436         if (*pcSrcSize == -1)
437             *pcSrcSize = lstrlenA(pSrcStr);
438
439         if (pDstStr)
440             *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, pDstStr, *pcDstSize);
441         else
442             *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, NULL, 0);
443         break;
444     }
445     
446     if (!*pcDstSize)
447         return E_FAIL;
448
449     return S_OK;
450 }
451
452 HRESULT WINAPI ConvertINetUnicodeToMultiByte(
453     LPDWORD pdwMode,
454     DWORD dwEncoding,
455     LPCWSTR pSrcStr,
456     LPINT pcSrcSize,
457     LPSTR pDstStr,
458     LPINT pcDstSize)
459 {
460
461     INT src_len = -1;
462
463     TRACE("%p %ld %s %p %p %p\n", pdwMode, dwEncoding,
464           debugstr_w(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
465
466     if (!pcDstSize)
467         return E_FAIL;
468
469     if (!pcSrcSize)
470         pcSrcSize = &src_len;
471
472     if (!*pcSrcSize)
473     {
474         *pcDstSize = 0;
475         return S_OK;
476     }
477
478     switch (dwEncoding)
479     {
480     case CP_UNICODE:
481         if (*pcSrcSize == -1)
482             *pcSrcSize = lstrlenW(pSrcStr);
483         *pcDstSize = min(*pcSrcSize * sizeof(WCHAR), *pcDstSize);
484         if (pDstStr)
485             memmove(pDstStr, pSrcStr, *pcDstSize);
486         break;
487
488     default:
489         if (*pcSrcSize == -1)
490             *pcSrcSize = lstrlenW(pSrcStr);
491
492         if (pDstStr)
493             *pcDstSize = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize, pDstStr, *pcDstSize, NULL, NULL);
494         else
495             *pcDstSize = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize, NULL, 0, NULL, NULL);
496         break;
497     }
498
499
500     if (!*pcDstSize)
501         return E_FAIL;
502
503     return S_OK;
504 }
505
506 HRESULT WINAPI ConvertINetString(
507     LPDWORD pdwMode,
508     DWORD dwSrcEncoding,
509     DWORD dwDstEncoding,
510     LPCSTR pSrcStr,
511     LPINT pcSrcSize,
512     LPSTR pDstStr,
513     LPINT pcDstSize
514 )
515 {
516     FIXME("%p %ld %ld %s %p %p %p: stub!\n", pdwMode, dwSrcEncoding, dwDstEncoding,
517           debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
518     return E_NOTIMPL;
519 }
520
521 static HRESULT GetFamilyCodePage(
522     UINT uiCodePage,
523     UINT* puiFamilyCodePage)
524 {
525     UINT i, n;
526
527     TRACE("%u %p\n", uiCodePage, puiFamilyCodePage);
528
529     if (!puiFamilyCodePage) return S_FALSE;
530
531     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
532     {
533         for (n = 0; n < mlang_data[i].number_of_cp; n++)
534         {
535             if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
536             {
537                 *puiFamilyCodePage = mlang_data[i].family_codepage;
538                 return S_OK;
539             }
540         }
541     }
542
543     return S_FALSE;
544 }
545
546 HRESULT WINAPI IsConvertINetStringAvailable(
547     DWORD dwSrcEncoding,
548     DWORD dwDstEncoding)
549 {
550     UINT src_family, dst_family;
551
552     TRACE("%ld %ld\n", dwSrcEncoding, dwDstEncoding);
553
554     if (GetFamilyCodePage(dwSrcEncoding, &src_family) != S_OK ||
555         GetFamilyCodePage(dwDstEncoding, &dst_family) != S_OK)
556         return S_FALSE;
557
558     if (src_family == dst_family) return S_OK;
559
560     /* we can convert any codepage to/from unicode */
561     if (src_family == CP_UNICODE || dst_family == CP_UNICODE) return S_OK;
562
563     return S_FALSE;
564 }
565
566 HRESULT WINAPI LcidToRfc1766A(
567     LCID Locale,
568     LPSTR pszRfc1766,
569     INT nChar)
570 {
571     FIXME("%ld %s %u\n", Locale, pszRfc1766, nChar);
572     return S_FALSE;
573 }
574
575 HRESULT WINAPI LcidToRfc1766W(
576     LCID Locale,
577     LPWSTR pszRfc1766,
578     INT nChar)
579 {
580     FIXME("%ld %p %u\n", Locale, pszRfc1766, nChar);
581     return S_FALSE;
582 }
583
584 /******************************************************************************
585  * MLANG ClassFactory
586  */
587 typedef struct {
588     IClassFactory ITF_IClassFactory;
589
590     DWORD ref;
591     HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
592 } IClassFactoryImpl;
593
594 struct object_creation_info
595 {
596     const CLSID *clsid;
597     LPCSTR szClassName;
598     HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
599 };
600
601 static const struct object_creation_info object_creation[] =
602 {
603     { &CLSID_CMultiLanguage, "CLSID_CMultiLanguage", MultiLanguage_create },
604 };
605
606 static HRESULT WINAPI
607 MLANGCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
608 {
609     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
610
611     TRACE("%s\n", debugstr_guid(riid) );
612
613     if (IsEqualGUID(riid, &IID_IUnknown)
614         || IsEqualGUID(riid, &IID_IClassFactory))
615     {
616         IClassFactory_AddRef(iface);
617         *ppobj = This;
618         return S_OK;
619     }
620
621     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
622     return E_NOINTERFACE;
623 }
624
625 static ULONG WINAPI MLANGCF_AddRef(LPCLASSFACTORY iface) {
626     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
627     return InterlockedIncrement(&This->ref);
628 }
629
630 static ULONG WINAPI MLANGCF_Release(LPCLASSFACTORY iface) {
631     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
632
633     ULONG ref = InterlockedDecrement(&This->ref);
634
635     if (ref == 0)
636     {
637         TRACE("Destroying %p\n", This);
638         HeapFree(GetProcessHeap(), 0, This);
639     }
640
641     return ref;
642 }
643
644 static HRESULT WINAPI MLANGCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter,
645                                           REFIID riid, LPVOID *ppobj) {
646     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
647     HRESULT hres;
648     LPUNKNOWN punk;
649     
650     TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
651
652     hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk);
653     if (FAILED(hres)) {
654         *ppobj = NULL;
655         return hres;
656     }
657     hres = IUnknown_QueryInterface(punk, riid, ppobj);
658     if (FAILED(hres)) {
659         *ppobj = NULL;
660         return hres;
661     }
662     IUnknown_Release(punk);
663     TRACE("returning (%p) -> %lx\n", *ppobj, hres);
664     return hres;
665 }
666
667 static HRESULT WINAPI MLANGCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
668     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
669     FIXME("(%p)->(%d),stub!\n",This,dolock);
670     return S_OK;
671 }
672
673 static IClassFactoryVtbl MLANGCF_Vtbl =
674 {
675     MLANGCF_QueryInterface,
676     MLANGCF_AddRef,
677     MLANGCF_Release,
678     MLANGCF_CreateInstance,
679     MLANGCF_LockServer
680 };
681
682 HRESULT WINAPI MLANG_DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
683 {
684     int i;
685     IClassFactoryImpl *factory;
686
687     TRACE("%s %s %p\n",debugstr_guid(rclsid), debugstr_guid(iid), ppv);
688
689     if ( !IsEqualGUID( &IID_IClassFactory, iid )
690          && ! IsEqualGUID( &IID_IUnknown, iid) )
691         return E_NOINTERFACE;
692
693     for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
694     {
695         if (IsEqualGUID(object_creation[i].clsid, rclsid))
696             break;
697     }
698
699     if (i == sizeof(object_creation)/sizeof(object_creation[0]))
700     {
701         FIXME("%s: no class found.\n", debugstr_guid(rclsid));
702         return CLASS_E_CLASSNOTAVAILABLE;
703     }
704
705     TRACE("Creating a class factory for %s\n",object_creation[i].szClassName);
706
707     factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));
708     if (factory == NULL) return E_OUTOFMEMORY;
709
710     factory->ITF_IClassFactory.lpVtbl = &MLANGCF_Vtbl;
711     factory->ref = 1;
712
713     factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
714
715     *ppv = &(factory->ITF_IClassFactory);
716
717     TRACE("(%p) <- %p\n", ppv, &(factory->ITF_IClassFactory) );
718
719     return S_OK;
720 }
721
722
723 /******************************************************************************/
724
725 typedef struct tagMLang_impl
726 {
727     IMLangFontLinkVtbl *vtbl_IMLangFontLink;
728     IMultiLanguageVtbl *vtbl_IMultiLanguage;
729     IMultiLanguage2Vtbl *vtbl_IMultiLanguage2;
730     DWORD ref;
731     DWORD total_cp, total_scripts;
732 } MLang_impl;
733
734 static ULONG WINAPI MLang_AddRef( MLang_impl* This)
735 {
736     return InterlockedIncrement(&This->ref);
737 }
738
739 static ULONG WINAPI MLang_Release( MLang_impl* This )
740 {
741     ULONG ref = InterlockedDecrement(&This->ref);
742
743     TRACE("%p ref = %ld\n", This, ref);
744     if (ref == 0)
745     {
746         TRACE("Destroying %p\n", This);
747         HeapFree(GetProcessHeap(), 0, This);
748     }
749
750     return ref;
751 }
752
753 static HRESULT WINAPI MLang_QueryInterface(
754         MLang_impl* This,
755         REFIID riid,
756         void** ppvObject)
757 {
758     TRACE("%p -> %s\n", This, debugstr_guid(riid) );
759
760     if (IsEqualGUID(riid, &IID_IUnknown)
761         || IsEqualGUID(riid, &IID_IMLangCodePages)
762         || IsEqualGUID(riid, &IID_IMLangFontLink))
763     {
764         MLang_AddRef(This);
765         TRACE("Returning IID_IMLangFontLink %p ref = %ld\n", This, This->ref);
766         *ppvObject = &(This->vtbl_IMLangFontLink);
767         return S_OK;
768     }
769
770     if (IsEqualGUID(riid, &IID_IMultiLanguage) )
771     {
772         MLang_AddRef(This);
773         TRACE("Returning IID_IMultiLanguage %p ref = %ld\n", This, This->ref);
774         *ppvObject = &(This->vtbl_IMultiLanguage);
775         return S_OK;
776     }
777
778     if (IsEqualGUID(riid, &IID_IMultiLanguage2) )
779     {
780         MLang_AddRef(This);
781         *ppvObject = &(This->vtbl_IMultiLanguage2);
782         TRACE("Returning IID_IMultiLanguage2 %p ref = %ld\n", This, This->ref);
783         return S_OK;
784     }
785
786     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
787     return E_NOINTERFACE;
788 }
789
790 /******************************************************************************/
791
792 typedef struct tagEnumCodePage_impl
793 {
794     IEnumCodePageVtbl *vtbl_IEnumCodePage;
795     DWORD ref;
796     MIMECPINFO *cpinfo;
797     DWORD total, pos;
798 } EnumCodePage_impl;
799
800 static HRESULT WINAPI fnIEnumCodePage_QueryInterface(
801         IEnumCodePage* iface,
802         REFIID riid,
803         void** ppvObject)
804 {
805     ICOM_THIS_MULTI(EnumCodePage_impl, vtbl_IEnumCodePage, iface);
806
807     TRACE("%p -> %s\n", This, debugstr_guid(riid) );
808
809     if (IsEqualGUID(riid, &IID_IUnknown)
810         || IsEqualGUID(riid, &IID_IEnumCodePage))
811     {
812         IEnumCodePage_AddRef(iface);
813         TRACE("Returning IID_IEnumCodePage %p ref = %ld\n", This, This->ref);
814         *ppvObject = &(This->vtbl_IEnumCodePage);
815         return S_OK;
816     }
817
818     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
819     return E_NOINTERFACE;
820 }
821
822 static ULONG WINAPI fnIEnumCodePage_AddRef(
823         IEnumCodePage* iface)
824 {
825     ICOM_THIS_MULTI(EnumCodePage_impl, vtbl_IEnumCodePage, iface);
826     return InterlockedIncrement(&This->ref);
827 }
828
829 static ULONG WINAPI fnIEnumCodePage_Release(
830         IEnumCodePage* iface)
831 {
832     ICOM_THIS_MULTI(EnumCodePage_impl, vtbl_IEnumCodePage, iface);
833     ULONG ref = InterlockedDecrement(&This->ref);
834
835     TRACE("%p ref = %ld\n", This, ref);
836     if (ref == 0)
837     {
838         TRACE("Destroying %p\n", This);
839         HeapFree(GetProcessHeap(), 0, This->cpinfo);
840         HeapFree(GetProcessHeap(), 0, This);
841     }
842
843     return ref;
844 }
845
846 static HRESULT WINAPI fnIEnumCodePage_Clone(
847         IEnumCodePage* iface,
848         IEnumCodePage** ppEnum)
849 {
850     ICOM_THIS_MULTI(EnumCodePage_impl, vtbl_IEnumCodePage, iface);
851     FIXME("%p %p\n", This, ppEnum);
852     return E_NOTIMPL;
853 }
854
855 static  HRESULT WINAPI fnIEnumCodePage_Next(
856         IEnumCodePage* iface,
857         ULONG celt,
858         PMIMECPINFO rgelt,
859         ULONG* pceltFetched)
860 {
861     ULONG i;
862
863     ICOM_THIS_MULTI(EnumCodePage_impl, vtbl_IEnumCodePage, iface);
864     TRACE("%p %lu %p %p\n", This, celt, rgelt, pceltFetched);
865
866     if (!pceltFetched) return S_FALSE;
867     *pceltFetched = 0;
868
869     if (!rgelt) return S_FALSE;
870
871     if (This->pos + celt > This->total)
872         celt = This->total - This->pos;
873
874     if (!celt) return S_FALSE;
875
876     memcpy(rgelt, This->cpinfo + This->pos, celt * sizeof(MIMECPINFO));
877     *pceltFetched = celt;
878     This->pos += celt;
879
880     for (i = 0; i < celt; i++)
881     {
882         TRACE("#%lu: %08lx %u %u %s %s %s %s %s %s %d\n",
883               i, rgelt[i].dwFlags, rgelt[i].uiCodePage,
884               rgelt[i].uiFamilyCodePage,
885               wine_dbgstr_w(rgelt[i].wszDescription),
886               wine_dbgstr_w(rgelt[i].wszWebCharset),
887               wine_dbgstr_w(rgelt[i].wszHeaderCharset),
888               wine_dbgstr_w(rgelt[i].wszBodyCharset),
889               wine_dbgstr_w(rgelt[i].wszFixedWidthFont),
890               wine_dbgstr_w(rgelt[i].wszProportionalFont),
891               rgelt[i].bGDICharset);
892     }
893     return S_OK;
894 }
895
896 static HRESULT WINAPI fnIEnumCodePage_Reset(
897         IEnumCodePage* iface)
898 {
899     ICOM_THIS_MULTI(EnumCodePage_impl, vtbl_IEnumCodePage, iface);
900     TRACE("%p\n", This);
901
902     This->pos = 0;
903     return S_OK;
904 }
905
906 static  HRESULT WINAPI fnIEnumCodePage_Skip(
907         IEnumCodePage* iface,
908         ULONG celt)
909 {
910     ICOM_THIS_MULTI(EnumCodePage_impl, vtbl_IEnumCodePage, iface);
911     TRACE("%p %lu\n", This, celt);
912
913     if (celt >= This->total) return S_FALSE;
914
915     This->pos = celt;  /* FIXME: should be += ?? */
916     return S_OK;
917 }
918
919 static IEnumCodePageVtbl IEnumCodePage_vtbl =
920 {
921     fnIEnumCodePage_QueryInterface,
922     fnIEnumCodePage_AddRef,
923     fnIEnumCodePage_Release,
924     fnIEnumCodePage_Clone,
925     fnIEnumCodePage_Next,
926     fnIEnumCodePage_Reset,
927     fnIEnumCodePage_Skip
928 };
929
930 static HRESULT EnumCodePage_create( MLang_impl* mlang, DWORD grfFlags,
931                      LANGID LangId, IEnumCodePage** ppEnumCodePage )
932 {
933     EnumCodePage_impl *ecp;
934     MIMECPINFO *cpinfo;
935     UINT i, n;
936
937     TRACE("%p, %08lx, %04x, %p\n", mlang, grfFlags, LangId, ppEnumCodePage);
938
939     if (!grfFlags) /* enumerate internal data base of encodings */
940         grfFlags = MIMECONTF_MIME_LATEST;
941
942     ecp = HeapAlloc( GetProcessHeap(), 0, sizeof (EnumCodePage_impl) );
943     ecp->vtbl_IEnumCodePage = &IEnumCodePage_vtbl;
944     ecp->ref = 1;
945     ecp->pos = 0;
946     ecp->total = 0;
947     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
948     {
949         for (n = 0; n < mlang_data[i].number_of_cp; n++)
950         {
951             if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
952                 ecp->total++;
953         }
954     }
955
956     ecp->cpinfo = HeapAlloc(GetProcessHeap(), 0,
957                             sizeof(MIMECPINFO) * ecp->total);
958     cpinfo = ecp->cpinfo;
959
960     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
961     {
962         for (n = 0; n < mlang_data[i].number_of_cp; n++)
963         {
964             if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
965                 fill_cp_info(&mlang_data[i], n, cpinfo++);
966         }
967     }
968
969     TRACE("enumerated %ld codepages with flags %08lx\n", ecp->total, grfFlags);
970
971     *ppEnumCodePage = (IEnumCodePage*) ecp;
972
973     return S_OK;
974 }
975
976 /******************************************************************************/
977
978 typedef struct tagEnumScript_impl
979 {
980     IEnumScriptVtbl *vtbl_IEnumScript;
981     DWORD ref;
982     SCRIPTINFO *script_info;
983     DWORD total, pos;
984 } EnumScript_impl;
985
986 static HRESULT WINAPI fnIEnumScript_QueryInterface(
987         IEnumScript* iface,
988         REFIID riid,
989         void** ppvObject)
990 {
991     ICOM_THIS_MULTI(EnumScript_impl, vtbl_IEnumScript, iface);
992
993     TRACE("%p -> %s\n", This, debugstr_guid(riid) );
994
995     if (IsEqualGUID(riid, &IID_IUnknown)
996         || IsEqualGUID(riid, &IID_IEnumScript))
997     {
998         IEnumScript_AddRef(iface);
999         TRACE("Returning IID_IEnumScript %p ref = %ld\n", This, This->ref);
1000         *ppvObject = &(This->vtbl_IEnumScript);
1001         return S_OK;
1002     }
1003
1004     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1005     return E_NOINTERFACE;
1006 }
1007
1008 static ULONG WINAPI fnIEnumScript_AddRef(
1009         IEnumScript* iface)
1010 {
1011     ICOM_THIS_MULTI(EnumScript_impl, vtbl_IEnumScript, iface);
1012     return InterlockedIncrement(&This->ref);
1013 }
1014
1015 static ULONG WINAPI fnIEnumScript_Release(
1016         IEnumScript* iface)
1017 {
1018     ICOM_THIS_MULTI(EnumScript_impl, vtbl_IEnumScript, iface);
1019     ULONG ref = InterlockedDecrement(&This->ref);
1020
1021     TRACE("%p ref = %ld\n", This, ref);
1022     if (ref == 0)
1023     {
1024         TRACE("Destroying %p\n", This);
1025         HeapFree(GetProcessHeap(), 0, This);
1026     }
1027
1028     return ref;
1029 }
1030
1031 static HRESULT WINAPI fnIEnumScript_Clone(
1032         IEnumScript* iface,
1033         IEnumScript** ppEnum)
1034 {
1035     ICOM_THIS_MULTI(EnumScript_impl, vtbl_IEnumScript, iface);
1036     FIXME("%p %p: stub!\n", This, ppEnum);
1037     return E_NOTIMPL;
1038 }
1039
1040 static  HRESULT WINAPI fnIEnumScript_Next(
1041         IEnumScript* iface,
1042         ULONG celt,
1043         PSCRIPTINFO rgelt,
1044         ULONG* pceltFetched)
1045 {
1046     ICOM_THIS_MULTI(EnumScript_impl, vtbl_IEnumScript, iface);
1047     TRACE("%p %lu %p %p\n", This, celt, rgelt, pceltFetched);
1048
1049     if (!pceltFetched || !rgelt) return E_FAIL;
1050
1051     *pceltFetched = 0;
1052
1053     if (This->pos + celt > This->total)
1054         celt = This->total - This->pos;
1055
1056     if (!celt) return S_FALSE;
1057
1058     memcpy(rgelt, This->script_info + This->pos, celt * sizeof(SCRIPTINFO));
1059     *pceltFetched = celt;
1060     This->pos += celt;
1061
1062     return S_OK;
1063 }
1064
1065 static HRESULT WINAPI fnIEnumScript_Reset(
1066         IEnumScript* iface)
1067 {
1068     ICOM_THIS_MULTI(EnumScript_impl, vtbl_IEnumScript, iface);
1069     TRACE("%p\n", This);
1070
1071     This->pos = 0;
1072     return S_OK;
1073 }
1074
1075 static  HRESULT WINAPI fnIEnumScript_Skip(
1076         IEnumScript* iface,
1077         ULONG celt)
1078 {
1079     ICOM_THIS_MULTI(EnumScript_impl, vtbl_IEnumScript, iface);
1080     TRACE("%p %lu\n", This, celt);
1081
1082     if (celt >= This->total) return S_FALSE;
1083
1084     This->pos = celt;  /* FIXME: should be += ?? */
1085     return S_OK;
1086 }
1087
1088 static IEnumScriptVtbl IEnumScript_vtbl =
1089 {
1090     fnIEnumScript_QueryInterface,
1091     fnIEnumScript_AddRef,
1092     fnIEnumScript_Release,
1093     fnIEnumScript_Clone,
1094     fnIEnumScript_Next,
1095     fnIEnumScript_Reset,
1096     fnIEnumScript_Skip
1097 };
1098
1099 static HRESULT EnumScript_create( MLang_impl* mlang, DWORD dwFlags,
1100                      LANGID LangId, IEnumScript** ppEnumScript )
1101 {
1102     EnumScript_impl *es;
1103     UINT i;
1104
1105     TRACE("%p, %08lx, %04x, %p: stub!\n", mlang, dwFlags, LangId, ppEnumScript);
1106
1107     if (!dwFlags) /* enumerate all available scripts */
1108         dwFlags = SCRIPTCONTF_SCRIPT_USER | SCRIPTCONTF_SCRIPT_HIDE | SCRIPTCONTF_SCRIPT_SYSTEM;
1109
1110     es = HeapAlloc( GetProcessHeap(), 0, sizeof (EnumScript_impl) );
1111     es->vtbl_IEnumScript = &IEnumScript_vtbl;
1112     es->ref = 1;
1113     es->pos = 0;
1114     /* do not enumerate unicode flavours */
1115     es->total = sizeof(mlang_data)/sizeof(mlang_data[0]) - 1;
1116     es->script_info = HeapAlloc(GetProcessHeap(), 0, sizeof(SCRIPTINFO) * es->total);
1117
1118     for (i = 0; i < es->total; i++)
1119     {
1120         es->script_info[i].ScriptId = i;
1121         es->script_info[i].uiCodePage = mlang_data[i].family_codepage;
1122         MultiByteToWideChar(CP_ACP, 0, mlang_data[i].description, -1,
1123             es->script_info[i].wszDescription, MAX_SCRIPT_NAME);
1124         MultiByteToWideChar(CP_ACP, 0, mlang_data[i].fixed_font, -1,
1125             es->script_info[i].wszFixedWidthFont, MAX_MIMEFACE_NAME);
1126         MultiByteToWideChar(CP_ACP, 0, mlang_data[i].proportional_font, -1,
1127             es->script_info[i].wszProportionalFont, MAX_MIMEFACE_NAME);
1128     }
1129
1130     TRACE("enumerated %ld scripts with flags %08lx\n", es->total, dwFlags);
1131
1132     *ppEnumScript = (IEnumScript *)es;
1133
1134     return S_OK;
1135 }
1136
1137 /******************************************************************************/
1138
1139 static HRESULT WINAPI fnIMLangFontLink_QueryInterface(
1140         IMLangFontLink* iface,
1141         REFIID riid,
1142         void** ppvObject)
1143 {
1144     ICOM_THIS_MULTI(MLang_impl, vtbl_IMLangFontLink, iface);
1145     return MLang_QueryInterface( This, riid, ppvObject );
1146 }
1147
1148 static ULONG WINAPI fnIMLangFontLink_AddRef(
1149         IMLangFontLink* iface)
1150 {
1151     ICOM_THIS_MULTI(MLang_impl, vtbl_IMLangFontLink, iface);
1152     return MLang_AddRef( This );
1153 }
1154
1155 static ULONG WINAPI fnIMLangFontLink_Release(
1156         IMLangFontLink* iface)
1157 {
1158     ICOM_THIS_MULTI(MLang_impl, vtbl_IMLangFontLink, iface);
1159     return MLang_Release( This );
1160 }
1161
1162 static HRESULT WINAPI fnIMLangFontLink_GetCharCodePages(
1163         IMLangFontLink* iface,
1164         WCHAR chSrc,
1165         DWORD* pdwCodePages)
1166 {
1167     FIXME("\n");
1168     return E_NOTIMPL;
1169 }
1170
1171 static HRESULT WINAPI fnIMLangFontLink_GetStrCodePages(
1172         IMLangFontLink* iface,
1173         const WCHAR* pszSrc,
1174         long cchSrc,
1175         DWORD dwPriorityCodePages,
1176         DWORD* pdwCodePages,
1177         long* pcchCodePages)
1178 {
1179     FIXME("\n");
1180     return E_NOTIMPL;
1181 }
1182
1183 static HRESULT WINAPI fnIMLangFontLink_CodePageToCodePages(
1184         IMLangFontLink* iface,
1185         UINT uCodePage,
1186         DWORD* pdwCodePages)
1187 {
1188     FIXME("\n");
1189     return E_NOTIMPL;
1190 }
1191
1192 static HRESULT WINAPI fnIMLangFontLink_CodePagesToCodePage(
1193         IMLangFontLink* iface,
1194         DWORD dwCodePages,
1195         UINT uDefaultCodePage,
1196         UINT* puCodePage)
1197 {
1198     FIXME("\n");
1199     return E_NOTIMPL;
1200 }
1201
1202 static HRESULT WINAPI fnIMLangFontLink_GetFontCodePages(
1203         IMLangFontLink* iface,
1204         HDC hDC,
1205         HFONT hFont,
1206         DWORD* pdwCodePages)
1207 {
1208     FIXME("\n");
1209     return E_NOTIMPL;
1210 }
1211
1212 static HRESULT WINAPI fnIMLangFontLink_MapFont(
1213         IMLangFontLink* iface,
1214         HDC hDC,
1215         DWORD dwCodePages,
1216         HFONT hSrcFont,
1217         HFONT* phDestFont)
1218 {
1219     FIXME("\n");
1220     return E_NOTIMPL;
1221 }
1222
1223 static HRESULT WINAPI fnIMLangFontLink_ReleaseFont(
1224         IMLangFontLink* iface,
1225         HFONT hFont)
1226 {
1227     FIXME("\n");
1228     return E_NOTIMPL;
1229 }
1230
1231 static HRESULT WINAPI fnIMLangFontLink_ResetFontMapping(
1232         IMLangFontLink* iface)
1233 {
1234     FIXME("\n");
1235     return E_NOTIMPL;
1236 }
1237
1238
1239 static IMLangFontLinkVtbl IMLangFontLink_vtbl =
1240 {
1241     fnIMLangFontLink_QueryInterface,
1242     fnIMLangFontLink_AddRef,
1243     fnIMLangFontLink_Release,
1244     fnIMLangFontLink_GetCharCodePages,
1245     fnIMLangFontLink_GetStrCodePages,
1246     fnIMLangFontLink_CodePageToCodePages,
1247     fnIMLangFontLink_CodePagesToCodePage,
1248     fnIMLangFontLink_GetFontCodePages,
1249     fnIMLangFontLink_MapFont,
1250     fnIMLangFontLink_ReleaseFont,
1251     fnIMLangFontLink_ResetFontMapping,
1252 };
1253
1254 /******************************************************************************/
1255
1256 static HRESULT WINAPI fnIMultiLanguage_QueryInterface(
1257     IMultiLanguage* iface,
1258     REFIID riid,
1259     void** ppvObject)
1260 {
1261     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage, iface);
1262     return MLang_QueryInterface( This, riid, ppvObject );
1263 }
1264
1265 static ULONG WINAPI fnIMultiLanguage_AddRef( IMultiLanguage* iface )
1266 {
1267     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage, iface);
1268     return IMLangFontLink_AddRef( ((IMLangFontLink*)This) );
1269 }
1270
1271 static ULONG WINAPI fnIMultiLanguage_Release( IMultiLanguage* iface )
1272 {
1273     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage, iface);
1274     return IMLangFontLink_Release( ((IMLangFontLink*)This) );
1275 }
1276
1277 static HRESULT WINAPI fnIMultiLanguage_GetNumberOfCodePageInfo(
1278     IMultiLanguage* iface,
1279     UINT* pcCodePage)
1280 {
1281     FIXME("\n");
1282     return E_NOTIMPL;
1283 }
1284
1285 static HRESULT WINAPI fnIMultiLanguage_GetCodePageInfo(
1286     IMultiLanguage* iface,
1287     UINT uiCodePage,
1288     PMIMECPINFO pCodePageInfo)
1289 {
1290     FIXME("\n");
1291     return E_NOTIMPL;
1292 }
1293
1294 static HRESULT WINAPI fnIMultiLanguage_GetFamilyCodePage(
1295     IMultiLanguage* iface,
1296     UINT uiCodePage,
1297     UINT* puiFamilyCodePage)
1298 {
1299     return GetFamilyCodePage(uiCodePage, puiFamilyCodePage);
1300 }
1301
1302 static HRESULT WINAPI fnIMultiLanguage_EnumCodePages(
1303     IMultiLanguage* iface,
1304     DWORD grfFlags,
1305     IEnumCodePage** ppEnumCodePage)
1306 {
1307     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage, iface);
1308     TRACE("%p %08lx %p\n", This, grfFlags, ppEnumCodePage);
1309
1310     return EnumCodePage_create( This, grfFlags, 0, ppEnumCodePage );
1311 }
1312
1313 static HRESULT WINAPI fnIMultiLanguage_GetCharsetInfo(
1314     IMultiLanguage* iface,
1315     BSTR Charset,
1316     PMIMECSETINFO pCharsetInfo)
1317 {
1318     FIXME("\n");
1319     return E_NOTIMPL;
1320 }
1321
1322 static HRESULT WINAPI fnIMultiLanguage_IsConvertible(
1323     IMultiLanguage* iface,
1324     DWORD dwSrcEncoding,
1325     DWORD dwDstEncoding)
1326 {
1327     return IsConvertINetStringAvailable(dwSrcEncoding, dwDstEncoding);
1328 }
1329
1330 static HRESULT WINAPI fnIMultiLanguage_ConvertString(
1331     IMultiLanguage* iface,
1332     DWORD* pdwMode,
1333     DWORD dwSrcEncoding,
1334     DWORD dwDstEncoding,
1335     BYTE* pSrcStr,
1336     UINT* pcSrcSize,
1337     BYTE* pDstStr,
1338     UINT* pcDstSize)
1339 {
1340     return ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding,
1341                              pSrcStr, pcSrcSize, pDstStr, pcDstSize);
1342 }
1343
1344 static HRESULT WINAPI fnIMultiLanguage_ConvertStringToUnicode(
1345     IMultiLanguage* iface,
1346     DWORD* pdwMode,
1347     DWORD dwEncoding,
1348     CHAR* pSrcStr,
1349     UINT* pcSrcSize,
1350     WCHAR* pDstStr,
1351     UINT* pcDstSize)
1352 {
1353     return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
1354                                          pSrcStr, pcSrcSize, pDstStr, pcDstSize);
1355 }
1356
1357 static HRESULT WINAPI fnIMultiLanguage_ConvertStringFromUnicode(
1358     IMultiLanguage* iface,
1359     DWORD* pdwMode,
1360     DWORD dwEncoding,
1361     WCHAR* pSrcStr,
1362     UINT* pcSrcSize,
1363     CHAR* pDstStr,
1364     UINT* pcDstSize)
1365 {
1366     return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
1367                                          pSrcStr, pcSrcSize, pDstStr, pcDstSize);
1368 }
1369
1370 static HRESULT WINAPI fnIMultiLanguage_ConvertStringReset(
1371     IMultiLanguage* iface)
1372 {
1373     FIXME("\n");
1374     return E_NOTIMPL;
1375 }
1376
1377 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766FromLcid(
1378     IMultiLanguage* iface,
1379     LCID Locale,
1380     BSTR* pbstrRfc1766)
1381 {
1382     FIXME("\n");
1383     return E_NOTIMPL;
1384 }
1385
1386 static HRESULT WINAPI fnIMultiLanguage_GetLcidFromRfc1766(
1387     IMultiLanguage* iface,
1388     LCID* pLocale,
1389     BSTR bstrRfc1766)
1390 {
1391     FIXME("\n");
1392     return E_NOTIMPL;
1393 }
1394
1395 static HRESULT WINAPI fnIMultiLanguage_EnumRfc1766(
1396     IMultiLanguage* iface,
1397     IEnumRfc1766** ppEnumRfc1766)
1398 {
1399     FIXME("\n");
1400     return E_NOTIMPL;
1401 }
1402
1403 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766Info(
1404     IMultiLanguage* iface,
1405     LCID Locale,
1406     PRFC1766INFO pRfc1766Info)
1407 {
1408     FIXME("\n");
1409     return E_NOTIMPL;
1410 }
1411
1412 static HRESULT WINAPI fnIMultiLanguage_CreateConvertCharset(
1413     IMultiLanguage* iface,
1414     UINT uiSrcCodePage,
1415     UINT uiDstCodePage,
1416     DWORD dwProperty,
1417     IMLangConvertCharset** ppMLangConvertCharset)
1418 {
1419     FIXME("\n");
1420     return E_NOTIMPL;
1421 }
1422
1423 static IMultiLanguageVtbl IMultiLanguage_vtbl =
1424 {
1425     fnIMultiLanguage_QueryInterface,
1426     fnIMultiLanguage_AddRef,
1427     fnIMultiLanguage_Release,
1428     fnIMultiLanguage_GetNumberOfCodePageInfo,
1429     fnIMultiLanguage_GetCodePageInfo,
1430     fnIMultiLanguage_GetFamilyCodePage,
1431     fnIMultiLanguage_EnumCodePages,
1432     fnIMultiLanguage_GetCharsetInfo,
1433     fnIMultiLanguage_IsConvertible,
1434     fnIMultiLanguage_ConvertString,
1435     fnIMultiLanguage_ConvertStringToUnicode,
1436     fnIMultiLanguage_ConvertStringFromUnicode,
1437     fnIMultiLanguage_ConvertStringReset,
1438     fnIMultiLanguage_GetRfc1766FromLcid,
1439     fnIMultiLanguage_GetLcidFromRfc1766,
1440     fnIMultiLanguage_EnumRfc1766,
1441     fnIMultiLanguage_GetRfc1766Info,
1442     fnIMultiLanguage_CreateConvertCharset,
1443 };
1444
1445
1446 /******************************************************************************/
1447
1448 static HRESULT WINAPI fnIMultiLanguage2_QueryInterface(
1449     IMultiLanguage2* iface,
1450     REFIID riid,
1451     void** ppvObject)
1452 {
1453     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage2, iface);
1454     return MLang_QueryInterface( This, riid, ppvObject );
1455 }
1456
1457 static ULONG WINAPI fnIMultiLanguage2_AddRef( IMultiLanguage2* iface )
1458 {
1459     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage2, iface);
1460     return MLang_AddRef( This );
1461 }
1462
1463 static ULONG WINAPI fnIMultiLanguage2_Release( IMultiLanguage2* iface )
1464 {
1465     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage2, iface);
1466     return MLang_Release( This );
1467 }
1468
1469 static HRESULT WINAPI fnIMultiLanguage2_GetNumberOfCodePageInfo(
1470     IMultiLanguage2* iface,
1471     UINT* pcCodePage)
1472 {
1473     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage2, iface);
1474     TRACE("%p, %p\n", This, pcCodePage);
1475
1476     if (!pcCodePage) return S_FALSE;
1477
1478     *pcCodePage = This->total_cp;
1479     return S_OK;
1480 }
1481
1482 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info)
1483 {
1484     CPINFOEXW cpinfo;
1485     CHARSETINFO csi;
1486
1487     if (TranslateCharsetInfo((DWORD *)ml_data->family_codepage, &csi, TCI_SRCCODEPAGE))
1488         mime_cp_info->bGDICharset = csi.ciCharset;
1489     else
1490         mime_cp_info->bGDICharset = DEFAULT_CHARSET;
1491
1492     if (!GetCPInfoExW(ml_data->mime_cp_info[index].cp, 0, &cpinfo))
1493     {
1494         /* fall back to family codepage in the case of alias */
1495         if (!GetCPInfoExW(ml_data->family_codepage, 0, &cpinfo))
1496             cpinfo.CodePageName[0] = 0;
1497     }
1498
1499     mime_cp_info->dwFlags = ml_data->mime_cp_info[index].flags;
1500     mime_cp_info->uiCodePage = ml_data->mime_cp_info[index].cp;
1501     mime_cp_info->uiFamilyCodePage = ml_data->family_codepage;
1502     strcpyW(mime_cp_info->wszDescription, cpinfo.CodePageName);
1503     MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].web_charset, -1,
1504                         mime_cp_info->wszWebCharset, sizeof(mime_cp_info->wszWebCharset)/sizeof(WCHAR));
1505     MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].header_charset, -1,
1506                         mime_cp_info->wszHeaderCharset, sizeof(mime_cp_info->wszHeaderCharset)/sizeof(WCHAR));
1507     MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].body_charset, -1,
1508                         mime_cp_info->wszBodyCharset, sizeof(mime_cp_info->wszBodyCharset)/sizeof(WCHAR));
1509
1510
1511     MultiByteToWideChar(CP_ACP, 0, ml_data->fixed_font, -1,
1512         mime_cp_info->wszFixedWidthFont, sizeof(mime_cp_info->wszFixedWidthFont)/sizeof(WCHAR));
1513     MultiByteToWideChar(CP_ACP, 0, ml_data->proportional_font, -1,
1514         mime_cp_info->wszProportionalFont, sizeof(mime_cp_info->wszProportionalFont)/sizeof(WCHAR));
1515
1516     TRACE("%08lx %u %u %s %s %s %s %s %s %d\n",
1517           mime_cp_info->dwFlags, mime_cp_info->uiCodePage,
1518           mime_cp_info->uiFamilyCodePage,
1519           wine_dbgstr_w(mime_cp_info->wszDescription),
1520           wine_dbgstr_w(mime_cp_info->wszWebCharset),
1521           wine_dbgstr_w(mime_cp_info->wszHeaderCharset),
1522           wine_dbgstr_w(mime_cp_info->wszBodyCharset),
1523           wine_dbgstr_w(mime_cp_info->wszFixedWidthFont),
1524           wine_dbgstr_w(mime_cp_info->wszProportionalFont),
1525           mime_cp_info->bGDICharset);
1526 }
1527
1528 static HRESULT WINAPI fnIMultiLanguage2_GetCodePageInfo(
1529     IMultiLanguage2* iface,
1530     UINT uiCodePage,
1531     LANGID LangId,
1532     PMIMECPINFO pCodePageInfo)
1533 {
1534     UINT i, n;
1535
1536     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage2, iface);
1537     TRACE("%p, %u, %04x, %p\n", This, uiCodePage, LangId, pCodePageInfo);
1538
1539     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
1540     {
1541         for (n = 0; n < mlang_data[i].number_of_cp; n++)
1542         {
1543             if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
1544             {
1545                 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
1546                 return S_OK;
1547             }
1548         }
1549     }
1550
1551     return S_FALSE;
1552 }
1553
1554 static HRESULT WINAPI fnIMultiLanguage2_GetFamilyCodePage(
1555     IMultiLanguage2* iface,
1556     UINT uiCodePage,
1557     UINT* puiFamilyCodePage)
1558 {
1559     return GetFamilyCodePage(uiCodePage, puiFamilyCodePage);
1560 }
1561
1562 static HRESULT WINAPI fnIMultiLanguage2_EnumCodePages(
1563     IMultiLanguage2* iface,
1564     DWORD grfFlags,
1565     LANGID LangId,
1566     IEnumCodePage** ppEnumCodePage)
1567 {
1568     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage2, iface);
1569     TRACE("%p %08lx %04x %p\n", This, grfFlags, LangId, ppEnumCodePage);
1570
1571     return EnumCodePage_create( This, grfFlags, LangId, ppEnumCodePage );
1572 }
1573
1574 static HRESULT WINAPI fnIMultiLanguage2_GetCharsetInfo(
1575     IMultiLanguage2* iface,
1576     BSTR Charset,
1577     PMIMECSETINFO pCharsetInfo)
1578 {
1579     UINT i, n;
1580
1581     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage2, iface);
1582     TRACE("%p %s %p\n", This, debugstr_w(Charset), pCharsetInfo);
1583
1584     if (!pCharsetInfo) return E_FAIL;
1585
1586     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
1587     {
1588         for (n = 0; n < mlang_data[i].number_of_cp; n++)
1589         {
1590             WCHAR csetW[MAX_MIMECSET_NAME];
1591
1592             MultiByteToWideChar(CP_ACP, 0, mlang_data[i].mime_cp_info[n].web_charset, -1, csetW, MAX_MIMECSET_NAME);
1593             if (!lstrcmpiW(Charset, csetW))
1594             {
1595                 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
1596                 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
1597                 strcpyW(pCharsetInfo->wszCharset, csetW);
1598                 return S_OK;
1599             }
1600         }
1601     }
1602
1603     /* FIXME:
1604      * Since we do not support charsets like iso-2022-jp and do not have
1605      * them in our database as a primary (web_charset) encoding this loop
1606      * does an attempt to 'approximate' charset name by header_charset.
1607      */
1608     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
1609     {
1610         for (n = 0; n < mlang_data[i].number_of_cp; n++)
1611         {
1612             WCHAR csetW[MAX_MIMECSET_NAME];
1613
1614             MultiByteToWideChar(CP_ACP, 0, mlang_data[i].mime_cp_info[n].header_charset, -1, csetW, MAX_MIMECSET_NAME);
1615             if (!lstrcmpiW(Charset, csetW))
1616             {
1617                 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
1618                 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
1619                 strcpyW(pCharsetInfo->wszCharset, csetW);
1620                 return S_OK;
1621             }
1622         }
1623     }
1624
1625     return E_FAIL;
1626 }
1627
1628 static HRESULT WINAPI fnIMultiLanguage2_IsConvertible(
1629     IMultiLanguage2* iface,
1630     DWORD dwSrcEncoding,
1631     DWORD dwDstEncoding)
1632 {
1633     return IsConvertINetStringAvailable(dwSrcEncoding, dwDstEncoding);
1634 }
1635
1636 static HRESULT WINAPI fnIMultiLanguage2_ConvertString(
1637     IMultiLanguage2* iface,
1638     DWORD* pdwMode,
1639     DWORD dwSrcEncoding,
1640     DWORD dwDstEncoding,
1641     BYTE* pSrcStr,
1642     UINT* pcSrcSize,
1643     BYTE* pDstStr,
1644     UINT* pcDstSize)
1645 {
1646     return ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding,
1647                              pSrcStr, pcSrcSize, pDstStr, pcDstSize);
1648 }
1649
1650 static HRESULT WINAPI fnIMultiLanguage2_ConvertStringToUnicode(
1651     IMultiLanguage2* iface,
1652     DWORD* pdwMode,
1653     DWORD dwEncoding,
1654     CHAR* pSrcStr,
1655     UINT* pcSrcSize,
1656     WCHAR* pDstStr,
1657     UINT* pcDstSize)
1658 {
1659     return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
1660                                          pSrcStr, pcSrcSize, pDstStr, pcDstSize);
1661 }
1662
1663 static HRESULT WINAPI fnIMultiLanguage2_ConvertStringFromUnicode(
1664     IMultiLanguage2* iface,
1665     DWORD* pdwMode,
1666     DWORD dwEncoding,
1667     WCHAR* pSrcStr,
1668     UINT* pcSrcSize,
1669     CHAR* pDstStr,
1670     UINT* pcDstSize)
1671 {
1672     return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
1673                                          pSrcStr, pcSrcSize, pDstStr, pcDstSize);
1674 }
1675
1676 static HRESULT WINAPI fnIMultiLanguage2_ConvertStringReset(
1677     IMultiLanguage2* iface)
1678 {
1679     FIXME("\n");
1680     return E_NOTIMPL;
1681 }
1682
1683 static HRESULT WINAPI fnIMultiLanguage2_GetRfc1766FromLcid(
1684     IMultiLanguage2* iface,
1685     LCID Locale,
1686     BSTR* pbstrRfc1766)
1687 {
1688     FIXME("\n");
1689     return E_NOTIMPL;
1690 }
1691
1692 static HRESULT WINAPI fnIMultiLanguage2_GetLcidFromRfc1766(
1693     IMultiLanguage2* iface,
1694     LCID* pLocale,
1695     BSTR bstrRfc1766)
1696 {
1697     FIXME("\n");
1698     return E_NOTIMPL;
1699 }
1700
1701 static HRESULT WINAPI fnIMultiLanguage2_EnumRfc1766(
1702     IMultiLanguage2* iface,
1703     LANGID LangId,
1704     IEnumRfc1766** ppEnumRfc1766)
1705 {
1706     FIXME("\n");
1707     return E_NOTIMPL;
1708 }
1709
1710 static HRESULT WINAPI fnIMultiLanguage2_GetRfc1766Info(
1711     IMultiLanguage2* iface,
1712     LCID Locale,
1713     LANGID LangId,
1714     PRFC1766INFO pRfc1766Info)
1715 {
1716     FIXME("\n");
1717     return E_NOTIMPL;
1718 }
1719
1720 static HRESULT WINAPI fnIMultiLanguage2_CreateConvertCharset(
1721     IMultiLanguage2* iface,
1722     UINT uiSrcCodePage,
1723     UINT uiDstCodePage,
1724     DWORD dwProperty,
1725     IMLangConvertCharset** ppMLangConvertCharset)
1726 {
1727     FIXME("\n");
1728     return E_NOTIMPL;
1729 }
1730
1731 static HRESULT WINAPI fnIMultiLanguage2_ConvertStringInIStream(
1732     IMultiLanguage2* iface,
1733     DWORD* pdwMode,
1734     DWORD dwFlag,
1735     WCHAR* lpFallBack,
1736     DWORD dwSrcEncoding,
1737     DWORD dwDstEncoding,
1738     IStream* pstmIn,
1739     IStream* pstmOut)
1740 {
1741     FIXME("\n");
1742     return E_NOTIMPL;
1743 }
1744
1745 static HRESULT WINAPI fnIMultiLanguage2_ConvertStringToUnicodeEx(
1746     IMultiLanguage2* iface,
1747     DWORD* pdwMode,
1748     DWORD dwEncoding,
1749     CHAR* pSrcStr,
1750     UINT* pcSrcSize,
1751     WCHAR* pDstStr,
1752     UINT* pcDstSize,
1753     DWORD dwFlag,
1754     WCHAR* lpFallBack)
1755 {
1756     FIXME("\n");
1757     return E_NOTIMPL;
1758 }
1759
1760 static HRESULT WINAPI fnIMultiLanguage2_ConvertStringFromUnicodeEx(
1761     IMultiLanguage2* This,
1762     DWORD* pdwMode,
1763     DWORD dwEncoding,
1764     WCHAR* pSrcStr,
1765     UINT* pcSrcSize,
1766     CHAR* pDstStr,
1767     UINT* pcDstSize,
1768     DWORD dwFlag,
1769     WCHAR* lpFallBack)
1770 {
1771     FIXME("\n");
1772     return E_NOTIMPL;
1773 }
1774
1775 static HRESULT WINAPI fnIMultiLanguage2_DetectCodepageInIStream(
1776     IMultiLanguage2* iface,
1777     DWORD dwFlag,
1778     DWORD dwPrefWinCodePage,
1779     IStream* pstmIn,
1780     DetectEncodingInfo* lpEncoding,
1781     INT* pnScores)
1782 {
1783     FIXME("\n");
1784     return E_NOTIMPL;
1785 }
1786
1787 static HRESULT WINAPI fnIMultiLanguage2_DetectInputCodepage(
1788     IMultiLanguage2* iface,
1789     DWORD dwFlag,
1790     DWORD dwPrefWinCodePage,
1791     CHAR* pSrcStr,
1792     INT* pcSrcSize,
1793     DetectEncodingInfo* lpEncoding,
1794     INT* pnScores)
1795 {
1796     FIXME("\n");
1797     return E_NOTIMPL;
1798 }
1799
1800 static HRESULT WINAPI fnIMultiLanguage2_ValidateCodePage(
1801     IMultiLanguage2* iface,
1802     UINT uiCodePage,
1803     HWND hwnd)
1804 {
1805     FIXME("\n");
1806     return E_NOTIMPL;
1807 }
1808
1809 static HRESULT WINAPI fnIMultiLanguage2_GetCodePageDescription(
1810     IMultiLanguage2* iface,
1811     UINT uiCodePage,
1812     LCID lcid,
1813     LPWSTR lpWideCharStr,
1814     int cchWideChar)
1815 {
1816     FIXME("\n");
1817     return E_NOTIMPL;
1818 }
1819
1820 static HRESULT WINAPI fnIMultiLanguage2_IsCodePageInstallable(
1821     IMultiLanguage2* iface,
1822     UINT uiCodePage)
1823 {
1824     FIXME("\n");
1825     return E_NOTIMPL;
1826 }
1827
1828 static HRESULT WINAPI fnIMultiLanguage2_SetMimeDBSource(
1829     IMultiLanguage2* iface,
1830     MIMECONTF dwSource)
1831 {
1832     FIXME("\n");
1833     return E_NOTIMPL;
1834 }
1835
1836 static HRESULT WINAPI fnIMultiLanguage2_GetNumberOfScripts(
1837     IMultiLanguage2* iface,
1838     UINT* pnScripts)
1839 {
1840     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage2, iface);
1841     TRACE("%p %p\n", This, pnScripts);
1842
1843     if (!pnScripts) return S_FALSE;
1844
1845     *pnScripts = This->total_scripts;
1846     return S_OK;
1847 }
1848
1849 static HRESULT WINAPI fnIMultiLanguage2_EnumScripts(
1850     IMultiLanguage2* iface,
1851     DWORD dwFlags,
1852     LANGID LangId,
1853     IEnumScript** ppEnumScript)
1854 {
1855     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage2, iface);
1856     TRACE("%p %08lx %04x %p\n", This, dwFlags, LangId, ppEnumScript);
1857
1858     return EnumScript_create( This, dwFlags, LangId, ppEnumScript );
1859 }
1860
1861 static HRESULT WINAPI fnIMultiLanguage2_ValidateCodePageEx(
1862     IMultiLanguage2* iface,
1863     UINT uiCodePage,
1864     HWND hwnd,
1865     DWORD dwfIODControl)
1866 {
1867     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage2, iface);
1868     FIXME("%p %u %p %08lx: stub!\n", This, uiCodePage, hwnd, dwfIODControl);
1869
1870     return S_FALSE;
1871 }
1872
1873 static IMultiLanguage2Vtbl IMultiLanguage2_vtbl =
1874 {
1875     fnIMultiLanguage2_QueryInterface,
1876     fnIMultiLanguage2_AddRef,
1877     fnIMultiLanguage2_Release,
1878     fnIMultiLanguage2_GetNumberOfCodePageInfo,
1879     fnIMultiLanguage2_GetCodePageInfo,
1880     fnIMultiLanguage2_GetFamilyCodePage,
1881     fnIMultiLanguage2_EnumCodePages,
1882     fnIMultiLanguage2_GetCharsetInfo,
1883     fnIMultiLanguage2_IsConvertible,
1884     fnIMultiLanguage2_ConvertString,
1885     fnIMultiLanguage2_ConvertStringToUnicode,
1886     fnIMultiLanguage2_ConvertStringFromUnicode,
1887     fnIMultiLanguage2_ConvertStringReset,
1888     fnIMultiLanguage2_GetRfc1766FromLcid,
1889     fnIMultiLanguage2_GetLcidFromRfc1766,
1890     fnIMultiLanguage2_EnumRfc1766,
1891     fnIMultiLanguage2_GetRfc1766Info,
1892     fnIMultiLanguage2_CreateConvertCharset,
1893     fnIMultiLanguage2_ConvertStringInIStream,
1894     fnIMultiLanguage2_ConvertStringToUnicodeEx,
1895     fnIMultiLanguage2_ConvertStringFromUnicodeEx,
1896     fnIMultiLanguage2_DetectCodepageInIStream,
1897     fnIMultiLanguage2_DetectInputCodepage,
1898     fnIMultiLanguage2_ValidateCodePage,
1899     fnIMultiLanguage2_GetCodePageDescription,
1900     fnIMultiLanguage2_IsCodePageInstallable,
1901     fnIMultiLanguage2_SetMimeDBSource,
1902     fnIMultiLanguage2_GetNumberOfScripts,
1903     fnIMultiLanguage2_EnumScripts,
1904     fnIMultiLanguage2_ValidateCodePageEx,
1905 };
1906
1907 static HRESULT MultiLanguage_create(IUnknown *pUnkOuter, LPVOID *ppObj)
1908 {
1909     MLang_impl *mlang;
1910     UINT i;
1911
1912     TRACE("Creating MultiLanguage object\n");
1913
1914     if( pUnkOuter )
1915         return CLASS_E_NOAGGREGATION;
1916
1917     mlang = HeapAlloc( GetProcessHeap(), 0, sizeof (MLang_impl) );
1918     mlang->vtbl_IMLangFontLink = &IMLangFontLink_vtbl;
1919     mlang->vtbl_IMultiLanguage = &IMultiLanguage_vtbl;
1920     mlang->vtbl_IMultiLanguage2 = &IMultiLanguage2_vtbl;
1921
1922     mlang->total_cp = 0;
1923     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
1924         mlang->total_cp += mlang_data[i].number_of_cp;
1925
1926     /* do not enumerate unicode flavours */
1927     mlang->total_scripts = sizeof(mlang_data)/sizeof(mlang_data[0]) - 1;
1928
1929     mlang->ref = 1;
1930     *ppObj = (LPVOID) mlang;
1931     TRACE("returning %p\n", mlang);
1932     return S_OK;
1933 }
1934
1935 /******************************************************************************/
1936
1937 HRESULT WINAPI MLANG_DllCanUnloadNow(void)
1938 {
1939     FIXME("\n");
1940     return S_FALSE;
1941 }