mciqtz32: Implement MCI_SEEK.
[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 #include <libxml/parserInternals.h>
48
49 typedef struct _saxreader
50 {
51     const struct IVBSAXXMLReaderVtbl *lpVBSAXXMLReaderVtbl;
52     const struct ISAXXMLReaderVtbl *lpSAXXMLReaderVtbl;
53     LONG ref;
54     struct ISAXContentHandler *contentHandler;
55     struct IVBSAXContentHandler *vbcontentHandler;
56     struct ISAXErrorHandler *errorHandler;
57     struct IVBSAXErrorHandler *vberrorHandler;
58     struct ISAXLexicalHandler *lexicalHandler;
59     struct IVBSAXLexicalHandler *vblexicalHandler;
60     struct ISAXDeclHandler *declHandler;
61     struct IVBSAXDeclHandler *vbdeclHandler;
62     xmlSAXHandler sax;
63     BOOL isParsing;
64 } saxreader;
65
66 typedef struct _saxlocator
67 {
68     const struct IVBSAXLocatorVtbl *lpVBSAXLocatorVtbl;
69     const struct ISAXLocatorVtbl *lpSAXLocatorVtbl;
70     LONG ref;
71     saxreader *saxreader;
72     HRESULT ret;
73     xmlParserCtxtPtr pParserCtxt;
74     WCHAR *publicId;
75     WCHAR *systemId;
76     xmlChar *lastCur;
77     int line;
78     int realLine;
79     int column;
80     int realColumn;
81     BOOL vbInterface;
82     int nsStackSize;
83     int nsStackLast;
84     int *nsStack;
85 } saxlocator;
86
87 typedef struct _saxattributes
88 {
89     const struct IVBSAXAttributesVtbl *lpVBSAXAttributesVtbl;
90     const struct ISAXAttributesVtbl *lpSAXAttributesVtbl;
91     LONG ref;
92     int nb_attributes;
93     BSTR *szLocalname;
94     BSTR *szURI;
95     BSTR *szValue;
96     BSTR *szQName;
97 } saxattributes;
98
99 static inline saxreader *impl_from_IVBSAXXMLReader( IVBSAXXMLReader *iface )
100 {
101     return (saxreader *)((char*)iface - FIELD_OFFSET(saxreader, lpVBSAXXMLReaderVtbl));
102 }
103
104 static inline saxreader *impl_from_ISAXXMLReader( ISAXXMLReader *iface )
105 {
106     return (saxreader *)((char*)iface - FIELD_OFFSET(saxreader, lpSAXXMLReaderVtbl));
107 }
108
109 static inline saxlocator *impl_from_IVBSAXLocator( IVBSAXLocator *iface )
110 {
111     return (saxlocator *)((char*)iface - FIELD_OFFSET(saxlocator, lpVBSAXLocatorVtbl));
112 }
113
114 static inline saxlocator *impl_from_ISAXLocator( ISAXLocator *iface )
115 {
116     return (saxlocator *)((char*)iface - FIELD_OFFSET(saxlocator, lpSAXLocatorVtbl));
117 }
118
119 static inline saxattributes *impl_from_IVBSAXAttributes( IVBSAXAttributes *iface )
120 {
121     return (saxattributes *)((char*)iface - FIELD_OFFSET(saxattributes, lpVBSAXAttributesVtbl));
122 }
123
124 static inline saxattributes *impl_from_ISAXAttributes( ISAXAttributes *iface )
125 {
126     return (saxattributes *)((char*)iface - FIELD_OFFSET(saxattributes, lpSAXAttributesVtbl));
127 }
128
129
130 static HRESULT namespacePush(saxlocator *locator, int ns)
131 {
132     if(locator->nsStackLast>=locator->nsStackSize)
133     {
134         int *new_stack;
135
136         new_stack = HeapReAlloc(GetProcessHeap(), 0,
137                 locator->nsStack, locator->nsStackSize*2);
138         if(!new_stack) return E_OUTOFMEMORY;
139         locator->nsStack = new_stack;
140         locator->nsStackSize *= 2;
141     }
142     locator->nsStack[locator->nsStackLast++] = ns;
143
144     return S_OK;
145 }
146
147 static int namespacePop(saxlocator *locator)
148 {
149     if(locator->nsStackLast == 0) return 0;
150     return locator->nsStack[--locator->nsStackLast];
151 }
152
153 static BSTR bstr_from_xmlCharN(const xmlChar *buf, int len)
154 {
155     DWORD dLen;
156     LPWSTR str;
157     BSTR bstr;
158
159     if (!buf)
160         return NULL;
161
162     dLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0);
163     if(len != -1) dLen++;
164     str = HeapAlloc(GetProcessHeap(), 0, dLen * sizeof (WCHAR));
165     if (!str)
166         return NULL;
167     MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, str, dLen);
168     if(len != -1) str[dLen-1] = '\0';
169     bstr = SysAllocString(str);
170     HeapFree(GetProcessHeap(), 0, str);
171
172     return bstr;
173 }
174
175 static BSTR QName_from_xmlChar(const xmlChar *prefix, const xmlChar *name)
176 {
177     DWORD dLen, dLast;
178     LPWSTR str;
179     BSTR bstr;
180
181     if(!name) return NULL;
182
183     if(!prefix || *prefix=='\0')
184         return bstr_from_xmlChar(name);
185
186     dLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)prefix, -1, NULL, 0)
187         + MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)name, -1, NULL, 0);
188     str = HeapAlloc(GetProcessHeap(), 0, dLen * sizeof(WCHAR));
189     if(!str)
190         return NULL;
191
192     dLast = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)prefix, -1, str, dLen);
193     str[dLast-1] = ':';
194     MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)name, -1, &str[dLast], dLen-dLast);
195     bstr = SysAllocString(str);
196
197     HeapFree(GetProcessHeap(), 0, str);
198
199     return bstr;
200 }
201
202 static void format_error_message_from_id(saxlocator *This, HRESULT hr)
203 {
204     xmlStopParser(This->pParserCtxt);
205     This->ret = hr;
206
207     if((This->vbInterface && This->saxreader->vberrorHandler)
208             || (!This->vbInterface && This->saxreader->errorHandler))
209     {
210         WCHAR msg[1024];
211         if(!FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
212                     NULL, hr, 0, msg, sizeof(msg), NULL))
213         {
214             FIXME("MSXML errors not yet supported.\n");
215             msg[0] = '\0';
216         }
217
218         if(This->vbInterface)
219         {
220             BSTR bstrMsg = SysAllocString(msg);
221             IVBSAXErrorHandler_fatalError(This->saxreader->vberrorHandler,
222                     (IVBSAXLocator*)&This->lpVBSAXLocatorVtbl, &bstrMsg, hr);
223         }
224         else
225             ISAXErrorHandler_fatalError(This->saxreader->errorHandler,
226                     (ISAXLocator*)&This->lpSAXLocatorVtbl, msg, hr);
227     }
228 }
229
230 static void update_position(saxlocator *This, xmlChar *end)
231 {
232     if(This->lastCur == NULL)
233     {
234         This->lastCur = (xmlChar*)This->pParserCtxt->input->base;
235         This->realLine = 1;
236         This->realColumn = 1;
237     }
238     else if(This->lastCur < This->pParserCtxt->input->base)
239     {
240         This->lastCur = (xmlChar*)This->pParserCtxt->input->base;
241         This->realLine = 1;
242         This->realColumn = 1;
243     }
244
245     if(This->pParserCtxt->input->cur<This->lastCur)
246     {
247         This->lastCur = (xmlChar*)This->pParserCtxt->input->base;
248         This->realLine -= 1;
249         This->realColumn = 1;
250     }
251
252     if(!end) end = (xmlChar*)This->pParserCtxt->input->cur;
253
254     while(This->lastCur < end)
255     {
256         if(*(This->lastCur) == '\n')
257         {
258             This->realLine++;
259             This->realColumn = 1;
260         }
261         else if(*(This->lastCur) == '\r' &&
262                 (This->lastCur==This->pParserCtxt->input->end ||
263                  *(This->lastCur+1)!='\n'))
264         {
265             This->realLine++;
266             This->realColumn = 1;
267         }
268         else This->realColumn++;
269
270         This->lastCur++;
271
272         /* Count multibyte UTF8 encoded characters once */
273         while((*(This->lastCur)&0xC0) == 0x80) This->lastCur++;
274     }
275
276     This->line = This->realLine;
277     This->column = This->realColumn;
278 }
279
280 /*** IVBSAXAttributes interface ***/
281 /*** IUnknown methods ***/
282 static HRESULT WINAPI ivbsaxattributes_QueryInterface(
283         IVBSAXAttributes* iface,
284         REFIID riid,
285         void **ppvObject)
286 {
287     saxattributes *This = impl_from_IVBSAXAttributes(iface);
288
289     TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
290
291     *ppvObject = NULL;
292
293     if (IsEqualGUID(riid, &IID_IUnknown) ||
294             IsEqualGUID(riid, &IID_IDispatch) ||
295             IsEqualGUID(riid, &IID_IVBSAXAttributes))
296     {
297         *ppvObject = iface;
298     }
299     else
300     {
301         FIXME("interface %s not implemented\n", debugstr_guid(riid));
302         return E_NOINTERFACE;
303     }
304
305     IVBSAXAttributes_AddRef(iface);
306
307     return S_OK;
308 }
309
310 static ULONG WINAPI ivbsaxattributes_AddRef(IVBSAXAttributes* iface)
311 {
312     saxattributes *This = impl_from_IVBSAXAttributes(iface);
313     return ISAXAttributes_AddRef((ISAXAttributes*)&This->lpSAXAttributesVtbl);
314 }
315
316 static ULONG WINAPI ivbsaxattributes_Release(IVBSAXAttributes* iface)
317 {
318     saxattributes *This = impl_from_IVBSAXAttributes(iface);
319     return ISAXAttributes_Release((ISAXAttributes*)&This->lpSAXAttributesVtbl);
320 }
321
322 /*** IDispatch methods ***/
323 static HRESULT WINAPI ivbsaxattributes_GetTypeInfoCount( IVBSAXAttributes *iface, UINT* pctinfo )
324 {
325     saxattributes *This = impl_from_IVBSAXAttributes( iface );
326
327     TRACE("(%p)->(%p)\n", This, pctinfo);
328
329     *pctinfo = 1;
330
331     return S_OK;
332 }
333
334 static HRESULT WINAPI ivbsaxattributes_GetTypeInfo(
335     IVBSAXAttributes *iface,
336     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
337 {
338     saxattributes *This = impl_from_IVBSAXAttributes( iface );
339     HRESULT hr;
340
341     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
342
343     hr = get_typeinfo(IVBSAXAttributes_tid, ppTInfo);
344
345     return hr;
346 }
347
348 static HRESULT WINAPI ivbsaxattributes_GetIDsOfNames(
349     IVBSAXAttributes *iface,
350     REFIID riid,
351     LPOLESTR* rgszNames,
352     UINT cNames,
353     LCID lcid,
354     DISPID* rgDispId)
355 {
356     saxattributes *This = impl_from_IVBSAXAttributes( iface );
357     ITypeInfo *typeinfo;
358     HRESULT hr;
359
360     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
361           lcid, rgDispId);
362
363     if(!rgszNames || cNames == 0 || !rgDispId)
364         return E_INVALIDARG;
365
366     hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
367     if(SUCCEEDED(hr))
368     {
369         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
370         ITypeInfo_Release(typeinfo);
371     }
372
373     return hr;
374 }
375
376 static HRESULT WINAPI ivbsaxattributes_Invoke(
377     IVBSAXAttributes *iface,
378     DISPID dispIdMember,
379     REFIID riid,
380     LCID lcid,
381     WORD wFlags,
382     DISPPARAMS* pDispParams,
383     VARIANT* pVarResult,
384     EXCEPINFO* pExcepInfo,
385     UINT* puArgErr)
386 {
387     saxattributes *This = impl_from_IVBSAXAttributes( iface );
388     ITypeInfo *typeinfo;
389     HRESULT hr;
390
391     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
392           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
393
394     hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
395     if(SUCCEEDED(hr))
396     {
397         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVBSAXAttributesVtbl), dispIdMember, wFlags, pDispParams,
398                 pVarResult, pExcepInfo, puArgErr);
399         ITypeInfo_Release(typeinfo);
400     }
401
402     return hr;
403 }
404
405 /*** IVBSAXAttributes methods ***/
406 static HRESULT WINAPI ivbsaxattributes_get_length(
407         IVBSAXAttributes* iface,
408         int *nLength)
409 {
410     saxattributes *This = impl_from_IVBSAXAttributes( iface );
411     return ISAXAttributes_getLength(
412             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
413             nLength);
414 }
415
416 static HRESULT WINAPI ivbsaxattributes_getURI(
417         IVBSAXAttributes* iface,
418         int nIndex,
419         BSTR *uri)
420 {
421     int len;
422     saxattributes *This = impl_from_IVBSAXAttributes( iface );
423     return ISAXAttributes_getURI(
424             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
425             nIndex, (const WCHAR**)uri, &len);
426 }
427
428 static HRESULT WINAPI ivbsaxattributes_getLocalName(
429         IVBSAXAttributes* iface,
430         int nIndex,
431         BSTR *localName)
432 {
433     int len;
434     saxattributes *This = impl_from_IVBSAXAttributes( iface );
435     return ISAXAttributes_getLocalName(
436             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
437             nIndex, (const WCHAR**)localName, &len);
438 }
439
440 static HRESULT WINAPI ivbsaxattributes_getQName(
441         IVBSAXAttributes* iface,
442         int nIndex,
443         BSTR *QName)
444 {
445     int len;
446     saxattributes *This = impl_from_IVBSAXAttributes( iface );
447     return ISAXAttributes_getQName(
448             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
449             nIndex, (const WCHAR**)QName, &len);
450 }
451
452 static HRESULT WINAPI ivbsaxattributes_getIndexFromName(
453         IVBSAXAttributes* iface,
454         BSTR uri,
455         BSTR localName,
456         int *index)
457 {
458     saxattributes *This = impl_from_IVBSAXAttributes( iface );
459     return ISAXAttributes_getIndexFromName(
460             (ISAXAttributes*)&This->lpSAXAttributesVtbl, uri, SysStringLen(uri),
461             localName, SysStringLen(localName), index);
462 }
463
464 static HRESULT WINAPI ivbsaxattributes_getIndexFromQName(
465         IVBSAXAttributes* iface,
466         BSTR QName,
467         int *index)
468 {
469     saxattributes *This = impl_from_IVBSAXAttributes( iface );
470     return ISAXAttributes_getIndexFromQName(
471             (ISAXAttributes*)&This->lpSAXAttributesVtbl, QName,
472             SysStringLen(QName), index);
473 }
474
475 static HRESULT WINAPI ivbsaxattributes_getType(
476         IVBSAXAttributes* iface,
477         int nIndex,
478         BSTR *type)
479 {
480     int len;
481     saxattributes *This = impl_from_IVBSAXAttributes( iface );
482     return ISAXAttributes_getType(
483             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
484             nIndex, (const WCHAR**)type, &len);
485 }
486
487 static HRESULT WINAPI ivbsaxattributes_getTypeFromName(
488         IVBSAXAttributes* iface,
489         BSTR uri,
490         BSTR localName,
491         BSTR *type)
492 {
493     int len;
494     saxattributes *This = impl_from_IVBSAXAttributes( iface );
495     return ISAXAttributes_getTypeFromName(
496             (ISAXAttributes*)&This->lpSAXAttributesVtbl, uri, SysStringLen(uri),
497             localName, SysStringLen(localName), (const WCHAR**)type, &len);
498 }
499
500 static HRESULT WINAPI ivbsaxattributes_getTypeFromQName(
501         IVBSAXAttributes* iface,
502         BSTR QName,
503         BSTR *type)
504 {
505     int len;
506     saxattributes *This = impl_from_IVBSAXAttributes( iface );
507     return ISAXAttributes_getTypeFromQName(
508             (ISAXAttributes*)&This->lpSAXAttributesVtbl, QName,
509             SysStringLen(QName), (const WCHAR**)type, &len);
510 }
511
512 static HRESULT WINAPI ivbsaxattributes_getValue(
513         IVBSAXAttributes* iface,
514         int nIndex,
515         BSTR *value)
516 {
517     int len;
518     saxattributes *This = impl_from_IVBSAXAttributes( iface );
519     return ISAXAttributes_getValue(
520             (ISAXAttributes*)&This->lpSAXAttributesVtbl,
521             nIndex, (const WCHAR**)value, &len);
522 }
523
524 static HRESULT WINAPI ivbsaxattributes_getValueFromName(
525         IVBSAXAttributes* iface,
526         BSTR uri,
527         BSTR localName,
528         BSTR *value)
529 {
530     int len;
531     saxattributes *This = impl_from_IVBSAXAttributes( iface );
532     return ISAXAttributes_getValueFromName(
533             (ISAXAttributes*)&This->lpSAXAttributesVtbl, uri, SysStringLen(uri),
534             localName, SysStringLen(localName), (const WCHAR**)value, &len);
535 }
536
537 static HRESULT WINAPI ivbsaxattributes_getValueFromQName(
538         IVBSAXAttributes* iface,
539         BSTR QName,
540         BSTR *value)
541 {
542     int len;
543     saxattributes *This = impl_from_IVBSAXAttributes( iface );
544     return ISAXAttributes_getValueFromQName(
545             (ISAXAttributes*)&This->lpSAXAttributesVtbl, QName,
546             SysStringLen(QName), (const WCHAR**)value, &len);
547 }
548
549 static const struct IVBSAXAttributesVtbl ivbsaxattributes_vtbl =
550 {
551     ivbsaxattributes_QueryInterface,
552     ivbsaxattributes_AddRef,
553     ivbsaxattributes_Release,
554     ivbsaxattributes_GetTypeInfoCount,
555     ivbsaxattributes_GetTypeInfo,
556     ivbsaxattributes_GetIDsOfNames,
557     ivbsaxattributes_Invoke,
558     ivbsaxattributes_get_length,
559     ivbsaxattributes_getURI,
560     ivbsaxattributes_getLocalName,
561     ivbsaxattributes_getQName,
562     ivbsaxattributes_getIndexFromName,
563     ivbsaxattributes_getIndexFromQName,
564     ivbsaxattributes_getType,
565     ivbsaxattributes_getTypeFromName,
566     ivbsaxattributes_getTypeFromQName,
567     ivbsaxattributes_getValue,
568     ivbsaxattributes_getValueFromName,
569     ivbsaxattributes_getValueFromQName
570 };
571
572 /*** ISAXAttributes interface ***/
573 /*** IUnknown methods ***/
574 static HRESULT WINAPI isaxattributes_QueryInterface(
575         ISAXAttributes* iface,
576         REFIID riid,
577         void **ppvObject)
578 {
579     saxattributes *This = impl_from_ISAXAttributes(iface);
580
581     TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
582
583     *ppvObject = NULL;
584
585     if (IsEqualGUID(riid, &IID_IUnknown) ||
586             IsEqualGUID(riid, &IID_ISAXAttributes))
587     {
588         *ppvObject = iface;
589     }
590     else
591     {
592         FIXME("interface %s not implemented\n", debugstr_guid(riid));
593         return E_NOINTERFACE;
594     }
595
596     ISAXAttributes_AddRef(iface);
597
598     return S_OK;
599 }
600
601 static ULONG WINAPI isaxattributes_AddRef(ISAXAttributes* iface)
602 {
603     saxattributes *This = impl_from_ISAXAttributes(iface);
604     TRACE("%p\n", This);
605     return InterlockedIncrement(&This->ref);
606 }
607
608 static ULONG WINAPI isaxattributes_Release(ISAXAttributes* iface)
609 {
610     saxattributes *This = impl_from_ISAXAttributes(iface);
611     LONG ref;
612
613     TRACE("%p\n", This);
614
615     ref = InterlockedDecrement(&This->ref);
616     if (ref==0)
617     {
618         int index;
619         for(index=0; index<This->nb_attributes; index++)
620         {
621             SysFreeString(This->szLocalname[index]);
622             SysFreeString(This->szURI[index]);
623             SysFreeString(This->szValue[index]);
624             SysFreeString(This->szQName[index]);
625         }
626
627         HeapFree(GetProcessHeap(), 0, This->szLocalname);
628         HeapFree(GetProcessHeap(), 0, This->szURI);
629         HeapFree(GetProcessHeap(), 0, This->szValue);
630         HeapFree(GetProcessHeap(), 0, This->szQName);
631
632         HeapFree(GetProcessHeap(), 0, This);
633     }
634
635     return ref;
636 }
637
638 /*** ISAXAttributes methods ***/
639 static HRESULT WINAPI isaxattributes_getLength(
640         ISAXAttributes* iface,
641         int *length)
642 {
643     saxattributes *This = impl_from_ISAXAttributes( iface );
644
645     *length = This->nb_attributes;
646     TRACE("Length set to %d\n", *length);
647     return S_OK;
648 }
649
650 static HRESULT WINAPI isaxattributes_getURI(
651         ISAXAttributes* iface,
652         int nIndex,
653         const WCHAR **pUrl,
654         int *pUriSize)
655 {
656     saxattributes *This = impl_from_ISAXAttributes( iface );
657     TRACE("(%p)->(%d)\n", This, nIndex);
658
659     if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
660     if(!pUrl || !pUriSize) return E_POINTER;
661
662     *pUriSize = SysStringLen(This->szURI[nIndex]);
663     *pUrl = This->szURI[nIndex];
664
665     return S_OK;
666 }
667
668 static HRESULT WINAPI isaxattributes_getLocalName(
669         ISAXAttributes* iface,
670         int nIndex,
671         const WCHAR **pLocalName,
672         int *pLocalNameLength)
673 {
674     saxattributes *This = impl_from_ISAXAttributes( iface );
675     TRACE("(%p)->(%d)\n", This, nIndex);
676
677     if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
678     if(!pLocalName || !pLocalNameLength) return E_POINTER;
679
680     *pLocalNameLength = SysStringLen(This->szLocalname[nIndex]);
681     *pLocalName = This->szLocalname[nIndex];
682
683     return S_OK;
684 }
685
686 static HRESULT WINAPI isaxattributes_getQName(
687         ISAXAttributes* iface,
688         int nIndex,
689         const WCHAR **pQName,
690         int *pQNameLength)
691 {
692     saxattributes *This = impl_from_ISAXAttributes( iface );
693     TRACE("(%p)->(%d)\n", This, nIndex);
694
695     if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
696     if(!pQName || !pQNameLength) return E_POINTER;
697
698     *pQNameLength = SysStringLen(This->szQName[nIndex]);
699     *pQName = This->szQName[nIndex];
700
701     return S_OK;
702 }
703
704 static HRESULT WINAPI isaxattributes_getName(
705         ISAXAttributes* iface,
706         int nIndex,
707         const WCHAR **pUri,
708         int *pUriLength,
709         const WCHAR **pLocalName,
710         int *pLocalNameSize,
711         const WCHAR **pQName,
712         int *pQNameLength)
713 {
714     saxattributes *This = impl_from_ISAXAttributes( iface );
715     TRACE("(%p)->(%d)\n", This, nIndex);
716
717     if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
718     if(!pUri || !pUriLength || !pLocalName || !pLocalNameSize
719             || !pQName || !pQNameLength) return E_POINTER;
720
721     *pUriLength = SysStringLen(This->szURI[nIndex]);
722     *pUri = This->szURI[nIndex];
723     *pLocalNameSize = SysStringLen(This->szLocalname[nIndex]);
724     *pLocalName = This->szLocalname[nIndex];
725     *pQNameLength = SysStringLen(This->szQName[nIndex]);
726     *pQName = This->szQName[nIndex];
727
728     return S_OK;
729 }
730
731 static HRESULT WINAPI isaxattributes_getIndexFromName(
732         ISAXAttributes* iface,
733         const WCHAR *pUri,
734         int cUriLength,
735         const WCHAR *pLocalName,
736         int cocalNameLength,
737         int *index)
738 {
739     saxattributes *This = impl_from_ISAXAttributes( iface );
740     int i;
741     TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), cUriLength,
742             debugstr_w(pLocalName), cocalNameLength);
743
744     if(!pUri || !pLocalName || !index) return E_POINTER;
745
746     for(i=0; i<This->nb_attributes; i++)
747     {
748         if(cUriLength!=SysStringLen(This->szURI[i])
749                 || cocalNameLength!=SysStringLen(This->szLocalname[i]))
750             continue;
751         if(cUriLength && memcmp(pUri, This->szURI[i],
752                     sizeof(WCHAR)*cUriLength))
753             continue;
754         if(cocalNameLength && memcmp(pLocalName, This->szLocalname[i],
755                     sizeof(WCHAR)*cocalNameLength))
756             continue;
757
758         *index = i;
759         return S_OK;
760     }
761
762     return E_INVALIDARG;
763 }
764
765 static HRESULT WINAPI isaxattributes_getIndexFromQName(
766         ISAXAttributes* iface,
767         const WCHAR *pQName,
768         int nQNameLength,
769         int *index)
770 {
771     saxattributes *This = impl_from_ISAXAttributes( iface );
772     int i;
773     TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQNameLength);
774
775     if(!pQName || !index) return E_POINTER;
776     if(!nQNameLength) return E_INVALIDARG;
777
778     for(i=0; i<This->nb_attributes; i++)
779     {
780         if(nQNameLength!=SysStringLen(This->szQName[i])) continue;
781         if(memcmp(pQName, This->szQName, sizeof(WCHAR)*nQNameLength)) continue;
782
783         *index = i;
784         return S_OK;
785     }
786
787     return E_INVALIDARG;
788 }
789
790 static HRESULT WINAPI isaxattributes_getType(
791         ISAXAttributes* iface,
792         int nIndex,
793         const WCHAR **pType,
794         int *pTypeLength)
795 {
796     saxattributes *This = impl_from_ISAXAttributes( iface );
797
798     FIXME("(%p)->(%d) stub\n", This, nIndex);
799     return E_NOTIMPL;
800 }
801
802 static HRESULT WINAPI isaxattributes_getTypeFromName(
803         ISAXAttributes* iface,
804         const WCHAR *pUri,
805         int nUri,
806         const WCHAR *pLocalName,
807         int nLocalName,
808         const WCHAR **pType,
809         int *nType)
810 {
811     saxattributes *This = impl_from_ISAXAttributes( iface );
812
813     FIXME("(%p)->(%s, %d, %s, %d) stub\n", This, debugstr_w(pUri), nUri,
814             debugstr_w(pLocalName), nLocalName);
815     return E_NOTIMPL;
816 }
817
818 static HRESULT WINAPI isaxattributes_getTypeFromQName(
819         ISAXAttributes* iface,
820         const WCHAR *pQName,
821         int nQName,
822         const WCHAR **pType,
823         int *nType)
824 {
825     saxattributes *This = impl_from_ISAXAttributes( iface );
826
827     FIXME("(%p)->(%s, %d) stub\n", This, debugstr_w(pQName), nQName);
828     return E_NOTIMPL;
829 }
830
831 static HRESULT WINAPI isaxattributes_getValue(
832         ISAXAttributes* iface,
833         int nIndex,
834         const WCHAR **pValue,
835         int *nValue)
836 {
837     saxattributes *This = impl_from_ISAXAttributes( iface );
838     TRACE("(%p)->(%d)\n", This, nIndex);
839
840     if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
841     if(!pValue || !nValue) return E_POINTER;
842
843     *nValue = SysStringLen(This->szValue[nIndex]);
844     *pValue = This->szValue[nIndex];
845
846     return S_OK;
847 }
848
849 static HRESULT WINAPI isaxattributes_getValueFromName(
850         ISAXAttributes* iface,
851         const WCHAR *pUri,
852         int nUri,
853         const WCHAR *pLocalName,
854         int nLocalName,
855         const WCHAR **pValue,
856         int *nValue)
857 {
858     HRESULT hr;
859     int index;
860     saxattributes *This = impl_from_ISAXAttributes( iface );
861     TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), nUri,
862             debugstr_w(pLocalName), nLocalName);
863
864     hr = ISAXAttributes_getIndexFromName(iface,
865             pUri, nUri, pLocalName, nLocalName, &index);
866     if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
867
868     return hr;
869 }
870
871 static HRESULT WINAPI isaxattributes_getValueFromQName(
872         ISAXAttributes* iface,
873         const WCHAR *pQName,
874         int nQName,
875         const WCHAR **pValue,
876         int *nValue)
877 {
878     HRESULT hr;
879     int index;
880     saxattributes *This = impl_from_ISAXAttributes( iface );
881     TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQName);
882
883     hr = ISAXAttributes_getIndexFromQName(iface, pQName, nQName, &index);
884     if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue);
885
886     return hr;
887 }
888
889 static const struct ISAXAttributesVtbl isaxattributes_vtbl =
890 {
891     isaxattributes_QueryInterface,
892     isaxattributes_AddRef,
893     isaxattributes_Release,
894     isaxattributes_getLength,
895     isaxattributes_getURI,
896     isaxattributes_getLocalName,
897     isaxattributes_getQName,
898     isaxattributes_getName,
899     isaxattributes_getIndexFromName,
900     isaxattributes_getIndexFromQName,
901     isaxattributes_getType,
902     isaxattributes_getTypeFromName,
903     isaxattributes_getTypeFromQName,
904     isaxattributes_getValue,
905     isaxattributes_getValueFromName,
906     isaxattributes_getValueFromQName
907 };
908
909 static HRESULT SAXAttributes_create(saxattributes **attr,
910         int nb_namespaces, const xmlChar **xmlNamespaces,
911         int nb_attributes, const xmlChar **xmlAttributes)
912 {
913     saxattributes *attributes;
914     int index;
915     static const xmlChar xmlns[] = "xmlns";
916
917     attributes = HeapAlloc(GetProcessHeap(), 0, sizeof(*attributes));
918     if(!attributes)
919         return E_OUTOFMEMORY;
920
921     attributes->lpVBSAXAttributesVtbl = &ivbsaxattributes_vtbl;
922     attributes->lpSAXAttributesVtbl = &isaxattributes_vtbl;
923     attributes->ref = 1;
924
925     attributes->nb_attributes = nb_namespaces+nb_attributes;
926
927     attributes->szLocalname =
928         HeapAlloc(GetProcessHeap(), 0, sizeof(BSTR)*attributes->nb_attributes);
929     attributes->szURI =
930         HeapAlloc(GetProcessHeap(), 0, sizeof(BSTR)*attributes->nb_attributes);
931     attributes->szValue =
932         HeapAlloc(GetProcessHeap(), 0, sizeof(BSTR)*attributes->nb_attributes);
933     attributes->szQName =
934         HeapAlloc(GetProcessHeap(), 0, sizeof(BSTR)*attributes->nb_attributes);
935
936     if(!attributes->szLocalname || !attributes->szURI
937             || !attributes->szValue || !attributes->szQName)
938     {
939         HeapFree(GetProcessHeap(), 0, attributes->szLocalname);
940         HeapFree(GetProcessHeap(), 0, attributes->szURI);
941         HeapFree(GetProcessHeap(), 0, attributes->szValue);
942         HeapFree(GetProcessHeap(), 0, attributes->szQName);
943         HeapFree(GetProcessHeap(), 0, attributes);
944         return E_FAIL;
945     }
946
947     for(index=0; index<nb_namespaces; index++)
948     {
949         attributes->szLocalname[index] = SysAllocStringLen(NULL, 0);
950         attributes->szURI[index] = SysAllocStringLen(NULL, 0);
951         attributes->szValue[index] = bstr_from_xmlChar(xmlNamespaces[2*index+1]);
952         attributes->szQName[index] = QName_from_xmlChar(xmlns, xmlNamespaces[2*index]);
953     }
954
955     for(index=0; index<nb_attributes; index++)
956     {
957         attributes->szLocalname[nb_namespaces+index] =
958             bstr_from_xmlChar(xmlAttributes[index*5]);
959         attributes->szURI[nb_namespaces+index] =
960             bstr_from_xmlChar(xmlAttributes[index*5+2]);
961         attributes->szValue[nb_namespaces+index] =
962             bstr_from_xmlCharN(xmlAttributes[index*5+3],
963                     xmlAttributes[index*5+4]-xmlAttributes[index*5+3]);
964         attributes->szQName[nb_namespaces+index] =
965             QName_from_xmlChar(xmlAttributes[index*5+1], xmlAttributes[index*5]);
966     }
967
968     *attr = attributes;
969
970     TRACE("returning %p\n", *attr);
971
972     return S_OK;
973 }
974
975 /*** LibXML callbacks ***/
976 static void libxmlStartDocument(void *ctx)
977 {
978     saxlocator *This = ctx;
979     HRESULT hr;
980
981     if((This->vbInterface && This->saxreader->vbcontentHandler)
982             || (!This->vbInterface && This->saxreader->contentHandler))
983     {
984         if(This->vbInterface)
985             hr = IVBSAXContentHandler_startDocument(This->saxreader->vbcontentHandler);
986         else
987             hr = ISAXContentHandler_startDocument(This->saxreader->contentHandler);
988
989         if(hr != S_OK)
990             format_error_message_from_id(This, hr);
991     }
992
993     update_position(This, NULL);
994 }
995
996 static void libxmlEndDocument(void *ctx)
997 {
998     saxlocator *This = ctx;
999     HRESULT hr;
1000
1001     This->column = 0;
1002     This->line = 0;
1003
1004     if(This->ret != S_OK) return;
1005
1006     if((This->vbInterface && This->saxreader->vbcontentHandler)
1007             || (!This->vbInterface && This->saxreader->contentHandler))
1008     {
1009         if(This->vbInterface)
1010             hr = IVBSAXContentHandler_endDocument(This->saxreader->vbcontentHandler);
1011         else
1012             hr = ISAXContentHandler_endDocument(This->saxreader->contentHandler);
1013
1014         if(hr != S_OK)
1015             format_error_message_from_id(This, hr);
1016     }
1017 }
1018
1019 static void libxmlStartElementNS(
1020         void *ctx,
1021         const xmlChar *localname,
1022         const xmlChar *prefix,
1023         const xmlChar *URI,
1024         int nb_namespaces,
1025         const xmlChar **namespaces,
1026         int nb_attributes,
1027         int nb_defaulted,
1028         const xmlChar **attributes)
1029 {
1030     BSTR NamespaceUri, LocalName, QName, Prefix, Uri;
1031     saxlocator *This = ctx;
1032     HRESULT hr;
1033     saxattributes *attr;
1034     int index;
1035
1036     if(*(This->pParserCtxt->input->cur) == '/')
1037         update_position(This, (xmlChar*)This->pParserCtxt->input->cur+2);
1038     else
1039         update_position(This, (xmlChar*)This->pParserCtxt->input->cur+1);
1040
1041     hr = namespacePush(This, nb_namespaces);
1042     if(hr==S_OK && ((This->vbInterface && This->saxreader->vbcontentHandler)
1043                 || (!This->vbInterface && This->saxreader->contentHandler)))
1044     {
1045         for(index=0; index<nb_namespaces; index++)
1046         {
1047             Prefix = bstr_from_xmlChar(namespaces[2*index]);
1048             Uri = bstr_from_xmlChar(namespaces[2*index+1]);
1049
1050             if(This->vbInterface)
1051                 hr = IVBSAXContentHandler_startPrefixMapping(
1052                         This->saxreader->vbcontentHandler,
1053                         &Prefix, &Uri);
1054             else
1055                 hr = ISAXContentHandler_startPrefixMapping(
1056                         This->saxreader->contentHandler,
1057                         Prefix, SysStringLen(Prefix),
1058                         Uri, SysStringLen(Uri));
1059
1060             SysFreeString(Prefix);
1061             SysFreeString(Uri);
1062
1063             if(hr != S_OK)
1064             {
1065                 format_error_message_from_id(This, hr);
1066                 return;
1067             }
1068         }
1069
1070         NamespaceUri = bstr_from_xmlChar(URI);
1071         LocalName = bstr_from_xmlChar(localname);
1072         QName = QName_from_xmlChar(prefix, localname);
1073
1074         hr = SAXAttributes_create(&attr, nb_namespaces, namespaces, nb_attributes, attributes);
1075         if(hr == S_OK)
1076         {
1077             if(This->vbInterface)
1078                 hr = IVBSAXContentHandler_startElement(
1079                         This->saxreader->vbcontentHandler,
1080                         &NamespaceUri, &LocalName, &QName,
1081                         (IVBSAXAttributes*)&attr->lpVBSAXAttributesVtbl);
1082             else
1083                 hr = ISAXContentHandler_startElement(
1084                         This->saxreader->contentHandler,
1085                         NamespaceUri, SysStringLen(NamespaceUri),
1086                         LocalName, SysStringLen(LocalName),
1087                         QName, SysStringLen(QName),
1088                         (ISAXAttributes*)&attr->lpSAXAttributesVtbl);
1089
1090             ISAXAttributes_Release((ISAXAttributes*)&attr->lpSAXAttributesVtbl);
1091         }
1092
1093         SysFreeString(NamespaceUri);
1094         SysFreeString(LocalName);
1095         SysFreeString(QName);
1096     }
1097
1098     if(hr != S_OK)
1099         format_error_message_from_id(This, hr);
1100 }
1101
1102 static void libxmlEndElementNS(
1103         void *ctx,
1104         const xmlChar *localname,
1105         const xmlChar *prefix,
1106         const xmlChar *URI)
1107 {
1108     BSTR NamespaceUri, LocalName, QName, Prefix;
1109     saxlocator *This = ctx;
1110     HRESULT hr;
1111     xmlChar *end;
1112     int nsNr, index;
1113
1114     end = (xmlChar*)This->pParserCtxt->input->cur;
1115     if(*(end-1) != '>' || *(end-2) != '/')
1116         while(*(end-2)!='<' && *(end-1)!='/') end--;
1117
1118     update_position(This, end);
1119
1120     nsNr = namespacePop(This);
1121
1122     if((This->vbInterface && This->saxreader->vbcontentHandler)
1123             || (!This->vbInterface && This->saxreader->contentHandler))
1124     {
1125         NamespaceUri = bstr_from_xmlChar(URI);
1126         LocalName = bstr_from_xmlChar(localname);
1127         QName = QName_from_xmlChar(prefix, localname);
1128
1129         if(This->vbInterface)
1130             hr = IVBSAXContentHandler_endElement(
1131                     This->saxreader->vbcontentHandler,
1132                     &NamespaceUri, &LocalName, &QName);
1133         else
1134             hr = ISAXContentHandler_endElement(
1135                     This->saxreader->contentHandler,
1136                     NamespaceUri, SysStringLen(NamespaceUri),
1137                     LocalName, SysStringLen(LocalName),
1138                     QName, SysStringLen(QName));
1139
1140         SysFreeString(NamespaceUri);
1141         SysFreeString(LocalName);
1142         SysFreeString(QName);
1143
1144         if(hr != S_OK)
1145         {
1146             format_error_message_from_id(This, hr);
1147             return;
1148         }
1149
1150         for(index=This->pParserCtxt->nsNr-2;
1151                 index>=This->pParserCtxt->nsNr-nsNr*2; index-=2)
1152         {
1153             Prefix = bstr_from_xmlChar(This->pParserCtxt->nsTab[index]);
1154
1155             if(This->vbInterface)
1156                 hr = IVBSAXContentHandler_endPrefixMapping(
1157                         This->saxreader->vbcontentHandler, &Prefix);
1158             else
1159                 hr = ISAXContentHandler_endPrefixMapping(
1160                         This->saxreader->contentHandler,
1161                         Prefix, SysStringLen(Prefix));
1162
1163             SysFreeString(Prefix);
1164
1165             if(hr != S_OK)
1166             {
1167                 format_error_message_from_id(This, hr);
1168                 return;
1169             }
1170
1171         }
1172     }
1173
1174     update_position(This, NULL);
1175 }
1176
1177 static void libxmlCharacters(
1178         void *ctx,
1179         const xmlChar *ch,
1180         int len)
1181 {
1182     saxlocator *This = ctx;
1183     BSTR Chars;
1184     HRESULT hr;
1185     xmlChar *cur;
1186     xmlChar *end;
1187     BOOL lastEvent = FALSE;
1188
1189     if((This->vbInterface && !This->saxreader->vbcontentHandler)
1190             || (!This->vbInterface && !This->saxreader->contentHandler))
1191         return;
1192
1193     cur = (xmlChar*)ch;
1194     if(*(ch-1)=='\r') cur--;
1195     end = cur;
1196
1197     if(ch<This->pParserCtxt->input->base || ch>This->pParserCtxt->input->end)
1198         This->column++;
1199
1200     while(1)
1201     {
1202         while(end-ch<len && *end!='\r') end++;
1203         if(end-ch==len)
1204         {
1205             end--;
1206             lastEvent = TRUE;
1207         }
1208
1209         if(!lastEvent) *end = '\n';
1210
1211         Chars = bstr_from_xmlCharN(cur, end-cur+1);
1212         if(This->vbInterface)
1213             hr = IVBSAXContentHandler_characters(
1214                     This->saxreader->vbcontentHandler, &Chars);
1215         else
1216             hr = ISAXContentHandler_characters(
1217                     This->saxreader->contentHandler,
1218                     Chars, SysStringLen(Chars));
1219         SysFreeString(Chars);
1220
1221         if(hr != S_OK)
1222         {
1223             format_error_message_from_id(This, hr);
1224             return;
1225         }
1226
1227         This->column += end-cur+1;
1228
1229         if(lastEvent)
1230             break;
1231
1232         *end = '\r';
1233         end++;
1234         if(*end == '\n')
1235         {
1236             end++;
1237             This->column++;
1238         }
1239         cur = end;
1240
1241         if(end-ch == len) break;
1242     }
1243
1244     if(ch<This->pParserCtxt->input->base || ch>This->pParserCtxt->input->end)
1245         This->column = This->realColumn
1246             +This->pParserCtxt->input->cur-This->lastCur;
1247 }
1248
1249 static void libxmlSetDocumentLocator(
1250         void *ctx,
1251         xmlSAXLocatorPtr loc)
1252 {
1253     saxlocator *This = ctx;
1254     HRESULT hr;
1255
1256     if(This->vbInterface)
1257         hr = IVBSAXContentHandler_putref_documentLocator(
1258                 This->saxreader->vbcontentHandler,
1259                 (IVBSAXLocator*)&This->lpVBSAXLocatorVtbl);
1260     else
1261         hr = ISAXContentHandler_putDocumentLocator(
1262                 This->saxreader->contentHandler,
1263                 (ISAXLocator*)&This->lpSAXLocatorVtbl);
1264
1265     if(FAILED(hr))
1266         format_error_message_from_id(This, hr);
1267 }
1268
1269 static void libxmlComment(void *ctx, const xmlChar *value)
1270 {
1271     saxlocator *This = ctx;
1272     BSTR bValue;
1273     HRESULT hr;
1274     xmlChar *beg = (xmlChar*)This->pParserCtxt->input->cur;
1275
1276     while(memcmp(beg-4, "<!--", sizeof(char[4]))) beg--;
1277     update_position(This, beg);
1278
1279     if(!This->vbInterface && !This->saxreader->lexicalHandler) return;
1280     if(This->vbInterface && !This->saxreader->vblexicalHandler) return;
1281
1282     bValue = bstr_from_xmlChar(value);
1283
1284     if(This->vbInterface)
1285         hr = IVBSAXLexicalHandler_comment(
1286                 This->saxreader->vblexicalHandler, &bValue);
1287     else
1288         hr = ISAXLexicalHandler_comment(
1289                 This->saxreader->lexicalHandler,
1290                 bValue, SysStringLen(bValue));
1291
1292     SysFreeString(bValue);
1293
1294     if(FAILED(hr))
1295         format_error_message_from_id(This, hr);
1296
1297     update_position(This, NULL);
1298 }
1299
1300 static void libxmlFatalError(void *ctx, const char *msg, ...)
1301 {
1302     saxlocator *This = ctx;
1303     char message[1024];
1304     WCHAR *wszError;
1305     DWORD len;
1306     va_list args;
1307
1308     if((This->vbInterface && !This->saxreader->vberrorHandler)
1309             || (!This->vbInterface && !This->saxreader->errorHandler))
1310     {
1311         xmlStopParser(This->pParserCtxt);
1312         This->ret = E_FAIL;
1313         return;
1314     }
1315
1316     FIXME("Error handling is not compatible.\n");
1317
1318     va_start(args, msg);
1319     vsprintf(message, msg, args);
1320     va_end(args);
1321
1322     len = MultiByteToWideChar(CP_UNIXCP, 0, message, -1, NULL, 0);
1323     wszError = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len);
1324     if(wszError)
1325         MultiByteToWideChar(CP_UNIXCP, 0, message, -1, wszError, len);
1326
1327     if(This->vbInterface)
1328     {
1329         BSTR bstrError = SysAllocString(wszError);
1330         IVBSAXErrorHandler_fatalError(This->saxreader->vberrorHandler,
1331                 (IVBSAXLocator*)&This->lpVBSAXLocatorVtbl, &bstrError, E_FAIL);
1332     }
1333     else
1334         ISAXErrorHandler_fatalError(This->saxreader->errorHandler,
1335                 (ISAXLocator*)&This->lpSAXLocatorVtbl, wszError, E_FAIL);
1336
1337     HeapFree(GetProcessHeap(), 0, wszError);
1338
1339     xmlStopParser(This->pParserCtxt);
1340     This->ret = E_FAIL;
1341 }
1342
1343 static void libxmlCDataBlock(void *ctx, const xmlChar *value, int len)
1344 {
1345     saxlocator *This = ctx;
1346     HRESULT hr = S_OK;
1347     xmlChar *beg = (xmlChar*)This->pParserCtxt->input->cur-len;
1348     xmlChar *cur, *end;
1349     int realLen;
1350     BSTR Chars;
1351     BOOL lastEvent = FALSE, change;
1352
1353     while(memcmp(beg-9, "<![CDATA[", sizeof(char[9]))) beg--;
1354     update_position(This, beg);
1355
1356     if(This->vbInterface && This->saxreader->vblexicalHandler)
1357         hr = IVBSAXLexicalHandler_startCDATA(This->saxreader->vblexicalHandler);
1358     if(!This->vbInterface && This->saxreader->lexicalHandler)
1359         hr = ISAXLexicalHandler_startCDATA(This->saxreader->lexicalHandler);
1360
1361     if(FAILED(hr))
1362     {
1363         format_error_message_from_id(This, hr);
1364         return;
1365     }
1366
1367     realLen = This->pParserCtxt->input->cur-beg-3;
1368     cur = beg;
1369     end = beg;
1370
1371     while(1)
1372     {
1373         while(end-beg<realLen && *end!='\r') end++;
1374         if(end-beg==realLen)
1375         {
1376             end--;
1377             lastEvent = TRUE;
1378         }
1379         else if(end-beg==realLen-1 && *end=='\r' && *(end+1)=='\n')
1380             lastEvent = TRUE;
1381
1382         if(*end == '\r') change = TRUE;
1383         else change = FALSE;
1384
1385         if(change) *end = '\n';
1386
1387         if((This->vbInterface && This->saxreader->vbcontentHandler) ||
1388                 (!This->vbInterface && This->saxreader->contentHandler))
1389         {
1390             Chars = bstr_from_xmlCharN(cur, end-cur+1);
1391             if(This->vbInterface)
1392                 hr = IVBSAXContentHandler_characters(
1393                         This->saxreader->vbcontentHandler, &Chars);
1394             else
1395                 hr = ISAXContentHandler_characters(
1396                         This->saxreader->contentHandler,
1397                         Chars, SysStringLen(Chars));
1398             SysFreeString(Chars);
1399         }
1400
1401         if(change) *end = '\r';
1402
1403         if(lastEvent)
1404             break;
1405
1406         This->column += end-cur+2;
1407         end += 2;
1408         cur = end;
1409     }
1410
1411     if(This->vbInterface && This->saxreader->vblexicalHandler)
1412         hr = IVBSAXLexicalHandler_endCDATA(This->saxreader->vblexicalHandler);
1413     if(!This->vbInterface && This->saxreader->lexicalHandler)
1414         hr = ISAXLexicalHandler_endCDATA(This->saxreader->lexicalHandler);
1415
1416     if(FAILED(hr))
1417         format_error_message_from_id(This, hr);
1418
1419     This->column += 4+end-cur;
1420 }
1421
1422 /*** IVBSAXLocator interface ***/
1423 /*** IUnknown methods ***/
1424 static HRESULT WINAPI ivbsaxlocator_QueryInterface(IVBSAXLocator* iface, REFIID riid, void **ppvObject)
1425 {
1426     saxlocator *This = impl_from_IVBSAXLocator( iface );
1427
1428     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject);
1429
1430     *ppvObject = NULL;
1431
1432     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
1433             IsEqualGUID( riid, &IID_IDispatch) ||
1434             IsEqualGUID( riid, &IID_IVBSAXLocator ))
1435     {
1436         *ppvObject = iface;
1437     }
1438     else
1439     {
1440         FIXME("interface %s not implemented\n", debugstr_guid(riid));
1441         return E_NOINTERFACE;
1442     }
1443
1444     IVBSAXLocator_AddRef( iface );
1445
1446     return S_OK;
1447 }
1448
1449 static ULONG WINAPI ivbsaxlocator_AddRef(IVBSAXLocator* iface)
1450 {
1451     saxlocator *This = impl_from_IVBSAXLocator( iface );
1452     TRACE("%p\n", This );
1453     return InterlockedIncrement( &This->ref );
1454 }
1455
1456 static ULONG WINAPI ivbsaxlocator_Release(
1457         IVBSAXLocator* iface)
1458 {
1459     saxlocator *This = impl_from_IVBSAXLocator( iface );
1460     return ISAXLocator_Release((ISAXLocator*)&This->lpVBSAXLocatorVtbl);
1461 }
1462
1463 /*** IDispatch methods ***/
1464 static HRESULT WINAPI ivbsaxlocator_GetTypeInfoCount( IVBSAXLocator *iface, UINT* pctinfo )
1465 {
1466     saxlocator *This = impl_from_IVBSAXLocator( iface );
1467
1468     TRACE("(%p)->(%p)\n", This, pctinfo);
1469
1470     *pctinfo = 1;
1471
1472     return S_OK;
1473 }
1474
1475 static HRESULT WINAPI ivbsaxlocator_GetTypeInfo(
1476     IVBSAXLocator *iface,
1477     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
1478 {
1479     saxlocator *This = impl_from_IVBSAXLocator( iface );
1480     HRESULT hr;
1481
1482     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1483
1484     hr = get_typeinfo(IVBSAXLocator_tid, ppTInfo);
1485
1486     return hr;
1487 }
1488
1489 static HRESULT WINAPI ivbsaxlocator_GetIDsOfNames(
1490     IVBSAXLocator *iface,
1491     REFIID riid,
1492     LPOLESTR* rgszNames,
1493     UINT cNames,
1494     LCID lcid,
1495     DISPID* rgDispId)
1496 {
1497     saxlocator *This = impl_from_IVBSAXLocator( iface );
1498     ITypeInfo *typeinfo;
1499     HRESULT hr;
1500
1501     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1502           lcid, rgDispId);
1503
1504     if(!rgszNames || cNames == 0 || !rgDispId)
1505         return E_INVALIDARG;
1506
1507     hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
1508     if(SUCCEEDED(hr))
1509     {
1510         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1511         ITypeInfo_Release(typeinfo);
1512     }
1513
1514     return hr;
1515 }
1516
1517 static HRESULT WINAPI ivbsaxlocator_Invoke(
1518     IVBSAXLocator *iface,
1519     DISPID dispIdMember,
1520     REFIID riid,
1521     LCID lcid,
1522     WORD wFlags,
1523     DISPPARAMS* pDispParams,
1524     VARIANT* pVarResult,
1525     EXCEPINFO* pExcepInfo,
1526     UINT* puArgErr)
1527 {
1528     saxlocator *This = impl_from_IVBSAXLocator( iface );
1529     ITypeInfo *typeinfo;
1530     HRESULT hr;
1531
1532     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1533           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1534
1535     hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
1536     if(SUCCEEDED(hr))
1537     {
1538         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVBSAXLocatorVtbl), dispIdMember, wFlags, pDispParams,
1539                 pVarResult, pExcepInfo, puArgErr);
1540         ITypeInfo_Release(typeinfo);
1541     }
1542
1543     return hr;
1544 }
1545
1546 /*** IVBSAXLocator methods ***/
1547 static HRESULT WINAPI ivbsaxlocator_get_columnNumber(
1548         IVBSAXLocator* iface,
1549         int *pnColumn)
1550 {
1551     saxlocator *This = impl_from_IVBSAXLocator( iface );
1552     return ISAXLocator_getColumnNumber(
1553             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1554             pnColumn);
1555 }
1556
1557 static HRESULT WINAPI ivbsaxlocator_get_lineNumber(
1558         IVBSAXLocator* iface,
1559         int *pnLine)
1560 {
1561     saxlocator *This = impl_from_IVBSAXLocator( iface );
1562     return ISAXLocator_getLineNumber(
1563             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1564             pnLine);
1565 }
1566
1567 static HRESULT WINAPI ivbsaxlocator_get_publicId(
1568         IVBSAXLocator* iface,
1569         BSTR* publicId)
1570 {
1571     saxlocator *This = impl_from_IVBSAXLocator( iface );
1572     return ISAXLocator_getPublicId(
1573             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1574             (const WCHAR**)publicId);
1575 }
1576
1577 static HRESULT WINAPI ivbsaxlocator_get_systemId(
1578         IVBSAXLocator* iface,
1579         BSTR* systemId)
1580 {
1581     saxlocator *This = impl_from_IVBSAXLocator( iface );
1582     return ISAXLocator_getSystemId(
1583             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1584             (const WCHAR**)systemId);
1585 }
1586
1587 static const struct IVBSAXLocatorVtbl ivbsaxlocator_vtbl =
1588 {
1589     ivbsaxlocator_QueryInterface,
1590     ivbsaxlocator_AddRef,
1591     ivbsaxlocator_Release,
1592     ivbsaxlocator_GetTypeInfoCount,
1593     ivbsaxlocator_GetTypeInfo,
1594     ivbsaxlocator_GetIDsOfNames,
1595     ivbsaxlocator_Invoke,
1596     ivbsaxlocator_get_columnNumber,
1597     ivbsaxlocator_get_lineNumber,
1598     ivbsaxlocator_get_publicId,
1599     ivbsaxlocator_get_systemId
1600 };
1601
1602 /*** ISAXLocator interface ***/
1603 /*** IUnknown methods ***/
1604 static HRESULT WINAPI isaxlocator_QueryInterface(ISAXLocator* iface, REFIID riid, void **ppvObject)
1605 {
1606     saxlocator *This = impl_from_ISAXLocator( iface );
1607
1608     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
1609
1610     *ppvObject = NULL;
1611
1612     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
1613             IsEqualGUID( riid, &IID_ISAXLocator ))
1614     {
1615         *ppvObject = iface;
1616     }
1617     else
1618     {
1619         FIXME("interface %s not implemented\n", debugstr_guid(riid));
1620         return E_NOINTERFACE;
1621     }
1622
1623     ISAXLocator_AddRef( iface );
1624
1625     return S_OK;
1626 }
1627
1628 static ULONG WINAPI isaxlocator_AddRef(ISAXLocator* iface)
1629 {
1630     saxlocator *This = impl_from_ISAXLocator( iface );
1631     TRACE("%p\n", This );
1632     return InterlockedIncrement( &This->ref );
1633 }
1634
1635 static ULONG WINAPI isaxlocator_Release(
1636         ISAXLocator* iface)
1637 {
1638     saxlocator *This = impl_from_ISAXLocator( iface );
1639     LONG ref;
1640
1641     TRACE("%p\n", This );
1642
1643     ref = InterlockedDecrement( &This->ref );
1644     if ( ref == 0 )
1645     {
1646         SysFreeString(This->publicId);
1647         SysFreeString(This->systemId);
1648         HeapFree(GetProcessHeap(), 0, This->nsStack);
1649
1650         ISAXXMLReader_Release((ISAXXMLReader*)&This->saxreader->lpSAXXMLReaderVtbl);
1651         HeapFree( GetProcessHeap(), 0, This );
1652     }
1653
1654     return ref;
1655 }
1656
1657 /*** ISAXLocator methods ***/
1658 static HRESULT WINAPI isaxlocator_getColumnNumber(
1659         ISAXLocator* iface,
1660         int *pnColumn)
1661 {
1662     saxlocator *This = impl_from_ISAXLocator( iface );
1663
1664     *pnColumn = This->column;
1665     return S_OK;
1666 }
1667
1668 static HRESULT WINAPI isaxlocator_getLineNumber(
1669         ISAXLocator* iface,
1670         int *pnLine)
1671 {
1672     saxlocator *This = impl_from_ISAXLocator( iface );
1673
1674     *pnLine = This->line;
1675     return S_OK;
1676 }
1677
1678 static HRESULT WINAPI isaxlocator_getPublicId(
1679         ISAXLocator* iface,
1680         const WCHAR ** ppwchPublicId)
1681 {
1682     BSTR publicId;
1683     saxlocator *This = impl_from_ISAXLocator( iface );
1684
1685     SysFreeString(This->publicId);
1686
1687     publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt));
1688     if(SysStringLen(publicId))
1689         This->publicId = (WCHAR*)&publicId;
1690     else
1691     {
1692         SysFreeString(publicId);
1693         This->publicId = NULL;
1694     }
1695
1696     *ppwchPublicId = This->publicId;
1697     return S_OK;
1698 }
1699
1700 static HRESULT WINAPI isaxlocator_getSystemId(
1701         ISAXLocator* iface,
1702         const WCHAR ** ppwchSystemId)
1703 {
1704     BSTR systemId;
1705     saxlocator *This = impl_from_ISAXLocator( iface );
1706
1707     SysFreeString(This->systemId);
1708
1709     systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt));
1710     if(SysStringLen(systemId))
1711         This->systemId = (WCHAR*)&systemId;
1712     else
1713     {
1714         SysFreeString(systemId);
1715         This->systemId = NULL;
1716     }
1717
1718     *ppwchSystemId = This->systemId;
1719     return S_OK;
1720 }
1721
1722 static const struct ISAXLocatorVtbl isaxlocator_vtbl =
1723 {
1724     isaxlocator_QueryInterface,
1725     isaxlocator_AddRef,
1726     isaxlocator_Release,
1727     isaxlocator_getColumnNumber,
1728     isaxlocator_getLineNumber,
1729     isaxlocator_getPublicId,
1730     isaxlocator_getSystemId
1731 };
1732
1733 static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator, BOOL vbInterface)
1734 {
1735     saxlocator *locator;
1736
1737     locator = HeapAlloc( GetProcessHeap(), 0, sizeof (*locator) );
1738     if( !locator )
1739         return E_OUTOFMEMORY;
1740
1741     locator->lpVBSAXLocatorVtbl = &ivbsaxlocator_vtbl;
1742     locator->lpSAXLocatorVtbl = &isaxlocator_vtbl;
1743     locator->ref = 1;
1744     locator->vbInterface = vbInterface;
1745
1746     locator->saxreader = reader;
1747     ISAXXMLReader_AddRef((ISAXXMLReader*)&reader->lpSAXXMLReaderVtbl);
1748
1749     locator->pParserCtxt = NULL;
1750     locator->publicId = NULL;
1751     locator->systemId = NULL;
1752     locator->lastCur = NULL;
1753     locator->line = 0;
1754     locator->column = 0;
1755     locator->ret = S_OK;
1756     locator->nsStackSize = 8;
1757     locator->nsStackLast = 0;
1758     locator->nsStack = HeapAlloc(GetProcessHeap(), 0, locator->nsStackSize);
1759     if(!locator->nsStack)
1760     {
1761         ISAXXMLReader_Release((ISAXXMLReader*)&reader->lpSAXXMLReaderVtbl);
1762         HeapFree(GetProcessHeap(), 0, locator);
1763         return E_OUTOFMEMORY;
1764     }
1765
1766     *ppsaxlocator = locator;
1767
1768     TRACE("returning %p\n", *ppsaxlocator);
1769
1770     return S_OK;
1771 }
1772
1773 /*** SAXXMLReader internal functions ***/
1774 static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int size, BOOL vbInterface)
1775 {
1776     saxlocator *locator;
1777     HRESULT hr;
1778
1779     hr = SAXLocator_create(This, &locator, vbInterface);
1780     if(FAILED(hr))
1781         return hr;
1782
1783     locator->pParserCtxt = xmlCreateMemoryParserCtxt(buffer, size);
1784     if(!locator->pParserCtxt)
1785     {
1786         ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1787         return E_FAIL;
1788     }
1789
1790     locator->pParserCtxt->sax = &locator->saxreader->sax;
1791     locator->pParserCtxt->userData = locator;
1792
1793     This->isParsing = TRUE;
1794     if(xmlParseDocument(locator->pParserCtxt)) hr = E_FAIL;
1795     else hr = locator->ret;
1796     This->isParsing = FALSE;
1797
1798     if(locator->pParserCtxt)
1799     {
1800         locator->pParserCtxt->sax = NULL;
1801         xmlFreeParserCtxt(locator->pParserCtxt);
1802         locator->pParserCtxt = NULL;
1803     }
1804
1805     ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1806     return hr;
1807 }
1808
1809 static HRESULT internal_parseStream(saxreader *This, IStream *stream, BOOL vbInterface)
1810 {
1811     saxlocator *locator;
1812     HRESULT hr;
1813     ULONG dataRead;
1814     char data[1024];
1815
1816     hr = IStream_Read(stream, data, sizeof(data), &dataRead);
1817     if(hr != S_OK)
1818         return hr;
1819
1820     hr = SAXLocator_create(This, &locator, vbInterface);
1821     if(FAILED(hr))
1822         return hr;
1823
1824     locator->pParserCtxt = xmlCreatePushParserCtxt(
1825             &locator->saxreader->sax, locator,
1826             data, dataRead, NULL);
1827     if(!locator->pParserCtxt)
1828     {
1829         ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1830         return E_FAIL;
1831     }
1832
1833     This->isParsing = TRUE;
1834     while(1)
1835     {
1836         hr = IStream_Read(stream, data, sizeof(data), &dataRead);
1837         if(hr != S_OK)
1838             break;
1839
1840         if(xmlParseChunk(locator->pParserCtxt, data, dataRead, 0)) hr = E_FAIL;
1841         else hr = locator->ret;
1842
1843         if(hr != S_OK) break;
1844
1845         if(dataRead != sizeof(data))
1846         {
1847             if(xmlParseChunk(locator->pParserCtxt, data, 0, 1)) hr = E_FAIL;
1848             else hr = locator->ret;
1849
1850             break;
1851         }
1852     }
1853     This->isParsing = FALSE;
1854
1855     locator->pParserCtxt->sax = NULL;
1856     xmlFreeParserCtxt(locator->pParserCtxt);
1857     locator->pParserCtxt = NULL;
1858     ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1859     return hr;
1860 }
1861
1862 static HRESULT internal_getEntityResolver(
1863         saxreader *This,
1864         void *pEntityResolver,
1865         BOOL vbInterface)
1866 {
1867     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
1868     return E_NOTIMPL;
1869 }
1870
1871 static HRESULT internal_putEntityResolver(
1872         saxreader *This,
1873         void *pEntityResolver,
1874         BOOL vbInterface)
1875 {
1876     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
1877     return E_NOTIMPL;
1878 }
1879
1880 static HRESULT internal_getContentHandler(
1881         saxreader* This,
1882         void *pContentHandler,
1883         BOOL vbInterface)
1884 {
1885     TRACE("(%p)->(%p)\n", This, pContentHandler);
1886     if(pContentHandler == NULL)
1887         return E_POINTER;
1888     if((vbInterface && This->vbcontentHandler)
1889             || (!vbInterface && This->contentHandler))
1890     {
1891         if(vbInterface)
1892             IVBSAXContentHandler_AddRef(This->vbcontentHandler);
1893         else
1894             ISAXContentHandler_AddRef(This->contentHandler);
1895     }
1896     if(vbInterface) *(IVBSAXContentHandler**)pContentHandler =
1897         This->vbcontentHandler;
1898     else *(ISAXContentHandler**)pContentHandler = This->contentHandler;
1899
1900     return S_OK;
1901 }
1902
1903 static HRESULT internal_putContentHandler(
1904         saxreader* This,
1905         void *contentHandler,
1906         BOOL vbInterface)
1907 {
1908     TRACE("(%p)->(%p)\n", This, contentHandler);
1909     if(contentHandler)
1910     {
1911         if(vbInterface)
1912             IVBSAXContentHandler_AddRef((IVBSAXContentHandler*)contentHandler);
1913         else
1914             ISAXContentHandler_AddRef((ISAXContentHandler*)contentHandler);
1915     }
1916     if((vbInterface && This->vbcontentHandler)
1917             || (!vbInterface && This->contentHandler))
1918     {
1919         if(vbInterface)
1920             IVBSAXContentHandler_Release(This->vbcontentHandler);
1921         else
1922             ISAXContentHandler_Release(This->contentHandler);
1923     }
1924     if(vbInterface)
1925         This->vbcontentHandler = contentHandler;
1926     else
1927         This->contentHandler = contentHandler;
1928
1929     return S_OK;
1930 }
1931
1932 static HRESULT internal_getDTDHandler(
1933         saxreader* This,
1934         void *pDTDHandler,
1935         BOOL vbInterface)
1936 {
1937     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
1938     return E_NOTIMPL;
1939 }
1940
1941 static HRESULT internal_putDTDHandler(
1942         saxreader* This,
1943         void *pDTDHandler,
1944         BOOL vbInterface)
1945 {
1946     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
1947     return E_NOTIMPL;
1948 }
1949
1950 static HRESULT internal_getErrorHandler(
1951         saxreader* This,
1952         void *pErrorHandler,
1953         BOOL vbInterface)
1954 {
1955     TRACE("(%p)->(%p)\n", This, pErrorHandler);
1956     if(pErrorHandler == NULL)
1957         return E_POINTER;
1958
1959     if(vbInterface && This->vberrorHandler)
1960         IVBSAXErrorHandler_AddRef(This->vberrorHandler);
1961     else if(!vbInterface && This->errorHandler)
1962         ISAXErrorHandler_AddRef(This->errorHandler);
1963
1964     if(vbInterface)
1965         *(IVBSAXErrorHandler**)pErrorHandler = This->vberrorHandler;
1966     else
1967         *(ISAXErrorHandler**)pErrorHandler = This->errorHandler;
1968
1969     return S_OK;
1970
1971 }
1972
1973 static HRESULT internal_putErrorHandler(
1974         saxreader* This,
1975         void *errorHandler,
1976         BOOL vbInterface)
1977 {
1978     TRACE("(%p)->(%p)\n", This, errorHandler);
1979     if(errorHandler)
1980     {
1981         if(vbInterface)
1982             IVBSAXErrorHandler_AddRef((IVBSAXErrorHandler*)errorHandler);
1983         else
1984             ISAXErrorHandler_AddRef((ISAXErrorHandler*)errorHandler);
1985     }
1986
1987     if(vbInterface && This->vberrorHandler)
1988         IVBSAXErrorHandler_Release(This->vberrorHandler);
1989     else if(!vbInterface && This->errorHandler)
1990         ISAXErrorHandler_Release(This->errorHandler);
1991
1992     if(vbInterface)
1993         This->vberrorHandler = errorHandler;
1994     else
1995         This->errorHandler = errorHandler;
1996
1997     return S_OK;
1998
1999 }
2000
2001 static HRESULT internal_parse(
2002         saxreader* This,
2003         VARIANT varInput,
2004         BOOL vbInterface)
2005 {
2006     HRESULT hr;
2007
2008     TRACE("(%p)\n", This);
2009
2010     hr = S_OK;
2011     switch(V_VT(&varInput))
2012     {
2013         case VT_BSTR:
2014             hr = internal_parseBuffer(This, (const char*)V_BSTR(&varInput),
2015                     SysStringByteLen(V_BSTR(&varInput)), vbInterface);
2016             break;
2017         case VT_ARRAY|VT_UI1: {
2018             void *pSAData;
2019             LONG lBound, uBound;
2020             ULONG dataRead;
2021
2022             hr = SafeArrayGetLBound(V_ARRAY(&varInput), 1, &lBound);
2023             if(hr != S_OK) break;
2024             hr = SafeArrayGetUBound(V_ARRAY(&varInput), 1, &uBound);
2025             if(hr != S_OK) break;
2026             dataRead = (uBound-lBound)*SafeArrayGetElemsize(V_ARRAY(&varInput));
2027             hr = SafeArrayAccessData(V_ARRAY(&varInput), &pSAData);
2028             if(hr != S_OK) break;
2029             hr = internal_parseBuffer(This, pSAData, dataRead, vbInterface);
2030             SafeArrayUnaccessData(V_ARRAY(&varInput));
2031             break;
2032         }
2033         case VT_UNKNOWN:
2034         case VT_DISPATCH: {
2035             IPersistStream *persistStream;
2036             IStream *stream = NULL;
2037             IXMLDOMDocument *xmlDoc;
2038
2039             if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2040                         &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK)
2041             {
2042                 BSTR bstrData;
2043
2044                 IXMLDOMDocument_get_xml(xmlDoc, &bstrData);
2045                 hr = internal_parseBuffer(This, (const char*)bstrData,
2046                         SysStringByteLen(bstrData), vbInterface);
2047                 IXMLDOMDocument_Release(xmlDoc);
2048                 break;
2049             }
2050             if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2051                         &IID_IPersistStream, (void**)&persistStream) == S_OK)
2052             {
2053                 hr = IPersistStream_Save(persistStream, stream, TRUE);
2054                 IPersistStream_Release(persistStream);
2055                 if(hr != S_OK) break;
2056             }
2057             if(stream || IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2058                         &IID_IStream, (void**)&stream) == S_OK)
2059             {
2060                 hr = internal_parseStream(This, stream, vbInterface);
2061                 IStream_Release(stream);
2062                 break;
2063             }
2064         }
2065         default:
2066             WARN("vt %d not implemented\n", V_VT(&varInput));
2067             hr = E_INVALIDARG;
2068     }
2069
2070     return hr;
2071 }
2072
2073 static HRESULT internal_vbonDataAvailable(void *obj, char *ptr, DWORD len)
2074 {
2075     saxreader *This = obj;
2076
2077     return internal_parseBuffer(This, ptr, len, TRUE);
2078 }
2079
2080 static HRESULT internal_onDataAvailable(void *obj, char *ptr, DWORD len)
2081 {
2082     saxreader *This = obj;
2083
2084     return internal_parseBuffer(This, ptr, len, FALSE);
2085 }
2086
2087 static HRESULT internal_parseURL(
2088         saxreader* This,
2089         const WCHAR *url,
2090         BOOL vbInterface)
2091 {
2092     bsc_t *bsc;
2093     HRESULT hr;
2094
2095     TRACE("(%p)->(%s)\n", This, debugstr_w(url));
2096
2097     if(vbInterface) hr = bind_url(url, internal_vbonDataAvailable, This, &bsc);
2098     else hr = bind_url(url, internal_onDataAvailable, This, &bsc);
2099
2100     if(FAILED(hr))
2101         return hr;
2102
2103     detach_bsc(bsc);
2104
2105     return S_OK;
2106 }
2107
2108 static HRESULT internal_putProperty(
2109     saxreader* This,
2110     const WCHAR *pProp,
2111     VARIANT value,
2112     BOOL vbInterface)
2113 {
2114     static const WCHAR wszCharset[] = {
2115         'c','h','a','r','s','e','t',0
2116     };
2117     static const WCHAR wszDeclarationHandler[] = {
2118         'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
2119         's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
2120         'd','e','c','l','a','r','a','t','i','o','n',
2121         '-','h','a','n','d','l','e','r',0
2122     };
2123     static const WCHAR wszDomNode[] = {
2124         'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
2125         's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
2126         'd','o','m','-','n','o','d','e',0
2127     };
2128     static const WCHAR wszInputSource[] = {
2129         'i','n','p','u','t','-','s','o','u','r','c','e',0
2130     };
2131     static const WCHAR wszLexicalHandler[] = {
2132         'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
2133         's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
2134         'l','e','x','i','c','a','l','-','h','a','n','d','l','e','r',0
2135     };
2136     static const WCHAR wszMaxElementDepth[] = {
2137         'm','a','x','-','e','l','e','m','e','n','t','-','d','e','p','t','h',0
2138     };
2139     static const WCHAR wszMaxXMLSize[] = {
2140         'm','a','x','-','x','m','l','-','s','i','z','e',0
2141     };
2142     static const WCHAR wszSchemaDeclarationHandler[] = {
2143         's','c','h','e','m','a','-',
2144         'd','e','c','l','a','r','a','t','i','o','n','-',
2145         'h','a','n','d','l','e','r',0
2146     };
2147     static const WCHAR wszXMLDeclEncoding[] = {
2148         'x','m','l','d','e','c','l','-','e','n','c','o','d','i','n','g',0
2149     };
2150     static const WCHAR wszXMLDeclStandalone[] = {
2151         'x','m','l','d','e','c','l',
2152         '-','s','t','a','n','d','a','l','o','n','e',0
2153     };
2154     static const WCHAR wszXMLDeclVersion[] = {
2155         'x','m','l','d','e','c','l','-','v','e','r','s','i','o','n',0
2156     };
2157
2158     FIXME("(%p)->(%s): semi-stub\n", This, debugstr_w(pProp));
2159
2160     if(!memcmp(pProp, wszCharset, sizeof(wszCharset)))
2161         return E_NOTIMPL;
2162
2163     if(!memcmp(pProp, wszDeclarationHandler, sizeof(wszDeclarationHandler)))
2164     {
2165         if(This->isParsing) return E_FAIL;
2166
2167         if(V_UNKNOWN(&value))
2168         {
2169             if(vbInterface)
2170                 IVBSAXDeclHandler_AddRef((IVBSAXDeclHandler*)V_UNKNOWN(&value));
2171             else
2172                 ISAXDeclHandler_AddRef((ISAXDeclHandler*)V_UNKNOWN(&value));
2173         }
2174         if((vbInterface && This->vbdeclHandler)
2175                 || (!vbInterface && This->declHandler))
2176         {
2177             if(vbInterface)
2178                 IVBSAXDeclHandler_Release(This->vbdeclHandler);
2179             else
2180                 ISAXDeclHandler_Release(This->declHandler);
2181         }
2182         if(vbInterface)
2183             This->vbdeclHandler = (IVBSAXDeclHandler*)V_UNKNOWN(&value);
2184         else
2185             This->declHandler = (ISAXDeclHandler*)V_UNKNOWN(&value);
2186         return S_OK;
2187     }
2188
2189     if(!memcmp(pProp, wszDomNode, sizeof(wszDomNode)))
2190         return E_FAIL;
2191
2192     if(!memcmp(pProp, wszInputSource, sizeof(wszInputSource)))
2193         return E_NOTIMPL;
2194
2195     if(!memcmp(pProp, wszLexicalHandler, sizeof(wszLexicalHandler)))
2196     {
2197         if(This->isParsing) return E_FAIL;
2198
2199         if(V_UNKNOWN(&value))
2200         {
2201             if(vbInterface)
2202                 IVBSAXLexicalHandler_AddRef(
2203                         (IVBSAXLexicalHandler*)V_UNKNOWN(&value));
2204             else
2205                 ISAXLexicalHandler_AddRef(
2206                         (ISAXLexicalHandler*)V_UNKNOWN(&value));
2207         }
2208         if((vbInterface && This->vblexicalHandler)
2209                 || (!vbInterface && This->lexicalHandler))
2210         {
2211             if(vbInterface)
2212                 IVBSAXLexicalHandler_Release(This->vblexicalHandler);
2213             else
2214                 ISAXLexicalHandler_Release(This->lexicalHandler);
2215         }
2216         if(vbInterface)
2217             This->vblexicalHandler = (IVBSAXLexicalHandler*)V_UNKNOWN(&value);
2218         else
2219             This->lexicalHandler = (ISAXLexicalHandler*)V_UNKNOWN(&value);
2220         return S_OK;
2221     }
2222
2223     if(!memcmp(pProp, wszMaxElementDepth, sizeof(wszMaxElementDepth)))
2224         return E_NOTIMPL;
2225
2226     if(!memcmp(pProp, wszMaxXMLSize, sizeof(wszMaxXMLSize)))
2227         return E_NOTIMPL;
2228
2229     if(!memcmp(pProp, wszSchemaDeclarationHandler,
2230                 sizeof(wszSchemaDeclarationHandler)))
2231         return E_NOTIMPL;
2232
2233     if(!memcmp(pProp, wszXMLDeclEncoding, sizeof(wszXMLDeclEncoding)))
2234         return E_FAIL;
2235
2236     if(!memcmp(pProp, wszXMLDeclStandalone, sizeof(wszXMLDeclStandalone)))
2237         return E_FAIL;
2238
2239     if(!memcmp(pProp, wszXMLDeclVersion, sizeof(wszXMLDeclVersion)))
2240         return E_FAIL;
2241
2242     return E_INVALIDARG;
2243 }
2244
2245 /*** IVBSAXXMLReader interface ***/
2246 /*** IUnknown methods ***/
2247 static HRESULT WINAPI saxxmlreader_QueryInterface(IVBSAXXMLReader* iface, REFIID riid, void **ppvObject)
2248 {
2249     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2250
2251     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2252
2253     *ppvObject = NULL;
2254
2255     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2256          IsEqualGUID( riid, &IID_IDispatch ) ||
2257          IsEqualGUID( riid, &IID_IVBSAXXMLReader ))
2258     {
2259         *ppvObject = iface;
2260     }
2261     else if( IsEqualGUID( riid, &IID_ISAXXMLReader ))
2262     {
2263         *ppvObject = &This->lpSAXXMLReaderVtbl;
2264     }
2265     else
2266     {
2267         FIXME("interface %s not implemented\n", debugstr_guid(riid));
2268         return E_NOINTERFACE;
2269     }
2270
2271     IVBSAXXMLReader_AddRef( iface );
2272
2273     return S_OK;
2274 }
2275
2276 static ULONG WINAPI saxxmlreader_AddRef(IVBSAXXMLReader* iface)
2277 {
2278     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2279     TRACE("%p\n", This );
2280     return InterlockedIncrement( &This->ref );
2281 }
2282
2283 static ULONG WINAPI saxxmlreader_Release(
2284     IVBSAXXMLReader* iface)
2285 {
2286     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2287     LONG ref;
2288
2289     TRACE("%p\n", This );
2290
2291     ref = InterlockedDecrement( &This->ref );
2292     if ( ref == 0 )
2293     {
2294         if(This->contentHandler)
2295             ISAXContentHandler_Release(This->contentHandler);
2296
2297         if(This->vbcontentHandler)
2298             IVBSAXContentHandler_Release(This->vbcontentHandler);
2299
2300         if(This->errorHandler)
2301             ISAXErrorHandler_Release(This->errorHandler);
2302
2303         if(This->vberrorHandler)
2304             IVBSAXErrorHandler_Release(This->vberrorHandler);
2305
2306         if(This->lexicalHandler)
2307             ISAXLexicalHandler_Release(This->lexicalHandler);
2308
2309         if(This->vblexicalHandler)
2310             IVBSAXLexicalHandler_Release(This->vblexicalHandler);
2311
2312         if(This->declHandler)
2313             ISAXDeclHandler_Release(This->declHandler);
2314
2315         if(This->vbdeclHandler)
2316             IVBSAXDeclHandler_Release(This->vbdeclHandler);
2317
2318         HeapFree( GetProcessHeap(), 0, This );
2319     }
2320
2321     return ref;
2322 }
2323 /*** IDispatch ***/
2324 static HRESULT WINAPI saxxmlreader_GetTypeInfoCount( IVBSAXXMLReader *iface, UINT* pctinfo )
2325 {
2326     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2327
2328     TRACE("(%p)->(%p)\n", This, pctinfo);
2329
2330     *pctinfo = 1;
2331
2332     return S_OK;
2333 }
2334
2335 static HRESULT WINAPI saxxmlreader_GetTypeInfo(
2336     IVBSAXXMLReader *iface,
2337     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2338 {
2339     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2340     HRESULT hr;
2341
2342     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
2343
2344     hr = get_typeinfo(IVBSAXXMLReader_tid, ppTInfo);
2345
2346     return hr;
2347 }
2348
2349 static HRESULT WINAPI saxxmlreader_GetIDsOfNames(
2350     IVBSAXXMLReader *iface,
2351     REFIID riid,
2352     LPOLESTR* rgszNames,
2353     UINT cNames,
2354     LCID lcid,
2355     DISPID* rgDispId)
2356 {
2357     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2358     ITypeInfo *typeinfo;
2359     HRESULT hr;
2360
2361     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
2362           lcid, rgDispId);
2363
2364     if(!rgszNames || cNames == 0 || !rgDispId)
2365         return E_INVALIDARG;
2366
2367     hr = get_typeinfo(IVBSAXXMLReader_tid, &typeinfo);
2368     if(SUCCEEDED(hr))
2369     {
2370         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2371         ITypeInfo_Release(typeinfo);
2372     }
2373
2374     return hr;
2375 }
2376
2377 static HRESULT WINAPI saxxmlreader_Invoke(
2378     IVBSAXXMLReader *iface,
2379     DISPID dispIdMember,
2380     REFIID riid,
2381     LCID lcid,
2382     WORD wFlags,
2383     DISPPARAMS* pDispParams,
2384     VARIANT* pVarResult,
2385     EXCEPINFO* pExcepInfo,
2386     UINT* puArgErr)
2387 {
2388     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2389     ITypeInfo *typeinfo;
2390     HRESULT hr;
2391
2392     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
2393           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2394
2395     hr = get_typeinfo(IVBSAXXMLReader_tid, &typeinfo);
2396     if(SUCCEEDED(hr))
2397     {
2398         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVBSAXXMLReaderVtbl), dispIdMember, wFlags, pDispParams,
2399                 pVarResult, pExcepInfo, puArgErr);
2400         ITypeInfo_Release(typeinfo);
2401     }
2402
2403     return hr;
2404 }
2405
2406 /*** IVBSAXXMLReader methods ***/
2407 static HRESULT WINAPI saxxmlreader_getFeature(
2408     IVBSAXXMLReader* iface,
2409     const WCHAR *pFeature,
2410     VARIANT_BOOL *pValue)
2411 {
2412     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2413
2414     FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pFeature), pValue);
2415     return E_NOTIMPL;
2416 }
2417
2418 static HRESULT WINAPI saxxmlreader_putFeature(
2419     IVBSAXXMLReader* iface,
2420     const WCHAR *pFeature,
2421     VARIANT_BOOL vfValue)
2422 {
2423     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2424
2425     FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(pFeature), vfValue);
2426     return E_NOTIMPL;
2427 }
2428
2429 static HRESULT WINAPI saxxmlreader_getProperty(
2430     IVBSAXXMLReader* iface,
2431     const WCHAR *pProp,
2432     VARIANT *pValue)
2433 {
2434     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2435
2436     FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pProp), pValue);
2437     return E_NOTIMPL;
2438 }
2439
2440 static HRESULT WINAPI saxxmlreader_putProperty(
2441     IVBSAXXMLReader* iface,
2442     const WCHAR *pProp,
2443     VARIANT value)
2444 {
2445     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2446     return internal_putProperty(This, pProp, value, TRUE);
2447 }
2448
2449 static HRESULT WINAPI saxxmlreader_get_entityResolver(
2450     IVBSAXXMLReader* iface,
2451     IVBSAXEntityResolver **pEntityResolver)
2452 {
2453     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2454     return internal_getEntityResolver(This, pEntityResolver, TRUE);
2455 }
2456
2457 static HRESULT WINAPI saxxmlreader_put_entityResolver(
2458     IVBSAXXMLReader* iface,
2459     IVBSAXEntityResolver *pEntityResolver)
2460 {
2461     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2462     return internal_putEntityResolver(This, pEntityResolver, TRUE);
2463 }
2464
2465 static HRESULT WINAPI saxxmlreader_get_contentHandler(
2466     IVBSAXXMLReader* iface,
2467     IVBSAXContentHandler **ppContentHandler)
2468 {
2469     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2470     return internal_getContentHandler(This, ppContentHandler, TRUE);
2471 }
2472
2473 static HRESULT WINAPI saxxmlreader_put_contentHandler(
2474     IVBSAXXMLReader* iface,
2475     IVBSAXContentHandler *contentHandler)
2476 {
2477     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2478     return internal_putContentHandler(This, contentHandler, TRUE);
2479 }
2480
2481 static HRESULT WINAPI saxxmlreader_get_dtdHandler(
2482     IVBSAXXMLReader* iface,
2483     IVBSAXDTDHandler **pDTDHandler)
2484 {
2485     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2486     return internal_getDTDHandler(This, pDTDHandler, TRUE);
2487 }
2488
2489 static HRESULT WINAPI saxxmlreader_put_dtdHandler(
2490     IVBSAXXMLReader* iface,
2491     IVBSAXDTDHandler *pDTDHandler)
2492 {
2493     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2494     return internal_putDTDHandler(This, pDTDHandler, TRUE);
2495 }
2496
2497 static HRESULT WINAPI saxxmlreader_get_errorHandler(
2498     IVBSAXXMLReader* iface,
2499     IVBSAXErrorHandler **pErrorHandler)
2500 {
2501     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2502     return internal_getErrorHandler(This, pErrorHandler, TRUE);
2503 }
2504
2505 static HRESULT WINAPI saxxmlreader_put_errorHandler(
2506     IVBSAXXMLReader* iface,
2507     IVBSAXErrorHandler *errorHandler)
2508 {
2509     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2510     return internal_putErrorHandler(This, errorHandler, TRUE);
2511 }
2512
2513 static HRESULT WINAPI saxxmlreader_get_baseURL(
2514     IVBSAXXMLReader* iface,
2515     const WCHAR **pBaseUrl)
2516 {
2517     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2518
2519     FIXME("(%p)->(%p) stub\n", This, pBaseUrl);
2520     return E_NOTIMPL;
2521 }
2522
2523 static HRESULT WINAPI saxxmlreader_put_baseURL(
2524     IVBSAXXMLReader* iface,
2525     const WCHAR *pBaseUrl)
2526 {
2527     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2528
2529     FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
2530     return E_NOTIMPL;
2531 }
2532
2533 static HRESULT WINAPI saxxmlreader_get_secureBaseURL(
2534     IVBSAXXMLReader* iface,
2535     const WCHAR **pSecureBaseUrl)
2536 {
2537     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2538
2539     FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
2540     return E_NOTIMPL;
2541 }
2542
2543
2544 static HRESULT WINAPI saxxmlreader_put_secureBaseURL(
2545     IVBSAXXMLReader* iface,
2546     const WCHAR *secureBaseUrl)
2547 {
2548     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2549
2550     FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
2551     return E_NOTIMPL;
2552 }
2553
2554 static HRESULT WINAPI saxxmlreader_parse(
2555     IVBSAXXMLReader* iface,
2556     VARIANT varInput)
2557 {
2558     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2559     return internal_parse(This, varInput, TRUE);
2560 }
2561
2562 static HRESULT WINAPI saxxmlreader_parseURL(
2563     IVBSAXXMLReader* iface,
2564     const WCHAR *url)
2565 {
2566     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2567     return internal_parseURL(This, url, TRUE);
2568 }
2569
2570 static const struct IVBSAXXMLReaderVtbl saxreader_vtbl =
2571 {
2572     saxxmlreader_QueryInterface,
2573     saxxmlreader_AddRef,
2574     saxxmlreader_Release,
2575     saxxmlreader_GetTypeInfoCount,
2576     saxxmlreader_GetTypeInfo,
2577     saxxmlreader_GetIDsOfNames,
2578     saxxmlreader_Invoke,
2579     saxxmlreader_getFeature,
2580     saxxmlreader_putFeature,
2581     saxxmlreader_getProperty,
2582     saxxmlreader_putProperty,
2583     saxxmlreader_get_entityResolver,
2584     saxxmlreader_put_entityResolver,
2585     saxxmlreader_get_contentHandler,
2586     saxxmlreader_put_contentHandler,
2587     saxxmlreader_get_dtdHandler,
2588     saxxmlreader_put_dtdHandler,
2589     saxxmlreader_get_errorHandler,
2590     saxxmlreader_put_errorHandler,
2591     saxxmlreader_get_baseURL,
2592     saxxmlreader_put_baseURL,
2593     saxxmlreader_get_secureBaseURL,
2594     saxxmlreader_put_secureBaseURL,
2595     saxxmlreader_parse,
2596     saxxmlreader_parseURL
2597 };
2598
2599 /*** ISAXXMLReader interface ***/
2600 /*** IUnknown methods ***/
2601 static HRESULT WINAPI isaxxmlreader_QueryInterface(ISAXXMLReader* iface, REFIID riid, void **ppvObject)
2602 {
2603     saxreader *This = impl_from_ISAXXMLReader( iface );
2604     return saxxmlreader_QueryInterface((IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl, riid, ppvObject);
2605 }
2606
2607 static ULONG WINAPI isaxxmlreader_AddRef(ISAXXMLReader* iface)
2608 {
2609     saxreader *This = impl_from_ISAXXMLReader( iface );
2610     return saxxmlreader_AddRef((IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl);
2611 }
2612
2613 static ULONG WINAPI isaxxmlreader_Release(ISAXXMLReader* iface)
2614 {
2615     saxreader *This = impl_from_ISAXXMLReader( iface );
2616     return saxxmlreader_Release((IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl);
2617 }
2618
2619 /*** ISAXXMLReader methods ***/
2620 static HRESULT WINAPI isaxxmlreader_getFeature(
2621         ISAXXMLReader* iface,
2622         const WCHAR *pFeature,
2623         VARIANT_BOOL *pValue)
2624 {
2625     saxreader *This = impl_from_ISAXXMLReader( iface );
2626     return IVBSAXXMLReader_getFeature(
2627             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2628             pFeature, pValue);
2629 }
2630
2631 static HRESULT WINAPI isaxxmlreader_putFeature(
2632         ISAXXMLReader* iface,
2633         const WCHAR *pFeature,
2634         VARIANT_BOOL vfValue)
2635 {
2636     saxreader *This = impl_from_ISAXXMLReader( iface );
2637     return IVBSAXXMLReader_putFeature(
2638             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2639             pFeature, vfValue);
2640 }
2641
2642 static HRESULT WINAPI isaxxmlreader_getProperty(
2643         ISAXXMLReader* iface,
2644         const WCHAR *pProp,
2645         VARIANT *pValue)
2646 {
2647     saxreader *This = impl_from_ISAXXMLReader( iface );
2648     return IVBSAXXMLReader_getProperty(
2649             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2650             pProp, pValue);
2651 }
2652
2653 static HRESULT WINAPI isaxxmlreader_putProperty(
2654         ISAXXMLReader* iface,
2655         const WCHAR *pProp,
2656         VARIANT value)
2657 {
2658     saxreader *This = impl_from_ISAXXMLReader( iface );
2659     return internal_putProperty(This, pProp, value, FALSE);
2660 }
2661
2662 static HRESULT WINAPI isaxxmlreader_getEntityResolver(
2663         ISAXXMLReader* iface,
2664         ISAXEntityResolver **ppEntityResolver)
2665 {
2666     saxreader *This = impl_from_ISAXXMLReader( iface );
2667     return internal_getEntityResolver(This, ppEntityResolver, FALSE);
2668 }
2669
2670 static HRESULT WINAPI isaxxmlreader_putEntityResolver(
2671         ISAXXMLReader* iface,
2672         ISAXEntityResolver *pEntityResolver)
2673 {
2674     saxreader *This = impl_from_ISAXXMLReader( iface );
2675     return internal_putEntityResolver(This, pEntityResolver, FALSE);
2676 }
2677
2678 static HRESULT WINAPI isaxxmlreader_getContentHandler(
2679         ISAXXMLReader* iface,
2680         ISAXContentHandler **pContentHandler)
2681 {
2682     saxreader *This = impl_from_ISAXXMLReader( iface );
2683     return internal_getContentHandler(This, pContentHandler, FALSE);
2684 }
2685
2686 static HRESULT WINAPI isaxxmlreader_putContentHandler(
2687         ISAXXMLReader* iface,
2688         ISAXContentHandler *contentHandler)
2689 {
2690     saxreader *This = impl_from_ISAXXMLReader( iface );
2691     return internal_putContentHandler(This, contentHandler, FALSE);
2692 }
2693
2694 static HRESULT WINAPI isaxxmlreader_getDTDHandler(
2695         ISAXXMLReader* iface,
2696         ISAXDTDHandler **pDTDHandler)
2697 {
2698     saxreader *This = impl_from_ISAXXMLReader( iface );
2699     return internal_getDTDHandler(This, pDTDHandler, FALSE);
2700 }
2701
2702 static HRESULT WINAPI isaxxmlreader_putDTDHandler(
2703         ISAXXMLReader* iface,
2704         ISAXDTDHandler *pDTDHandler)
2705 {
2706     saxreader *This = impl_from_ISAXXMLReader( iface );
2707     return internal_putDTDHandler(This, pDTDHandler, FALSE);
2708 }
2709
2710 static HRESULT WINAPI isaxxmlreader_getErrorHandler(
2711         ISAXXMLReader* iface,
2712         ISAXErrorHandler **pErrorHandler)
2713 {
2714     saxreader *This = impl_from_ISAXXMLReader( iface );
2715     return internal_getErrorHandler(This, pErrorHandler, FALSE);
2716 }
2717
2718 static HRESULT WINAPI isaxxmlreader_putErrorHandler(
2719         ISAXXMLReader* iface,
2720         ISAXErrorHandler *errorHandler)
2721 {
2722     saxreader *This = impl_from_ISAXXMLReader( iface );
2723     return internal_putErrorHandler(This, errorHandler, FALSE);
2724 }
2725
2726 static HRESULT WINAPI isaxxmlreader_getBaseURL(
2727         ISAXXMLReader* iface,
2728         const WCHAR **pBaseUrl)
2729 {
2730     saxreader *This = impl_from_ISAXXMLReader( iface );
2731     return IVBSAXXMLReader_get_baseURL(
2732             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2733             pBaseUrl);
2734 }
2735
2736 static HRESULT WINAPI isaxxmlreader_putBaseURL(
2737         ISAXXMLReader* iface,
2738         const WCHAR *pBaseUrl)
2739 {
2740     saxreader *This = impl_from_ISAXXMLReader( iface );
2741     return IVBSAXXMLReader_put_baseURL(
2742             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2743             pBaseUrl);
2744 }
2745
2746 static HRESULT WINAPI isaxxmlreader_getSecureBaseURL(
2747         ISAXXMLReader* iface,
2748         const WCHAR **pSecureBaseUrl)
2749 {
2750     saxreader *This = impl_from_ISAXXMLReader( iface );
2751     return IVBSAXXMLReader_get_secureBaseURL(
2752             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2753             pSecureBaseUrl);
2754 }
2755
2756 static HRESULT WINAPI isaxxmlreader_putSecureBaseURL(
2757         ISAXXMLReader* iface,
2758         const WCHAR *secureBaseUrl)
2759 {
2760     saxreader *This = impl_from_ISAXXMLReader( iface );
2761     return IVBSAXXMLReader_put_secureBaseURL(
2762             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2763             secureBaseUrl);
2764 }
2765
2766 static HRESULT WINAPI isaxxmlreader_parse(
2767         ISAXXMLReader* iface,
2768         VARIANT varInput)
2769 {
2770     saxreader *This = impl_from_ISAXXMLReader( iface );
2771     return internal_parse(This, varInput, FALSE);
2772 }
2773
2774 static HRESULT WINAPI isaxxmlreader_parseURL(
2775         ISAXXMLReader* iface,
2776         const WCHAR *url)
2777 {
2778     saxreader *This = impl_from_ISAXXMLReader( iface );
2779     return internal_parseURL(This, url, FALSE);
2780 }
2781
2782 static const struct ISAXXMLReaderVtbl isaxreader_vtbl =
2783 {
2784     isaxxmlreader_QueryInterface,
2785     isaxxmlreader_AddRef,
2786     isaxxmlreader_Release,
2787     isaxxmlreader_getFeature,
2788     isaxxmlreader_putFeature,
2789     isaxxmlreader_getProperty,
2790     isaxxmlreader_putProperty,
2791     isaxxmlreader_getEntityResolver,
2792     isaxxmlreader_putEntityResolver,
2793     isaxxmlreader_getContentHandler,
2794     isaxxmlreader_putContentHandler,
2795     isaxxmlreader_getDTDHandler,
2796     isaxxmlreader_putDTDHandler,
2797     isaxxmlreader_getErrorHandler,
2798     isaxxmlreader_putErrorHandler,
2799     isaxxmlreader_getBaseURL,
2800     isaxxmlreader_putBaseURL,
2801     isaxxmlreader_getSecureBaseURL,
2802     isaxxmlreader_putSecureBaseURL,
2803     isaxxmlreader_parse,
2804     isaxxmlreader_parseURL
2805 };
2806
2807 HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2808 {
2809     saxreader *reader;
2810
2811     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
2812
2813     reader = HeapAlloc( GetProcessHeap(), 0, sizeof (*reader) );
2814     if( !reader )
2815         return E_OUTOFMEMORY;
2816
2817     reader->lpVBSAXXMLReaderVtbl = &saxreader_vtbl;
2818     reader->lpSAXXMLReaderVtbl = &isaxreader_vtbl;
2819     reader->ref = 1;
2820     reader->contentHandler = NULL;
2821     reader->vbcontentHandler = NULL;
2822     reader->errorHandler = NULL;
2823     reader->vberrorHandler = NULL;
2824     reader->lexicalHandler = NULL;
2825     reader->vblexicalHandler = NULL;
2826     reader->declHandler = NULL;
2827     reader->vbdeclHandler = NULL;
2828     reader->isParsing = FALSE;
2829
2830     memset(&reader->sax, 0, sizeof(xmlSAXHandler));
2831     reader->sax.initialized = XML_SAX2_MAGIC;
2832     reader->sax.startDocument = libxmlStartDocument;
2833     reader->sax.endDocument = libxmlEndDocument;
2834     reader->sax.startElementNs = libxmlStartElementNS;
2835     reader->sax.endElementNs = libxmlEndElementNS;
2836     reader->sax.characters = libxmlCharacters;
2837     reader->sax.setDocumentLocator = libxmlSetDocumentLocator;
2838     reader->sax.comment = libxmlComment;
2839     reader->sax.error = libxmlFatalError;
2840     reader->sax.fatalError = libxmlFatalError;
2841     reader->sax.cdataBlock = libxmlCDataBlock;
2842
2843     *ppObj = &reader->lpVBSAXXMLReaderVtbl;
2844
2845     TRACE("returning iface %p\n", *ppObj);
2846
2847     return S_OK;
2848 }
2849
2850 #else
2851
2852 HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2853 {
2854     MESSAGE("This program tried to use a SAX XML Reader object, but\n"
2855             "libxml2 support was not present at compile time.\n");
2856     return E_NOTIMPL;
2857 }
2858
2859 #endif