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