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