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