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