winmm: Fix a failing mixer test on 98 and ME.
[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     }
1173
1174     update_position(This, NULL);
1175 }
1176
1177 static void libxmlCharacters(
1178         void *ctx,
1179         const xmlChar *ch,
1180         int len)
1181 {
1182     saxlocator *This = ctx;
1183     BSTR Chars;
1184     HRESULT hr;
1185     xmlChar *cur;
1186     xmlChar *end;
1187     BOOL lastEvent = FALSE;
1188
1189     if((This->vbInterface && !This->saxreader->vbcontentHandler)
1190             || (!This->vbInterface && !This->saxreader->contentHandler))
1191         return;
1192
1193     cur = (xmlChar*)ch;
1194     if(*(ch-1)=='\r') cur--;
1195     end = cur;
1196
1197     if(ch<This->pParserCtxt->input->base || ch>This->pParserCtxt->input->end)
1198         This->column++;
1199
1200     while(1)
1201     {
1202         while(end-ch<len && *end!='\r') end++;
1203         if(end-ch==len)
1204         {
1205             end--;
1206             lastEvent = TRUE;
1207         }
1208
1209         if(!lastEvent) *end = '\n';
1210
1211         Chars = bstr_from_xmlCharN(cur, end-cur+1);
1212         if(This->vbInterface)
1213             hr = IVBSAXContentHandler_characters(
1214                     This->saxreader->vbcontentHandler, &Chars);
1215         else
1216             hr = ISAXContentHandler_characters(
1217                     This->saxreader->contentHandler,
1218                     Chars, SysStringLen(Chars));
1219         SysFreeString(Chars);
1220
1221         This->column += end-cur+1;
1222
1223         if(lastEvent)
1224             break;
1225
1226         *end = '\r';
1227         end++;
1228         if(*end == '\n')
1229         {
1230             end++;
1231             This->column++;
1232         }
1233         cur = end;
1234
1235         if(end-ch == len) break;
1236     }
1237
1238     if(ch<This->pParserCtxt->input->base || ch>This->pParserCtxt->input->end)
1239         This->column = This->realColumn
1240             +This->pParserCtxt->input->cur-This->lastCur;
1241 }
1242
1243 static void libxmlSetDocumentLocator(
1244         void *ctx,
1245         xmlSAXLocatorPtr loc)
1246 {
1247     saxlocator *This = ctx;
1248     HRESULT hr;
1249
1250     if(This->vbInterface)
1251         hr = IVBSAXContentHandler_putref_documentLocator(
1252                 This->saxreader->vbcontentHandler,
1253                 (IVBSAXLocator*)&This->lpVBSAXLocatorVtbl);
1254     else
1255         hr = ISAXContentHandler_putDocumentLocator(
1256                 This->saxreader->contentHandler,
1257                 (ISAXLocator*)&This->lpSAXLocatorVtbl);
1258
1259     if(FAILED(hr))
1260         format_error_message_from_id(This, hr);
1261 }
1262
1263 static void libxmlComment(void *ctx, const xmlChar *value)
1264 {
1265     saxlocator *This = ctx;
1266     BSTR bValue;
1267     HRESULT hr;
1268     xmlChar *beg = (xmlChar*)This->pParserCtxt->input->cur;
1269
1270     while(memcmp(beg-4, "<!--", sizeof(char[4]))) beg--;
1271     update_position(This, beg);
1272
1273     if(!This->vbInterface && !This->saxreader->lexicalHandler) return;
1274     if(This->vbInterface && !This->saxreader->vblexicalHandler) return;
1275
1276     bValue = bstr_from_xmlChar(value);
1277
1278     if(This->vbInterface)
1279         hr = IVBSAXLexicalHandler_comment(
1280                 This->saxreader->vblexicalHandler, &bValue);
1281     else
1282         hr = ISAXLexicalHandler_comment(
1283                 This->saxreader->lexicalHandler,
1284                 bValue, SysStringLen(bValue));
1285
1286     SysFreeString(bValue);
1287
1288     if(FAILED(hr))
1289         format_error_message_from_id(This, hr);
1290
1291     update_position(This, NULL);
1292 }
1293
1294 static void libxmlFatalError(void *ctx, const char *msg, ...)
1295 {
1296     saxlocator *This = ctx;
1297     char message[1024];
1298     WCHAR *wszError;
1299     DWORD len;
1300     va_list args;
1301
1302     if((This->vbInterface && !This->saxreader->vberrorHandler)
1303             || (!This->vbInterface && !This->saxreader->errorHandler))
1304     {
1305         xmlStopParser(This->pParserCtxt);
1306         This->ret = E_FAIL;
1307         return;
1308     }
1309
1310     FIXME("Error handling is not compatible.\n");
1311
1312     va_start(args, msg);
1313     vsprintf(message, msg, args);
1314     va_end(args);
1315
1316     len = MultiByteToWideChar(CP_UNIXCP, 0, message, -1, NULL, 0);
1317     wszError = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len);
1318     if(wszError)
1319         MultiByteToWideChar(CP_UNIXCP, 0, message, -1, (LPWSTR)wszError, len);
1320
1321     if(This->vbInterface)
1322     {
1323         BSTR bstrError = SysAllocString(wszError);
1324         IVBSAXErrorHandler_fatalError(This->saxreader->vberrorHandler,
1325                 (IVBSAXLocator*)&This->lpVBSAXLocatorVtbl, &bstrError, E_FAIL);
1326     }
1327     else
1328         ISAXErrorHandler_fatalError(This->saxreader->errorHandler,
1329                 (ISAXLocator*)&This->lpSAXLocatorVtbl, wszError, E_FAIL);
1330
1331     HeapFree(GetProcessHeap(), 0, wszError);
1332
1333     xmlStopParser(This->pParserCtxt);
1334     This->ret = E_FAIL;
1335 }
1336
1337 static void libxmlCDataBlock(void *ctx, const xmlChar *value, int len)
1338 {
1339     saxlocator *This = ctx;
1340     HRESULT hr = S_OK;
1341     xmlChar *beg = (xmlChar*)This->pParserCtxt->input->cur-len;
1342     xmlChar *cur, *end;
1343     int realLen;
1344     BSTR Chars;
1345     BOOL lastEvent = FALSE, change;
1346
1347     while(memcmp(beg-9, "<![CDATA[", sizeof(char[9]))) beg--;
1348     update_position(This, beg);
1349
1350     if(This->vbInterface && This->saxreader->vblexicalHandler)
1351         hr = IVBSAXLexicalHandler_startCDATA(This->saxreader->vblexicalHandler);
1352     if(!This->vbInterface && This->saxreader->lexicalHandler)
1353         hr = ISAXLexicalHandler_startCDATA(This->saxreader->lexicalHandler);
1354
1355     if(FAILED(hr))
1356         return format_error_message_from_id(This, hr);
1357
1358     realLen = This->pParserCtxt->input->cur-beg-3;
1359     cur = beg;
1360     end = beg;
1361
1362     while(1)
1363     {
1364         while(end-beg<realLen && *end!='\r') end++;
1365         if(end-beg==realLen)
1366         {
1367             end--;
1368             lastEvent = TRUE;
1369         }
1370         else if(end-beg==realLen-1 && *end=='\r' && *(end+1)=='\n')
1371             lastEvent = TRUE;
1372
1373         if(*end == '\r') change = TRUE;
1374         else change = FALSE;
1375
1376         if(change) *end = '\n';
1377
1378         if((This->vbInterface && This->saxreader->vbcontentHandler) ||
1379                 (!This->vbInterface && This->saxreader->contentHandler))
1380         {
1381             Chars = bstr_from_xmlCharN(cur, end-cur+1);
1382             if(This->vbInterface)
1383                 hr = IVBSAXContentHandler_characters(
1384                         This->saxreader->vbcontentHandler, &Chars);
1385             else
1386                 hr = ISAXContentHandler_characters(
1387                         This->saxreader->contentHandler,
1388                         Chars, SysStringLen(Chars));
1389             SysFreeString(Chars);
1390         }
1391
1392         if(change) *end = '\r';
1393
1394         if(lastEvent)
1395             break;
1396
1397         This->column += end-cur+2;
1398         end += 2;
1399         cur = end;
1400     }
1401
1402     if(This->vbInterface && This->saxreader->vblexicalHandler)
1403         hr = IVBSAXLexicalHandler_endCDATA(This->saxreader->vblexicalHandler);
1404     if(!This->vbInterface && This->saxreader->lexicalHandler)
1405         hr = ISAXLexicalHandler_endCDATA(This->saxreader->lexicalHandler);
1406
1407     if(FAILED(hr))
1408         format_error_message_from_id(This, hr);
1409
1410     This->column += 4+end-cur;
1411 }
1412
1413 /*** IVBSAXLocator interface ***/
1414 /*** IUnknown methods ***/
1415 static HRESULT WINAPI ivbsaxlocator_QueryInterface(IVBSAXLocator* iface, REFIID riid, void **ppvObject)
1416 {
1417     saxlocator *This = impl_from_IVBSAXLocator( iface );
1418
1419     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject);
1420
1421     *ppvObject = NULL;
1422
1423     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
1424             IsEqualGUID( riid, &IID_IDispatch) ||
1425             IsEqualGUID( riid, &IID_IVBSAXLocator ))
1426     {
1427         *ppvObject = iface;
1428     }
1429     else
1430     {
1431         FIXME("interface %s not implemented\n", debugstr_guid(riid));
1432         return E_NOINTERFACE;
1433     }
1434
1435     IVBSAXLocator_AddRef( iface );
1436
1437     return S_OK;
1438 }
1439
1440 static ULONG WINAPI ivbsaxlocator_AddRef(IVBSAXLocator* iface)
1441 {
1442     saxlocator *This = impl_from_IVBSAXLocator( iface );
1443     TRACE("%p\n", This );
1444     return InterlockedIncrement( &This->ref );
1445 }
1446
1447 static ULONG WINAPI ivbsaxlocator_Release(
1448         IVBSAXLocator* iface)
1449 {
1450     saxlocator *This = impl_from_IVBSAXLocator( iface );
1451     return ISAXLocator_Release((ISAXLocator*)&This->lpVBSAXLocatorVtbl);
1452 }
1453
1454 /*** IDispatch methods ***/
1455 static HRESULT WINAPI ivbsaxlocator_GetTypeInfoCount( IVBSAXLocator *iface, UINT* pctinfo )
1456 {
1457     saxlocator *This = impl_from_IVBSAXLocator( iface );
1458
1459     TRACE("(%p)->(%p)\n", This, pctinfo);
1460
1461     *pctinfo = 1;
1462
1463     return S_OK;
1464 }
1465
1466 static HRESULT WINAPI ivbsaxlocator_GetTypeInfo(
1467     IVBSAXLocator *iface,
1468     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
1469 {
1470     saxlocator *This = impl_from_IVBSAXLocator( iface );
1471     HRESULT hr;
1472
1473     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1474
1475     hr = get_typeinfo(IVBSAXLocator_tid, ppTInfo);
1476
1477     return hr;
1478 }
1479
1480 static HRESULT WINAPI ivbsaxlocator_GetIDsOfNames(
1481     IVBSAXLocator *iface,
1482     REFIID riid,
1483     LPOLESTR* rgszNames,
1484     UINT cNames,
1485     LCID lcid,
1486     DISPID* rgDispId)
1487 {
1488     saxlocator *This = impl_from_IVBSAXLocator( iface );
1489     ITypeInfo *typeinfo;
1490     HRESULT hr;
1491
1492     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1493           lcid, rgDispId);
1494
1495     if(!rgszNames || cNames == 0 || !rgDispId)
1496         return E_INVALIDARG;
1497
1498     hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
1499     if(SUCCEEDED(hr))
1500     {
1501         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1502         ITypeInfo_Release(typeinfo);
1503     }
1504
1505     return hr;
1506 }
1507
1508 static HRESULT WINAPI ivbsaxlocator_Invoke(
1509     IVBSAXLocator *iface,
1510     DISPID dispIdMember,
1511     REFIID riid,
1512     LCID lcid,
1513     WORD wFlags,
1514     DISPPARAMS* pDispParams,
1515     VARIANT* pVarResult,
1516     EXCEPINFO* pExcepInfo,
1517     UINT* puArgErr)
1518 {
1519     saxlocator *This = impl_from_IVBSAXLocator( iface );
1520     ITypeInfo *typeinfo;
1521     HRESULT hr;
1522
1523     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1524           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1525
1526     hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo);
1527     if(SUCCEEDED(hr))
1528     {
1529         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVBSAXLocatorVtbl), dispIdMember, wFlags, pDispParams,
1530                 pVarResult, pExcepInfo, puArgErr);
1531         ITypeInfo_Release(typeinfo);
1532     }
1533
1534     return hr;
1535 }
1536
1537 /*** IVBSAXLocator methods ***/
1538 static HRESULT WINAPI ivbsaxlocator_get_columnNumber(
1539         IVBSAXLocator* iface,
1540         int *pnColumn)
1541 {
1542     saxlocator *This = impl_from_IVBSAXLocator( iface );
1543     return ISAXLocator_getColumnNumber(
1544             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1545             pnColumn);
1546 }
1547
1548 static HRESULT WINAPI ivbsaxlocator_get_lineNumber(
1549         IVBSAXLocator* iface,
1550         int *pnLine)
1551 {
1552     saxlocator *This = impl_from_IVBSAXLocator( iface );
1553     return ISAXLocator_getLineNumber(
1554             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1555             pnLine);
1556 }
1557
1558 static HRESULT WINAPI ivbsaxlocator_get_publicId(
1559         IVBSAXLocator* iface,
1560         BSTR* publicId)
1561 {
1562     saxlocator *This = impl_from_IVBSAXLocator( iface );
1563     return ISAXLocator_getPublicId(
1564             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1565             (const WCHAR**)publicId);
1566 }
1567
1568 static HRESULT WINAPI ivbsaxlocator_get_systemId(
1569         IVBSAXLocator* iface,
1570         BSTR* systemId)
1571 {
1572     saxlocator *This = impl_from_IVBSAXLocator( iface );
1573     return ISAXLocator_getSystemId(
1574             (ISAXLocator*)&This->lpVBSAXLocatorVtbl,
1575             (const WCHAR**)systemId);
1576 }
1577
1578 static const struct IVBSAXLocatorVtbl ivbsaxlocator_vtbl =
1579 {
1580     ivbsaxlocator_QueryInterface,
1581     ivbsaxlocator_AddRef,
1582     ivbsaxlocator_Release,
1583     ivbsaxlocator_GetTypeInfoCount,
1584     ivbsaxlocator_GetTypeInfo,
1585     ivbsaxlocator_GetIDsOfNames,
1586     ivbsaxlocator_Invoke,
1587     ivbsaxlocator_get_columnNumber,
1588     ivbsaxlocator_get_lineNumber,
1589     ivbsaxlocator_get_publicId,
1590     ivbsaxlocator_get_systemId
1591 };
1592
1593 /*** ISAXLocator interface ***/
1594 /*** IUnknown methods ***/
1595 static HRESULT WINAPI isaxlocator_QueryInterface(ISAXLocator* iface, REFIID riid, void **ppvObject)
1596 {
1597     saxlocator *This = impl_from_ISAXLocator( iface );
1598
1599     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
1600
1601     *ppvObject = NULL;
1602
1603     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
1604             IsEqualGUID( riid, &IID_ISAXLocator ))
1605     {
1606         *ppvObject = iface;
1607     }
1608     else
1609     {
1610         FIXME("interface %s not implemented\n", debugstr_guid(riid));
1611         return E_NOINTERFACE;
1612     }
1613
1614     ISAXLocator_AddRef( iface );
1615
1616     return S_OK;
1617 }
1618
1619 static ULONG WINAPI isaxlocator_AddRef(ISAXLocator* iface)
1620 {
1621     saxlocator *This = impl_from_ISAXLocator( iface );
1622     TRACE("%p\n", This );
1623     return InterlockedIncrement( &This->ref );
1624 }
1625
1626 static ULONG WINAPI isaxlocator_Release(
1627         ISAXLocator* iface)
1628 {
1629     saxlocator *This = impl_from_ISAXLocator( iface );
1630     LONG ref;
1631
1632     TRACE("%p\n", This );
1633
1634     ref = InterlockedDecrement( &This->ref );
1635     if ( ref == 0 )
1636     {
1637         SysFreeString(This->publicId);
1638         SysFreeString(This->systemId);
1639         HeapFree(GetProcessHeap(), 0, This->nsStack);
1640
1641         ISAXXMLReader_Release((ISAXXMLReader*)&This->saxreader->lpSAXXMLReaderVtbl);
1642         HeapFree( GetProcessHeap(), 0, This );
1643     }
1644
1645     return ref;
1646 }
1647
1648 /*** ISAXLocator methods ***/
1649 static HRESULT WINAPI isaxlocator_getColumnNumber(
1650         ISAXLocator* iface,
1651         int *pnColumn)
1652 {
1653     saxlocator *This = impl_from_ISAXLocator( iface );
1654
1655     *pnColumn = This->column;
1656     return S_OK;
1657 }
1658
1659 static HRESULT WINAPI isaxlocator_getLineNumber(
1660         ISAXLocator* iface,
1661         int *pnLine)
1662 {
1663     saxlocator *This = impl_from_ISAXLocator( iface );
1664
1665     *pnLine = This->line;
1666     return S_OK;
1667 }
1668
1669 static HRESULT WINAPI isaxlocator_getPublicId(
1670         ISAXLocator* iface,
1671         const WCHAR ** ppwchPublicId)
1672 {
1673     BSTR publicId;
1674     saxlocator *This = impl_from_ISAXLocator( iface );
1675
1676     SysFreeString(This->publicId);
1677
1678     publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt));
1679     if(SysStringLen(publicId))
1680         This->publicId = (WCHAR*)&publicId;
1681     else
1682     {
1683         SysFreeString(publicId);
1684         This->publicId = NULL;
1685     }
1686
1687     *ppwchPublicId = This->publicId;
1688     return S_OK;
1689 }
1690
1691 static HRESULT WINAPI isaxlocator_getSystemId(
1692         ISAXLocator* iface,
1693         const WCHAR ** ppwchSystemId)
1694 {
1695     BSTR systemId;
1696     saxlocator *This = impl_from_ISAXLocator( iface );
1697
1698     SysFreeString(This->systemId);
1699
1700     systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt));
1701     if(SysStringLen(systemId))
1702         This->systemId = (WCHAR*)&systemId;
1703     else
1704     {
1705         SysFreeString(systemId);
1706         This->systemId = NULL;
1707     }
1708
1709     *ppwchSystemId = This->systemId;
1710     return S_OK;
1711 }
1712
1713 static const struct ISAXLocatorVtbl isaxlocator_vtbl =
1714 {
1715     isaxlocator_QueryInterface,
1716     isaxlocator_AddRef,
1717     isaxlocator_Release,
1718     isaxlocator_getColumnNumber,
1719     isaxlocator_getLineNumber,
1720     isaxlocator_getPublicId,
1721     isaxlocator_getSystemId
1722 };
1723
1724 static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator, BOOL vbInterface)
1725 {
1726     saxlocator *locator;
1727
1728     locator = HeapAlloc( GetProcessHeap(), 0, sizeof (*locator) );
1729     if( !locator )
1730         return E_OUTOFMEMORY;
1731
1732     locator->lpVBSAXLocatorVtbl = &ivbsaxlocator_vtbl;
1733     locator->lpSAXLocatorVtbl = &isaxlocator_vtbl;
1734     locator->ref = 1;
1735     locator->vbInterface = vbInterface;
1736
1737     locator->saxreader = reader;
1738     ISAXXMLReader_AddRef((ISAXXMLReader*)&reader->lpSAXXMLReaderVtbl);
1739
1740     locator->pParserCtxt = NULL;
1741     locator->publicId = NULL;
1742     locator->systemId = NULL;
1743     locator->lastCur = NULL;
1744     locator->line = 0;
1745     locator->column = 0;
1746     locator->ret = S_OK;
1747     locator->nsStackSize = 8;
1748     locator->nsStackLast = 0;
1749     locator->nsStack = HeapAlloc(GetProcessHeap(), 0, locator->nsStackSize);
1750     if(!locator->nsStack)
1751     {
1752         ISAXXMLReader_Release((ISAXXMLReader*)&reader->lpSAXXMLReaderVtbl);
1753         HeapFree(GetProcessHeap(), 0, locator);
1754         return E_OUTOFMEMORY;
1755     }
1756
1757     *ppsaxlocator = locator;
1758
1759     TRACE("returning %p\n", *ppsaxlocator);
1760
1761     return S_OK;
1762 }
1763
1764 /*** SAXXMLReader internal functions ***/
1765 static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int size, BOOL vbInterface)
1766 {
1767     saxlocator *locator;
1768     HRESULT hr;
1769
1770     hr = SAXLocator_create(This, &locator, vbInterface);
1771     if(FAILED(hr))
1772         return E_FAIL;
1773
1774     locator->pParserCtxt = xmlCreateMemoryParserCtxt(buffer, size);
1775     if(!locator->pParserCtxt)
1776     {
1777         ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1778         return E_FAIL;
1779     }
1780
1781     locator->pParserCtxt->sax = &locator->saxreader->sax;
1782     locator->pParserCtxt->userData = locator;
1783
1784     This->isParsing = TRUE;
1785     if(xmlParseDocument(locator->pParserCtxt)) hr = E_FAIL;
1786     else hr = locator->ret;
1787     This->isParsing = FALSE;
1788
1789     if(locator->pParserCtxt)
1790     {
1791         locator->pParserCtxt->sax = NULL;
1792         xmlFreeParserCtxt(locator->pParserCtxt);
1793         locator->pParserCtxt = NULL;
1794     }
1795
1796     ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1797     return S_OK;
1798 }
1799
1800 static HRESULT internal_parseStream(saxreader *This, IStream *stream, BOOL vbInterface)
1801 {
1802     saxlocator *locator;
1803     HRESULT hr;
1804     ULONG dataRead;
1805     char data[1024];
1806
1807     hr = IStream_Read(stream, data, sizeof(data), &dataRead);
1808     if(hr != S_OK)
1809         return hr;
1810
1811     hr = SAXLocator_create(This, &locator, vbInterface);
1812     if(FAILED(hr))
1813         return E_FAIL;
1814
1815     locator->pParserCtxt = xmlCreatePushParserCtxt(
1816             &locator->saxreader->sax, locator,
1817             data, dataRead, NULL);
1818     if(!locator->pParserCtxt)
1819     {
1820         ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1821         return E_FAIL;
1822     }
1823
1824     This->isParsing = TRUE;
1825     while(1)
1826     {
1827         hr = IStream_Read(stream, data, sizeof(data), &dataRead);
1828         if(hr != S_OK)
1829             break;
1830
1831         if(xmlParseChunk(locator->pParserCtxt, data, dataRead, 0)) hr = E_FAIL;
1832         else hr = locator->ret;
1833
1834         if(hr != S_OK) break;
1835
1836         if(dataRead != sizeof(data))
1837         {
1838             if(xmlParseChunk(locator->pParserCtxt, data, 0, 1)) hr = E_FAIL;
1839             else hr = locator->ret;
1840
1841             break;
1842         }
1843     }
1844     This->isParsing = FALSE;
1845
1846     locator->pParserCtxt->sax = NULL;
1847     xmlFreeParserCtxt(locator->pParserCtxt);
1848     locator->pParserCtxt = NULL;
1849     ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl);
1850     return hr;
1851 }
1852
1853 static HRESULT WINAPI internal_getEntityResolver(
1854         saxreader *This,
1855         void *pEntityResolver,
1856         BOOL vbInterface)
1857 {
1858     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
1859     return E_NOTIMPL;
1860 }
1861
1862 static HRESULT WINAPI internal_putEntityResolver(
1863         saxreader *This,
1864         void *pEntityResolver,
1865         BOOL vbInterface)
1866 {
1867     FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
1868     return E_NOTIMPL;
1869 }
1870
1871 static HRESULT WINAPI internal_getContentHandler(
1872         saxreader* This,
1873         void *pContentHandler,
1874         BOOL vbInterface)
1875 {
1876     TRACE("(%p)->(%p)\n", This, pContentHandler);
1877     if(pContentHandler == NULL)
1878         return E_POINTER;
1879     if((vbInterface && This->vbcontentHandler)
1880             || (!vbInterface && This->contentHandler))
1881     {
1882         if(vbInterface)
1883             IVBSAXContentHandler_AddRef(This->vbcontentHandler);
1884         else
1885             ISAXContentHandler_AddRef(This->contentHandler);
1886     }
1887     if(vbInterface) *(IVBSAXContentHandler**)pContentHandler =
1888         This->vbcontentHandler;
1889     else *(ISAXContentHandler**)pContentHandler = This->contentHandler;
1890
1891     return S_OK;
1892 }
1893
1894 static HRESULT WINAPI internal_putContentHandler(
1895         saxreader* This,
1896         void *contentHandler,
1897         BOOL vbInterface)
1898 {
1899     TRACE("(%p)->(%p)\n", This, contentHandler);
1900     if(contentHandler)
1901     {
1902         if(vbInterface)
1903             IVBSAXContentHandler_AddRef((IVBSAXContentHandler*)contentHandler);
1904         else
1905             ISAXContentHandler_AddRef((ISAXContentHandler*)contentHandler);
1906     }
1907     if((vbInterface && This->vbcontentHandler)
1908             || (!vbInterface && This->contentHandler))
1909     {
1910         if(vbInterface)
1911             IVBSAXContentHandler_Release(This->vbcontentHandler);
1912         else
1913             ISAXContentHandler_Release(This->contentHandler);
1914     }
1915     if(vbInterface)
1916         This->vbcontentHandler = contentHandler;
1917     else
1918         This->contentHandler = contentHandler;
1919
1920     return S_OK;
1921 }
1922
1923 static HRESULT WINAPI internal_getDTDHandler(
1924         saxreader* This,
1925         void *pDTDHandler,
1926         BOOL vbInterface)
1927 {
1928     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
1929     return E_NOTIMPL;
1930 }
1931
1932 static HRESULT WINAPI internal_putDTDHandler(
1933         saxreader* This,
1934         void *pDTDHandler,
1935         BOOL vbInterface)
1936 {
1937     FIXME("(%p)->(%p) stub\n", This, pDTDHandler);
1938     return E_NOTIMPL;
1939 }
1940
1941 static HRESULT WINAPI internal_getErrorHandler(
1942         saxreader* This,
1943         void *pErrorHandler,
1944         BOOL vbInterface)
1945 {
1946     TRACE("(%p)->(%p)\n", This, pErrorHandler);
1947     if(pErrorHandler == NULL)
1948         return E_POINTER;
1949
1950     if(vbInterface && This->vberrorHandler)
1951         IVBSAXErrorHandler_AddRef(This->vberrorHandler);
1952     else if(!vbInterface && This->errorHandler)
1953         ISAXErrorHandler_AddRef(This->errorHandler);
1954
1955     if(vbInterface)
1956         *(IVBSAXErrorHandler**)pErrorHandler = This->vberrorHandler;
1957     else
1958         *(ISAXErrorHandler**)pErrorHandler = This->errorHandler;
1959
1960     return S_OK;
1961
1962 }
1963
1964 static HRESULT WINAPI internal_putErrorHandler(
1965         saxreader* This,
1966         void *errorHandler,
1967         BOOL vbInterface)
1968 {
1969     TRACE("(%p)->(%p)\n", This, errorHandler);
1970     if(errorHandler)
1971     {
1972         if(vbInterface)
1973             IVBSAXErrorHandler_AddRef((IVBSAXErrorHandler*)errorHandler);
1974         else
1975             ISAXErrorHandler_AddRef((ISAXErrorHandler*)errorHandler);
1976     }
1977
1978     if(vbInterface && This->vberrorHandler)
1979         IVBSAXErrorHandler_Release(This->vberrorHandler);
1980     else if(!vbInterface && This->errorHandler)
1981         ISAXErrorHandler_Release(This->errorHandler);
1982
1983     if(vbInterface)
1984         This->vberrorHandler = errorHandler;
1985     else
1986         This->errorHandler = errorHandler;
1987
1988     return S_OK;
1989
1990 }
1991
1992 static HRESULT WINAPI internal_parse(
1993         saxreader* This,
1994         VARIANT varInput,
1995         BOOL vbInterface)
1996 {
1997     HRESULT hr;
1998
1999     TRACE("(%p)\n", This);
2000
2001     hr = S_OK;
2002     switch(V_VT(&varInput))
2003     {
2004         case VT_BSTR:
2005             hr = internal_parseBuffer(This, (const char*)V_BSTR(&varInput),
2006                     SysStringByteLen(V_BSTR(&varInput)), vbInterface);
2007             break;
2008         case VT_ARRAY|VT_UI1: {
2009             void *pSAData;
2010             LONG lBound, uBound;
2011             ULONG dataRead;
2012
2013             hr = SafeArrayGetLBound(V_ARRAY(&varInput), 1, &lBound);
2014             if(hr != S_OK) break;
2015             hr = SafeArrayGetUBound(V_ARRAY(&varInput), 1, &uBound);
2016             if(hr != S_OK) break;
2017             dataRead = (uBound-lBound)*SafeArrayGetElemsize(V_ARRAY(&varInput));
2018             hr = SafeArrayAccessData(V_ARRAY(&varInput), (void**)&pSAData);
2019             if(hr != S_OK) break;
2020             hr = internal_parseBuffer(This, pSAData, dataRead, vbInterface);
2021             SafeArrayUnaccessData(V_ARRAY(&varInput));
2022             break;
2023         }
2024         case VT_UNKNOWN:
2025         case VT_DISPATCH: {
2026             IPersistStream *persistStream;
2027             IStream *stream = NULL;
2028             IXMLDOMDocument *xmlDoc;
2029
2030             if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2031                         &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK)
2032             {
2033                 BSTR bstrData;
2034
2035                 IXMLDOMDocument_get_xml(xmlDoc, &bstrData);
2036                 hr = internal_parseBuffer(This, (const char*)bstrData,
2037                         SysStringByteLen(bstrData), vbInterface);
2038                 IXMLDOMDocument_Release(xmlDoc);
2039                 break;
2040             }
2041             if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2042                         &IID_IPersistStream, (void**)&persistStream) == S_OK)
2043             {
2044                 hr = IPersistStream_Save(persistStream, stream, TRUE);
2045                 IPersistStream_Release(persistStream);
2046                 if(hr != S_OK) break;
2047             }
2048             if(stream || IUnknown_QueryInterface(V_UNKNOWN(&varInput),
2049                         &IID_IStream, (void**)&stream) == S_OK)
2050             {
2051                 hr = internal_parseStream(This, stream, vbInterface);
2052                 IStream_Release(stream);
2053                 break;
2054             }
2055         }
2056         default:
2057             WARN("vt %d not implemented\n", V_VT(&varInput));
2058             hr = E_INVALIDARG;
2059     }
2060
2061     return hr;
2062 }
2063
2064 static HRESULT internal_vbonDataAvailable(void *obj, char *ptr, DWORD len)
2065 {
2066     saxreader *This = obj;
2067
2068     return internal_parseBuffer(This, ptr, len, TRUE);
2069 }
2070
2071 static HRESULT internal_onDataAvailable(void *obj, char *ptr, DWORD len)
2072 {
2073     saxreader *This = obj;
2074
2075     return internal_parseBuffer(This, ptr, len, FALSE);
2076 }
2077
2078 static HRESULT WINAPI internal_parseURL(
2079         saxreader* This,
2080         const WCHAR *url,
2081         BOOL vbInterface)
2082 {
2083     bsc_t *bsc;
2084     HRESULT hr;
2085
2086     TRACE("(%p)->(%s)\n", This, debugstr_w(url));
2087
2088     if(vbInterface) hr = bind_url(url, internal_vbonDataAvailable, This, &bsc);
2089     else hr = bind_url(url, internal_onDataAvailable, This, &bsc);
2090
2091     if(FAILED(hr))
2092         return hr;
2093
2094     detach_bsc(bsc);
2095
2096     return S_OK;
2097 }
2098
2099 static HRESULT WINAPI internal_putProperty(
2100     saxreader* This,
2101     const WCHAR *pProp,
2102     VARIANT value,
2103     BOOL vbInterface)
2104 {
2105     static const WCHAR wszCharset[] = {
2106         'c','h','a','r','s','e','t',0
2107     };
2108     static const WCHAR wszDeclarationHandler[] = {
2109         'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
2110         's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
2111         'd','e','c','l','a','r','a','t','i','o','n',
2112         '-','h','a','n','d','l','e','r',0
2113     };
2114     static const WCHAR wszDomNode[] = {
2115         'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
2116         's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
2117         'd','o','m','-','n','o','d','e',0
2118     };
2119     static const WCHAR wszInputSource[] = {
2120         'i','n','p','u','t','-','s','o','u','r','c','e',0
2121     };
2122     static const WCHAR wszLexicalHandler[] = {
2123         'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/',
2124         's','a','x','/','p','r','o','p','e','r','t','i','e','s','/',
2125         'l','e','x','i','c','a','l','-','h','a','n','d','l','e','r',0
2126     };
2127     static const WCHAR wszMaxElementDepth[] = {
2128         'm','a','x','-','e','l','e','m','e','n','t','-','d','e','p','t','h',0
2129     };
2130     static const WCHAR wszMaxXMLSize[] = {
2131         'm','a','x','-','x','m','l','-','s','i','z','e',0
2132     };
2133     static const WCHAR wszSchemaDeclarationHandler[] = {
2134         's','c','h','e','m','a','-',
2135         'd','e','c','l','a','r','a','t','i','o','n','-',
2136         'h','a','n','d','l','e','r',0
2137     };
2138     static const WCHAR wszXMLDeclEncoding[] = {
2139         'x','m','l','d','e','c','l','-','e','n','c','o','d','i','n','g',0
2140     };
2141     static const WCHAR wszXMLDeclStandalone[] = {
2142         'x','m','l','d','e','c','l',
2143         '-','s','t','a','n','d','a','l','o','n','e',0
2144     };
2145     static const WCHAR wszXMLDeclVersion[] = {
2146         'x','m','l','d','e','c','l','-','v','e','r','s','i','o','n',0
2147     };
2148
2149     FIXME("(%p)->(%s): semi-stub\n", This, debugstr_w(pProp));
2150
2151     if(!memcmp(pProp, wszCharset, sizeof(wszCharset)))
2152         return E_NOTIMPL;
2153
2154     if(!memcmp(pProp, wszDeclarationHandler, sizeof(wszDeclarationHandler)))
2155     {
2156         if(This->isParsing) return E_FAIL;
2157
2158         if(V_UNKNOWN(&value))
2159         {
2160             if(vbInterface)
2161                 IVBSAXDeclHandler_AddRef((IVBSAXDeclHandler*)V_UNKNOWN(&value));
2162             else
2163                 ISAXDeclHandler_AddRef((ISAXDeclHandler*)V_UNKNOWN(&value));
2164         }
2165         if((vbInterface && This->vbdeclHandler)
2166                 || (!vbInterface && This->declHandler))
2167         {
2168             if(vbInterface)
2169                 IVBSAXDeclHandler_Release(This->vbdeclHandler);
2170             else
2171                 ISAXDeclHandler_Release(This->declHandler);
2172         }
2173         if(vbInterface)
2174             This->vbdeclHandler = (IVBSAXDeclHandler*)V_UNKNOWN(&value);
2175         else
2176             This->declHandler = (ISAXDeclHandler*)V_UNKNOWN(&value);
2177         return S_OK;
2178     }
2179
2180     if(!memcmp(pProp, wszDomNode, sizeof(wszDomNode)))
2181         return E_FAIL;
2182
2183     if(!memcmp(pProp, wszInputSource, sizeof(wszInputSource)))
2184         return E_NOTIMPL;
2185
2186     if(!memcmp(pProp, wszLexicalHandler, sizeof(wszLexicalHandler)))
2187     {
2188         if(This->isParsing) return E_FAIL;
2189
2190         if(V_UNKNOWN(&value))
2191         {
2192             if(vbInterface)
2193                 IVBSAXLexicalHandler_AddRef(
2194                         (IVBSAXLexicalHandler*)V_UNKNOWN(&value));
2195             else
2196                 ISAXLexicalHandler_AddRef(
2197                         (ISAXLexicalHandler*)V_UNKNOWN(&value));
2198         }
2199         if((vbInterface && This->vblexicalHandler)
2200                 || (!vbInterface && This->lexicalHandler))
2201         {
2202             if(vbInterface)
2203                 IVBSAXLexicalHandler_Release(This->vblexicalHandler);
2204             else
2205                 ISAXLexicalHandler_Release(This->lexicalHandler);
2206         }
2207         if(vbInterface)
2208             This->vblexicalHandler = (IVBSAXLexicalHandler*)V_UNKNOWN(&value);
2209         else
2210             This->lexicalHandler = (ISAXLexicalHandler*)V_UNKNOWN(&value);
2211         return S_OK;
2212     }
2213
2214     if(!memcmp(pProp, wszMaxElementDepth, sizeof(wszMaxElementDepth)))
2215         return E_NOTIMPL;
2216
2217     if(!memcmp(pProp, wszMaxXMLSize, sizeof(wszMaxXMLSize)))
2218         return E_NOTIMPL;
2219
2220     if(!memcmp(pProp, wszSchemaDeclarationHandler,
2221                 sizeof(wszSchemaDeclarationHandler)))
2222         return E_NOTIMPL;
2223
2224     if(!memcmp(pProp, wszXMLDeclEncoding, sizeof(wszXMLDeclEncoding)))
2225         return E_FAIL;
2226
2227     if(!memcmp(pProp, wszXMLDeclStandalone, sizeof(wszXMLDeclStandalone)))
2228         return E_FAIL;
2229
2230     if(!memcmp(pProp, wszXMLDeclVersion, sizeof(wszXMLDeclVersion)))
2231         return E_FAIL;
2232
2233     return E_INVALIDARG;
2234 }
2235
2236 /*** IVBSAXXMLReader interface ***/
2237 /*** IUnknown methods ***/
2238 static HRESULT WINAPI saxxmlreader_QueryInterface(IVBSAXXMLReader* iface, REFIID riid, void **ppvObject)
2239 {
2240     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2241
2242     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
2243
2244     *ppvObject = NULL;
2245
2246     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2247          IsEqualGUID( riid, &IID_IDispatch ) ||
2248          IsEqualGUID( riid, &IID_IVBSAXXMLReader ))
2249     {
2250         *ppvObject = iface;
2251     }
2252     else if( IsEqualGUID( riid, &IID_ISAXXMLReader ))
2253     {
2254         *ppvObject = (ISAXXMLReader*)&This->lpSAXXMLReaderVtbl;
2255     }
2256     else
2257     {
2258         FIXME("interface %s not implemented\n", debugstr_guid(riid));
2259         return E_NOINTERFACE;
2260     }
2261
2262     IVBSAXXMLReader_AddRef( iface );
2263
2264     return S_OK;
2265 }
2266
2267 static ULONG WINAPI saxxmlreader_AddRef(IVBSAXXMLReader* iface)
2268 {
2269     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2270     TRACE("%p\n", This );
2271     return InterlockedIncrement( &This->ref );
2272 }
2273
2274 static ULONG WINAPI saxxmlreader_Release(
2275     IVBSAXXMLReader* iface)
2276 {
2277     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2278     LONG ref;
2279
2280     TRACE("%p\n", This );
2281
2282     ref = InterlockedDecrement( &This->ref );
2283     if ( ref == 0 )
2284     {
2285         if(This->contentHandler)
2286             ISAXContentHandler_Release(This->contentHandler);
2287
2288         if(This->vbcontentHandler)
2289             IVBSAXContentHandler_Release(This->vbcontentHandler);
2290
2291         if(This->errorHandler)
2292             ISAXErrorHandler_Release(This->errorHandler);
2293
2294         if(This->vberrorHandler)
2295             IVBSAXErrorHandler_Release(This->vberrorHandler);
2296
2297         if(This->lexicalHandler)
2298             ISAXLexicalHandler_Release(This->lexicalHandler);
2299
2300         if(This->vblexicalHandler)
2301             IVBSAXLexicalHandler_Release(This->vblexicalHandler);
2302
2303         if(This->declHandler)
2304             ISAXDeclHandler_Release(This->declHandler);
2305
2306         if(This->vbdeclHandler)
2307             IVBSAXDeclHandler_Release(This->vbdeclHandler);
2308
2309         HeapFree( GetProcessHeap(), 0, This );
2310     }
2311
2312     return ref;
2313 }
2314 /*** IDispatch ***/
2315 static HRESULT WINAPI saxxmlreader_GetTypeInfoCount( IVBSAXXMLReader *iface, UINT* pctinfo )
2316 {
2317     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2318
2319     TRACE("(%p)->(%p)\n", This, pctinfo);
2320
2321     *pctinfo = 1;
2322
2323     return S_OK;
2324 }
2325
2326 static HRESULT WINAPI saxxmlreader_GetTypeInfo(
2327     IVBSAXXMLReader *iface,
2328     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2329 {
2330     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2331     HRESULT hr;
2332
2333     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
2334
2335     hr = get_typeinfo(IVBSAXXMLReader_tid, ppTInfo);
2336
2337     return hr;
2338 }
2339
2340 static HRESULT WINAPI saxxmlreader_GetIDsOfNames(
2341     IVBSAXXMLReader *iface,
2342     REFIID riid,
2343     LPOLESTR* rgszNames,
2344     UINT cNames,
2345     LCID lcid,
2346     DISPID* rgDispId)
2347 {
2348     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2349     ITypeInfo *typeinfo;
2350     HRESULT hr;
2351
2352     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
2353           lcid, rgDispId);
2354
2355     if(!rgszNames || cNames == 0 || !rgDispId)
2356         return E_INVALIDARG;
2357
2358     hr = get_typeinfo(IVBSAXXMLReader_tid, &typeinfo);
2359     if(SUCCEEDED(hr))
2360     {
2361         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2362         ITypeInfo_Release(typeinfo);
2363     }
2364
2365     return hr;
2366 }
2367
2368 static HRESULT WINAPI saxxmlreader_Invoke(
2369     IVBSAXXMLReader *iface,
2370     DISPID dispIdMember,
2371     REFIID riid,
2372     LCID lcid,
2373     WORD wFlags,
2374     DISPPARAMS* pDispParams,
2375     VARIANT* pVarResult,
2376     EXCEPINFO* pExcepInfo,
2377     UINT* puArgErr)
2378 {
2379     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2380     ITypeInfo *typeinfo;
2381     HRESULT hr;
2382
2383     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
2384           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2385
2386     hr = get_typeinfo(IVBSAXXMLReader_tid, &typeinfo);
2387     if(SUCCEEDED(hr))
2388     {
2389         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVBSAXXMLReaderVtbl), dispIdMember, wFlags, pDispParams,
2390                 pVarResult, pExcepInfo, puArgErr);
2391         ITypeInfo_Release(typeinfo);
2392     }
2393
2394     return hr;
2395 }
2396
2397 /*** IVBSAXXMLReader methods ***/
2398 static HRESULT WINAPI saxxmlreader_getFeature(
2399     IVBSAXXMLReader* iface,
2400     const WCHAR *pFeature,
2401     VARIANT_BOOL *pValue)
2402 {
2403     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2404
2405     FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pFeature), pValue);
2406     return E_NOTIMPL;
2407 }
2408
2409 static HRESULT WINAPI saxxmlreader_putFeature(
2410     IVBSAXXMLReader* iface,
2411     const WCHAR *pFeature,
2412     VARIANT_BOOL vfValue)
2413 {
2414     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2415
2416     FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(pFeature), vfValue);
2417     return E_NOTIMPL;
2418 }
2419
2420 static HRESULT WINAPI saxxmlreader_getProperty(
2421     IVBSAXXMLReader* iface,
2422     const WCHAR *pProp,
2423     VARIANT *pValue)
2424 {
2425     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2426
2427     FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pProp), pValue);
2428     return E_NOTIMPL;
2429 }
2430
2431 static HRESULT WINAPI saxxmlreader_putProperty(
2432     IVBSAXXMLReader* iface,
2433     const WCHAR *pProp,
2434     VARIANT value)
2435 {
2436     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2437     return internal_putProperty(This, pProp, value, TRUE);
2438 }
2439
2440 static HRESULT WINAPI saxxmlreader_get_entityResolver(
2441     IVBSAXXMLReader* iface,
2442     IVBSAXEntityResolver **pEntityResolver)
2443 {
2444     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2445     return internal_getEntityResolver(This, pEntityResolver, TRUE);
2446 }
2447
2448 static HRESULT WINAPI saxxmlreader_put_entityResolver(
2449     IVBSAXXMLReader* iface,
2450     IVBSAXEntityResolver *pEntityResolver)
2451 {
2452     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2453     return internal_putEntityResolver(This, pEntityResolver, TRUE);
2454 }
2455
2456 static HRESULT WINAPI saxxmlreader_get_contentHandler(
2457     IVBSAXXMLReader* iface,
2458     IVBSAXContentHandler **ppContentHandler)
2459 {
2460     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2461     return internal_getContentHandler(This, ppContentHandler, TRUE);
2462 }
2463
2464 static HRESULT WINAPI saxxmlreader_put_contentHandler(
2465     IVBSAXXMLReader* iface,
2466     IVBSAXContentHandler *contentHandler)
2467 {
2468     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2469     return internal_putContentHandler(This, contentHandler, TRUE);
2470 }
2471
2472 static HRESULT WINAPI saxxmlreader_get_dtdHandler(
2473     IVBSAXXMLReader* iface,
2474     IVBSAXDTDHandler **pDTDHandler)
2475 {
2476     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2477     return internal_getDTDHandler(This, pDTDHandler, TRUE);
2478 }
2479
2480 static HRESULT WINAPI saxxmlreader_put_dtdHandler(
2481     IVBSAXXMLReader* iface,
2482     IVBSAXDTDHandler *pDTDHandler)
2483 {
2484     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2485     return internal_putDTDHandler(This, pDTDHandler, TRUE);
2486 }
2487
2488 static HRESULT WINAPI saxxmlreader_get_errorHandler(
2489     IVBSAXXMLReader* iface,
2490     IVBSAXErrorHandler **pErrorHandler)
2491 {
2492     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2493     return internal_getErrorHandler(This, pErrorHandler, TRUE);
2494 }
2495
2496 static HRESULT WINAPI saxxmlreader_put_errorHandler(
2497     IVBSAXXMLReader* iface,
2498     IVBSAXErrorHandler *errorHandler)
2499 {
2500     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2501     return internal_putErrorHandler(This, errorHandler, TRUE);
2502 }
2503
2504 static HRESULT WINAPI saxxmlreader_get_baseURL(
2505     IVBSAXXMLReader* iface,
2506     const WCHAR **pBaseUrl)
2507 {
2508     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2509
2510     FIXME("(%p)->(%p) stub\n", This, pBaseUrl);
2511     return E_NOTIMPL;
2512 }
2513
2514 static HRESULT WINAPI saxxmlreader_put_baseURL(
2515     IVBSAXXMLReader* iface,
2516     const WCHAR *pBaseUrl)
2517 {
2518     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2519
2520     FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
2521     return E_NOTIMPL;
2522 }
2523
2524 static HRESULT WINAPI saxxmlreader_get_secureBaseURL(
2525     IVBSAXXMLReader* iface,
2526     const WCHAR **pSecureBaseUrl)
2527 {
2528     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2529
2530     FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
2531     return E_NOTIMPL;
2532 }
2533
2534
2535 static HRESULT WINAPI saxxmlreader_put_secureBaseURL(
2536     IVBSAXXMLReader* iface,
2537     const WCHAR *secureBaseUrl)
2538 {
2539     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2540
2541     FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
2542     return E_NOTIMPL;
2543 }
2544
2545 static HRESULT WINAPI saxxmlreader_parse(
2546     IVBSAXXMLReader* iface,
2547     VARIANT varInput)
2548 {
2549     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2550     return internal_parse(This, varInput, TRUE);
2551 }
2552
2553 static HRESULT WINAPI saxxmlreader_parseURL(
2554     IVBSAXXMLReader* iface,
2555     const WCHAR *url)
2556 {
2557     saxreader *This = impl_from_IVBSAXXMLReader( iface );
2558     return internal_parseURL(This, url, TRUE);
2559 }
2560
2561 static const struct IVBSAXXMLReaderVtbl saxreader_vtbl =
2562 {
2563     saxxmlreader_QueryInterface,
2564     saxxmlreader_AddRef,
2565     saxxmlreader_Release,
2566     saxxmlreader_GetTypeInfoCount,
2567     saxxmlreader_GetTypeInfo,
2568     saxxmlreader_GetIDsOfNames,
2569     saxxmlreader_Invoke,
2570     saxxmlreader_getFeature,
2571     saxxmlreader_putFeature,
2572     saxxmlreader_getProperty,
2573     saxxmlreader_putProperty,
2574     saxxmlreader_get_entityResolver,
2575     saxxmlreader_put_entityResolver,
2576     saxxmlreader_get_contentHandler,
2577     saxxmlreader_put_contentHandler,
2578     saxxmlreader_get_dtdHandler,
2579     saxxmlreader_put_dtdHandler,
2580     saxxmlreader_get_errorHandler,
2581     saxxmlreader_put_errorHandler,
2582     saxxmlreader_get_baseURL,
2583     saxxmlreader_put_baseURL,
2584     saxxmlreader_get_secureBaseURL,
2585     saxxmlreader_put_secureBaseURL,
2586     saxxmlreader_parse,
2587     saxxmlreader_parseURL
2588 };
2589
2590 /*** ISAXXMLReader interface ***/
2591 /*** IUnknown methods ***/
2592 static HRESULT WINAPI isaxxmlreader_QueryInterface(ISAXXMLReader* iface, REFIID riid, void **ppvObject)
2593 {
2594     saxreader *This = impl_from_ISAXXMLReader( iface );
2595     return saxxmlreader_QueryInterface((IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl, riid, ppvObject);
2596 }
2597
2598 static ULONG WINAPI isaxxmlreader_AddRef(ISAXXMLReader* iface)
2599 {
2600     saxreader *This = impl_from_ISAXXMLReader( iface );
2601     return saxxmlreader_AddRef((IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl);
2602 }
2603
2604 static ULONG WINAPI isaxxmlreader_Release(ISAXXMLReader* iface)
2605 {
2606     saxreader *This = impl_from_ISAXXMLReader( iface );
2607     return saxxmlreader_Release((IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl);
2608 }
2609
2610 /*** ISAXXMLReader methods ***/
2611 static HRESULT WINAPI isaxxmlreader_getFeature(
2612         ISAXXMLReader* iface,
2613         const WCHAR *pFeature,
2614         VARIANT_BOOL *pValue)
2615 {
2616     saxreader *This = impl_from_ISAXXMLReader( iface );
2617     return IVBSAXXMLReader_getFeature(
2618             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2619             pFeature, pValue);
2620 }
2621
2622 static HRESULT WINAPI isaxxmlreader_putFeature(
2623         ISAXXMLReader* iface,
2624         const WCHAR *pFeature,
2625         VARIANT_BOOL vfValue)
2626 {
2627     saxreader *This = impl_from_ISAXXMLReader( iface );
2628     return IVBSAXXMLReader_putFeature(
2629             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2630             pFeature, vfValue);
2631 }
2632
2633 static HRESULT WINAPI isaxxmlreader_getProperty(
2634         ISAXXMLReader* iface,
2635         const WCHAR *pProp,
2636         VARIANT *pValue)
2637 {
2638     saxreader *This = impl_from_ISAXXMLReader( iface );
2639     return IVBSAXXMLReader_getProperty(
2640             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2641             pProp, pValue);
2642 }
2643
2644 static HRESULT WINAPI isaxxmlreader_putProperty(
2645         ISAXXMLReader* iface,
2646         const WCHAR *pProp,
2647         VARIANT value)
2648 {
2649     saxreader *This = impl_from_ISAXXMLReader( iface );
2650     return internal_putProperty(This, pProp, value, FALSE);
2651 }
2652
2653 static HRESULT WINAPI isaxxmlreader_getEntityResolver(
2654         ISAXXMLReader* iface,
2655         ISAXEntityResolver **ppEntityResolver)
2656 {
2657     saxreader *This = impl_from_ISAXXMLReader( iface );
2658     return internal_getEntityResolver(This, ppEntityResolver, FALSE);
2659 }
2660
2661 static HRESULT WINAPI isaxxmlreader_putEntityResolver(
2662         ISAXXMLReader* iface,
2663         ISAXEntityResolver *pEntityResolver)
2664 {
2665     saxreader *This = impl_from_ISAXXMLReader( iface );
2666     return internal_putEntityResolver(This, pEntityResolver, FALSE);
2667 }
2668
2669 static HRESULT WINAPI isaxxmlreader_getContentHandler(
2670         ISAXXMLReader* iface,
2671         ISAXContentHandler **pContentHandler)
2672 {
2673     saxreader *This = impl_from_ISAXXMLReader( iface );
2674     return internal_getContentHandler(This, pContentHandler, FALSE);
2675 }
2676
2677 static HRESULT WINAPI isaxxmlreader_putContentHandler(
2678         ISAXXMLReader* iface,
2679         ISAXContentHandler *contentHandler)
2680 {
2681     saxreader *This = impl_from_ISAXXMLReader( iface );
2682     return internal_putContentHandler(This, contentHandler, FALSE);
2683 }
2684
2685 static HRESULT WINAPI isaxxmlreader_getDTDHandler(
2686         ISAXXMLReader* iface,
2687         ISAXDTDHandler **pDTDHandler)
2688 {
2689     saxreader *This = impl_from_ISAXXMLReader( iface );
2690     return internal_getDTDHandler(This, pDTDHandler, FALSE);
2691 }
2692
2693 static HRESULT WINAPI isaxxmlreader_putDTDHandler(
2694         ISAXXMLReader* iface,
2695         ISAXDTDHandler *pDTDHandler)
2696 {
2697     saxreader *This = impl_from_ISAXXMLReader( iface );
2698     return internal_putDTDHandler(This, pDTDHandler, FALSE);
2699 }
2700
2701 static HRESULT WINAPI isaxxmlreader_getErrorHandler(
2702         ISAXXMLReader* iface,
2703         ISAXErrorHandler **pErrorHandler)
2704 {
2705     saxreader *This = impl_from_ISAXXMLReader( iface );
2706     return internal_getErrorHandler(This, pErrorHandler, FALSE);
2707 }
2708
2709 static HRESULT WINAPI isaxxmlreader_putErrorHandler(
2710         ISAXXMLReader* iface,
2711         ISAXErrorHandler *errorHandler)
2712 {
2713     saxreader *This = impl_from_ISAXXMLReader( iface );
2714     return internal_putErrorHandler(This, errorHandler, FALSE);
2715 }
2716
2717 static HRESULT WINAPI isaxxmlreader_getBaseURL(
2718         ISAXXMLReader* iface,
2719         const WCHAR **pBaseUrl)
2720 {
2721     saxreader *This = impl_from_ISAXXMLReader( iface );
2722     return IVBSAXXMLReader_get_baseURL(
2723             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2724             pBaseUrl);
2725 }
2726
2727 static HRESULT WINAPI isaxxmlreader_putBaseURL(
2728         ISAXXMLReader* iface,
2729         const WCHAR *pBaseUrl)
2730 {
2731     saxreader *This = impl_from_ISAXXMLReader( iface );
2732     return IVBSAXXMLReader_put_baseURL(
2733             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2734             pBaseUrl);
2735 }
2736
2737 static HRESULT WINAPI isaxxmlreader_getSecureBaseURL(
2738         ISAXXMLReader* iface,
2739         const WCHAR **pSecureBaseUrl)
2740 {
2741     saxreader *This = impl_from_ISAXXMLReader( iface );
2742     return IVBSAXXMLReader_get_secureBaseURL(
2743             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2744             pSecureBaseUrl);
2745 }
2746
2747 static HRESULT WINAPI isaxxmlreader_putSecureBaseURL(
2748         ISAXXMLReader* iface,
2749         const WCHAR *secureBaseUrl)
2750 {
2751     saxreader *This = impl_from_ISAXXMLReader( iface );
2752     return IVBSAXXMLReader_put_secureBaseURL(
2753             (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl,
2754             secureBaseUrl);
2755 }
2756
2757 static HRESULT WINAPI isaxxmlreader_parse(
2758         ISAXXMLReader* iface,
2759         VARIANT varInput)
2760 {
2761     saxreader *This = impl_from_ISAXXMLReader( iface );
2762     return internal_parse(This, varInput, FALSE);
2763 }
2764
2765 static HRESULT WINAPI isaxxmlreader_parseURL(
2766         ISAXXMLReader* iface,
2767         const WCHAR *url)
2768 {
2769     saxreader *This = impl_from_ISAXXMLReader( iface );
2770     return internal_parseURL(This, url, FALSE);
2771 }
2772
2773 static const struct ISAXXMLReaderVtbl isaxreader_vtbl =
2774 {
2775     isaxxmlreader_QueryInterface,
2776     isaxxmlreader_AddRef,
2777     isaxxmlreader_Release,
2778     isaxxmlreader_getFeature,
2779     isaxxmlreader_putFeature,
2780     isaxxmlreader_getProperty,
2781     isaxxmlreader_putProperty,
2782     isaxxmlreader_getEntityResolver,
2783     isaxxmlreader_putEntityResolver,
2784     isaxxmlreader_getContentHandler,
2785     isaxxmlreader_putContentHandler,
2786     isaxxmlreader_getDTDHandler,
2787     isaxxmlreader_putDTDHandler,
2788     isaxxmlreader_getErrorHandler,
2789     isaxxmlreader_putErrorHandler,
2790     isaxxmlreader_getBaseURL,
2791     isaxxmlreader_putBaseURL,
2792     isaxxmlreader_getSecureBaseURL,
2793     isaxxmlreader_putSecureBaseURL,
2794     isaxxmlreader_parse,
2795     isaxxmlreader_parseURL
2796 };
2797
2798 HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2799 {
2800     saxreader *reader;
2801
2802     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
2803
2804     reader = HeapAlloc( GetProcessHeap(), 0, sizeof (*reader) );
2805     if( !reader )
2806         return E_OUTOFMEMORY;
2807
2808     reader->lpVBSAXXMLReaderVtbl = &saxreader_vtbl;
2809     reader->lpSAXXMLReaderVtbl = &isaxreader_vtbl;
2810     reader->ref = 1;
2811     reader->contentHandler = NULL;
2812     reader->vbcontentHandler = NULL;
2813     reader->errorHandler = NULL;
2814     reader->vberrorHandler = NULL;
2815     reader->lexicalHandler = NULL;
2816     reader->vblexicalHandler = NULL;
2817     reader->declHandler = NULL;
2818     reader->vbdeclHandler = NULL;
2819     reader->isParsing = FALSE;
2820
2821     memset(&reader->sax, 0, sizeof(xmlSAXHandler));
2822     reader->sax.initialized = XML_SAX2_MAGIC;
2823     reader->sax.startDocument = libxmlStartDocument;
2824     reader->sax.endDocument = libxmlEndDocument;
2825     reader->sax.startElementNs = libxmlStartElementNS;
2826     reader->sax.endElementNs = libxmlEndElementNS;
2827     reader->sax.characters = libxmlCharacters;
2828     reader->sax.setDocumentLocator = libxmlSetDocumentLocator;
2829     reader->sax.comment = libxmlComment;
2830     reader->sax.error = libxmlFatalError;
2831     reader->sax.fatalError = libxmlFatalError;
2832     reader->sax.cdataBlock = libxmlCDataBlock;
2833
2834     *ppObj = &reader->lpVBSAXXMLReaderVtbl;
2835
2836     TRACE("returning iface %p\n", *ppObj);
2837
2838     return S_OK;
2839 }
2840
2841 #else
2842
2843 HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj)
2844 {
2845     MESSAGE("This program tried to use a SAX XML Reader object, but\n"
2846             "libxml2 support was not present at compile time.\n");
2847     return E_NOTIMPL;
2848 }
2849
2850 #endif