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