mshtml: Added IHTMLElement::get_offsetHeight implementation.
[wine] / dlls / msxml3 / saxreader.c
1 /*
2  *    SAX Reader implementation
3  *
4  * Copyright 2008 Alistair Leslie-Hughes
5  * Copyright 2008 Piotr Caban
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 #define COBJMACROS
22
23 #include "config.h"
24
25 #include <stdarg.h>
26 #include <assert.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "winnls.h"
31 #include "ole2.h"
32 #include "msxml2.h"
33 #include "wininet.h"
34 #include "urlmon.h"
35 #include "winreg.h"
36 #include "shlwapi.h"
37
38 #include "wine/debug.h"
39
40 #include "msxml_private.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
43
44 #ifdef HAVE_LIBXML2
45
46 #include <libxml/SAX2.h>
47
48 typedef struct _saxreader
49 {
50     const struct IVBSAXXMLReaderVtbl *lpVtbl;
51     const struct ISAXXMLReaderVtbl *lpSAXXMLReaderVtbl;
52     LONG ref;
53     struct ISAXContentHandler *contentHandler;
54     struct ISAXErrorHandler *errorHandler;
55     xmlSAXHandler sax;
56 } saxreader;
57
58 typedef struct _saxlocator
59 {
60     const struct ISAXLocatorVtbl *lpSAXLocatorVtbl;
61     LONG ref;
62     saxreader *saxreader;
63     HRESULT ret;
64     xmlParserCtxtPtr pParserCtxt;
65     WCHAR *publicId;
66     WCHAR *systemId;
67     xmlChar *lastCur;
68     int line;
69     int column;
70 } saxlocator;
71
72 typedef struct _saxattributes
73 {
74     const struct ISAXAttributesVtbl *lpSAXAttributesVtbl;
75     LONG ref;
76     int nb_attributes;
77     BSTR *szLocalname;
78     BSTR *szPrefix;
79     BSTR *szURI;
80     BSTR *szValue;
81 } saxattributes;
82
83 static inline saxreader *impl_from_IVBSAXXMLReader( IVBSAXXMLReader *iface )
84 {
85     return (saxreader *)((char*)iface - FIELD_OFFSET(saxreader, lpVtbl));
86 }
87
88 static inline saxreader *impl_from_ISAXXMLReader( ISAXXMLReader *iface )
89 {
90     return (saxreader *)((char*)iface - FIELD_OFFSET(saxreader, lpSAXXMLReaderVtbl));
91 }
92
93 static inline saxlocator *impl_from_ISAXLocator( ISAXLocator *iface )
94 {
95     return (saxlocator *)((char*)iface - FIELD_OFFSET(saxlocator, lpSAXLocatorVtbl));
96 }
97
98 static inline saxattributes *impl_from_ISAXAttributes( ISAXAttributes *iface )
99 {
100     return (saxattributes *)((char*)iface - FIELD_OFFSET(saxattributes, lpSAXAttributesVtbl));
101 }
102
103
104 BSTR bstr_from_xmlCharN(const xmlChar *buf, int len)
105 {
106     DWORD dLen;
107     LPWSTR str;
108     BSTR bstr;
109
110     if (!buf)
111         return NULL;
112
113     dLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0);
114     if(len != -1) dLen++;
115     str = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dLen * sizeof (WCHAR));
116     if (!str)
117         return NULL;
118     MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, str, dLen);
119     if(len != -1) str[dLen-1] = '\0';
120     bstr = SysAllocString(str);
121     HeapFree(GetProcessHeap(), 0, str);
122
123     return bstr;
124 }
125
126 static void format_error_message_from_id(saxlocator *This, HRESULT hr)
127 {
128     xmlStopParser(This->pParserCtxt);
129     This->ret = hr;
130
131     if(This->saxreader->errorHandler)
132     {
133         WCHAR msg[1024];
134         if(!FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
135                     NULL, hr, 0, msg, sizeof(msg), NULL))
136         {
137             FIXME("MSXML errors not yet supported.\n");
138             msg[0] = '\0';
139         }
140
141         ISAXErrorHandler_fatalError(This->saxreader->errorHandler,
142                 (ISAXLocator*)&This->lpSAXLocatorVtbl, msg, hr);
143     }
144 }
145
146 static void update_position(saxlocator *This, xmlChar *end)
147 {
148     if(This->lastCur == NULL)
149     {
150         This->lastCur = (xmlChar*)This->pParserCtxt->input->base;
151         This->line = 1;
152         This->column = 1;
153     }
154
155     if(!end) end = (xmlChar*)This->pParserCtxt->input->cur;
156
157     while(This->lastCur < end)
158     {
159         if(*(This->lastCur) == '\n')
160         {
161             This->line++;
162             This->column = 1;
163         }
164         else if(*(This->lastCur) == '\r' && (This->lastCur==This->pParserCtxt->input->end || *(This->lastCur+1)!='\n'))
165         {
166             This->line++;
167             This->column = 1;
168         }
169         else This->column++;
170
171         This->lastCur++;
172     }
173 }
174
175 /*** ISAXAttributes interface ***/
176 /*** IUnknown methods ***/
177 static HRESULT WINAPI isaxattributes_QueryInterface(
178         ISAXAttributes* iface,
179         REFIID riid,
180         void **ppvObject)
181 {
182     saxattributes *This = impl_from_ISAXAttributes(iface);
183
184     TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
185
186     *ppvObject = NULL;
187
188     if (IsEqualGUID(riid, &IID_IUnknown) ||
189             IsEqualGUID(riid, &IID_ISAXAttributes))
190     {
191         *ppvObject = iface;
192     }
193     else
194     {
195         FIXME("interface %s not implemented\n", debugstr_guid(riid));
196         return E_NOINTERFACE;
197     }
198
199     ISAXAttributes_AddRef(iface);
200
201     return S_OK;
202 }
203
204 static ULONG WINAPI isaxattributes_AddRef(ISAXAttributes* iface)
205 {
206     saxattributes *This = impl_from_ISAXAttributes(iface);
207     TRACE("%p\n", This);
208     return InterlockedIncrement(&This->ref);
209 }
210
211 static ULONG WINAPI isaxattributes_Release(ISAXAttributes* iface)
212 {
213     saxattributes *This = impl_from_ISAXAttributes(iface);
214     LONG ref;
215
216     TRACE("%p\n", This);
217
218     ref = InterlockedDecrement(&This->ref);
219     if (ref==0)
220     {
221         int index;
222         for(index=0; index<This->nb_attributes; index++)
223         {
224             SysFreeString(This->szLocalname[index]);
225             SysFreeString(This->szPrefix[index]);
226             SysFreeString(This->szURI[index]);
227             SysFreeString(This->szValue[index]);
228         }
229
230         HeapFree(GetProcessHeap(), 0, This->szLocalname);
231         HeapFree(GetProcessHeap(), 0, This->szPrefix);
232         HeapFree(GetProcessHeap(), 0, This->szURI);
233         HeapFree(GetProcessHeap(), 0, This->szValue);
234
235         HeapFree(GetProcessHeap(), 0, This);
236     }
237
238     return ref;
239 }
240
241 /*** ISAXAttributes methods ***/
242 static HRESULT WINAPI isaxattributes_getLength(
243         ISAXAttributes* iface,
244         int *length)
245 {
246     saxattributes *This = impl_from_ISAXAttributes( iface );
247
248     *length = This->nb_attributes;
249     TRACE("Length set to %d\n", *length);
250     return S_OK;
251 }
252
253 static HRESULT WINAPI isaxattributes_getURI(
254         ISAXAttributes* iface,
255         int nIndex,
256         const WCHAR **pUrl,
257         int *pUriSize)
258 {
259     saxattributes *This = impl_from_ISAXAttributes( iface );
260
261     FIXME("(%p)->(%d) stub\n", This, nIndex);
262     return E_NOTIMPL;
263 }
264
265 static HRESULT WINAPI isaxattributes_getLocalName(
266         ISAXAttributes* iface,
267         int nIndex,
268         const WCHAR **pLocalName,
269         int *pLocalNameLength)
270 {
271     saxattributes *This = impl_from_ISAXAttributes( iface );
272     TRACE("(%p)->(%d)\n", This, nIndex);
273
274     if(nIndex >= This->nb_attributes) return E_INVALIDARG;
275
276     *pLocalNameLength = SysStringLen(This->szLocalname[nIndex]);
277     *pLocalName = This->szLocalname[nIndex];
278
279     return S_OK;
280 }
281
282 static HRESULT WINAPI isaxattributes_getQName(
283         ISAXAttributes* iface,
284         int nIndex,
285         const WCHAR **pQName,
286         int *pQNameLength)
287 {
288     saxattributes *This = impl_from_ISAXAttributes( iface );
289
290     FIXME("(%p)->(%d) stub\n", This, nIndex);
291     return E_NOTIMPL;
292 }
293
294 static HRESULT WINAPI isaxattributes_getName(
295         ISAXAttributes* iface,
296         int nIndex,
297         const WCHAR **pUri,
298         int *pUriLength,
299         const WCHAR **pLocalName,
300         int *pLocalNameSize,
301         const WCHAR **pQName,
302         int *pQNameLength)
303 {
304     saxattributes *This = impl_from_ISAXAttributes( iface );
305
306     FIXME("(%p)->(%d) stub\n", This, nIndex);
307     return E_NOTIMPL;
308 }
309
310 static HRESULT WINAPI isaxattributes_getIndexFromName(
311         ISAXAttributes* iface,
312         const WCHAR *pUri,
313         int cUriLength,
314         const WCHAR *pLocalName,
315         int cocalNameLength,
316         int *index)
317 {
318     saxattributes *This = impl_from_ISAXAttributes( iface );
319
320     FIXME("(%p)->(%s, %d, %s, %d) stub\n", This, debugstr_w(pUri), cUriLength,
321             debugstr_w(pLocalName), cocalNameLength);
322     return E_NOTIMPL;
323 }
324
325 static HRESULT WINAPI isaxattributes_getIndexFromQName(
326         ISAXAttributes* iface,
327         const WCHAR *pQName,
328         int nQNameLength,
329         int *index)
330 {
331     saxattributes *This = impl_from_ISAXAttributes( iface );
332
333     FIXME("(%p)->(%s, %d) stub\n", This, debugstr_w(pQName), nQNameLength);
334     return E_NOTIMPL;
335 }
336
337 static HRESULT WINAPI isaxattributes_getType(
338         ISAXAttributes* iface,
339         int nIndex,
340         const WCHAR **pType,
341         int *pTypeLength)
342 {
343     saxattributes *This = impl_from_ISAXAttributes( iface );
344
345     FIXME("(%p)->(%d) stub\n", This, nIndex);
346     return E_NOTIMPL;
347 }
348
349 static HRESULT WINAPI isaxattributes_getTypeFromName(
350         ISAXAttributes* iface,
351         const WCHAR *pUri,
352         int nUri,
353         const WCHAR *pLocalName,
354         int nLocalName,
355         const WCHAR **pType,
356         int *nType)
357 {
358     saxattributes *This = impl_from_ISAXAttributes( iface );
359
360     FIXME("(%p)->(%s, %d, %s, %d) stub\n", This, debugstr_w(pUri), nUri,
361             debugstr_w(pLocalName), nLocalName);
362     return E_NOTIMPL;
363 }
364
365 static HRESULT WINAPI isaxattributes_getTypeFromQName(
366         ISAXAttributes* iface,
367         const WCHAR *pQName,
368         int nQName,
369         const WCHAR **pType,
370         int *nType)
371 {
372     saxattributes *This = impl_from_ISAXAttributes( iface );
373
374     FIXME("(%p)->(%s, %d) stub\n", This, debugstr_w(pQName), nQName);
375     return E_NOTIMPL;
376 }
377
378 static HRESULT WINAPI isaxattributes_getValue(
379         ISAXAttributes* iface,
380         int nIndex,
381         const WCHAR **pValue,
382         int *nValue)
383 {
384     saxattributes *This = impl_from_ISAXAttributes( iface );
385     TRACE("(%p)->(%d)\n", This, nIndex);
386
387     if(nIndex >= This->nb_attributes) return E_INVALIDARG;
388
389     *nValue = SysStringLen(This->szValue[nIndex]);
390     *pValue = This->szValue[nIndex];
391
392     return S_OK;
393 }
394
395 static HRESULT WINAPI isaxattributes_getValueFromName(
396         ISAXAttributes* iface,
397         const WCHAR *pUri,
398         int nUri,
399         const WCHAR *pLocalName,
400         int nLocalName,
401         const WCHAR **pValue,
402         int *nValue)
403 {
404     saxattributes *This = impl_from_ISAXAttributes( iface );
405
406     FIXME("(%p)->(%s, %d, %s, %d) stub\n", This, debugstr_w(pUri), nUri,
407             debugstr_w(pLocalName), nLocalName);
408     return E_NOTIMPL;
409 }
410
411 static HRESULT WINAPI isaxattributes_getValueFromQName(
412         ISAXAttributes* iface,
413         const WCHAR *pQName,
414         int nQName,
415         const WCHAR **pValue,
416         int *nValue)
417 {
418     saxattributes *This = impl_from_ISAXAttributes( iface );
419
420     FIXME("(%p)->(%s, %d) stub\n", This, debugstr_w(pQName), nQName);
421     return E_NOTIMPL;
422 }
423
424 static const struct ISAXAttributesVtbl isaxattributes_vtbl =
425 {
426     isaxattributes_QueryInterface,
427     isaxattributes_AddRef,
428     isaxattributes_Release,
429     isaxattributes_getLength,
430     isaxattributes_getURI,
431     isaxattributes_getLocalName,
432     isaxattributes_getQName,
433     isaxattributes_getName,
434     isaxattributes_getIndexFromName,
435     isaxattributes_getIndexFromQName,
436     isaxattributes_getType,
437     isaxattributes_getTypeFromName,
438     isaxattributes_getTypeFromQName,
439     isaxattributes_getValue,
440     isaxattributes_getValueFromName,
441     isaxattributes_getValueFromQName
442 };
443
444 static HRESULT SAXAttributes_create(saxattributes **attr,
445         int nb_attributes, const xmlChar **xmlAttributes)
446 {
447     saxattributes *attributes;
448     int index;
449
450     attributes = HeapAlloc(GetProcessHeap(), 0, sizeof(*attributes));
451     if(!attributes)
452         return E_OUTOFMEMORY;
453
454     attributes->lpSAXAttributesVtbl = &isaxattributes_vtbl;
455     attributes->ref = 1;
456
457     attributes->nb_attributes = nb_attributes;
458
459     attributes->szLocalname =
460         HeapAlloc(GetProcessHeap(), 0, sizeof(BSTR)*nb_attributes);
461     attributes->szPrefix =
462         HeapAlloc(GetProcessHeap(), 0, sizeof(BSTR)*nb_attributes);
463     attributes->szURI =
464         HeapAlloc(GetProcessHeap(), 0, sizeof(BSTR)*nb_attributes);
465     attributes->szValue =
466         HeapAlloc(GetProcessHeap(), 0, sizeof(BSTR)*nb_attributes);
467
468     if(!attributes->szLocalname || !attributes->szPrefix
469             || !attributes->szURI || !attributes->szValue)
470     {
471         if(attributes->szLocalname)
472             HeapFree(GetProcessHeap(), 0, attributes->szLocalname);
473         if(attributes->szPrefix)
474             HeapFree(GetProcessHeap(), 0, attributes->szPrefix);
475         if(attributes->szURI)
476             HeapFree(GetProcessHeap(), 0, attributes->szURI);
477         if(attributes->szValue)
478             HeapFree(GetProcessHeap(), 0, attributes->szValue);
479         return E_FAIL;
480     }
481
482     for(index=0; index<nb_attributes; index++)
483     {
484         attributes->szLocalname[index] =
485             bstr_from_xmlChar(xmlAttributes[index*5]);
486         attributes->szPrefix[index] =
487             bstr_from_xmlChar(xmlAttributes[index*5+1]);
488         attributes->szURI[index] =
489             bstr_from_xmlChar(xmlAttributes[index*5+2]);
490         attributes->szValue[index] =
491             bstr_from_xmlCharN(xmlAttributes[index*5+3],
492                     xmlAttributes[index*5+4]-xmlAttributes[index*5+3]);
493     }
494
495     *attr = attributes;
496
497     TRACE("returning %p\n", *attr);
498
499     return S_OK;
500 }
501
502 /*** LibXML callbacks ***/
503 static void libxmlStartDocument(void *ctx)
504 {
505     saxlocator *This = ctx;
506     HRESULT hr;
507
508     if(This->saxreader->contentHandler)
509     {
510         hr = ISAXContentHandler_startDocument(This->saxreader->contentHandler);
511         if(hr != S_OK)
512             format_error_message_from_id(This, hr);
513     }
514
515     update_position(This, NULL);
516 }
517
518 static void libxmlEndDocument(void *ctx)
519 {
520     saxlocator *This = ctx;
521     HRESULT hr;
522
523     This->column = 0;
524     This->line = 0;
525
526     if(This->ret != S_OK) return;
527
528     if(This->saxreader->contentHandler)
529     {
530         hr = ISAXContentHandler_endDocument(This->saxreader->contentHandler);
531         if(hr != S_OK)
532             format_error_message_from_id(This, hr);
533     }
534 }
535
536 static void libxmlStartElementNS(
537         void *ctx,
538         const xmlChar *localname,
539         const xmlChar *prefix,
540         const xmlChar *URI,
541         int nb_namespaces,
542         const xmlChar **namespaces,
543         int nb_attributes,
544         int nb_defaulted,
545         const xmlChar **attributes)
546 {
547     BSTR NamespaceUri, LocalName, QName;
548     saxlocator *This = ctx;
549     HRESULT hr;
550     saxattributes *attr;
551
552     update_position(This, (xmlChar*)This->pParserCtxt->input->cur+1);
553
554     if(This->saxreader->contentHandler)
555     {
556         NamespaceUri = bstr_from_xmlChar(URI);
557         LocalName = bstr_from_xmlChar(localname);
558         QName = bstr_from_xmlChar(localname);
559
560         hr = SAXAttributes_create(&attr, nb_attributes, attributes);
561         if(hr == S_OK)
562         {
563             hr = ISAXContentHandler_startElement(
564                     This->saxreader->contentHandler,
565                     NamespaceUri, SysStringLen(NamespaceUri),
566                     LocalName, SysStringLen(LocalName),
567                     QName, SysStringLen(QName),
568                     (ISAXAttributes*)&attr->lpSAXAttributesVtbl);
569
570             ISAXAttributes_Release((ISAXAttributes*)&attr->lpSAXAttributesVtbl);
571         }
572
573         SysFreeString(NamespaceUri);
574         SysFreeString(LocalName);
575         SysFreeString(QName);
576
577         if(hr != S_OK)
578             format_error_message_from_id(This, hr);
579     }
580 }
581
582 static void libxmlEndElementNS(
583         void *ctx,
584         const xmlChar *localname,
585         const xmlChar *prefix,
586         const xmlChar *URI)
587 {
588     BSTR NamespaceUri, LocalName, QName;
589     saxlocator *This = ctx;
590     HRESULT hr;
591     xmlChar *end;
592
593     end = This->lastCur;
594     while(*end != '<' && *(end+1) != '/') end++;
595     update_position(This, end+2);
596
597     if(This->saxreader->contentHandler)
598     {
599         NamespaceUri = bstr_from_xmlChar(URI);
600         LocalName = bstr_from_xmlChar(localname);
601         QName = bstr_from_xmlChar(localname);
602
603         hr = ISAXContentHandler_endElement(
604                 This->saxreader->contentHandler,
605                 NamespaceUri, SysStringLen(NamespaceUri),
606                 LocalName, SysStringLen(LocalName),
607                 QName, SysStringLen(QName));
608
609         SysFreeString(NamespaceUri);
610         SysFreeString(LocalName);
611         SysFreeString(QName);
612
613         if(hr != S_OK)
614             format_error_message_from_id(This, hr);
615     }
616 }
617
618 static void libxmlCharacters(
619         void *ctx,
620         const xmlChar *ch,
621         int len)
622 {
623     BSTR Chars;
624     saxlocator *This = ctx;
625     HRESULT hr;
626     xmlChar *end;
627     xmlChar *lastCurCopy;
628     xmlChar *chEnd;
629     int columnCopy;
630     int lineCopy;
631
632     if(*(This->lastCur-1) != '>' && *(This->lastCur-1) != '/') return;
633
634     if(*(This->lastCur-1) != '>')
635     {
636         end = (xmlChar*)This->pParserCtxt->input->cur-len;
637         while(*(end-1) != '>') end--;
638         update_position(This, end);
639     }
640
641     chEnd = This->lastCur+len;
642     while(*chEnd != '<') chEnd++;
643
644     Chars = bstr_from_xmlChar(ch);
645
646     lastCurCopy = This->lastCur;
647     columnCopy = This->column;
648     lineCopy = This->line;
649     end = This->lastCur;
650
651     if(This->saxreader->contentHandler)
652     {
653         while(This->lastCur < chEnd)
654         {
655             end = This->lastCur;
656             while(end < chEnd-1)
657             {
658                 if(*end == '\r') break;
659                 end++;
660             }
661
662             Chars = bstr_from_xmlChar(This->lastCur);
663
664             if(*end == '\r' && *(end+1) == '\n')
665             {
666                 memmove((WCHAR*)Chars+(end-This->lastCur),
667                         (WCHAR*)Chars+(end-This->lastCur)+1,
668                         (SysStringLen(Chars)-(end-This->lastCur))*sizeof(WCHAR));
669                 SysReAllocStringLen(&Chars, Chars, SysStringLen(Chars)-1);
670             }
671             else if(*end == '\r') Chars[end-This->lastCur] = '\n';
672
673             hr = ISAXContentHandler_characters(This->saxreader->contentHandler, Chars, end-This->lastCur+1);
674             SysFreeString(Chars);
675             if(hr != S_OK)
676             {
677                 format_error_message_from_id(This, hr);
678                 return;
679             }
680
681             if(*(end+1) == '\n') end++;
682             if(end < chEnd) end++;
683
684             This->column += end-This->lastCur;
685             This->lastCur = end;
686         }
687
688         This->lastCur = lastCurCopy;
689         This->column = columnCopy;
690         This->line = lineCopy;
691         update_position(This, chEnd);
692     }
693 }
694
695 static void libxmlSetDocumentLocator(
696         void *ctx,
697         xmlSAXLocatorPtr loc)
698 {
699     saxlocator *This = ctx;
700     HRESULT hr;
701
702     hr = ISAXContentHandler_putDocumentLocator(This->saxreader->contentHandler,
703             (ISAXLocator*)&This->lpSAXLocatorVtbl);
704
705     if(FAILED(hr))
706         format_error_message_from_id(This, hr);
707 }
708
709 void libxmlFatalError(void *ctx, const char *msg, ...)
710 {
711     saxlocator *This = ctx;
712     char message[1024];
713     WCHAR *wszError;
714     DWORD len;
715     va_list args;
716
717     if(!This->saxreader->errorHandler)
718     {
719         xmlStopParser(This->pParserCtxt);
720         This->ret = E_FAIL;
721         return;
722     }
723
724     FIXME("Error handling is not compatible.\n");
725
726     va_start(args, msg);
727     vsprintf(message, msg, args);
728     va_end(args);
729
730     len = MultiByteToWideChar(CP_ACP, 0, message, -1, NULL, 0);
731     wszError = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len);
732     MultiByteToWideChar(CP_ACP, 0, message, -1, (LPWSTR)wszError, len);
733
734     ISAXErrorHandler_fatalError(This->saxreader->errorHandler,
735             (ISAXLocator*)&This->lpSAXLocatorVtbl, wszError, E_FAIL);
736
737     HeapFree(GetProcessHeap(), 0, wszError);
738
739     xmlStopParser(This->pParserCtxt);
740     This->ret = E_FAIL;
741 }
742
743 /*** ISAXLocator interface ***/
744 /*** IUnknown methods ***/
745 static HRESULT WINAPI isaxlocator_QueryInterface(ISAXLocator* iface, REFIID riid, void **ppvObject)
746 {
747     saxlocator *This = impl_from_ISAXLocator( iface );
748
749     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
750
751     *ppvObject = NULL;
752
753     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
754             IsEqualGUID( riid, &IID_ISAXLocator ))
755     {
756         *ppvObject = iface;
757     }
758     else
759     {
760         FIXME("interface %s not implemented\n", debugstr_guid(riid));
761         return E_NOINTERFACE;
762     }
763
764     ISAXLocator_AddRef( iface );
765
766     return S_OK;
767 }
768
769 static ULONG WINAPI isaxlocator_AddRef(ISAXLocator* iface)
770 {
771     saxlocator *This = impl_from_ISAXLocator( iface );
772     TRACE("%p\n", This );
773     return InterlockedIncrement( &This->ref );
774 }
775
776 static ULONG WINAPI isaxlocator_Release(
777         ISAXLocator* iface)
778 {
779     saxlocator *This = impl_from_ISAXLocator( iface );
780     LONG ref;
781
782     TRACE("%p\n", This );
783
784     ref = InterlockedDecrement( &This->ref );
785     if ( ref == 0 )
786     {
787         if(This->publicId)
788             SysFreeString(This->publicId);
789         if(This->systemId)
790             SysFreeString(This->systemId);
791
792         ISAXXMLReader_Release((ISAXXMLReader*)&This->saxreader->lpSAXXMLReaderVtbl);
793         HeapFree( GetProcessHeap(), 0, This );
794     }
795
796     return ref;
797 }
798
799 /*** ISAXLocator methods ***/
800 static HRESULT WINAPI isaxlocator_getColumnNumber(
801         ISAXLocator* iface,
802         int *pnColumn)
803 {
804     saxlocator *This = impl_from_ISAXLocator( iface );
805
806     *pnColumn = This->column;
807     return S_OK;
808 }
809
810 static HRESULT WINAPI isaxlocator_getLineNumber(
811         ISAXLocator* iface,
812         int *pnLine)
813 {
814     saxlocator *This = impl_from_ISAXLocator( iface );
815
816     *pnLine = This->line;
817     return S_OK;
818 }
819
820 static HRESULT WINAPI isaxlocator_getPublicId(
821         ISAXLocator* iface,
822         const WCHAR ** ppwchPublicId)
823 {
824     BSTR publicId;
825     saxlocator *This = impl_from_ISAXLocator( iface );
826
827     if(This->publicId) SysFreeString(This->publicId);
828
829     publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt));
830     if(SysStringLen(publicId))
831         This->publicId = (WCHAR*)&publicId;
832     else
833     {
834         SysFreeString(publicId);
835         This->publicId = NULL;
836     }
837
838     *ppwchPublicId = This->publicId;
839     return S_OK;
840 }
841
842 static HRESULT WINAPI isaxlocator_getSystemId(
843         ISAXLocator* iface,
844         const WCHAR ** ppwchSystemId)
845 {
846     BSTR systemId;
847     saxlocator *This = impl_from_ISAXLocator( iface );
848
849     if(This->systemId) SysFreeString(This->systemId);
850
851     systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt));
852     if(SysStringLen(systemId))
853         This->systemId = (WCHAR*)&systemId;
854     else
855     {
856         SysFreeString(systemId);
857         This->systemId = NULL;
858     }
859
860     *ppwchSystemId = This->systemId;
861     return S_OK;
862 }
863
864 static const struct ISAXLocatorVtbl isaxlocator_vtbl =
865 {
866     isaxlocator_QueryInterface,
867     isaxlocator_AddRef,
868     isaxlocator_Release,
869     isaxlocator_getColumnNumber,
870     isaxlocator_getLineNumber,
871     isaxlocator_getPublicId,
872     isaxlocator_getSystemId
873 };
874
875 static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator)
876 {
877     saxlocator *locator;
878
879     locator = HeapAlloc( GetProcessHeap(), 0, sizeof (*locator) );
880     if( !locator )
881         return E_OUTOFMEMORY;
882
883     locator->lpSAXLocatorVtbl = &isaxlocator_vtbl;
884     locator->ref = 1;
885
886     locator->saxreader = reader;
887     ISAXXMLReader_AddRef((ISAXXMLReader*)&reader->lpSAXXMLReaderVtbl);
888
889     locator->pParserCtxt = NULL;
890     locator->publicId = NULL;
891     locator->systemId = NULL;
892     locator->lastCur = NULL;
893     locator->line = 0;
894     locator->column = 0;
895     locator->ret = S_OK;
896
897     *ppsaxlocator = locator;
898
899     TRACE("returning %p\n", *ppsaxlocator);
900
901     return S_OK;
902 }
903
904 /*** IVBSAXXMLReader interface ***/
905 /*** IUnknown methods ***/
906 static HRESULT WINAPI saxxmlreader_QueryInterface(IVBSAXXMLReader* iface, REFIID riid, void **ppvObject)
907 {
908     saxreader *This = impl_from_IVBSAXXMLReader( iface );
909
910     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
911
912     *ppvObject = NULL;
913
914     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
915          IsEqualGUID( riid, &IID_IDispatch ) ||
916          IsEqualGUID( riid, &IID_IVBSAXXMLReader ))
917     {
918         *ppvObject = iface;
919     }
920     else if( IsEqualGUID( riid, &IID_ISAXXMLReader ))
921     {
922         *ppvObject = (ISAXXMLReader*)&This->lpSAXXMLReaderVtbl;
923     }
924     else
925     {
926         FIXME("interface %s not implemented\n", debugstr_guid(riid));
927         return E_NOINTERFACE;
928     }
929
930     IVBSAXXMLReader_AddRef( iface );
931
932     return S_OK;
933 }
934
935 static ULONG WINAPI saxxmlreader_AddRef(IVBSAXXMLReader* iface)
936 {
937     saxreader *This = impl_from_IVBSAXXMLReader( iface );
938     TRACE("%p\n", This );
939     return InterlockedIncrement( &This->ref );
940 }
941
942 static ULONG WINAPI saxxmlreader_Release(
943     IVBSAXXMLReader* iface)
944 {
945     saxreader *This = impl_from_IVBSAXXMLReader( iface );
946     LONG ref;
947
948     TRACE("%p\n", This );
949
950     ref = InterlockedDecrement( &This->ref );
951     if ( ref == 0 )
952     {
953         if(This->contentHandler)
954             ISAXContentHandler_Release(This->contentHandler);
955
956         if(This->errorHandler)
957             ISAXErrorHandler_Release(This->errorHandler);
958
959         HeapFree( GetProcessHeap(), 0, This );
960     }
961
962     return ref;
963 }
964 /*** IDispatch ***/
965 static HRESULT WINAPI saxxmlreader_GetTypeInfoCount( IVBSAXXMLReader *iface, UINT* pctinfo )
966 {
967     saxreader *This = impl_from_IVBSAXXMLReader( iface );
968
969     TRACE("(%p)->(%p)\n", This, pctinfo);
970
971     *pctinfo = 1;
972
973     return S_OK;
974 }
975
976 static HRESULT WINAPI saxxmlreader_GetTypeInfo(
977     IVBSAXXMLReader *iface,
978     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
979 {
980     saxreader *This = impl_from_IVBSAXXMLReader( iface );
981     HRESULT hr;
982
983     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
984
985     hr = get_typeinfo(IVBSAXXMLReader_tid, ppTInfo);
986
987     return hr;
988 }
989
990 static HRESULT WINAPI saxxmlreader_GetIDsOfNames(
991     IVBSAXXMLReader *iface,
992     REFIID riid,
993     LPOLESTR* rgszNames,
994     UINT cNames,
995     LCID lcid,
996     DISPID* rgDispId)
997 {
998     saxreader *This = impl_from_IVBSAXXMLReader( iface );
999     ITypeInfo *typeinfo;
1000     HRESULT hr;
1001
1002     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1003           lcid, rgDispId);
1004
1005     if(!rgszNames || cNames == 0 || !rgDispId)
1006         return E_INVALIDARG;
1007
1008     hr = get_typeinfo(IVBSAXXMLReader_tid, &typeinfo);
1009     if(SUCCEEDED(hr))
1010     {
1011         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1012         ITypeInfo_Release(typeinfo);
1013     }
1014
1015     return hr;
1016 }
1017
1018 static HRESULT WINAPI saxxmlreader_Invoke(
1019     IVBSAXXMLReader *iface,
1020     DISPID dispIdMember,
1021     REFIID riid,
1022     LCID lcid,
1023     WORD wFlags,
1024     DISPPARAMS* pDispParams,
1025     VARIANT* pVarResult,
1026     EXCEPINFO* pExcepInfo,
1027     UINT* puArgErr)
1028 {
1029     saxreader *This = impl_from_IVBSAXXMLReader( iface );
1030     ITypeInfo *typeinfo;
1031     HRESULT hr;
1032
1033     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1034           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1035
1036     hr = get_typeinfo(IVBSAXXMLReader_tid, &typeinfo);
1037     if(SUCCEEDED(hr))
1038     {
1039         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
1040                 pVarResult, pExcepInfo, puArgErr);
1041         ITypeInfo_Release(typeinfo);
1042     }
1043
1044     return hr;
1045 }
1046
1047 /*** IVBSAXXMLReader methods ***/
1048 static HRESULT WINAPI saxxmlreader_getFeature(
1049     IVBSAXXMLReader* iface,
1050     const WCHAR *pFeature,
1051     VARIANT_BOOL *pValue)
1052 {
1053     saxreader *This = impl_from_IVBSAXXMLReader( iface );
1054
1055     FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pFeature), pValue);
1056     return E_NOTIMPL;
1057 }
1058
1059 static HRESULT WINAPI saxxmlreader_putFeature(
1060     IVBSAXXMLReader* iface,
1061     const WCHAR *pFeature,
1062     VARIANT_BOOL vfValue)
1063 {
1064     saxreader *This = impl_from_IVBSAXXMLReader( iface );
1065
1066     FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(pFeature), vfValue);
1067     return E_NOTIMPL;
1068 }
1069
1070 static HRESULT WINAPI saxxmlreader_getProperty(
1071     IVBSAXXMLReader* iface,
1072     const WCHAR *pProp,
1073     VARIANT *pValue)
1074 {
1075     saxreader *This = impl_from_IVBSAXXMLReader( iface );
1076
1077     FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pProp), pValue);
1078     return E_NOTIMPL;
1079 }
1080
1081 static HRESULT WINAPI saxxmlreader_putProperty(
1082     IVBSAXXMLReader* iface,
1083     const WCHAR *pProp,
1084     VARIANT value)
1085 {
1086     saxreader *This = impl_from_IVBSAXXMLReader( iface );
1087
1088     FIXME("(%p)->(%s) stub\n", This, debugstr_w(pProp));
1089     return E_NOTIMPL;
1090 }
1091
1092 static HRESULT WINAPI saxxmlreader_getEntityResolver(
1093     IVBSAXXMLReader* iface,
1094     IVBSAXEntityResolver **pEntityResolver)
1095 {
1096     saxreader *This = impl_from_IVBSAXXMLReader( iface );
1097
1098     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
1099     return E_NOTIMPL;
1100 }
1101
1102 static HRESULT WINAPI saxxmlreader_putEntityResolver(
1103     IVBSAXXMLReader* iface,
1104     IVBSAXEntityResolver *pEntityResolver)
1105 {
1106     saxreader *This = impl_from_IVBSAXXMLReader( iface );
1107
1108     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
1109     return E_NOTIMPL;
1110 }
1111
1112 static HRESULT WINAPI saxxmlreader_getContentHandler(
1113     IVBSAXXMLReader* iface,
1114     IVBSAXContentHandler **ppContentHandler)
1115 {
1116     saxreader *This = impl_from_IVBSAXXMLReader( iface );
1117
1118     FIXME("(%p)->(%p) stub\n", This, ppContentHandler);
1119     return E_NOTIMPL;
1120 }
1121
1122 static HRESULT WINAPI saxxmlreader_putContentHandler(
1123     IVBSAXXMLReader* iface,
1124     IVBSAXContentHandler *contentHandler)
1125 {
1126     saxreader *This = impl_from_IVBSAXXMLReader( iface );
1127
1128     FIXME("(%p)->(%p) stub\n", This, contentHandler);
1129     return E_NOTIMPL;
1130 }
1131
1132 static HRESULT WINAPI saxxmlreader_getDTDHandler(
1133     IVBSAXXMLReader* iface,
1134     IVBSAXDTDHandler **pDTDHandler)
1135 {
1136     saxreader *This = impl_from_IVBSAXXMLReader( iface );
1137
1138     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
1139     return E_NOTIMPL;
1140 }
1141
1142 static HRESULT WINAPI saxxmlreader_putDTDHandler(
1143     IVBSAXXMLReader* iface,
1144     IVBSAXDTDHandler *pDTDHandler)
1145 {
1146     saxreader *This = impl_from_IVBSAXXMLReader( iface );
1147
1148     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
1149     return E_NOTIMPL;
1150 }
1151
1152 static HRESULT WINAPI saxxmlreader_getErrorHandler(
1153     IVBSAXXMLReader* iface,
1154     IVBSAXErrorHandler **pErrorHandler)
1155 {
1156     saxreader *This = impl_from_IVBSAXXMLReader( iface );
1157
1158     FIXME("(%p)->(%p) stub\n", This, pErrorHandler);
1159     return E_NOTIMPL;
1160 }
1161
1162 static HRESULT WINAPI saxxmlreader_putErrorHandler(
1163     IVBSAXXMLReader* iface,
1164     IVBSAXErrorHandler *errorHandler)
1165 {
1166     saxreader *This = impl_from_IVBSAXXMLReader( iface );
1167
1168     FIXME("(%p)->(%p) stub\n", This, errorHandler);
1169     return E_NOTIMPL;
1170 }
1171
1172 static HRESULT WINAPI saxxmlreader_getBaseURL(
1173     IVBSAXXMLReader* iface,
1174     const WCHAR **pBaseUrl)
1175 {
1176     saxreader *This = impl_from_IVBSAXXMLReader( iface );
1177
1178     FIXME("(%p)->(%p) stub\n", This, pBaseUrl);
1179     return E_NOTIMPL;
1180 }
1181
1182 static HRESULT WINAPI saxxmlreader_putBaseURL(
1183     IVBSAXXMLReader* iface,
1184     const WCHAR *pBaseUrl)
1185 {
1186     saxreader *This = impl_from_IVBSAXXMLReader( iface );
1187
1188     FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
1189     return E_NOTIMPL;
1190 }
1191
1192 static HRESULT WINAPI saxxmlreader_getSecureBaseURL(
1193     IVBSAXXMLReader* iface,
1194     const WCHAR **pSecureBaseUrl)
1195 {
1196     saxreader *This = impl_from_IVBSAXXMLReader( iface );
1197
1198     FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
1199     return E_NOTIMPL;
1200 }
1201
1202
1203 static HRESULT WINAPI saxxmlreader_putSecureBaseURL(
1204     IVBSAXXMLReader* iface,
1205     const WCHAR *secureBaseUrl)
1206 {
1207     saxreader *This = impl_from_IVBSAXXMLReader( iface );
1208
1209     FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
1210     return E_NOTIMPL;
1211 }
1212
1213 static HRESULT WINAPI saxxmlreader_parse(
1214     IVBSAXXMLReader* iface,
1215     VARIANT varInput)
1216 {
1217     saxreader *This = impl_from_IVBSAXXMLReader( iface );
1218
1219     FIXME("(%p) stub\n", This);
1220     return E_NOTIMPL;
1221 }
1222
1223 static HRESULT WINAPI saxxmlreader_parseURL(
1224     IVBSAXXMLReader* iface,
1225     const WCHAR *url)
1226 {
1227     saxreader *This = impl_from_IVBSAXXMLReader( iface );
1228
1229     FIXME("(%p)->(%s) stub\n", This, debugstr_w(url));
1230     return E_NOTIMPL;
1231 }
1232
1233 static const struct IVBSAXXMLReaderVtbl saxreader_vtbl =
1234 {
1235     saxxmlreader_QueryInterface,
1236     saxxmlreader_AddRef,
1237     saxxmlreader_Release,
1238     saxxmlreader_GetTypeInfoCount,
1239     saxxmlreader_GetTypeInfo,
1240     saxxmlreader_GetIDsOfNames,
1241     saxxmlreader_Invoke,
1242     saxxmlreader_getFeature,
1243     saxxmlreader_putFeature,
1244     saxxmlreader_getProperty,
1245     saxxmlreader_putProperty,
1246     saxxmlreader_getEntityResolver,
1247     saxxmlreader_putEntityResolver,
1248     saxxmlreader_getContentHandler,
1249     saxxmlreader_putContentHandler,
1250     saxxmlreader_getDTDHandler,
1251     saxxmlreader_putDTDHandler,
1252     saxxmlreader_getErrorHandler,
1253     saxxmlreader_putErrorHandler,
1254     saxxmlreader_getBaseURL,
1255     saxxmlreader_putBaseURL,
1256     saxxmlreader_getSecureBaseURL,
1257     saxxmlreader_putSecureBaseURL,
1258     saxxmlreader_parse,
1259     saxxmlreader_parseURL
1260 };
1261
1262 /*** ISAXXMLReader interface ***/
1263 /*** IUnknown methods ***/
1264 static HRESULT WINAPI isaxxmlreader_QueryInterface(ISAXXMLReader* iface, REFIID riid, void **ppvObject)
1265 {
1266     saxreader *This = impl_from_ISAXXMLReader( iface );
1267     return saxxmlreader_QueryInterface((IVBSAXXMLReader*)&This->lpVtbl, riid, ppvObject);
1268 }
1269
1270 static ULONG WINAPI isaxxmlreader_AddRef(ISAXXMLReader* iface)
1271 {
1272     saxreader *This = impl_from_ISAXXMLReader( iface );
1273     return saxxmlreader_AddRef((IVBSAXXMLReader*)&This->lpVtbl);
1274 }
1275
1276 static ULONG WINAPI isaxxmlreader_Release(ISAXXMLReader* iface)
1277 {
1278     saxreader *This = impl_from_ISAXXMLReader( iface );
1279     return saxxmlreader_Release((IVBSAXXMLReader*)&This->lpVtbl);
1280 }
1281
1282 /*** ISAXXMLReader methods ***/
1283 static HRESULT WINAPI isaxxmlreader_getFeature(
1284         ISAXXMLReader* iface,
1285         const WCHAR *pFeature,
1286         VARIANT_BOOL *pValue)
1287 {
1288     saxreader *This = impl_from_ISAXXMLReader( iface );
1289
1290     FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pFeature), pValue);
1291     return E_NOTIMPL;
1292 }
1293
1294 static HRESULT WINAPI isaxxmlreader_putFeature(
1295         ISAXXMLReader* iface,
1296         const WCHAR *pFeature,
1297         VARIANT_BOOL vfValue)
1298 {
1299     saxreader *This = impl_from_ISAXXMLReader( iface );
1300
1301     FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(pFeature), vfValue);
1302     return E_NOTIMPL;
1303 }
1304
1305 static HRESULT WINAPI isaxxmlreader_getProperty(
1306         ISAXXMLReader* iface,
1307         const WCHAR *pProp,
1308         VARIANT *pValue)
1309 {
1310     saxreader *This = impl_from_ISAXXMLReader( iface );
1311
1312     FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pProp), pValue);
1313     return E_NOTIMPL;
1314 }
1315
1316 static HRESULT WINAPI isaxxmlreader_putProperty(
1317         ISAXXMLReader* iface,
1318         const WCHAR *pProp,
1319         VARIANT value)
1320 {
1321     saxreader *This = impl_from_ISAXXMLReader( iface );
1322
1323     FIXME("(%p)->(%s) stub\n", This, debugstr_w(pProp));
1324     return E_NOTIMPL;
1325 }
1326
1327 static HRESULT WINAPI isaxxmlreader_getEntityResolver(
1328         ISAXXMLReader* iface,
1329         ISAXEntityResolver **ppEntityResolver)
1330 {
1331     saxreader *This = impl_from_ISAXXMLReader( iface );
1332
1333     FIXME("(%p)->(%p) stub\n", This, ppEntityResolver);
1334     return E_NOTIMPL;
1335 }
1336
1337 static HRESULT WINAPI isaxxmlreader_putEntityResolver(
1338         ISAXXMLReader* iface,
1339         ISAXEntityResolver *pEntityResolver)
1340 {
1341     saxreader *This = impl_from_ISAXXMLReader( iface );
1342
1343     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
1344     return E_NOTIMPL;
1345 }
1346
1347 static HRESULT WINAPI isaxxmlreader_getContentHandler(
1348         ISAXXMLReader* iface,
1349         ISAXContentHandler **pContentHandler)
1350 {
1351     saxreader *This = impl_from_ISAXXMLReader( iface );
1352
1353     TRACE("(%p)->(%p)\n", This, pContentHandler);
1354     if(pContentHandler == NULL)
1355         return E_POINTER;
1356     if(This->contentHandler)
1357         ISAXContentHandler_AddRef(This->contentHandler);
1358     *pContentHandler = This->contentHandler;
1359
1360     return S_OK;
1361 }
1362
1363 static HRESULT WINAPI isaxxmlreader_putContentHandler(
1364         ISAXXMLReader* iface,
1365         ISAXContentHandler *contentHandler)
1366 {
1367     saxreader *This = impl_from_ISAXXMLReader( iface );
1368
1369     TRACE("(%p)->(%p)\n", This, contentHandler);
1370     if(contentHandler)
1371         ISAXContentHandler_AddRef(contentHandler);
1372     if(This->contentHandler)
1373         ISAXContentHandler_Release(This->contentHandler);
1374     This->contentHandler = contentHandler;
1375
1376     return S_OK;
1377 }
1378
1379 static HRESULT WINAPI isaxxmlreader_getDTDHandler(
1380         ISAXXMLReader* iface,
1381         ISAXDTDHandler **pDTDHandler)
1382 {
1383     saxreader *This = impl_from_ISAXXMLReader( iface );
1384
1385     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
1386     return E_NOTIMPL;
1387 }
1388
1389 static HRESULT WINAPI isaxxmlreader_putDTDHandler(
1390         ISAXXMLReader* iface,
1391         ISAXDTDHandler *pDTDHandler)
1392 {
1393     saxreader *This = impl_from_ISAXXMLReader( iface );
1394
1395     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
1396     return E_NOTIMPL;
1397 }
1398
1399 static HRESULT WINAPI isaxxmlreader_getErrorHandler(
1400         ISAXXMLReader* iface,
1401         ISAXErrorHandler **pErrorHandler)
1402 {
1403     saxreader *This = impl_from_ISAXXMLReader( iface );
1404
1405     TRACE("(%p)->(%p)\n", This, pErrorHandler);
1406     if(pErrorHandler == NULL)
1407         return E_POINTER;
1408     if(This->errorHandler)
1409         ISAXErrorHandler_AddRef(This->errorHandler);
1410     *pErrorHandler = This->errorHandler;
1411
1412     return S_OK;
1413 }
1414
1415 static HRESULT WINAPI isaxxmlreader_putErrorHandler(
1416         ISAXXMLReader* iface,
1417         ISAXErrorHandler *errorHandler)
1418 {
1419     saxreader *This = impl_from_ISAXXMLReader( iface );
1420
1421     TRACE("(%p)->(%p)\n", This, errorHandler);
1422     if(errorHandler)
1423         ISAXErrorHandler_AddRef(errorHandler);
1424     if(This->errorHandler)
1425         ISAXErrorHandler_Release(This->errorHandler);
1426     This->errorHandler = errorHandler;
1427
1428     return S_OK;
1429 }
1430
1431 static HRESULT WINAPI isaxxmlreader_getBaseURL(
1432         ISAXXMLReader* iface,
1433         const WCHAR **pBaseUrl)
1434 {
1435     saxreader *This = impl_from_ISAXXMLReader( iface );
1436
1437     FIXME("(%p)->(%p) stub\n", This, pBaseUrl);
1438     return E_NOTIMPL;
1439 }
1440
1441 static HRESULT WINAPI isaxxmlreader_putBaseURL(
1442         ISAXXMLReader* iface,
1443         const WCHAR *pBaseUrl)
1444 {
1445     saxreader *This = impl_from_ISAXXMLReader( iface );
1446
1447     FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
1448     return E_NOTIMPL;
1449 }
1450
1451 static HRESULT WINAPI isaxxmlreader_getSecureBaseURL(
1452         ISAXXMLReader* iface,
1453         const WCHAR **pSecureBaseUrl)
1454 {
1455     saxreader *This = impl_from_ISAXXMLReader( iface );
1456
1457     FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
1458     return E_NOTIMPL;
1459 }
1460
1461 static HRESULT WINAPI isaxxmlreader_putSecureBaseURL(
1462         ISAXXMLReader* iface,
1463         const WCHAR *secureBaseUrl)
1464 {
1465     saxreader *This = impl_from_ISAXXMLReader( iface );
1466
1467     FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
1468     return E_NOTIMPL;
1469 }
1470
1471 static HRESULT parse_buffer(saxreader *This, xmlChar *buffer)
1472 {
1473     saxlocator *locator;
1474     HRESULT hr;
1475
1476     hr = SAXLocator_create(This, &locator);
1477     if(FAILED(hr))
1478         return E_FAIL;
1479
1480     locator->pParserCtxt = xmlNewParserCtxt();
1481     if(!locator->pParserCtxt)
1482     {
1483         ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1484         return E_FAIL;
1485     }
1486
1487     locator->pParserCtxt->sax = &locator->saxreader->sax;
1488     locator->pParserCtxt->userData = locator;
1489
1490     xmlSetupParserForBuffer(locator->pParserCtxt, buffer, NULL);
1491
1492     if(xmlParseDocument(locator->pParserCtxt)) hr = E_FAIL;
1493     else hr = locator->ret;
1494
1495     if(locator->pParserCtxt)
1496     {
1497         locator->pParserCtxt->sax = NULL;
1498         xmlFreeParserCtxt(locator->pParserCtxt);
1499         locator->pParserCtxt = NULL;
1500     }
1501
1502     ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1503     return S_OK;
1504 }
1505
1506 static HRESULT WINAPI isaxxmlreader_parse(
1507         ISAXXMLReader* iface,
1508         VARIANT varInput)
1509 {
1510     saxreader *This = impl_from_ISAXXMLReader( iface );
1511     xmlChar *data = NULL;
1512     HRESULT hr;
1513
1514     TRACE("(%p)\n", This);
1515
1516     hr = S_OK;
1517     switch(V_VT(&varInput))
1518     {
1519         case VT_BSTR:
1520             data = xmlChar_from_wchar(V_BSTR(&varInput));
1521             hr = parse_buffer(This, data);
1522             break;
1523         case VT_ARRAY|VT_UI1: {
1524             void *pSAData;
1525             LONG lBound, uBound;
1526             ULONG dataRead;
1527
1528             hr = SafeArrayGetLBound(V_ARRAY(&varInput), 1, &lBound);
1529             if(hr != S_OK) break;
1530             hr = SafeArrayGetUBound(V_ARRAY(&varInput), 1, &uBound);
1531             if(hr != S_OK) break;
1532             dataRead = (uBound-lBound)*SafeArrayGetElemsize(V_ARRAY(&varInput));
1533             data = HeapAlloc(GetProcessHeap(), 0, dataRead+1);
1534             if(!data) break;
1535             hr = SafeArrayAccessData(V_ARRAY(&varInput), (void**)&pSAData);
1536             if(hr != S_OK) break;
1537             memcpy(data, pSAData, dataRead);
1538             data[dataRead] = '\0';
1539             hr = parse_buffer(This, data);
1540             SafeArrayUnaccessData(V_ARRAY(&varInput));
1541             break;
1542         }
1543         case VT_UNKNOWN:
1544         case VT_DISPATCH: {
1545             IPersistStream *persistStream;
1546             IStream *stream = NULL;
1547             IXMLDOMDocument *xmlDoc;
1548
1549             if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
1550                         &IID_IPersistStream, (void**)&persistStream) == S_OK)
1551             {
1552                 hr = IPersistStream_Save(persistStream, stream, TRUE);
1553                 IPersistStream_Release(persistStream);
1554                 if(hr != S_OK) break;
1555             }
1556             if(stream || IUnknown_QueryInterface(V_UNKNOWN(&varInput),
1557                         &IID_IStream, (void**)&stream) == S_OK)
1558             {
1559                 STATSTG dataInfo;
1560                 ULONG dataRead;
1561
1562                 while(1)
1563                 {
1564                     hr = IStream_Stat(stream, &dataInfo, STATFLAG_NONAME);
1565                     if(hr == E_PENDING) continue;
1566                     break;
1567                 }
1568                 data = HeapAlloc(GetProcessHeap(), 0,
1569                         dataInfo.cbSize.QuadPart+1);
1570                 while(1)
1571                 {
1572                     hr = IStream_Read(stream, data,
1573                             dataInfo.cbSize.QuadPart, &dataRead);
1574                     if(hr == E_PENDING) continue;
1575                     break;
1576                 }
1577                 data[dataInfo.cbSize.QuadPart] = '\0';
1578                 hr = parse_buffer(This, data);
1579                 IStream_Release(stream);
1580                 break;
1581             }
1582             if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
1583                                        &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK)
1584             {
1585                 BSTR bstrData;
1586
1587                 IXMLDOMDocument_get_xml(xmlDoc, &bstrData);
1588                 data = xmlChar_from_wchar(bstrData);
1589                 hr = parse_buffer(This, data);
1590                 IXMLDOMDocument_Release(xmlDoc);
1591                 hr = E_NOTIMPL;
1592                 break;
1593             }
1594         }
1595         default:
1596             WARN("vt %d not implemented\n", V_VT(&varInput));
1597             hr = E_INVALIDARG;
1598     }
1599
1600     HeapFree(GetProcessHeap(), 0, data);
1601     return hr;
1602 }
1603
1604 static HRESULT saxreader_onDataAvailable(void *obj, char *ptr, DWORD len)
1605 {
1606     saxreader *This = obj;
1607     xmlChar *data;
1608     HRESULT hr;
1609
1610     data = HeapAlloc(GetProcessHeap(), 0, len+1);
1611     memcpy(data, ptr, len);
1612     data[len] = 0;
1613
1614     hr = parse_buffer(This, data);
1615
1616     HeapFree(GetProcessHeap(), 0, data);
1617     return hr;
1618 }
1619
1620 static HRESULT WINAPI isaxxmlreader_parseURL(
1621         ISAXXMLReader* iface,
1622         const WCHAR *url)
1623 {
1624     saxreader *This = impl_from_ISAXXMLReader( iface );
1625     bsc_t *bsc;
1626     HRESULT hr;
1627
1628     TRACE("(%p)->(%s) stub\n", This, debugstr_w(url));
1629
1630     hr = bind_url(url, saxreader_onDataAvailable, This, &bsc);
1631     if(FAILED(hr))
1632         return hr;
1633
1634     detach_bsc(bsc);
1635
1636     return S_OK;
1637 }
1638
1639 static const struct ISAXXMLReaderVtbl isaxreader_vtbl =
1640 {
1641     isaxxmlreader_QueryInterface,
1642     isaxxmlreader_AddRef,
1643     isaxxmlreader_Release,
1644     isaxxmlreader_getFeature,
1645     isaxxmlreader_putFeature,
1646     isaxxmlreader_getProperty,
1647     isaxxmlreader_putProperty,
1648     isaxxmlreader_getEntityResolver,
1649     isaxxmlreader_putEntityResolver,
1650     isaxxmlreader_getContentHandler,
1651     isaxxmlreader_putContentHandler,
1652     isaxxmlreader_getDTDHandler,
1653     isaxxmlreader_putDTDHandler,
1654     isaxxmlreader_getErrorHandler,
1655     isaxxmlreader_putErrorHandler,
1656     isaxxmlreader_getBaseURL,
1657     isaxxmlreader_putBaseURL,
1658     isaxxmlreader_getSecureBaseURL,
1659     isaxxmlreader_putSecureBaseURL,
1660     isaxxmlreader_parse,
1661     isaxxmlreader_parseURL
1662 };
1663
1664 HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj)
1665 {
1666     saxreader *reader;
1667
1668     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
1669
1670     reader = HeapAlloc( GetProcessHeap(), 0, sizeof (*reader) );
1671     if( !reader )
1672         return E_OUTOFMEMORY;
1673
1674     reader->lpVtbl = &saxreader_vtbl;
1675     reader->lpSAXXMLReaderVtbl = &isaxreader_vtbl;
1676     reader->ref = 1;
1677     reader->contentHandler = NULL;
1678     reader->errorHandler = NULL;
1679
1680     memset(&reader->sax, 0, sizeof(xmlSAXHandler));
1681     reader->sax.initialized = XML_SAX2_MAGIC;
1682     reader->sax.startDocument = libxmlStartDocument;
1683     reader->sax.endDocument = libxmlEndDocument;
1684     reader->sax.startElementNs = libxmlStartElementNS;
1685     reader->sax.endElementNs = libxmlEndElementNS;
1686     reader->sax.characters = libxmlCharacters;
1687     reader->sax.setDocumentLocator = libxmlSetDocumentLocator;
1688     reader->sax.error = libxmlFatalError;
1689     reader->sax.fatalError = libxmlFatalError;
1690
1691     *ppObj = &reader->lpVtbl;
1692
1693     TRACE("returning iface %p\n", *ppObj);
1694
1695     return S_OK;
1696 }
1697
1698 #else
1699
1700 HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj)
1701 {
1702     MESSAGE("This program tried to use a SAX XML Reader object, but\n"
1703             "libxml2 support was not present at compile time.\n");
1704     return E_NOTIMPL;
1705 }
1706
1707 #endif