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