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