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