mshtml: Improved error handling in HTMLElement_Create calls.
[wine] / dlls / msxml3 / main.c
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 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "ole2.h"
32 #include "msxml.h"
33 #include "msxml6.h"
34
35 #include "wine/unicode.h"
36 #include "wine/debug.h"
37 #include "wine/library.h"
38
39 #include "msxml_private.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
42
43 HINSTANCE MSXML_hInstance = NULL;
44
45 #ifdef HAVE_LIBXML2
46
47 void wineXmlCallbackLog(char const* caller, xmlErrorLevel lvl, char const* msg, va_list ap)
48 {
49     char* buf = NULL;
50     int len = 32, needed;
51     enum __wine_debug_class dbcl = __WINE_DBCL_ERR;
52     switch (lvl)
53     {
54         case XML_ERR_NONE:
55             dbcl = __WINE_DBCL_TRACE;
56             break;
57         case XML_ERR_WARNING:
58             dbcl = __WINE_DBCL_WARN;
59             break;
60         default:
61             break;
62     }
63
64     do
65     {
66         heap_free(buf);
67         buf = heap_alloc(len);
68         needed = vsnprintf(buf, len, msg, ap);
69         if (needed == -1)
70             len *= 2;
71         else if (needed >= len)
72             len = needed + 1;
73         else
74             needed = 0;
75     }
76     while (needed);
77
78     wine_dbg_log(dbcl, &__wine_dbch_msxml, caller, "%s", buf);
79     heap_free(buf);
80 }
81
82 void wineXmlCallbackError(char const* caller, xmlErrorPtr err)
83 {
84     enum __wine_debug_class dbcl;
85
86     switch (err->level)
87     {
88     case XML_ERR_NONE:    dbcl = __WINE_DBCL_TRACE; break;
89     case XML_ERR_WARNING: dbcl = __WINE_DBCL_WARN; break;
90     default:              dbcl = __WINE_DBCL_ERR; break;
91     }
92     wine_dbg_log(dbcl, &__wine_dbch_msxml, caller, "%s", err->message);
93 }
94
95 /* Support for loading xml files from a Wine Windows drive */
96 static int wineXmlMatchCallback (char const * filename)
97 {
98     int nRet = 0;
99
100     TRACE("%s\n", filename);
101
102     /*
103      * We will deal with loading XML files from the file system
104      *   We only care about files that linux cannot find.
105      *    e.g. C:,D: etc
106      */
107     if(isalpha(filename[0]) && filename[1] == ':')
108         nRet = 1;
109
110     return nRet;
111 }
112
113 static void *wineXmlOpenCallback (char const * filename)
114 {
115     BSTR sFilename = bstr_from_xmlChar( (const xmlChar*)filename);
116     HANDLE hFile;
117
118     TRACE("%s\n", debugstr_w(sFilename));
119
120     hFile = CreateFileW(sFilename, GENERIC_READ,FILE_SHARE_READ, NULL,
121                        OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL);
122     if(hFile == INVALID_HANDLE_VALUE) hFile = 0;
123     SysFreeString(sFilename);
124     return hFile;
125 }
126
127 static int wineXmlReadCallback(void * context, char * buffer, int len)
128 {
129     DWORD dwBytesRead;
130
131     TRACE("%p %s %d\n", context, buffer, len);
132
133     if ((context == NULL) || (buffer == NULL))
134         return(-1);
135
136     if(!ReadFile( context, buffer,len, &dwBytesRead, NULL))
137     {
138         ERR("Failed to read file\n");
139         return -1;
140     }
141
142     TRACE("Read %d\n", dwBytesRead);
143
144     return dwBytesRead;
145 }
146
147 static int wineXmlFileCloseCallback (void * context)
148 {
149     return CloseHandle(context) ? 0 : -1;
150 }
151
152 #endif
153
154
155 HRESULT WINAPI DllCanUnloadNow(void)
156 {
157     return S_FALSE;
158 }
159
160
161 void* libxslt_handle = NULL;
162 #ifdef SONAME_LIBXSLT
163 # define DECL_FUNCPTR(f) typeof(f) * p##f = NULL
164 DECL_FUNCPTR(xsltApplyStylesheet);
165 DECL_FUNCPTR(xsltCleanupGlobals);
166 DECL_FUNCPTR(xsltFreeStylesheet);
167 DECL_FUNCPTR(xsltParseStylesheetDoc);
168 # undef DECL_FUNCPTR
169 #endif
170
171 static void init_libxslt(void)
172 {
173 #ifdef SONAME_LIBXSLT
174     void (*pxsltInit)(void); /* Missing in libxslt <= 1.1.14 */
175
176     libxslt_handle = wine_dlopen(SONAME_LIBXSLT, RTLD_NOW, NULL, 0);
177     if (!libxslt_handle)
178         return;
179
180 #define LOAD_FUNCPTR(f, needed) if ((p##f = wine_dlsym(libxslt_handle, #f, NULL, 0)) == NULL && needed) { WARN("Can't find symbol %s\n", #f); goto sym_not_found; }
181     LOAD_FUNCPTR(xsltInit, 0);
182     LOAD_FUNCPTR(xsltApplyStylesheet, 1);
183     LOAD_FUNCPTR(xsltCleanupGlobals, 1);
184     LOAD_FUNCPTR(xsltFreeStylesheet, 1);
185     LOAD_FUNCPTR(xsltParseStylesheetDoc, 1);
186 #undef LOAD_FUNCPTR
187
188     if (pxsltInit)
189         pxsltInit();
190     return;
191
192  sym_not_found:
193     wine_dlclose(libxslt_handle, NULL, 0);
194     libxslt_handle = NULL;
195 #endif
196 }
197
198
199 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
200 {
201     MSXML_hInstance = hInstDLL;
202
203     switch(fdwReason)
204     {
205     case DLL_PROCESS_ATTACH:
206 #ifdef HAVE_LIBXML2
207         xmlInitParser();
208
209         /* Set the default indent character to a single tab,
210            for this thread and as default for new threads */
211         xmlTreeIndentString = "\t";
212         xmlThrDefTreeIndentString("\t");
213
214          /* Register callbacks for loading XML files */
215         if(xmlRegisterInputCallbacks(wineXmlMatchCallback, wineXmlOpenCallback,
216                             wineXmlReadCallback, wineXmlFileCloseCallback) == -1)
217             WARN("Failed to register callbacks\n");
218
219         schemasInit();
220 #endif
221         init_libxslt();
222         DisableThreadLibraryCalls(hInstDLL);
223         break;
224     case DLL_PROCESS_DETACH:
225 #ifdef SONAME_LIBXSLT
226         if (libxslt_handle)
227         {
228             pxsltCleanupGlobals();
229             wine_dlclose(libxslt_handle, NULL, 0);
230             libxslt_handle = NULL;
231         }
232 #endif
233 #ifdef HAVE_LIBXML2
234         /* Restore default Callbacks */
235         xmlCleanupInputCallbacks();
236         xmlRegisterDefaultInputCallbacks();
237
238         xmlCleanupParser();
239         schemasCleanup();
240 #endif
241         release_typelib();
242         break;
243     }
244     return TRUE;
245 }