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