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