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