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