1 /* 2 * MSXML Class Factory 3 * 4 * Copyright 2002 Lionel Ulmer 5 * Copyright 2005 Mike McCormack 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include "config.h" 23 #include "wine/port.h" 24 25 #define COBJMACROS 26 27 #include <stdarg.h> 28 #ifdef HAVE_LIBXML2 29 # include <libxml/parser.h> 30 # include <libxml/xmlerror.h> 31 # ifdef SONAME_LIBXSLT 32 # ifdef HAVE_LIBXSLT_PATTERN_H 33 # include <libxslt/pattern.h> 34 # endif 35 # ifdef HAVE_LIBXSLT_TRANSFORM_H 36 # include <libxslt/transform.h> 37 # endif 38 # include <libxslt/imports.h> 39 # include <libxslt/xsltutils.h> 40 # include <libxslt/variables.h> 41 # include <libxslt/xsltInternals.h> 42 # include <libxslt/documents.h> 43 # include <libxslt/extensions.h> 44 # include <libxslt/extra.h> 45 # endif 46 #endif 47 48 #include "windef.h" 49 #include "winbase.h" 50 #include "winuser.h" 51 #include "ole2.h" 52 #include "rpcproxy.h" 53 #include "msxml.h" 54 #include "msxml6.h" 55 56 #include "wine/unicode.h" 57 #include "wine/debug.h" 58 #include "wine/library.h" 59 60 #include "msxml_private.h" 61 62 HINSTANCE MSXML_hInstance = NULL; 63 64 #ifdef HAVE_LIBXML2 65 66 WINE_DEFAULT_DEBUG_CHANNEL(msxml); 67 68 void wineXmlCallbackLog(char const* caller, xmlErrorLevel lvl, char const* msg, va_list ap) 69 { 70 enum __wine_debug_class dbcl; 71 char buff[200]; 72 const int max_size = ARRAY_SIZE(buff); 73 int len; 74 75 switch (lvl) 76 { 77 case XML_ERR_NONE: 78 dbcl = __WINE_DBCL_TRACE; 79 break; 80 case XML_ERR_WARNING: 81 dbcl = __WINE_DBCL_WARN; 82 break; 83 default: 84 dbcl = __WINE_DBCL_ERR; 85 break; 86 } 87 88 len = vsnprintf(buff, max_size, msg, ap); 89 if (len == -1 || len >= max_size) buff[max_size-1] = 0; 90 91 wine_dbg_log(dbcl, &__wine_dbch_msxml, caller, "%s", buff); 92 } 93 94 void wineXmlCallbackError(char const* caller, xmlErrorPtr err) 95 { 96 enum __wine_debug_class dbcl; 97 98 switch (err->level) 99 { 100 case XML_ERR_NONE: dbcl = __WINE_DBCL_TRACE; break; 101 case XML_ERR_WARNING: dbcl = __WINE_DBCL_WARN; break; 102 default: dbcl = __WINE_DBCL_ERR; break; 103 } 104 105 wine_dbg_log(dbcl, &__wine_dbch_msxml, caller, "error code %d", err->code); 106 if (err->message) 107 wine_dbg_log(dbcl, &__wine_dbch_msxml, caller, ": %s", err->message); 108 else 109 wine_dbg_log(dbcl, &__wine_dbch_msxml, caller, "\n"); 110 } 111 112 /* Support for loading xml files from a Wine Windows drive */ 113 static int wineXmlMatchCallback (char const * filename) 114 { 115 int nRet = 0; 116 117 TRACE("%s\n", filename); 118 119 /* 120 * We will deal with loading XML files from the file system 121 * We only care about files that linux cannot find. 122 * e.g. C:,D: etc 123 */ 124 if(isalpha(filename[0]) && filename[1] == ':') 125 nRet = 1; 126 127 return nRet; 128 } 129 130 static void *wineXmlOpenCallback (char const * filename) 131 { 132 BSTR sFilename = bstr_from_xmlChar( (const xmlChar*)filename); 133 HANDLE hFile; 134 135 TRACE("%s\n", debugstr_w(sFilename)); 136 137 hFile = CreateFileW(sFilename, GENERIC_READ,FILE_SHARE_READ, NULL, 138 OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL); 139 if(hFile == INVALID_HANDLE_VALUE) hFile = 0; 140 SysFreeString(sFilename); 141 return hFile; 142 } 143 144 static int wineXmlReadCallback(void * context, char * buffer, int len) 145 { 146 DWORD dwBytesRead; 147 148 TRACE("%p %s %d\n", context, buffer, len); 149 150 if ((context == NULL) || (buffer == NULL)) 151 return(-1); 152 153 if(!ReadFile( context, buffer,len, &dwBytesRead, NULL)) 154 { 155 ERR("Failed to read file\n"); 156 return -1; 157 } 158 159 TRACE("Read %d\n", dwBytesRead); 160 161 return dwBytesRead; 162 } 163 164 static int wineXmlFileCloseCallback (void * context) 165 { 166 return CloseHandle(context) ? 0 : -1; 167 } 168 169 void* libxslt_handle = NULL; 170 #ifdef SONAME_LIBXSLT 171 # define DECL_FUNCPTR(f) typeof(f) * p##f = NULL 172 DECL_FUNCPTR(xsltApplyStylesheet); 173 DECL_FUNCPTR(xsltApplyStylesheetUser); 174 DECL_FUNCPTR(xsltCleanupGlobals); 175 DECL_FUNCPTR(xsltFreeStylesheet); 176 DECL_FUNCPTR(xsltFreeTransformContext); 177 DECL_FUNCPTR(xsltFunctionNodeSet); 178 DECL_FUNCPTR(xsltNewTransformContext); 179 DECL_FUNCPTR(xsltNextImport); 180 DECL_FUNCPTR(xsltParseStylesheetDoc); 181 DECL_FUNCPTR(xsltQuoteUserParams); 182 DECL_FUNCPTR(xsltRegisterExtModuleFunction); 183 DECL_FUNCPTR(xsltSaveResultTo); 184 DECL_FUNCPTR(xsltSetLoaderFunc); 185 # undef DECL_FUNCPTR 186 #endif 187 188 static void init_libxslt(void) 189 { 190 #ifdef SONAME_LIBXSLT 191 void (*pxsltInit)(void); /* Missing in libxslt <= 1.1.14 */ 192 193 libxslt_handle = wine_dlopen(SONAME_LIBXSLT, RTLD_NOW, NULL, 0); 194 if (!libxslt_handle) 195 return; 196 197 #define LOAD_FUNCPTR(f, needed) \ 198 if ((p##f = wine_dlsym(libxslt_handle, #f, NULL, 0)) == NULL) \ 199 if (needed) { WARN("Can't find symbol %s\n", #f); goto sym_not_found; } 200 LOAD_FUNCPTR(xsltInit, 0); 201 LOAD_FUNCPTR(xsltApplyStylesheet, 1); 202 LOAD_FUNCPTR(xsltApplyStylesheetUser, 1); 203 LOAD_FUNCPTR(xsltCleanupGlobals, 1); 204 LOAD_FUNCPTR(xsltFreeStylesheet, 1); 205 LOAD_FUNCPTR(xsltFreeTransformContext, 1); 206 LOAD_FUNCPTR(xsltFunctionNodeSet, 1); 207 LOAD_FUNCPTR(xsltNewTransformContext, 1); 208 LOAD_FUNCPTR(xsltNextImport, 1); 209 LOAD_FUNCPTR(xsltParseStylesheetDoc, 1); 210 LOAD_FUNCPTR(xsltQuoteUserParams, 1); 211 LOAD_FUNCPTR(xsltRegisterExtModuleFunction, 1); 212 LOAD_FUNCPTR(xsltSaveResultTo, 1); 213 LOAD_FUNCPTR(xsltSetLoaderFunc, 1); 214 #undef LOAD_FUNCPTR 215 216 if (pxsltInit) 217 pxsltInit(); 218 219 pxsltSetLoaderFunc(xslt_doc_default_loader); 220 pxsltRegisterExtModuleFunction( 221 (const xmlChar *)"node-set", 222 (const xmlChar *)"urn:schemas-microsoft-com:xslt", 223 pxsltFunctionNodeSet); 224 225 return; 226 227 sym_not_found: 228 wine_dlclose(libxslt_handle, NULL, 0); 229 libxslt_handle = NULL; 230 #endif 231 } 232 233 static int to_utf8(int cp, unsigned char *out, int *outlen, const unsigned char *in, int *inlen) 234 { 235 WCHAR *tmp; 236 int len; 237 238 if (!in || !inlen) return 0; 239 240 len = MultiByteToWideChar(cp, 0, (const char *)in, *inlen, NULL, 0); 241 tmp = heap_alloc(len * sizeof(WCHAR)); 242 if (!tmp) return -1; 243 MultiByteToWideChar(cp, 0, (const char *)in, *inlen, tmp, len); 244 245 len = WideCharToMultiByte(CP_UTF8, 0, tmp, len, (char *)out, *outlen, NULL, NULL); 246 heap_free(tmp); 247 if (!len) return -1; 248 249 *outlen = len; 250 return len; 251 } 252 253 static int from_utf8(int cp, unsigned char *out, int *outlen, const unsigned char *in, int *inlen) 254 { 255 WCHAR *tmp; 256 int len; 257 258 if (!in || !inlen) return 0; 259 260 len = MultiByteToWideChar(CP_UTF8, 0, (const char *)in, *inlen, NULL, 0); 261 tmp = heap_alloc(len * sizeof(WCHAR)); 262 if (!tmp) return -1; 263 MultiByteToWideChar(CP_UTF8, 0, (const char *)in, *inlen, tmp, len); 264 265 len = WideCharToMultiByte(cp, 0, tmp, len, (char *)out, *outlen, NULL, NULL); 266 heap_free(tmp); 267 if (!len) return -1; 268 269 *outlen = len; 270 return len; 271 } 272 273 static int win1250_to_utf8(unsigned char *out, int *outlen, const unsigned char *in, int *inlen) 274 { 275 return to_utf8(1250, out, outlen, in, inlen); 276 } 277 278 static int utf8_to_win1250(unsigned char *out, int *outlen, const unsigned char *in, int *inlen) 279 { 280 return from_utf8(1250, out, outlen, in, inlen); 281 } 282 283 static int win1251_to_utf8(unsigned char *out, int *outlen, const unsigned char *in, int *inlen) 284 { 285 return to_utf8(1251, out, outlen, in, inlen); 286 } 287 288 static int utf8_to_win1251(unsigned char *out, int *outlen, const unsigned char *in, int *inlen) 289 { 290 return from_utf8(1251, out, outlen, in, inlen); 291 } 292 293 static int win1252_to_utf8(unsigned char *out, int *outlen, const unsigned char *in, int *inlen) 294 { 295 return to_utf8(1252, out, outlen, in, inlen); 296 } 297 298 static int utf8_to_win1252(unsigned char *out, int *outlen, const unsigned char *in, int *inlen) 299 { 300 return from_utf8(1252, out, outlen, in, inlen); 301 } 302 303 static int win1253_to_utf8(unsigned char *out, int *outlen, const unsigned char *in, int *inlen) 304 { 305 return to_utf8(1253, out, outlen, in, inlen); 306 } 307 308 static int utf8_to_win1253(unsigned char *out, int *outlen, const unsigned char *in, int *inlen) 309 { 310 return from_utf8(1253, out, outlen, in, inlen); 311 } 312 static int win1254_to_utf8(unsigned char *out, int *outlen, const unsigned char *in, int *inlen) 313 { 314 return to_utf8(1254, out, outlen, in, inlen); 315 } 316 317 static int utf8_to_win1254(unsigned char *out, int *outlen, const unsigned char *in, int *inlen) 318 { 319 return from_utf8(1254, out, outlen, in, inlen); 320 } 321 322 static int win1255_to_utf8(unsigned char *out, int *outlen, const unsigned char *in, int *inlen) 323 { 324 return to_utf8(1255, out, outlen, in, inlen); 325 } 326 327 static int utf8_to_win1255(unsigned char *out, int *outlen, const unsigned char *in, int *inlen) 328 { 329 return from_utf8(1255, out, outlen, in, inlen); 330 } 331 332 static int win1256_to_utf8(unsigned char *out, int *outlen, const unsigned char *in, int *inlen) 333 { 334 return to_utf8(1256, out, outlen, in, inlen); 335 } 336 337 static int utf8_to_win1256(unsigned char *out, int *outlen, const unsigned char *in, int *inlen) 338 { 339 return from_utf8(1256, out, outlen, in, inlen); 340 } 341 342 static int win1257_to_utf8(unsigned char *out, int *outlen, const unsigned char *in, int *inlen) 343 { 344 return to_utf8(1257, out, outlen, in, inlen); 345 } 346 347 static int utf8_to_win1257(unsigned char *out, int *outlen, const unsigned char *in, int *inlen) 348 { 349 return from_utf8(1257, out, outlen, in, inlen); 350 } 351 352 static int win1258_to_utf8(unsigned char *out, int *outlen, const unsigned char *in, int *inlen) 353 { 354 return to_utf8(1258, out, outlen, in, inlen); 355 } 356 357 static int utf8_to_win1258(unsigned char *out, int *outlen, const unsigned char *in, int *inlen) 358 { 359 return from_utf8(1258, out, outlen, in, inlen); 360 } 361 362 static void init_char_encoders(void) 363 { 364 static const struct 365 { 366 const char *encoding; 367 xmlCharEncodingInputFunc input; 368 xmlCharEncodingOutputFunc output; 369 } encoder[] = 370 { 371 { "windows-1250", win1250_to_utf8, utf8_to_win1250 }, 372 { "windows-1251", win1251_to_utf8, utf8_to_win1251 }, 373 { "windows-1252", win1252_to_utf8, utf8_to_win1252 }, 374 { "windows-1253", win1253_to_utf8, utf8_to_win1253 }, 375 { "windows-1254", win1254_to_utf8, utf8_to_win1254 }, 376 { "windows-1255", win1255_to_utf8, utf8_to_win1255 }, 377 { "windows-1256", win1256_to_utf8, utf8_to_win1256 }, 378 { "windows-1257", win1257_to_utf8, utf8_to_win1257 }, 379 { "windows-1258", win1258_to_utf8, utf8_to_win1258 } 380 }; 381 int i; 382 383 xmlInitCharEncodingHandlers(); 384 385 for (i = 0; i < ARRAY_SIZE(encoder); i++) 386 { 387 if (!xmlFindCharEncodingHandler(encoder[i].encoding)) 388 { 389 TRACE("Adding %s encoding handler\n", encoder[i].encoding); 390 xmlNewCharEncodingHandler(encoder[i].encoding, encoder[i].input, encoder[i].output); 391 } 392 } 393 } 394 395 #endif /* HAVE_LIBXML2 */ 396 397 398 HRESULT WINAPI DllCanUnloadNow(void) 399 { 400 return S_FALSE; 401 } 402 403 404 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID reserved) 405 { 406 MSXML_hInstance = hInstDLL; 407 408 switch(fdwReason) 409 { 410 case DLL_PROCESS_ATTACH: 411 #ifdef HAVE_LIBXML2 412 xmlInitParser(); 413 414 /* Set the default indent character to a single tab, 415 for this thread and as default for new threads */ 416 xmlTreeIndentString = "\t"; 417 xmlThrDefTreeIndentString("\t"); 418 419 /* Register callbacks for loading XML files */ 420 if(xmlRegisterInputCallbacks(wineXmlMatchCallback, wineXmlOpenCallback, 421 wineXmlReadCallback, wineXmlFileCloseCallback) == -1) 422 WARN("Failed to register callbacks\n"); 423 424 init_char_encoders(); 425 426 schemasInit(); 427 init_libxslt(); 428 #endif 429 DisableThreadLibraryCalls(hInstDLL); 430 break; 431 case DLL_PROCESS_DETACH: 432 if (reserved) break; 433 #ifdef HAVE_LIBXML2 434 #ifdef SONAME_LIBXSLT 435 if (libxslt_handle) 436 { 437 pxsltCleanupGlobals(); 438 wine_dlclose(libxslt_handle, NULL, 0); 439 } 440 #endif 441 /* Restore default Callbacks */ 442 xmlCleanupInputCallbacks(); 443 xmlRegisterDefaultInputCallbacks(); 444 445 xmlCleanupParser(); 446 schemasCleanup(); 447 #endif 448 release_typelib(); 449 break; 450 } 451 return TRUE; 452 } 453 454 /*********************************************************************** 455 * DllRegisterServer (MSXML3.@) 456 */ 457 HRESULT WINAPI DllRegisterServer(void) 458 { 459 return __wine_register_resources( MSXML_hInstance ); 460 } 461 462 /*********************************************************************** 463 * DllUnregisterServer (MSXML3.@) 464 */ 465 HRESULT WINAPI DllUnregisterServer(void) 466 { 467 return __wine_unregister_resources( MSXML_hInstance ); 468 } 469