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