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