Implement A->W call for GetNamedSecurityInfo.
[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 static HRESULT MultiLanguage_create(IUnknown *pUnkOuter, LPVOID *ppObj);
49
50 /* FIXME:
51  * Under what circumstances HKEY_CLASSES_ROOT\MIME\Database\Codepage and
52  * HKEY_CLASSES_ROOT\MIME\Database\Charset are used?
53  */
54
55 typedef struct
56 {
57     UINT cp;
58     DWORD flags;
59     const char *web_charset;
60     const char *header_charset;
61     const char *body_charset;
62 } MIME_CP_INFO;
63
64 /* These data are based on the codepage info in libs/unicode/cpmap.pl */
65 /* FIXME: Add 28604 (Celtic), 28606 (Balkan) */
66
67 static const MIME_CP_INFO arabic_cp[] =
68 {
69     { 864, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
70            MIMECONTF_MIME_LATEST,
71       "ibm864", "ibm864", "ibm864" },
72     { 1006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
73             MIMECONTF_MIME_LATEST,
74       "ibm1006", "ibm1006", "ibm1006" },
75     { 1256, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
76             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
77             MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
78       "windows-1256", "windows-1256", "windows-1256" },
79     { 28596, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
80              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
81              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
82              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
83       "iso-8859-6", "iso-8859-6", "iso-8859-6" }
84 };
85 static const MIME_CP_INFO baltic_cp[] =
86 {
87     { 775, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
88            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
89       "ibm775", "ibm775", "ibm775" },
90     { 1257, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
91             MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
92             MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
93             MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
94       "windows-1257", "windows-1257", "windows-1257" },
95     { 28594, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
96              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
97              MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
98              MIMECONTF_MIME_LATEST,
99       "iso-8859-4", "iso-8859-4", "iso-8859-4" },
100     { 28603, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
101              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
102       "iso-8859-13", "iso-8859-13", "iso-8859-13" }
103 };
104 static const MIME_CP_INFO chinese_simplified_cp[] =
105 {
106     { 936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
107            MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
108            MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
109            MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
110       "gb2312", "gb2312", "gb2312" }
111 };
112 static const MIME_CP_INFO chinese_traditional_cp[] =
113 {
114     { 950, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
115            MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
116            MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
117            MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
118       "big5", "big5", "big5" }
119 };
120 static const MIME_CP_INFO central_european_cp[] =
121 {
122     { 852, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
123            MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
124            MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
125       "ibm852", "ibm852", "ibm852" },
126     { 1250, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
127             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
128             MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
129             MIMECONTF_MIME_LATEST,
130       "windows-1250", "windows-1250", "windows-1250" },
131     { 10029, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
132              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
133       "x-mac-ce", "x-mac-ce", "x-mac-ce" },
134     { 28592, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
135              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
136              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
137              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
138       "iso-8859-2", "iso-8859-2", "iso-8859-2" }
139 };
140 static const MIME_CP_INFO cyrillic_cp[] =
141 {
142     { 855, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
143            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
144       "ibm855", "ibm855", "ibm855" },
145     { 866, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
146            MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
147            MIMECONTF_MIME_LATEST,
148       "cp866", "cp866", "cp866" },
149     { 878, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
150            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
151       "koi8-r", "koi8-r", "koi8-r" },
152     { 1251, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
153             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
154             MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
155       "windows-1251", "windows-1251", "windows-1251" },
156     { 10007, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
157              MIMECONTF_MIME_LATEST,
158       "x-mac-cyrillic", "x-mac-cyrillic", "x-mac-cyrillic" },
159     { 20866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
160              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
161              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
162              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
163       "koi8-r", "koi8-r", "koi8-r" },
164     { 28595, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
165              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
166              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
167              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
168       "iso-8859-5", "iso-8859-5", "iso-8859-5" }
169 };
170 static const MIME_CP_INFO greek_cp[] =
171 {
172     { 737, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
173            MIMECONTF_MIME_LATEST,
174       "ibm737", "ibm737", "ibm737" },
175     { 869, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
176            MIMECONTF_MIME_LATEST,
177       "ibm869", "ibm869", "ibm869" },
178     { 875, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
179            MIMECONTF_MIME_LATEST,
180       "cp875", "cp875", "cp875" },
181     { 1253, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
182             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
183             MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
184       "windows-1253", "windows-1253", "windows-1253" },
185     { 10006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
186              MIMECONTF_MIME_LATEST,
187       "x-mac-greek", "x-mac-greek", "x-mac-greek" },
188     { 28597, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
189              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
190              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
191              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
192       "iso-8859-7", "iso-8859-7", "iso-8859-7" }
193 };
194 static const MIME_CP_INFO hebrew_cp[] =
195 {
196     { 424, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
197            MIMECONTF_MIME_LATEST,
198       "ibm424", "ibm424", "ibm424" },
199     { 856, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
200            MIMECONTF_MIME_LATEST,
201       "cp856", "cp856", "cp856" },
202     { 862, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
203            MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
204            MIMECONTF_MIME_LATEST,
205       "dos-862", "dos-862", "dos-862" },
206     { 1255, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
207             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
208             MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
209       "windows-1255", "windows-1255", "windows-1255" },
210     { 28598, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
211              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
212              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
213       "iso-8859-8", "iso-8859-8", "iso-8859-8" }
214 };
215 static const MIME_CP_INFO japanese_cp[] =
216 {
217     { 932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
218            MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
219            MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
220            MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
221       "shift_jis", "iso-2022-jp", "iso-2022-jp" },
222     { 20932, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
223              MIMECONTF_MIME_LATEST,
224       "euc-jp", "euc-jp", "euc-jp" }
225 };
226 static const MIME_CP_INFO korean_cp[] =
227 {
228     { 949, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
229            MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
230            MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
231            MIMECONTF_MIME_LATEST,
232       "ks_c_5601-1987", "ks_c_5601-1987", "ks_c_5601-1987" }
233 };
234 static const MIME_CP_INFO thai_cp[] =
235 {
236     { 874, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_MIME_LATEST,
237       "ibm-thai", "ibm-thai", "ibm-thai" }
238 };
239 static const MIME_CP_INFO turkish_cp[] =
240 {
241     { 857, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
242            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
243       "ibm857", "ibm857", "ibm857" },
244     { 1026, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
245             MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
246       "ibm1026", "ibm1026", "ibm1026" },
247     { 1254, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
248             MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
249             MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
250             MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
251       "windows-1254", "windows-1254", "windows-1254" },
252     { 10081, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
253              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
254       "x-mac-turkish", "x-mac-turkish", "x-mac-turkish" },
255     { 28593, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
256              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
257              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
258       "iso-8859-3", "iso-8859-3", "iso-8859-3" },
259     { 28599, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
260              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
261              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
262              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
263       "iso-8859-9", "iso-8859-9", "iso-8859-9" }
264 };
265 static const MIME_CP_INFO vietnamese_cp[] =
266 {
267     { 1258, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
268             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
269             MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
270             MIMECONTF_MIME_LATEST,
271       "windows-1258", "windows-1258", "windows-1258" }
272 };
273 static const MIME_CP_INFO western_cp[] =
274 {
275     { 37, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
276           MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
277       "ibm037", "ibm037", "ibm037" },
278     { 437, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
279            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
280       "ibm437", "ibm437", "ibm437" },
281     { 500, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
282            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
283       "ibm500", "ibm500", "ibm500" },
284     { 850, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
285            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
286       "ibm850", "ibm850", "ibm850" },
287     { 860, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
288            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
289       "ibm860", "ibm860", "ibm860" },
290     { 861, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
291            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
292       "ibm861", "ibm861", "ibm861" },
293     { 863, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
294            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
295       "ibm863", "ibm863", "ibm863" },
296     { 865, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
297            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
298       "ibm865", "ibm865", "ibm865" },
299     { 1252, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
300             MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
301             MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
302             MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
303       "windows-1252", "windows-1252", "iso-8859-1" },
304     { 10000, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
305              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
306       "macintosh", "macintosh", "macintosh" },
307     { 10079, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
308              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
309       "x-mac-icelandic", "x-mac-icelandic", "x-mac-icelandic" },
310     { 28591, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
311              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
312              MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
313              MIMECONTF_MIME_LATEST,
314       "iso-8859-1", "iso-8859-1", "iso-8859-1" },
315     { 28605, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
316              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
317              MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
318              MIMECONTF_MIME_LATEST,
319       "iso-8859-15", "iso-8859-15", "iso-8859-15" }
320 };
321 static const MIME_CP_INFO unicode_cp[] =
322 {
323     { CP_UNICODE, MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
324                   MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
325                   MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
326                   MIMECONTF_MIME_LATEST,
327       "unicode", "unicode", "unicode" },
328     { CP_UTF7, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
329                MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
330                MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
331       "utf-7", "utf-7", "utf-7" },
332     { CP_UTF8, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
333                MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
334                MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
335                MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
336       "utf-8", "utf-8", "utf-8" }
337 };
338
339 static const struct mlang_data
340 {
341     LANGID langid;
342     UINT family_codepage;
343     UINT number_of_cp;
344     const MIME_CP_INFO *mime_cp_info;
345     const char *fixed_font; /* FIXME: Add */
346     const char *proportional_font; /* FIXME: Add */
347 } mlang_data[] =
348 {
349     { MAKELANGID(LANG_ARABIC,SUBLANG_DEFAULT),1256,sizeof(arabic_cp)/sizeof(arabic_cp[0]),arabic_cp },
350     /* FIXME */
351     { MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT),1257,sizeof(baltic_cp)/sizeof(baltic_cp[0]),baltic_cp },
352     { MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),936,sizeof(chinese_simplified_cp)/sizeof(chinese_simplified_cp[0]),chinese_simplified_cp },
353     { MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_TRADITIONAL),950,sizeof(chinese_traditional_cp)/sizeof(chinese_traditional_cp[0]),chinese_traditional_cp },
354     /* FIXME */
355     { MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT),1250,sizeof(central_european_cp)/sizeof(central_european_cp[0]),central_european_cp },
356     { MAKELANGID(LANG_RUSSIAN,SUBLANG_DEFAULT),1251,sizeof(cyrillic_cp)/sizeof(cyrillic_cp[0]),cyrillic_cp },
357     { MAKELANGID(LANG_GREEK,SUBLANG_DEFAULT),1253,sizeof(greek_cp)/sizeof(greek_cp[0]),greek_cp },
358     { MAKELANGID(LANG_HEBREW,SUBLANG_DEFAULT),1255,sizeof(hebrew_cp)/sizeof(hebrew_cp[0]),hebrew_cp },
359     { MAKELANGID(LANG_JAPANESE,SUBLANG_DEFAULT),932,sizeof(japanese_cp)/sizeof(japanese_cp[0]),japanese_cp },
360     { MAKELANGID(LANG_KOREAN,SUBLANG_DEFAULT),949,sizeof(korean_cp)/sizeof(korean_cp[0]),korean_cp },
361     { MAKELANGID(LANG_THAI,SUBLANG_DEFAULT),874,sizeof(thai_cp)/sizeof(thai_cp[0]),thai_cp },
362     { MAKELANGID(LANG_TURKISH,SUBLANG_DEFAULT),1254,sizeof(turkish_cp)/sizeof(turkish_cp[0]),turkish_cp },
363     { MAKELANGID(LANG_VIETNAMESE,SUBLANG_DEFAULT),1258,sizeof(vietnamese_cp)/sizeof(vietnamese_cp[0]),vietnamese_cp },
364     { MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT),1252,sizeof(western_cp)/sizeof(western_cp[0]),western_cp },
365     /* FIXME */
366     { MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT),CP_UNICODE,sizeof(unicode_cp)/sizeof(unicode_cp[0]),unicode_cp }
367 };
368
369 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info);
370
371 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
372 {
373     switch(fdwReason) {
374         case DLL_PROCESS_ATTACH:
375             DisableThreadLibraryCalls(hInstDLL);
376             break;
377         case DLL_PROCESS_DETACH:
378             break;
379     }
380     return TRUE;
381 }
382
383 /******************************************************************************
384  * MLANG ClassFactory
385  */
386 typedef struct {
387     IClassFactory ITF_IClassFactory;
388
389     DWORD ref;
390     HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
391 } IClassFactoryImpl;
392
393 struct object_creation_info
394 {
395     const CLSID *clsid;
396     LPCSTR szClassName;
397     HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
398 };
399
400 static const struct object_creation_info object_creation[] =
401 {
402     { &CLSID_CMultiLanguage, "CLSID_CMultiLanguage", MultiLanguage_create },
403 };
404
405 static HRESULT WINAPI
406 MLANGCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
407 {
408     ICOM_THIS(IClassFactoryImpl,iface);
409
410     TRACE("%s\n", debugstr_guid(riid) );
411
412     if (IsEqualGUID(riid, &IID_IUnknown)
413         || IsEqualGUID(riid, &IID_IClassFactory))
414     {
415         IClassFactory_AddRef(iface);
416         *ppobj = This;
417         return S_OK;
418     }
419
420     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
421     return E_NOINTERFACE;
422 }
423
424 static ULONG WINAPI MLANGCF_AddRef(LPCLASSFACTORY iface) {
425     ICOM_THIS(IClassFactoryImpl,iface);
426     return ++(This->ref);
427 }
428
429 static ULONG WINAPI MLANGCF_Release(LPCLASSFACTORY iface) {
430     ICOM_THIS(IClassFactoryImpl,iface);
431
432     ULONG ref = --This->ref;
433
434     if (ref == 0)
435     {
436         TRACE("Destroying %p\n", This);
437         HeapFree(GetProcessHeap(), 0, This);
438     }
439
440     return ref;
441 }
442
443 static HRESULT WINAPI MLANGCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter,
444                                           REFIID riid, LPVOID *ppobj) {
445     ICOM_THIS(IClassFactoryImpl,iface);
446     HRESULT hres;
447     LPUNKNOWN punk;
448     
449     TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
450
451     hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk);
452     if (FAILED(hres)) {
453         *ppobj = NULL;
454         return hres;
455     }
456     hres = IUnknown_QueryInterface(punk, riid, ppobj);
457     if (FAILED(hres)) {
458         *ppobj = NULL;
459         return hres;
460     }
461     IUnknown_Release(punk);
462     TRACE("returning (%p) -> %lx\n", *ppobj, hres);
463     return hres;
464 }
465
466 static HRESULT WINAPI MLANGCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
467     ICOM_THIS(IClassFactoryImpl,iface);
468     FIXME("(%p)->(%d),stub!\n",This,dolock);
469     return S_OK;
470 }
471
472 static ICOM_VTABLE(IClassFactory) MLANGCF_Vtbl =
473 {
474     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
475     MLANGCF_QueryInterface,
476     MLANGCF_AddRef,
477     MLANGCF_Release,
478     MLANGCF_CreateInstance,
479     MLANGCF_LockServer
480 };
481
482 HRESULT WINAPI MLANG_DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
483 {
484     int i;
485     IClassFactoryImpl *factory;
486
487     TRACE("%s %s %p\n",debugstr_guid(rclsid), debugstr_guid(iid), ppv);
488
489     if ( !IsEqualGUID( &IID_IClassFactory, iid )
490          && ! IsEqualGUID( &IID_IUnknown, iid) )
491         return E_NOINTERFACE;
492
493     for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
494     {
495         if (IsEqualGUID(object_creation[i].clsid, rclsid))
496             break;
497     }
498
499     if (i == sizeof(object_creation)/sizeof(object_creation[0]))
500     {
501         FIXME("%s: no class found.\n", debugstr_guid(rclsid));
502         return CLASS_E_CLASSNOTAVAILABLE;
503     }
504
505     TRACE("Creating a class factory for %s\n",object_creation[i].szClassName);
506
507     factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));
508     if (factory == NULL) return E_OUTOFMEMORY;
509
510     factory->ITF_IClassFactory.lpVtbl = &MLANGCF_Vtbl;
511     factory->ref = 1;
512
513     factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
514
515     *ppv = &(factory->ITF_IClassFactory);
516
517     TRACE("(%p) <- %p\n", ppv, &(factory->ITF_IClassFactory) );
518
519     return S_OK;
520 }
521
522
523 /******************************************************************************/
524
525 typedef struct tagMLang_impl
526 {
527     ICOM_VTABLE(IMLangFontLink) *vtbl_IMLangFontLink;
528     ICOM_VTABLE(IMultiLanguage) *vtbl_IMultiLanguage;
529     ICOM_VTABLE(IMultiLanguage2) *vtbl_IMultiLanguage2;
530     DWORD ref;
531     DWORD total;
532 } MLang_impl;
533
534 static ULONG WINAPI MLang_AddRef( MLang_impl* This)
535 {
536     return ++(This->ref);
537 }
538
539 static ULONG WINAPI MLang_Release( MLang_impl* This )
540 {
541     ULONG ref = --This->ref;
542
543     TRACE("%p ref = %ld\n", This, ref);
544     if (ref == 0)
545     {
546         TRACE("Destroying %p\n", This);
547         HeapFree(GetProcessHeap(), 0, This);
548     }
549
550     return ref;
551 }
552
553 static HRESULT WINAPI MLang_QueryInterface(
554         MLang_impl* This,
555         REFIID riid,
556         void** ppvObject)
557 {
558     TRACE("%p -> %s\n", This, debugstr_guid(riid) );
559
560     if (IsEqualGUID(riid, &IID_IUnknown)
561         || IsEqualGUID(riid, &IID_IMLangCodePages)
562         || IsEqualGUID(riid, &IID_IMLangFontLink))
563     {
564         MLang_AddRef(This);
565         TRACE("Returning IID_IMLangFontLink %p ref = %ld\n", This, This->ref);
566         *ppvObject = &(This->vtbl_IMLangFontLink);
567         return S_OK;
568     }
569
570     if (IsEqualGUID(riid, &IID_IMultiLanguage) )
571     {
572         MLang_AddRef(This);
573         TRACE("Returning IID_IMultiLanguage %p ref = %ld\n", This, This->ref);
574         *ppvObject = &(This->vtbl_IMultiLanguage);
575         return S_OK;
576     }
577
578     if (IsEqualGUID(riid, &IID_IMultiLanguage2) )
579     {
580         MLang_AddRef(This);
581         *ppvObject = &(This->vtbl_IMultiLanguage2);
582         TRACE("Returning IID_IMultiLanguage2 %p ref = %ld\n", This, This->ref);
583         return S_OK;
584     }
585
586     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
587     return E_NOINTERFACE;
588 }
589
590 /******************************************************************************/
591
592 typedef struct tagEnumCodePage_impl
593 {
594     ICOM_VTABLE(IEnumCodePage) *vtbl_IEnumCodePage;
595     DWORD ref;
596     MIMECPINFO *cpinfo;
597     DWORD total, pos;
598 } EnumCodePage_impl;
599
600 static HRESULT WINAPI fnIEnumCodePage_QueryInterface(
601         IEnumCodePage* iface,
602         REFIID riid,
603         void** ppvObject)
604 {
605     ICOM_THIS_MULTI(EnumCodePage_impl, vtbl_IEnumCodePage, iface);
606
607     TRACE("%p -> %s\n", This, debugstr_guid(riid) );
608
609     if (IsEqualGUID(riid, &IID_IUnknown)
610         || IsEqualGUID(riid, &IID_IEnumCodePage))
611     {
612         IEnumCodePage_AddRef(iface);
613         TRACE("Returning IID_IEnumCodePage %p ref = %ld\n", This, This->ref);
614         *ppvObject = &(This->vtbl_IEnumCodePage);
615         return S_OK;
616     }
617
618     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
619     return E_NOINTERFACE;
620 }
621
622 static ULONG WINAPI fnIEnumCodePage_AddRef(
623         IEnumCodePage* iface)
624 {
625     ICOM_THIS_MULTI(EnumCodePage_impl, vtbl_IEnumCodePage, iface);
626     return ++(This->ref);
627 }
628
629 static ULONG WINAPI fnIEnumCodePage_Release(
630         IEnumCodePage* iface)
631 {
632     ICOM_THIS_MULTI(EnumCodePage_impl, vtbl_IEnumCodePage, iface);
633     ULONG ref = --This->ref;
634
635     TRACE("%p ref = %ld\n", This, ref);
636     if (ref == 0)
637     {
638         TRACE("Destroying %p\n", This);
639         HeapFree(GetProcessHeap(), 0, This->cpinfo);
640         HeapFree(GetProcessHeap(), 0, This);
641     }
642
643     return ref;
644 }
645
646 static HRESULT WINAPI fnIEnumCodePage_Clone(
647         IEnumCodePage* iface,
648         IEnumCodePage** ppEnum)
649 {
650     ICOM_THIS_MULTI(EnumCodePage_impl, vtbl_IEnumCodePage, iface);
651     FIXME("%p %p\n", This, ppEnum);
652     return E_NOTIMPL;
653 }
654
655 static  HRESULT WINAPI fnIEnumCodePage_Next(
656         IEnumCodePage* iface,
657         ULONG celt,
658         PMIMECPINFO rgelt,
659         ULONG* pceltFetched)
660 {
661     ICOM_THIS_MULTI(EnumCodePage_impl, vtbl_IEnumCodePage, iface);
662     TRACE("%p %lu %p %p\n", This, celt, rgelt, pceltFetched);
663
664     if (!pceltFetched) return S_FALSE;
665     *pceltFetched = 0;
666
667     if (!rgelt) return S_FALSE;
668
669     if (This->pos + celt > This->total)
670         celt = This->total - This->pos;
671
672     if (!celt) return S_FALSE;
673
674     memcpy(rgelt, This->cpinfo + This->pos, celt * sizeof(MIMECPINFO));
675     *pceltFetched = celt;
676     This->pos += celt;
677
678     return S_OK;
679 }
680
681 static HRESULT WINAPI fnIEnumCodePage_Reset(
682         IEnumCodePage* iface)
683 {
684     ICOM_THIS_MULTI(EnumCodePage_impl, vtbl_IEnumCodePage, iface);
685     TRACE("%p\n", This);
686
687     This->pos = 0;
688     return S_OK;
689 }
690
691 static  HRESULT WINAPI fnIEnumCodePage_Skip(
692         IEnumCodePage* iface,
693         ULONG celt)
694 {
695     ICOM_THIS_MULTI(EnumCodePage_impl, vtbl_IEnumCodePage, iface);
696     TRACE("%p %lu\n", This, celt);
697
698     if (celt >= This->total) return S_FALSE;
699
700     This->pos = celt;  /* FIXME: should be += ?? */
701     return S_OK;
702 }
703
704 static ICOM_VTABLE(IEnumCodePage) IEnumCodePage_vtbl =
705 {
706     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
707     fnIEnumCodePage_QueryInterface,
708     fnIEnumCodePage_AddRef,
709     fnIEnumCodePage_Release,
710     fnIEnumCodePage_Clone,
711     fnIEnumCodePage_Next,
712     fnIEnumCodePage_Reset,
713     fnIEnumCodePage_Skip
714 };
715
716 static HRESULT EnumCodePage_create( MLang_impl* mlang, DWORD grfFlags,
717                      LANGID LangId, IEnumCodePage** ppEnumCodePage )
718 {
719     EnumCodePage_impl *ecp;
720     MIMECPINFO *cpinfo;
721     UINT i, n;
722
723     TRACE("%p, %08lx, %04x, %p\n", mlang, grfFlags, LangId, ppEnumCodePage);
724
725     if (!grfFlags) /* enumerate internal data base of encodings */
726         grfFlags = MIMECONTF_MIME_LATEST;
727
728     ecp = HeapAlloc( GetProcessHeap(), 0, sizeof (EnumCodePage_impl) );
729     ecp->vtbl_IEnumCodePage = &IEnumCodePage_vtbl;
730     ecp->ref = 1;
731     ecp->total = 0;
732     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
733     {
734         for (n = 0; n < mlang_data[i].number_of_cp; n++)
735         {
736             if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
737                 ecp->total++;
738         }
739     }
740
741     ecp->cpinfo = HeapAlloc(GetProcessHeap(), 0,
742                             sizeof(MIMECPINFO) * ecp->total);
743     cpinfo = ecp->cpinfo;
744
745     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
746     {
747         for (n = 0; n < mlang_data[i].number_of_cp; n++)
748         {
749             if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
750                 fill_cp_info(&mlang_data[i], n, cpinfo++);
751         }
752     }
753
754     TRACE("enumerated %ld codepages with flags %08lx\n", ecp->total, grfFlags);
755
756     *ppEnumCodePage = (IEnumCodePage*) ecp;
757
758     return S_OK;
759 }
760
761 /******************************************************************************/
762
763 static HRESULT WINAPI fnIMLangFontLink_QueryInterface(
764         IMLangFontLink* iface,
765         REFIID riid,
766         void** ppvObject)
767 {
768     ICOM_THIS_MULTI(MLang_impl, vtbl_IMLangFontLink, iface);
769     return MLang_QueryInterface( This, riid, ppvObject );
770 }
771
772 static ULONG WINAPI fnIMLangFontLink_AddRef(
773         IMLangFontLink* iface)
774 {
775     ICOM_THIS_MULTI(MLang_impl, vtbl_IMLangFontLink, iface);
776     return MLang_AddRef( This );
777 }
778
779 static ULONG WINAPI fnIMLangFontLink_Release(
780         IMLangFontLink* iface)
781 {
782     ICOM_THIS_MULTI(MLang_impl, vtbl_IMLangFontLink, iface);
783     return MLang_Release( This );
784 }
785
786 static HRESULT WINAPI fnIMLangFontLink_GetCharCodePages(
787         IMLangFontLink* iface,
788         WCHAR chSrc,
789         DWORD* pdwCodePages)
790 {
791     FIXME("\n");
792     return E_NOTIMPL;
793 }
794
795 static HRESULT WINAPI fnIMLangFontLink_GetStrCodePages(
796         IMLangFontLink* iface,
797         const WCHAR* pszSrc,
798         long cchSrc,
799         DWORD dwPriorityCodePages,
800         DWORD* pdwCodePages,
801         long* pcchCodePages)
802 {
803     FIXME("\n");
804     return E_NOTIMPL;
805 }
806
807 static HRESULT WINAPI fnIMLangFontLink_CodePageToCodePages(
808         IMLangFontLink* iface,
809         UINT uCodePage,
810         DWORD* pdwCodePages)
811 {
812     FIXME("\n");
813     return E_NOTIMPL;
814 }
815
816 static HRESULT WINAPI fnIMLangFontLink_CodePagesToCodePage(
817         IMLangFontLink* iface,
818         DWORD dwCodePages,
819         UINT uDefaultCodePage,
820         UINT* puCodePage)
821 {
822     FIXME("\n");
823     return E_NOTIMPL;
824 }
825
826 static HRESULT WINAPI fnIMLangFontLink_GetFontCodePages(
827         IMLangFontLink* iface,
828         HDC hDC,
829         HFONT hFont,
830         DWORD* pdwCodePages)
831 {
832     FIXME("\n");
833     return E_NOTIMPL;
834 }
835
836 static HRESULT WINAPI fnIMLangFontLink_MapFont(
837         IMLangFontLink* iface,
838         HDC hDC,
839         DWORD dwCodePages,
840         HFONT hSrcFont,
841         HFONT* phDestFont)
842 {
843     FIXME("\n");
844     return E_NOTIMPL;
845 }
846
847 static HRESULT WINAPI fnIMLangFontLink_ReleaseFont(
848         IMLangFontLink* iface,
849         HFONT hFont)
850 {
851     FIXME("\n");
852     return E_NOTIMPL;
853 }
854
855 static HRESULT WINAPI fnIMLangFontLink_ResetFontMapping(
856         IMLangFontLink* iface)
857 {
858     FIXME("\n");
859     return E_NOTIMPL;
860 }
861
862
863 static ICOM_VTABLE(IMLangFontLink) IMLangFontLink_vtbl =
864 {
865     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
866     fnIMLangFontLink_QueryInterface,
867     fnIMLangFontLink_AddRef,
868     fnIMLangFontLink_Release,
869     fnIMLangFontLink_GetCharCodePages,
870     fnIMLangFontLink_GetStrCodePages,
871     fnIMLangFontLink_CodePageToCodePages,
872     fnIMLangFontLink_CodePagesToCodePage,
873     fnIMLangFontLink_GetFontCodePages,
874     fnIMLangFontLink_MapFont,
875     fnIMLangFontLink_ReleaseFont,
876     fnIMLangFontLink_ResetFontMapping,
877 };
878
879 /******************************************************************************/
880
881 static HRESULT WINAPI fnIMultiLanguage_QueryInterface(
882     IMultiLanguage* iface,
883     REFIID riid,
884     void** ppvObject)
885 {
886     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage, iface);
887     return MLang_QueryInterface( This, riid, ppvObject );
888 }
889
890 static ULONG WINAPI fnIMultiLanguage_AddRef( IMultiLanguage* iface )
891 {
892     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage, iface);
893     return IMLangFontLink_AddRef( ((IMLangFontLink*)This) );
894 }
895
896 static ULONG WINAPI fnIMultiLanguage_Release( IMultiLanguage* iface )
897 {
898     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage, iface);
899     return IMLangFontLink_Release( ((IMLangFontLink*)This) );
900 }
901
902 static HRESULT WINAPI fnIMultiLanguage_GetNumberOfCodePageInfo(
903     IMultiLanguage* iface,
904     UINT* pcCodePage)
905 {
906     FIXME("\n");
907     return E_NOTIMPL;
908 }
909
910 static HRESULT WINAPI fnIMultiLanguage_GetCodePageInfo(
911     IMultiLanguage* iface,
912     UINT uiCodePage,
913     PMIMECPINFO pCodePageInfo)
914 {
915     FIXME("\n");
916     return E_NOTIMPL;
917 }
918
919 static HRESULT WINAPI fnIMultiLanguage_GetFamilyCodePage(
920     IMultiLanguage* iface,
921     UINT uiCodePage,
922     UINT* puiFamilyCodePage)
923 {
924     FIXME("\n");
925     return E_NOTIMPL;
926 }
927
928 static HRESULT WINAPI fnIMultiLanguage_EnumCodePages(
929     IMultiLanguage* iface,
930     DWORD grfFlags,
931     IEnumCodePage** ppEnumCodePage)
932 {
933     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage, iface);
934     TRACE("%p %08lx %p\n", This, grfFlags, ppEnumCodePage);
935
936     return EnumCodePage_create( This, grfFlags, 0, ppEnumCodePage );
937 }
938
939 static HRESULT WINAPI fnIMultiLanguage_GetCharsetInfo(
940     IMultiLanguage* iface,
941     BSTR Charset,
942     PMIMECSETINFO pCharsetInfo)
943 {
944     FIXME("\n");
945     return E_NOTIMPL;
946 }
947
948 static HRESULT WINAPI fnIMultiLanguage_IsConvertible(
949     IMultiLanguage* iface,
950     DWORD dwSrcEncoding,
951     DWORD dwDstEncoding)
952 {
953     FIXME("\n");
954     return E_NOTIMPL;
955 }
956
957 static HRESULT WINAPI fnIMultiLanguage_ConvertString(
958     IMultiLanguage* iface,
959     DWORD* pdwMode,
960     DWORD dwSrcEncoding,
961     DWORD dwDstEncoding,
962     BYTE* pSrcStr,
963     UINT* pcSrcSize,
964     BYTE* pDstStr,
965     UINT* pcDstSize)
966 {
967     FIXME("\n");
968     return E_NOTIMPL;
969 }
970
971 static HRESULT WINAPI fnIMultiLanguage_ConvertStringToUnicode(
972     IMultiLanguage* iface,
973     DWORD* pdwMode,
974     DWORD dwEncoding,
975     CHAR* pSrcStr,
976     UINT* pcSrcSize,
977     WCHAR* pDstStr,
978     UINT* pcDstSize)
979 {
980     FIXME("\n");
981     return E_NOTIMPL;
982 }
983
984 static HRESULT WINAPI fnIMultiLanguage_ConvertStringFromUnicode(
985     IMultiLanguage* iface,
986     DWORD* pdwMode,
987     DWORD dwEncoding,
988     WCHAR* pSrcStr,
989     UINT* pcSrcSize,
990     CHAR* pDstStr,
991     UINT* pcDstSize)
992 {
993     FIXME("\n");
994     return E_NOTIMPL;
995 }
996
997 static HRESULT WINAPI fnIMultiLanguage_ConvertStringReset(
998     IMultiLanguage* iface)
999 {
1000     FIXME("\n");
1001     return E_NOTIMPL;
1002 }
1003
1004 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766FromLcid(
1005     IMultiLanguage* iface,
1006     LCID Locale,
1007     BSTR* pbstrRfc1766)
1008 {
1009     FIXME("\n");
1010     return E_NOTIMPL;
1011 }
1012
1013 static HRESULT WINAPI fnIMultiLanguage_GetLcidFromRfc1766(
1014     IMultiLanguage* iface,
1015     LCID* pLocale,
1016     BSTR bstrRfc1766)
1017 {
1018     FIXME("\n");
1019     return E_NOTIMPL;
1020 }
1021
1022 static HRESULT WINAPI fnIMultiLanguage_EnumRfc1766(
1023     IMultiLanguage* iface,
1024     IEnumRfc1766** ppEnumRfc1766)
1025 {
1026     FIXME("\n");
1027     return E_NOTIMPL;
1028 }
1029
1030 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766Info(
1031     IMultiLanguage* iface,
1032     LCID Locale,
1033     PRFC1766INFO pRfc1766Info)
1034 {
1035     FIXME("\n");
1036     return E_NOTIMPL;
1037 }
1038
1039 static HRESULT WINAPI fnIMultiLanguage_CreateConvertCharset(
1040     IMultiLanguage* iface,
1041     UINT uiSrcCodePage,
1042     UINT uiDstCodePage,
1043     DWORD dwProperty,
1044     IMLangConvertCharset** ppMLangConvertCharset)
1045 {
1046     FIXME("\n");
1047     return E_NOTIMPL;
1048 }
1049
1050 static ICOM_VTABLE(IMultiLanguage) IMultiLanguage_vtbl =
1051 {
1052     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1053     fnIMultiLanguage_QueryInterface,
1054     fnIMultiLanguage_AddRef,
1055     fnIMultiLanguage_Release,
1056     fnIMultiLanguage_GetNumberOfCodePageInfo,
1057     fnIMultiLanguage_GetCodePageInfo,
1058     fnIMultiLanguage_GetFamilyCodePage,
1059     fnIMultiLanguage_EnumCodePages,
1060     fnIMultiLanguage_GetCharsetInfo,
1061     fnIMultiLanguage_IsConvertible,
1062     fnIMultiLanguage_ConvertString,
1063     fnIMultiLanguage_ConvertStringToUnicode,
1064     fnIMultiLanguage_ConvertStringFromUnicode,
1065     fnIMultiLanguage_ConvertStringReset,
1066     fnIMultiLanguage_GetRfc1766FromLcid,
1067     fnIMultiLanguage_GetLcidFromRfc1766,
1068     fnIMultiLanguage_EnumRfc1766,
1069     fnIMultiLanguage_GetRfc1766Info,
1070     fnIMultiLanguage_CreateConvertCharset,
1071 };
1072
1073
1074 /******************************************************************************/
1075
1076 static HRESULT WINAPI fnIMultiLanguage2_QueryInterface(
1077     IMultiLanguage2* iface,
1078     REFIID riid,
1079     void** ppvObject)
1080 {
1081     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage2, iface);
1082     return MLang_QueryInterface( This, riid, ppvObject );
1083 }
1084
1085 static ULONG WINAPI fnIMultiLanguage2_AddRef( IMultiLanguage2* iface )
1086 {
1087     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage2, iface);
1088     return MLang_AddRef( This );
1089 }
1090
1091 static ULONG WINAPI fnIMultiLanguage2_Release( IMultiLanguage2* iface )
1092 {
1093     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage2, iface);
1094     return MLang_Release( This );
1095 }
1096
1097 static HRESULT WINAPI fnIMultiLanguage2_GetNumberOfCodePageInfo(
1098     IMultiLanguage2* iface,
1099     UINT* pcCodePage)
1100 {
1101     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage2, iface);
1102     TRACE("%p, %p\n", This, pcCodePage);
1103
1104     if (!pcCodePage) return S_FALSE;
1105
1106     *pcCodePage = This->total;
1107     return S_OK;
1108 }
1109
1110 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info)
1111 {
1112     CPINFOEXW cpinfo;
1113     CHARSETINFO csi;
1114     LOGFONTW lf;
1115
1116     if (TranslateCharsetInfo((DWORD *)ml_data->family_codepage, &csi, TCI_SRCCODEPAGE))
1117         mime_cp_info->bGDICharset = csi.ciCharset;
1118     else
1119         mime_cp_info->bGDICharset = DEFAULT_CHARSET;
1120
1121     if (!GetCPInfoExW(ml_data->mime_cp_info[index].cp, 0, &cpinfo))
1122     {
1123         /* fall back to family codepage in the case of alias */
1124         if (!GetCPInfoExW(ml_data->family_codepage, 0, &cpinfo))
1125             cpinfo.CodePageName[0] = 0;
1126     }
1127
1128     mime_cp_info->dwFlags = ml_data->mime_cp_info[index].flags;
1129     mime_cp_info->uiCodePage = ml_data->mime_cp_info[index].cp;
1130     mime_cp_info->uiFamilyCodePage = ml_data->family_codepage;
1131     strcpyW(mime_cp_info->wszDescription, cpinfo.CodePageName);
1132     MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].web_charset, -1,
1133                         mime_cp_info->wszWebCharset, sizeof(mime_cp_info->wszWebCharset)/sizeof(WCHAR));
1134     MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].header_charset, -1,
1135                         mime_cp_info->wszHeaderCharset, sizeof(mime_cp_info->wszHeaderCharset)/sizeof(WCHAR));
1136     MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].body_charset, -1,
1137                         mime_cp_info->wszBodyCharset, sizeof(mime_cp_info->wszBodyCharset)/sizeof(WCHAR));
1138
1139     /* FIXME */
1140     GetObjectW(GetStockObject(SYSTEM_FIXED_FONT), sizeof(lf), &lf);
1141     strcpyW(mime_cp_info->wszFixedWidthFont, lf.lfFaceName);
1142     /* FIXME */
1143     GetObjectW(GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf);
1144     strcpyW(mime_cp_info->wszProportionalFont, lf.lfFaceName);
1145 }
1146
1147 static HRESULT WINAPI fnIMultiLanguage2_GetCodePageInfo(
1148     IMultiLanguage2* iface,
1149     UINT uiCodePage,
1150     LANGID LangId,
1151     PMIMECPINFO pCodePageInfo)
1152 {
1153     UINT i, n;
1154
1155     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage2, iface);
1156     TRACE("%p, %u, %04x, %p\n", This, uiCodePage, LangId, pCodePageInfo);
1157
1158     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
1159     {
1160         for (n = 0; n < mlang_data[i].number_of_cp; n++)
1161         {
1162             if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
1163             {
1164                 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
1165                 return S_OK;
1166             }
1167         }
1168     }
1169
1170     return S_FALSE;
1171 }
1172
1173 static HRESULT WINAPI fnIMultiLanguage2_GetFamilyCodePage(
1174     IMultiLanguage2* iface,
1175     UINT uiCodePage,
1176     UINT* puiFamilyCodePage)
1177 {
1178     UINT i, n;
1179
1180     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage2, iface);
1181     TRACE("%p %d %p\n", This, uiCodePage, puiFamilyCodePage);
1182
1183     if (!puiFamilyCodePage) return S_FALSE;
1184
1185     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
1186     {
1187         for (n = 0; n < mlang_data[i].number_of_cp; n++)
1188         {
1189             if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
1190             {
1191                 *puiFamilyCodePage = mlang_data[i].family_codepage;
1192                 return S_OK;
1193             }
1194         }
1195     }
1196
1197     return S_FALSE;
1198 }
1199
1200 static HRESULT WINAPI fnIMultiLanguage2_EnumCodePages(
1201     IMultiLanguage2* iface,
1202     DWORD grfFlags,
1203     LANGID LangId,
1204     IEnumCodePage** ppEnumCodePage)
1205 {
1206     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage2, iface);
1207     TRACE("%p %08lx %04x %p\n", This, grfFlags, LangId, ppEnumCodePage);
1208
1209     return EnumCodePage_create( This, grfFlags, LangId, ppEnumCodePage );
1210 }
1211
1212 static HRESULT WINAPI fnIMultiLanguage2_GetCharsetInfo(
1213     IMultiLanguage2* iface,
1214     BSTR Charset,
1215     PMIMECSETINFO pCharsetInfo)
1216 {
1217     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage2, iface);
1218     FIXME("%p %s %p\n", This, debugstr_w(Charset), pCharsetInfo);
1219     return E_NOTIMPL;
1220 }
1221
1222 static HRESULT WINAPI fnIMultiLanguage2_IsConvertible(
1223     IMultiLanguage2* iface,
1224     DWORD dwSrcEncoding,
1225     DWORD dwDstEncoding)
1226 {
1227     UINT src_family, dst_family;
1228
1229     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage2, iface);
1230     TRACE("%p %ld %ld\n", This, dwSrcEncoding, dwDstEncoding);
1231
1232     if (fnIMultiLanguage2_GetFamilyCodePage(iface, dwSrcEncoding, &src_family) != S_OK ||
1233         fnIMultiLanguage2_GetFamilyCodePage(iface, dwDstEncoding, &dst_family) != S_OK)
1234         return S_FALSE;
1235
1236     if (src_family == dst_family) return S_OK;
1237
1238     /* we can convert any codepage to/from unicode */
1239     if (src_family == CP_UNICODE || dst_family == CP_UNICODE) return S_OK;
1240
1241     return S_FALSE;
1242 }
1243
1244 static HRESULT WINAPI fnIMultiLanguage2_ConvertString(
1245     IMultiLanguage2* iface,
1246     DWORD* pdwMode,
1247     DWORD dwSrcEncoding,
1248     DWORD dwDstEncoding,
1249     BYTE* pSrcStr,
1250     UINT* pcSrcSize,
1251     BYTE* pDstStr,
1252     UINT* pcDstSize)
1253 {
1254     FIXME("\n");
1255     return E_NOTIMPL;
1256 }
1257
1258 static HRESULT WINAPI fnIMultiLanguage2_ConvertStringToUnicode(
1259     IMultiLanguage2* iface,
1260     DWORD* pdwMode,
1261     DWORD dwEncoding,
1262     CHAR* pSrcStr,
1263     UINT* pcSrcSize,
1264     WCHAR* pDstStr,
1265     UINT* pcDstSize)
1266 {
1267     INT src_len = -1;
1268
1269     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage2, iface);
1270     TRACE("%p %p %ld %s %p %p %p\n", This, pdwMode, dwEncoding,
1271           debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
1272
1273     if (!pcDstSize)
1274         return E_FAIL;
1275
1276     if (!pcSrcSize)
1277         pcSrcSize = &src_len;
1278
1279     if (!*pcSrcSize)
1280     {
1281         *pcDstSize = 0;
1282         return S_OK;
1283     }
1284
1285     switch (dwEncoding)
1286     {
1287     case CP_UNICODE:
1288         if (*pcSrcSize == -1)
1289             *pcSrcSize = lstrlenW((LPCWSTR)pSrcStr);
1290         *pcDstSize = min(*pcSrcSize, *pcDstSize);
1291         *pcSrcSize *= sizeof(WCHAR);
1292         memmove(pDstStr, pSrcStr, *pcDstSize * sizeof(WCHAR));
1293         break;
1294
1295     default:
1296         if (*pcSrcSize == -1)
1297             *pcSrcSize = lstrlenA(pSrcStr);
1298
1299         *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, pDstStr, *pcDstSize);
1300         break;
1301     }
1302     
1303     if (!*pcDstSize)
1304         return E_FAIL;
1305
1306     return S_OK;
1307 }
1308
1309 static HRESULT WINAPI fnIMultiLanguage2_ConvertStringFromUnicode(
1310     IMultiLanguage2* iface,
1311     DWORD* pdwMode,
1312     DWORD dwEncoding,
1313     WCHAR* pSrcStr,
1314     UINT* pcSrcSize,
1315     CHAR* pDstStr,
1316     UINT* pcDstSize)
1317 {
1318     INT src_len = -1;
1319
1320     ICOM_THIS_MULTI(MLang_impl, vtbl_IMultiLanguage2, iface);
1321     TRACE("%p %p %ld %s %p %p %p\n", This, pdwMode, dwEncoding,
1322           debugstr_w(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
1323
1324     if (!pcDstSize)
1325         return E_FAIL;
1326
1327     if (!pcSrcSize)
1328         pcSrcSize = &src_len;
1329
1330     if (!*pcSrcSize)
1331     {
1332         *pcDstSize = 0;
1333         return S_OK;
1334     }
1335
1336     switch (dwEncoding)
1337     {
1338     case CP_UNICODE:
1339         if (*pcSrcSize == -1)
1340             *pcSrcSize = lstrlenW(pSrcStr);
1341         *pcDstSize = min(*pcSrcSize * sizeof(WCHAR), *pcDstSize);
1342         memmove(pDstStr, pSrcStr, *pcDstSize);
1343         break;
1344
1345     default:
1346         if (*pcSrcSize == -1)
1347             *pcSrcSize = lstrlenW(pSrcStr);
1348
1349         *pcDstSize = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize, pDstStr, *pcDstSize, NULL, NULL);
1350         break;
1351     }
1352
1353
1354     if (!*pcDstSize)
1355         return E_FAIL;
1356
1357     return S_OK;
1358 }
1359
1360 static HRESULT WINAPI fnIMultiLanguage2_ConvertStringReset(
1361     IMultiLanguage2* iface)
1362 {
1363     FIXME("\n");
1364     return E_NOTIMPL;
1365 }
1366
1367 static HRESULT WINAPI fnIMultiLanguage2_GetRfc1766FromLcid(
1368     IMultiLanguage2* iface,
1369     LCID Locale,
1370     BSTR* pbstrRfc1766)
1371 {
1372     FIXME("\n");
1373     return E_NOTIMPL;
1374 }
1375
1376 static HRESULT WINAPI fnIMultiLanguage2_GetLcidFromRfc1766(
1377     IMultiLanguage2* iface,
1378     LCID* pLocale,
1379     BSTR bstrRfc1766)
1380 {
1381     FIXME("\n");
1382     return E_NOTIMPL;
1383 }
1384
1385 static HRESULT WINAPI fnIMultiLanguage2_EnumRfc1766(
1386     IMultiLanguage2* iface,
1387     LANGID LangId,
1388     IEnumRfc1766** ppEnumRfc1766)
1389 {
1390     FIXME("\n");
1391     return E_NOTIMPL;
1392 }
1393
1394 static HRESULT WINAPI fnIMultiLanguage2_GetRfc1766Info(
1395     IMultiLanguage2* iface,
1396     LCID Locale,
1397     LANGID LangId,
1398     PRFC1766INFO pRfc1766Info)
1399 {
1400     FIXME("\n");
1401     return E_NOTIMPL;
1402 }
1403
1404 static HRESULT WINAPI fnIMultiLanguage2_CreateConvertCharset(
1405     IMultiLanguage2* iface,
1406     UINT uiSrcCodePage,
1407     UINT uiDstCodePage,
1408     DWORD dwProperty,
1409     IMLangConvertCharset** ppMLangConvertCharset)
1410 {
1411     FIXME("\n");
1412     return E_NOTIMPL;
1413 }
1414
1415 static HRESULT WINAPI fnIMultiLanguage2_ConvertStringInIStream(
1416     IMultiLanguage2* iface,
1417     DWORD* pdwMode,
1418     DWORD dwFlag,
1419     WCHAR* lpFallBack,
1420     DWORD dwSrcEncoding,
1421     DWORD dwDstEncoding,
1422     IStream* pstmIn,
1423     IStream* pstmOut)
1424 {
1425     FIXME("\n");
1426     return E_NOTIMPL;
1427 }
1428
1429 static HRESULT WINAPI fnIMultiLanguage2_ConvertStringToUnicodeEx(
1430     IMultiLanguage2* iface,
1431     DWORD* pdwMode,
1432     DWORD dwEncoding,
1433     CHAR* pSrcStr,
1434     UINT* pcSrcSize,
1435     WCHAR* pDstStr,
1436     UINT* pcDstSize,
1437     DWORD dwFlag,
1438     WCHAR* lpFallBack)
1439 {
1440     FIXME("\n");
1441     return E_NOTIMPL;
1442 }
1443
1444 static HRESULT WINAPI fnIMultiLanguage2_DetectCodepageInIStream(
1445     IMultiLanguage2* iface,
1446     DWORD dwFlag,
1447     DWORD dwPrefWinCodePage,
1448     IStream* pstmIn,
1449     DetectEncodingInfo* lpEncoding,
1450     INT* pnScores)
1451 {
1452     FIXME("\n");
1453     return E_NOTIMPL;
1454 }
1455
1456 static HRESULT WINAPI fnIMultiLanguage2_DetectInputCodepage(
1457     IMultiLanguage2* iface,
1458     DWORD dwFlag,
1459     DWORD dwPrefWinCodePage,
1460     CHAR* pSrcStr,
1461     INT* pcSrcSize,
1462     DetectEncodingInfo* lpEncoding,
1463     INT* pnScores)
1464 {
1465     FIXME("\n");
1466     return E_NOTIMPL;
1467 }
1468
1469 static HRESULT WINAPI fnIMultiLanguage2_ValidateCodePage(
1470     IMultiLanguage2* iface,
1471     UINT uiCodePage,
1472     HWND hwnd)
1473 {
1474     FIXME("\n");
1475     return E_NOTIMPL;
1476 }
1477
1478 static HRESULT WINAPI fnIMultiLanguage2_GetCodePageDescription(
1479     IMultiLanguage2* iface,
1480     UINT uiCodePage,
1481     LCID lcid,
1482     LPWSTR lpWideCharStr,
1483     int cchWideChar)
1484 {
1485     FIXME("\n");
1486     return E_NOTIMPL;
1487 }
1488
1489 static HRESULT WINAPI fnIMultiLanguage2_IsCodePageInstallable(
1490     IMultiLanguage2* iface,
1491     UINT uiCodePage)
1492 {
1493     FIXME("\n");
1494     return E_NOTIMPL;
1495 }
1496
1497 static HRESULT WINAPI fnIMultiLanguage2_SetMimeDBSource(
1498     IMultiLanguage2* iface,
1499     MIMECONTF dwSource)
1500 {
1501     FIXME("\n");
1502     return E_NOTIMPL;
1503 }
1504
1505 static HRESULT WINAPI fnIMultiLanguage2_GetNumberOfScripts(
1506     IMultiLanguage2* iface,
1507     UINT* pnScripts)
1508 {
1509     FIXME("\n");
1510     return E_NOTIMPL;
1511 }
1512
1513 static HRESULT WINAPI fnIMultiLanguage2_EnumScripts(
1514     IMultiLanguage2* iface,
1515     DWORD dwFlags,
1516     LANGID LangId,
1517     IEnumScript** ppEnumScript)
1518 {
1519     FIXME("\n");
1520     return E_NOTIMPL;
1521 }
1522
1523 static HRESULT WINAPI fnIMultiLanguage2_ValidateCodePageEx(
1524     IMultiLanguage2* iface,
1525     UINT uiCodePage,
1526     HWND hwnd,
1527     DWORD dwfIODControl)
1528 {
1529     FIXME("\n");
1530     return E_NOTIMPL;
1531 }
1532
1533 static ICOM_VTABLE(IMultiLanguage2) IMultiLanguage2_vtbl =
1534 {
1535     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1536     fnIMultiLanguage2_QueryInterface,
1537     fnIMultiLanguage2_AddRef,
1538     fnIMultiLanguage2_Release,
1539     fnIMultiLanguage2_GetNumberOfCodePageInfo,
1540     fnIMultiLanguage2_GetCodePageInfo,
1541     fnIMultiLanguage2_GetFamilyCodePage,
1542     fnIMultiLanguage2_EnumCodePages,
1543     fnIMultiLanguage2_GetCharsetInfo,
1544     fnIMultiLanguage2_IsConvertible,
1545     fnIMultiLanguage2_ConvertString,
1546     fnIMultiLanguage2_ConvertStringToUnicode,
1547     fnIMultiLanguage2_ConvertStringFromUnicode,
1548     fnIMultiLanguage2_ConvertStringReset,
1549     fnIMultiLanguage2_GetRfc1766FromLcid,
1550     fnIMultiLanguage2_GetLcidFromRfc1766,
1551     fnIMultiLanguage2_EnumRfc1766,
1552     fnIMultiLanguage2_GetRfc1766Info,
1553     fnIMultiLanguage2_CreateConvertCharset,
1554     fnIMultiLanguage2_ConvertStringInIStream,
1555     fnIMultiLanguage2_ConvertStringToUnicodeEx,
1556     fnIMultiLanguage2_DetectCodepageInIStream,
1557     fnIMultiLanguage2_DetectInputCodepage,
1558     fnIMultiLanguage2_ValidateCodePage,
1559     fnIMultiLanguage2_GetCodePageDescription,
1560     fnIMultiLanguage2_IsCodePageInstallable,
1561     fnIMultiLanguage2_SetMimeDBSource,
1562     fnIMultiLanguage2_GetNumberOfScripts,
1563     fnIMultiLanguage2_EnumScripts,
1564     fnIMultiLanguage2_ValidateCodePageEx,
1565 };
1566
1567 static HRESULT MultiLanguage_create(IUnknown *pUnkOuter, LPVOID *ppObj)
1568 {
1569     MLang_impl *mlang;
1570     UINT i;
1571
1572     TRACE("Creating MultiLanguage object\n");
1573
1574     mlang = HeapAlloc( GetProcessHeap(), 0, sizeof (MLang_impl) );
1575     mlang->vtbl_IMLangFontLink = &IMLangFontLink_vtbl;
1576     mlang->vtbl_IMultiLanguage = &IMultiLanguage_vtbl;
1577     mlang->vtbl_IMultiLanguage2 = &IMultiLanguage2_vtbl;
1578
1579     mlang->total = 0;
1580     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
1581         mlang->total += mlang_data[i].number_of_cp;
1582
1583     mlang->ref = 1;
1584     *ppObj = (LPVOID) mlang;
1585     TRACE("returning %p\n", mlang);
1586     return S_OK;
1587 }
1588
1589 /******************************************************************************/
1590
1591 HRESULT WINAPI MLANG_DllCanUnloadNow(void)
1592 {
1593     FIXME("\n");
1594     return S_FALSE;
1595 }
1596
1597 HRESULT WINAPI MLANG_DllRegisterServer(void)
1598 {
1599     FIXME("\n");
1600     return S_OK;
1601 }
1602
1603 HRESULT WINAPI MLANG_DllUnregisterServer(void)
1604 {
1605     FIXME("\n");
1606     return S_OK;
1607 }