msxml3: Added ISAXContentHandler_endElement event.
[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     int lastLine;
66     int lastColumn;
67 } saxlocator;
68
69 static inline saxreader *impl_from_IVBSAXXMLReader( IVBSAXXMLReader *iface )
70 {
71     return (saxreader *)((char*)iface - FIELD_OFFSET(saxreader, lpVtbl));
72 }
73
74 static inline saxreader *impl_from_ISAXXMLReader( ISAXXMLReader *iface )
75 {
76     return (saxreader *)((char*)iface - FIELD_OFFSET(saxreader, lpSAXXMLReaderVtbl));
77 }
78
79 static inline saxlocator *impl_from_ISAXLocator( ISAXLocator *iface )
80 {
81     return (saxlocator *)((char*)iface - FIELD_OFFSET(saxlocator, lpSAXLocatorVtbl));
82 }
83
84 /*** LibXML callbacks ***/
85 static void libxmlStartDocument(void *ctx)
86 {
87     saxlocator *This = ctx;
88     HRESULT hr;
89
90     if(This->saxreader->contentHandler)
91     {
92         hr = ISAXContentHandler_startDocument(This->saxreader->contentHandler);
93         if(FAILED(hr))
94         {
95             xmlStopParser(This->pParserCtxt);
96             This->ret = hr;
97         }
98     }
99
100     This->lastColumn = xmlSAX2GetColumnNumber(This->pParserCtxt);
101     This->lastLine = xmlSAX2GetLineNumber(This->pParserCtxt);
102 }
103
104 static void libxmlEndDocument(void *ctx)
105 {
106     saxlocator *This = ctx;
107     HRESULT hr;
108
109     This->lastColumn = 0;
110     This->lastLine = 0;
111
112     if(This->saxreader->contentHandler)
113     {
114         hr = ISAXContentHandler_endDocument(This->saxreader->contentHandler);
115         if(FAILED(hr))
116         {
117             xmlStopParser(This->pParserCtxt);
118             This->ret = hr;
119         }
120     }
121 }
122
123 static void libxmlStartElementNS(
124         void *ctx,
125         const xmlChar *localname,
126         const xmlChar *prefix,
127         const xmlChar *URI,
128         int nb_namespaces,
129         const xmlChar **namespaces,
130         int nb_attributes,
131         int nb_defaulted,
132         const xmlChar **attributes)
133 {
134     BSTR NamespaceUri, LocalName, QName;
135     saxlocator *This = ctx;
136     HRESULT hr;
137
138     FIXME("Arguments processing not yet implemented.\n");
139
140     This->lastColumn = xmlSAX2GetColumnNumber(This->pParserCtxt)+1;
141     This->lastLine = xmlSAX2GetLineNumber(This->pParserCtxt);
142
143     if(This->saxreader->contentHandler)
144     {
145         NamespaceUri = bstr_from_xmlChar(URI);
146         LocalName = bstr_from_xmlChar(localname);
147         QName = bstr_from_xmlChar(localname);
148
149         hr = ISAXContentHandler_startElement(
150                 This->saxreader->contentHandler,
151                 NamespaceUri, SysStringLen(NamespaceUri),
152                 LocalName, SysStringLen(LocalName),
153                 QName, SysStringLen(QName),
154                 NULL);
155
156         SysFreeString(NamespaceUri);
157         SysFreeString(LocalName);
158         SysFreeString(QName);
159
160         if(FAILED(hr))
161         {
162             xmlStopParser(This->pParserCtxt);
163             This->ret = hr;
164         }
165     }
166 }
167
168 static void libxmlEndElementNS(
169         void *ctx,
170         const xmlChar *localname,
171         const xmlChar *prefix,
172         const xmlChar *URI)
173 {
174     BSTR NamespaceUri, LocalName, QName;
175     saxlocator *This = ctx;
176     HRESULT hr;
177
178     This->lastColumn = xmlSAX2GetColumnNumber(This->pParserCtxt);
179     This->lastLine = xmlSAX2GetLineNumber(This->pParserCtxt);
180
181     if(This->saxreader->contentHandler)
182     {
183         NamespaceUri = bstr_from_xmlChar(URI);
184         LocalName = bstr_from_xmlChar(localname);
185         QName = bstr_from_xmlChar(localname);
186
187         hr = ISAXContentHandler_endElement(
188                 This->saxreader->contentHandler,
189                 NamespaceUri, SysStringLen(NamespaceUri),
190                 LocalName, SysStringLen(LocalName),
191                 QName, SysStringLen(QName));
192
193         SysFreeString(NamespaceUri);
194         SysFreeString(LocalName);
195         SysFreeString(QName);
196
197         if(FAILED(hr))
198         {
199             xmlStopParser(This->pParserCtxt);
200             This->ret = hr;
201         }
202     }
203 }
204
205 /*** ISAXLocator interface ***/
206 /*** IUnknown methods ***/
207 static HRESULT WINAPI isaxlocator_QueryInterface(ISAXLocator* iface, REFIID riid, void **ppvObject)
208 {
209     saxlocator *This = impl_from_ISAXLocator( iface );
210
211     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
212
213     *ppvObject = NULL;
214
215     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
216             IsEqualGUID( riid, &IID_ISAXLocator ))
217     {
218         *ppvObject = iface;
219     }
220     else
221     {
222         FIXME("interface %s not implemented\n", debugstr_guid(riid));
223         return E_NOINTERFACE;
224     }
225
226     ISAXLocator_AddRef( iface );
227
228     return S_OK;
229 }
230
231 static ULONG WINAPI isaxlocator_AddRef(ISAXLocator* iface)
232 {
233     saxlocator *This = impl_from_ISAXLocator( iface );
234     TRACE("%p\n", This );
235     return InterlockedIncrement( &This->ref );
236 }
237
238 static ULONG WINAPI isaxlocator_Release(
239         ISAXLocator* iface)
240 {
241     saxlocator *This = impl_from_ISAXLocator( iface );
242     LONG ref;
243
244     TRACE("%p\n", This );
245
246     ref = InterlockedDecrement( &This->ref );
247     if ( ref == 0 )
248     {
249         ISAXXMLReader_Release((ISAXXMLReader*)&This->saxreader->lpSAXXMLReaderVtbl);
250         HeapFree( GetProcessHeap(), 0, This );
251     }
252
253     return ref;
254 }
255
256 /*** ISAXLocator methods ***/
257 static HRESULT WINAPI isaxlocator_getColumnNumber(
258         ISAXLocator* iface,
259         int *pnColumn)
260 {
261     saxlocator *This = impl_from_ISAXLocator( iface );
262
263     *pnColumn = This->lastColumn;
264     return S_OK;
265 }
266
267 static HRESULT WINAPI isaxlocator_getLineNumber(
268         ISAXLocator* iface,
269         int *pnLine)
270 {
271     saxlocator *This = impl_from_ISAXLocator( iface );
272
273     *pnLine = This->lastLine;
274     return S_OK;
275 }
276
277 static HRESULT WINAPI isaxlocator_getPublicId(
278         ISAXLocator* iface,
279         const WCHAR ** ppwchPublicId)
280 {
281     saxlocator *This = impl_from_ISAXLocator( iface );
282
283     FIXME("(%p)->(%p) stub\n", This, ppwchPublicId);
284     return E_NOTIMPL;
285 }
286
287 static HRESULT WINAPI isaxlocator_getSystemId(
288         ISAXLocator* iface,
289         const WCHAR ** ppwchSystemId)
290 {
291     saxlocator *This = impl_from_ISAXLocator( iface );
292
293     FIXME("(%p)->(%p) stub\n", This, ppwchSystemId);
294     return E_NOTIMPL;
295 }
296
297 static const struct ISAXLocatorVtbl isaxlocator_vtbl =
298 {
299     isaxlocator_QueryInterface,
300     isaxlocator_AddRef,
301     isaxlocator_Release,
302     isaxlocator_getColumnNumber,
303     isaxlocator_getLineNumber,
304     isaxlocator_getPublicId,
305     isaxlocator_getSystemId
306 };
307
308 static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator)
309 {
310     saxlocator *locator;
311
312     locator = HeapAlloc( GetProcessHeap(), 0, sizeof (*locator) );
313     if( !locator )
314         return E_OUTOFMEMORY;
315
316     locator->lpSAXLocatorVtbl = &isaxlocator_vtbl;
317     locator->ref = 1;
318
319     locator->saxreader = reader;
320     ISAXXMLReader_AddRef((ISAXXMLReader*)&reader->lpSAXXMLReaderVtbl);
321
322     locator->pParserCtxt = NULL;
323     locator->lastLine = 0;
324     locator->lastColumn = 0;
325     locator->ret = S_OK;
326
327     *ppsaxlocator = locator;
328
329     TRACE("returning %p\n", *ppsaxlocator);
330
331     return S_OK;
332 }
333
334 /*** IVBSAXXMLReader interface ***/
335 /*** IUnknown methods ***/
336 static HRESULT WINAPI saxxmlreader_QueryInterface(IVBSAXXMLReader* iface, REFIID riid, void **ppvObject)
337 {
338     saxreader *This = impl_from_IVBSAXXMLReader( iface );
339
340     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
341
342     *ppvObject = NULL;
343
344     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
345          IsEqualGUID( riid, &IID_IDispatch ) ||
346          IsEqualGUID( riid, &IID_IVBSAXXMLReader ))
347     {
348         *ppvObject = iface;
349     }
350     else if( IsEqualGUID( riid, &IID_ISAXXMLReader ))
351     {
352         *ppvObject = (ISAXXMLReader*)&This->lpSAXXMLReaderVtbl;
353     }
354     else
355     {
356         FIXME("interface %s not implemented\n", debugstr_guid(riid));
357         return E_NOINTERFACE;
358     }
359
360     IVBSAXXMLReader_AddRef( iface );
361
362     return S_OK;
363 }
364
365 static ULONG WINAPI saxxmlreader_AddRef(IVBSAXXMLReader* iface)
366 {
367     saxreader *This = impl_from_IVBSAXXMLReader( iface );
368     TRACE("%p\n", This );
369     return InterlockedIncrement( &This->ref );
370 }
371
372 static ULONG WINAPI saxxmlreader_Release(
373     IVBSAXXMLReader* iface)
374 {
375     saxreader *This = impl_from_IVBSAXXMLReader( iface );
376     LONG ref;
377
378     TRACE("%p\n", This );
379
380     ref = InterlockedDecrement( &This->ref );
381     if ( ref == 0 )
382     {
383         if(This->contentHandler)
384             ISAXContentHandler_Release(This->contentHandler);
385
386         if(This->errorHandler)
387             ISAXErrorHandler_Release(This->errorHandler);
388
389         HeapFree( GetProcessHeap(), 0, This );
390     }
391
392     return ref;
393 }
394 /*** IDispatch ***/
395 static HRESULT WINAPI saxxmlreader_GetTypeInfoCount( IVBSAXXMLReader *iface, UINT* pctinfo )
396 {
397     saxreader *This = impl_from_IVBSAXXMLReader( iface );
398
399     TRACE("(%p)->(%p)\n", This, pctinfo);
400
401     *pctinfo = 1;
402
403     return S_OK;
404 }
405
406 static HRESULT WINAPI saxxmlreader_GetTypeInfo(
407     IVBSAXXMLReader *iface,
408     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
409 {
410     saxreader *This = impl_from_IVBSAXXMLReader( iface );
411     HRESULT hr;
412
413     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
414
415     hr = get_typeinfo(IVBSAXXMLReader_tid, ppTInfo);
416
417     return hr;
418 }
419
420 static HRESULT WINAPI saxxmlreader_GetIDsOfNames(
421     IVBSAXXMLReader *iface,
422     REFIID riid,
423     LPOLESTR* rgszNames,
424     UINT cNames,
425     LCID lcid,
426     DISPID* rgDispId)
427 {
428     saxreader *This = impl_from_IVBSAXXMLReader( iface );
429     ITypeInfo *typeinfo;
430     HRESULT hr;
431
432     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
433           lcid, rgDispId);
434
435     if(!rgszNames || cNames == 0 || !rgDispId)
436         return E_INVALIDARG;
437
438     hr = get_typeinfo(IVBSAXXMLReader_tid, &typeinfo);
439     if(SUCCEEDED(hr))
440     {
441         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
442         ITypeInfo_Release(typeinfo);
443     }
444
445     return hr;
446 }
447
448 static HRESULT WINAPI saxxmlreader_Invoke(
449     IVBSAXXMLReader *iface,
450     DISPID dispIdMember,
451     REFIID riid,
452     LCID lcid,
453     WORD wFlags,
454     DISPPARAMS* pDispParams,
455     VARIANT* pVarResult,
456     EXCEPINFO* pExcepInfo,
457     UINT* puArgErr)
458 {
459     saxreader *This = impl_from_IVBSAXXMLReader( iface );
460     ITypeInfo *typeinfo;
461     HRESULT hr;
462
463     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
464           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
465
466     hr = get_typeinfo(IVBSAXXMLReader_tid, &typeinfo);
467     if(SUCCEEDED(hr))
468     {
469         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
470                 pVarResult, pExcepInfo, puArgErr);
471         ITypeInfo_Release(typeinfo);
472     }
473
474     return hr;
475 }
476
477 /*** IVBSAXXMLReader methods ***/
478 static HRESULT WINAPI saxxmlreader_getFeature(
479     IVBSAXXMLReader* iface,
480     const WCHAR *pFeature,
481     VARIANT_BOOL *pValue)
482 {
483     saxreader *This = impl_from_IVBSAXXMLReader( iface );
484
485     FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pFeature), pValue);
486     return E_NOTIMPL;
487 }
488
489 static HRESULT WINAPI saxxmlreader_putFeature(
490     IVBSAXXMLReader* iface,
491     const WCHAR *pFeature,
492     VARIANT_BOOL vfValue)
493 {
494     saxreader *This = impl_from_IVBSAXXMLReader( iface );
495
496     FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(pFeature), vfValue);
497     return E_NOTIMPL;
498 }
499
500 static HRESULT WINAPI saxxmlreader_getProperty(
501     IVBSAXXMLReader* iface,
502     const WCHAR *pProp,
503     VARIANT *pValue)
504 {
505     saxreader *This = impl_from_IVBSAXXMLReader( iface );
506
507     FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pProp), pValue);
508     return E_NOTIMPL;
509 }
510
511 static HRESULT WINAPI saxxmlreader_putProperty(
512     IVBSAXXMLReader* iface,
513     const WCHAR *pProp,
514     VARIANT value)
515 {
516     saxreader *This = impl_from_IVBSAXXMLReader( iface );
517
518     FIXME("(%p)->(%s) stub\n", This, debugstr_w(pProp));
519     return E_NOTIMPL;
520 }
521
522 static HRESULT WINAPI saxxmlreader_getEntityResolver(
523     IVBSAXXMLReader* iface,
524     IVBSAXEntityResolver **pEntityResolver)
525 {
526     saxreader *This = impl_from_IVBSAXXMLReader( iface );
527
528     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
529     return E_NOTIMPL;
530 }
531
532 static HRESULT WINAPI saxxmlreader_putEntityResolver(
533     IVBSAXXMLReader* iface,
534     IVBSAXEntityResolver *pEntityResolver)
535 {
536     saxreader *This = impl_from_IVBSAXXMLReader( iface );
537
538     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
539     return E_NOTIMPL;
540 }
541
542 static HRESULT WINAPI saxxmlreader_getContentHandler(
543     IVBSAXXMLReader* iface,
544     IVBSAXContentHandler **ppContentHandler)
545 {
546     saxreader *This = impl_from_IVBSAXXMLReader( iface );
547
548     FIXME("(%p)->(%p) stub\n", This, ppContentHandler);
549     return E_NOTIMPL;
550 }
551
552 static HRESULT WINAPI saxxmlreader_putContentHandler(
553     IVBSAXXMLReader* iface,
554     IVBSAXContentHandler *contentHandler)
555 {
556     saxreader *This = impl_from_IVBSAXXMLReader( iface );
557
558     FIXME("(%p)->(%p) stub\n", This, contentHandler);
559     return E_NOTIMPL;
560 }
561
562 static HRESULT WINAPI saxxmlreader_getDTDHandler(
563     IVBSAXXMLReader* iface,
564     IVBSAXDTDHandler **pDTDHandler)
565 {
566     saxreader *This = impl_from_IVBSAXXMLReader( iface );
567
568     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
569     return E_NOTIMPL;
570 }
571
572 static HRESULT WINAPI saxxmlreader_putDTDHandler(
573     IVBSAXXMLReader* iface,
574     IVBSAXDTDHandler *pDTDHandler)
575 {
576     saxreader *This = impl_from_IVBSAXXMLReader( iface );
577
578     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
579     return E_NOTIMPL;
580 }
581
582 static HRESULT WINAPI saxxmlreader_getErrorHandler(
583     IVBSAXXMLReader* iface,
584     IVBSAXErrorHandler **pErrorHandler)
585 {
586     saxreader *This = impl_from_IVBSAXXMLReader( iface );
587
588     FIXME("(%p)->(%p) stub\n", This, pErrorHandler);
589     return E_NOTIMPL;
590 }
591
592 static HRESULT WINAPI saxxmlreader_putErrorHandler(
593     IVBSAXXMLReader* iface,
594     IVBSAXErrorHandler *errorHandler)
595 {
596     saxreader *This = impl_from_IVBSAXXMLReader( iface );
597
598     FIXME("(%p)->(%p) stub\n", This, errorHandler);
599     return E_NOTIMPL;
600 }
601
602 static HRESULT WINAPI saxxmlreader_getBaseURL(
603     IVBSAXXMLReader* iface,
604     const WCHAR **pBaseUrl)
605 {
606     saxreader *This = impl_from_IVBSAXXMLReader( iface );
607
608     FIXME("(%p)->(%p) stub\n", This, pBaseUrl);
609     return E_NOTIMPL;
610 }
611
612 static HRESULT WINAPI saxxmlreader_putBaseURL(
613     IVBSAXXMLReader* iface,
614     const WCHAR *pBaseUrl)
615 {
616     saxreader *This = impl_from_IVBSAXXMLReader( iface );
617
618     FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
619     return E_NOTIMPL;
620 }
621
622 static HRESULT WINAPI saxxmlreader_getSecureBaseURL(
623     IVBSAXXMLReader* iface,
624     const WCHAR **pSecureBaseUrl)
625 {
626     saxreader *This = impl_from_IVBSAXXMLReader( iface );
627
628     FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
629     return E_NOTIMPL;
630 }
631
632
633 static HRESULT WINAPI saxxmlreader_putSecureBaseURL(
634     IVBSAXXMLReader* iface,
635     const WCHAR *secureBaseUrl)
636 {
637     saxreader *This = impl_from_IVBSAXXMLReader( iface );
638
639     FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
640     return E_NOTIMPL;
641 }
642
643 static HRESULT WINAPI saxxmlreader_parse(
644     IVBSAXXMLReader* iface,
645     VARIANT varInput)
646 {
647     saxreader *This = impl_from_IVBSAXXMLReader( iface );
648
649     FIXME("(%p) stub\n", This);
650     return E_NOTIMPL;
651 }
652
653 static HRESULT WINAPI saxxmlreader_parseURL(
654     IVBSAXXMLReader* iface,
655     const WCHAR *url)
656 {
657     saxreader *This = impl_from_IVBSAXXMLReader( iface );
658
659     FIXME("(%p)->(%s) stub\n", This, debugstr_w(url));
660     return E_NOTIMPL;
661 }
662
663 static const struct IVBSAXXMLReaderVtbl saxreader_vtbl =
664 {
665     saxxmlreader_QueryInterface,
666     saxxmlreader_AddRef,
667     saxxmlreader_Release,
668     saxxmlreader_GetTypeInfoCount,
669     saxxmlreader_GetTypeInfo,
670     saxxmlreader_GetIDsOfNames,
671     saxxmlreader_Invoke,
672     saxxmlreader_getFeature,
673     saxxmlreader_putFeature,
674     saxxmlreader_getProperty,
675     saxxmlreader_putProperty,
676     saxxmlreader_getEntityResolver,
677     saxxmlreader_putEntityResolver,
678     saxxmlreader_getContentHandler,
679     saxxmlreader_putContentHandler,
680     saxxmlreader_getDTDHandler,
681     saxxmlreader_putDTDHandler,
682     saxxmlreader_getErrorHandler,
683     saxxmlreader_putErrorHandler,
684     saxxmlreader_getBaseURL,
685     saxxmlreader_putBaseURL,
686     saxxmlreader_getSecureBaseURL,
687     saxxmlreader_putSecureBaseURL,
688     saxxmlreader_parse,
689     saxxmlreader_parseURL
690 };
691
692 /*** ISAXXMLReader interface ***/
693 /*** IUnknown methods ***/
694 static HRESULT WINAPI isaxxmlreader_QueryInterface(ISAXXMLReader* iface, REFIID riid, void **ppvObject)
695 {
696     saxreader *This = impl_from_ISAXXMLReader( iface );
697     return saxxmlreader_QueryInterface((IVBSAXXMLReader*)&This->lpVtbl, riid, ppvObject);
698 }
699
700 static ULONG WINAPI isaxxmlreader_AddRef(ISAXXMLReader* iface)
701 {
702     saxreader *This = impl_from_ISAXXMLReader( iface );
703     return saxxmlreader_AddRef((IVBSAXXMLReader*)&This->lpVtbl);
704 }
705
706 static ULONG WINAPI isaxxmlreader_Release(ISAXXMLReader* iface)
707 {
708     saxreader *This = impl_from_ISAXXMLReader( iface );
709     return saxxmlreader_Release((IVBSAXXMLReader*)&This->lpVtbl);
710 }
711
712 /*** ISAXXMLReader methods ***/
713 static HRESULT WINAPI isaxxmlreader_getFeature(
714         ISAXXMLReader* iface,
715         const WCHAR *pFeature,
716         VARIANT_BOOL *pValue)
717 {
718     saxreader *This = impl_from_ISAXXMLReader( iface );
719
720     FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pFeature), pValue);
721     return E_NOTIMPL;
722 }
723
724 static HRESULT WINAPI isaxxmlreader_putFeature(
725         ISAXXMLReader* iface,
726         const WCHAR *pFeature,
727         VARIANT_BOOL vfValue)
728 {
729     saxreader *This = impl_from_ISAXXMLReader( iface );
730
731     FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(pFeature), vfValue);
732     return E_NOTIMPL;
733 }
734
735 static HRESULT WINAPI isaxxmlreader_getProperty(
736         ISAXXMLReader* iface,
737         const WCHAR *pProp,
738         VARIANT *pValue)
739 {
740     saxreader *This = impl_from_ISAXXMLReader( iface );
741
742     FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pProp), pValue);
743     return E_NOTIMPL;
744 }
745
746 static HRESULT WINAPI isaxxmlreader_putProperty(
747         ISAXXMLReader* iface,
748         const WCHAR *pProp,
749         VARIANT value)
750 {
751     saxreader *This = impl_from_ISAXXMLReader( iface );
752
753     FIXME("(%p)->(%s) stub\n", This, debugstr_w(pProp));
754     return E_NOTIMPL;
755 }
756
757 static HRESULT WINAPI isaxxmlreader_getEntityResolver(
758         ISAXXMLReader* iface,
759         ISAXEntityResolver **ppEntityResolver)
760 {
761     saxreader *This = impl_from_ISAXXMLReader( iface );
762
763     FIXME("(%p)->(%p) stub\n", This, ppEntityResolver);
764     return E_NOTIMPL;
765 }
766
767 static HRESULT WINAPI isaxxmlreader_putEntityResolver(
768         ISAXXMLReader* iface,
769         ISAXEntityResolver *pEntityResolver)
770 {
771     saxreader *This = impl_from_ISAXXMLReader( iface );
772
773     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
774     return E_NOTIMPL;
775 }
776
777 static HRESULT WINAPI isaxxmlreader_getContentHandler(
778         ISAXXMLReader* iface,
779         ISAXContentHandler **pContentHandler)
780 {
781     saxreader *This = impl_from_ISAXXMLReader( iface );
782
783     TRACE("(%p)->(%p)\n", This, pContentHandler);
784     if(pContentHandler == NULL)
785         return E_POINTER;
786     if(This->contentHandler)
787         ISAXContentHandler_AddRef(This->contentHandler);
788     *pContentHandler = This->contentHandler;
789
790     return S_OK;
791 }
792
793 static HRESULT WINAPI isaxxmlreader_putContentHandler(
794         ISAXXMLReader* iface,
795         ISAXContentHandler *contentHandler)
796 {
797     saxreader *This = impl_from_ISAXXMLReader( iface );
798
799     TRACE("(%p)->(%p)\n", This, contentHandler);
800     if(contentHandler)
801         ISAXContentHandler_AddRef(contentHandler);
802     if(This->contentHandler)
803         ISAXContentHandler_Release(This->contentHandler);
804     This->contentHandler = contentHandler;
805
806     return S_OK;
807 }
808
809 static HRESULT WINAPI isaxxmlreader_getDTDHandler(
810         ISAXXMLReader* iface,
811         ISAXDTDHandler **pDTDHandler)
812 {
813     saxreader *This = impl_from_ISAXXMLReader( iface );
814
815     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
816     return E_NOTIMPL;
817 }
818
819 static HRESULT WINAPI isaxxmlreader_putDTDHandler(
820         ISAXXMLReader* iface,
821         ISAXDTDHandler *pDTDHandler)
822 {
823     saxreader *This = impl_from_ISAXXMLReader( iface );
824
825     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
826     return E_NOTIMPL;
827 }
828
829 static HRESULT WINAPI isaxxmlreader_getErrorHandler(
830         ISAXXMLReader* iface,
831         ISAXErrorHandler **pErrorHandler)
832 {
833     saxreader *This = impl_from_ISAXXMLReader( iface );
834
835     TRACE("(%p)->(%p)\n", This, pErrorHandler);
836     if(pErrorHandler == NULL)
837         return E_POINTER;
838     if(This->errorHandler)
839         ISAXErrorHandler_AddRef(This->errorHandler);
840     *pErrorHandler = This->errorHandler;
841
842     return S_OK;
843 }
844
845 static HRESULT WINAPI isaxxmlreader_putErrorHandler(
846         ISAXXMLReader* iface,
847         ISAXErrorHandler *errorHandler)
848 {
849     saxreader *This = impl_from_ISAXXMLReader( iface );
850
851     TRACE("(%p)->(%p)\n", This, errorHandler);
852     if(errorHandler)
853         ISAXErrorHandler_AddRef(errorHandler);
854     if(This->errorHandler)
855         ISAXErrorHandler_Release(This->errorHandler);
856     This->errorHandler = errorHandler;
857
858     return S_OK;
859 }
860
861 static HRESULT WINAPI isaxxmlreader_getBaseURL(
862         ISAXXMLReader* iface,
863         const WCHAR **pBaseUrl)
864 {
865     saxreader *This = impl_from_ISAXXMLReader( iface );
866
867     FIXME("(%p)->(%p) stub\n", This, pBaseUrl);
868     return E_NOTIMPL;
869 }
870
871 static HRESULT WINAPI isaxxmlreader_putBaseURL(
872         ISAXXMLReader* iface,
873         const WCHAR *pBaseUrl)
874 {
875     saxreader *This = impl_from_ISAXXMLReader( iface );
876
877     FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
878     return E_NOTIMPL;
879 }
880
881 static HRESULT WINAPI isaxxmlreader_getSecureBaseURL(
882         ISAXXMLReader* iface,
883         const WCHAR **pSecureBaseUrl)
884 {
885     saxreader *This = impl_from_ISAXXMLReader( iface );
886
887     FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
888     return E_NOTIMPL;
889 }
890
891 static HRESULT WINAPI isaxxmlreader_putSecureBaseURL(
892         ISAXXMLReader* iface,
893         const WCHAR *secureBaseUrl)
894 {
895     saxreader *This = impl_from_ISAXXMLReader( iface );
896
897     FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
898     return E_NOTIMPL;
899 }
900
901 static HRESULT WINAPI isaxxmlreader_parse(
902         ISAXXMLReader* iface,
903         VARIANT varInput)
904 {
905     saxreader *This = impl_from_ISAXXMLReader( iface );
906     saxlocator *locator;
907     xmlChar *data = NULL;
908     HRESULT hr;
909
910     FIXME("(%p) semi-stub\n", This);
911
912     hr = SAXLocator_create(This, &locator);
913     if(FAILED(hr))
914         return E_FAIL;
915
916     hr = S_OK;
917     switch(V_VT(&varInput))
918     {
919         case VT_BSTR:
920             locator->pParserCtxt = xmlNewParserCtxt();
921             if(!locator->pParserCtxt)
922             {
923                 hr = E_FAIL;
924                 break;
925             }
926             data = xmlChar_from_wchar(V_BSTR(&varInput));
927             xmlSetupParserForBuffer(locator->pParserCtxt, data, NULL);
928
929             locator->pParserCtxt->sax = &locator->saxreader->sax;
930             locator->pParserCtxt->userData = locator;
931
932             if(xmlParseDocument(locator->pParserCtxt)) hr = E_FAIL;
933             else hr = locator->ret;
934             break;
935         default:
936             hr = E_NOTIMPL;
937     }
938
939     if(locator->pParserCtxt)
940     {
941         locator->pParserCtxt->sax = NULL;
942         xmlFreeParserCtxt(locator->pParserCtxt);
943         locator->pParserCtxt = NULL;
944     }
945     if(data) HeapFree(GetProcessHeap(), 0, data);
946     ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
947     return hr;
948 }
949
950 static HRESULT WINAPI isaxxmlreader_parseURL(
951         ISAXXMLReader* iface,
952         const WCHAR *url)
953 {
954     saxreader *This = impl_from_ISAXXMLReader( iface );
955
956     FIXME("(%p)->(%s) stub\n", This, debugstr_w(url));
957     return E_NOTIMPL;
958 }
959
960 static const struct ISAXXMLReaderVtbl isaxreader_vtbl =
961 {
962     isaxxmlreader_QueryInterface,
963     isaxxmlreader_AddRef,
964     isaxxmlreader_Release,
965     isaxxmlreader_getFeature,
966     isaxxmlreader_putFeature,
967     isaxxmlreader_getProperty,
968     isaxxmlreader_putProperty,
969     isaxxmlreader_getEntityResolver,
970     isaxxmlreader_putEntityResolver,
971     isaxxmlreader_getContentHandler,
972     isaxxmlreader_putContentHandler,
973     isaxxmlreader_getDTDHandler,
974     isaxxmlreader_putDTDHandler,
975     isaxxmlreader_getErrorHandler,
976     isaxxmlreader_putErrorHandler,
977     isaxxmlreader_getBaseURL,
978     isaxxmlreader_putBaseURL,
979     isaxxmlreader_getSecureBaseURL,
980     isaxxmlreader_putSecureBaseURL,
981     isaxxmlreader_parse,
982     isaxxmlreader_parseURL
983 };
984
985 HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj)
986 {
987     saxreader *reader;
988
989     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
990
991     reader = HeapAlloc( GetProcessHeap(), 0, sizeof (*reader) );
992     if( !reader )
993         return E_OUTOFMEMORY;
994
995     reader->lpVtbl = &saxreader_vtbl;
996     reader->lpSAXXMLReaderVtbl = &isaxreader_vtbl;
997     reader->ref = 1;
998     reader->contentHandler = NULL;
999     reader->errorHandler = NULL;
1000
1001     memset(&reader->sax, 0, sizeof(xmlSAXHandler));
1002     reader->sax.initialized = XML_SAX2_MAGIC;
1003     reader->sax.startDocument = libxmlStartDocument;
1004     reader->sax.endDocument = libxmlEndDocument;
1005     reader->sax.startElementNs = libxmlStartElementNS;
1006     reader->sax.endElementNs = libxmlEndElementNS;
1007
1008     *ppObj = &reader->lpVtbl;
1009
1010     TRACE("returning iface %p\n", *ppObj);
1011
1012     return S_OK;
1013 }
1014
1015 #else
1016
1017 HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj)
1018 {
1019     MESSAGE("This program tried to use a SAX XML Reader object, but\n"
1020             "libxml2 support was not present at compile time.\n");
1021     return E_NOTIMPL;
1022 }
1023
1024 #endif