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