/* * SAX Reader implementation * * Copyright 2008 Alistair Leslie-Hughes * Copyright 2008 Piotr Caban * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #define COBJMACROS #include "config.h" #include #ifdef HAVE_LIBXML2 # include # include # include # include #endif #include "windef.h" #include "winbase.h" #include "winuser.h" #include "winnls.h" #include "ole2.h" #include "msxml6.h" #include "wininet.h" #include "urlmon.h" #include "winreg.h" #include "shlwapi.h" #include "wine/debug.h" #include "msxml_private.h" WINE_DEFAULT_DEBUG_CHANNEL(msxml); #ifdef HAVE_LIBXML2 enum ReaderFeatures { ExhaustiveErrors = 1 << 1, ExternalGeneralEntities = 1 << 2, ExternalParameterEntities = 1 << 3, ForcedResync = 1 << 4, NamespacePrefixes = 1 << 5, Namespaces = 1 << 6, ParameterEntities = 1 << 7, PreserveSystemIndentifiers = 1 << 8, ProhibitDTD = 1 << 9, SchemaValidation = 1 << 10, ServerHttpRequest = 1 << 11, SuppressValidationfatalError = 1 << 12, UseInlineSchema = 1 << 13, UseSchemaLocation = 1 << 14, LexicalHandlerParEntities = 1 << 15 }; struct bstrpool { BSTR *pool; unsigned int index; unsigned int len; }; typedef struct _saxreader { IVBSAXXMLReader IVBSAXXMLReader_iface; ISAXXMLReader ISAXXMLReader_iface; LONG ref; struct ISAXContentHandler *contentHandler; struct IVBSAXContentHandler *vbcontentHandler; struct ISAXErrorHandler *errorHandler; struct IVBSAXErrorHandler *vberrorHandler; struct ISAXLexicalHandler *lexicalHandler; struct IVBSAXLexicalHandler *vblexicalHandler; struct ISAXDeclHandler *declHandler; struct IVBSAXDeclHandler *vbdeclHandler; xmlSAXHandler sax; BOOL isParsing; struct bstrpool pool; enum ReaderFeatures features; } saxreader; typedef struct _saxlocator { IVBSAXLocator IVBSAXLocator_iface; ISAXLocator ISAXLocator_iface; LONG ref; saxreader *saxreader; HRESULT ret; xmlParserCtxtPtr pParserCtxt; WCHAR *publicId; WCHAR *systemId; xmlChar *lastCur; int line; int realLine; int column; int realColumn; BOOL vbInterface; int nsStackSize; int nsStackLast; int *nsStack; } saxlocator; typedef struct _saxattributes { IVBSAXAttributes IVBSAXAttributes_iface; ISAXAttributes ISAXAttributes_iface; LONG ref; int nb_attributes; BSTR *szLocalname; BSTR *szURI; BSTR *szValue; BSTR *szQName; } saxattributes; static inline saxreader *impl_from_IVBSAXXMLReader( IVBSAXXMLReader *iface ) { return CONTAINING_RECORD(iface, saxreader, IVBSAXXMLReader_iface); } static inline saxreader *impl_from_ISAXXMLReader( ISAXXMLReader *iface ) { return CONTAINING_RECORD(iface, saxreader, ISAXXMLReader_iface); } static inline saxlocator *impl_from_IVBSAXLocator( IVBSAXLocator *iface ) { return CONTAINING_RECORD(iface, saxlocator, IVBSAXLocator_iface); } static inline saxlocator *impl_from_ISAXLocator( ISAXLocator *iface ) { return CONTAINING_RECORD(iface, saxlocator, ISAXLocator_iface); } static inline saxattributes *impl_from_IVBSAXAttributes( IVBSAXAttributes *iface ) { return CONTAINING_RECORD(iface, saxattributes, IVBSAXAttributes_iface); } static inline saxattributes *impl_from_ISAXAttributes( ISAXAttributes *iface ) { return CONTAINING_RECORD(iface, saxattributes, ISAXAttributes_iface); } /* property names */ static const WCHAR PropertyCharsetW[] = { 'c','h','a','r','s','e','t',0 }; static const WCHAR PropertyDeclHandlerW[] = { 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/', 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/', 'd','e','c','l','a','r','a','t','i','o','n', '-','h','a','n','d','l','e','r',0 }; static const WCHAR PropertyDomNodeW[] = { 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/', 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/', 'd','o','m','-','n','o','d','e',0 }; static const WCHAR PropertyInputSourceW[] = { 'i','n','p','u','t','-','s','o','u','r','c','e',0 }; static const WCHAR PropertyLexicalHandlerW[] = { 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/', 's','a','x','/','p','r','o','p','e','r','t','i','e','s','/', 'l','e','x','i','c','a','l','-','h','a','n','d','l','e','r',0 }; static const WCHAR PropertyMaxElementDepthW[] = { 'm','a','x','-','e','l','e','m','e','n','t','-','d','e','p','t','h',0 }; static const WCHAR PropertyMaxXMLSizeW[] = { 'm','a','x','-','x','m','l','-','s','i','z','e',0 }; static const WCHAR PropertySchemaDeclHandlerW[] = { 's','c','h','e','m','a','-','d','e','c','l','a','r','a','t','i','o','n','-', 'h','a','n','d','l','e','r',0 }; static const WCHAR PropertyXMLDeclEncodingW[] = { 'x','m','l','d','e','c','l','-','e','n','c','o','d','i','n','g',0 }; static const WCHAR PropertyXMLDeclStandaloneW[] = { 'x','m','l','d','e','c','l','-','s','t','a','n','d','a','l','o','n','e',0 }; static const WCHAR PropertyXMLDeclVersionW[] = { 'x','m','l','d','e','c','l','-','v','e','r','s','i','o','n',0 }; /* feature names */ static const WCHAR FeatureExternalGeneralEntitiesW[] = { 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/', 'f','e','a','t','u','r','e','s','/','e','x','t','e','r','n','a','l','-','g','e','n','e','r','a','l', '-','e','n','t','i','t','i','e','s',0 }; static const WCHAR FeatureExternalParameterEntitiesW[] = { 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s', '/','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 }; static const WCHAR FeatureLexicalHandlerParEntitiesW[] = { 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s', '/','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 }; static const WCHAR FeatureProhibitDTDW[] = { 'p','r','o','h','i','b','i','t','-','d','t','d',0 }; static const WCHAR FeatureNamespacesW[] = { 'h','t','t','p',':','/','/','x','m','l','.','o','r','g','/','s','a','x','/','f','e','a','t','u','r','e','s', '/','n','a','m','e','s','p','a','c','e','s',0 }; static inline HRESULT set_feature_value(saxreader *reader, enum ReaderFeatures feature, VARIANT_BOOL value) { if (value == VARIANT_TRUE) reader->features |= feature; else reader->features &= ~feature; return S_OK; } static inline HRESULT get_feature_value(const saxreader *reader, enum ReaderFeatures feature, VARIANT_BOOL *value) { *value = reader->features & feature ? VARIANT_TRUE : VARIANT_FALSE; return S_OK; } static inline BOOL has_content_handler(const saxlocator *locator) { return (locator->vbInterface && locator->saxreader->vbcontentHandler) || (!locator->vbInterface && locator->saxreader->contentHandler); } static inline BOOL has_error_handler(const saxlocator *locator) { return (locator->vbInterface && locator->saxreader->vberrorHandler) || (!locator->vbInterface && locator->saxreader->errorHandler); } static HRESULT namespacePush(saxlocator *locator, int ns) { if(locator->nsStackLast>=locator->nsStackSize) { int *new_stack; new_stack = HeapReAlloc(GetProcessHeap(), 0, locator->nsStack, sizeof(int)*locator->nsStackSize*2); if(!new_stack) return E_OUTOFMEMORY; locator->nsStack = new_stack; locator->nsStackSize *= 2; } locator->nsStack[locator->nsStackLast++] = ns; return S_OK; } static int namespacePop(saxlocator *locator) { if(locator->nsStackLast == 0) return 0; return locator->nsStack[--locator->nsStackLast]; } static BOOL bstr_pool_insert(struct bstrpool *pool, BSTR pool_entry) { if (!pool->pool) { pool->pool = HeapAlloc(GetProcessHeap(), 0, 16 * sizeof(*pool->pool)); if (!pool->pool) return FALSE; pool->index = 0; pool->len = 16; } else if (pool->index == pool->len) { BSTR *realloc = HeapReAlloc(GetProcessHeap(), 0, pool->pool, pool->len * 2 * sizeof(*realloc)); if (!realloc) return FALSE; pool->pool = realloc; pool->len *= 2; } pool->pool[pool->index++] = pool_entry; return TRUE; } static void free_bstr_pool(struct bstrpool *pool) { unsigned int i; for (i = 0; i < pool->index; i++) SysFreeString(pool->pool[i]); HeapFree(GetProcessHeap(), 0, pool->pool); pool->pool = NULL; pool->index = pool->len = 0; } static BSTR bstr_from_xmlCharN(const xmlChar *buf, int len) { DWORD dLen; BSTR bstr; if (!buf) return NULL; dLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0); if(len != -1) dLen++; bstr = SysAllocStringLen(NULL, dLen-1); if (!bstr) return NULL; MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, bstr, dLen); if(len != -1) bstr[dLen-1] = '\0'; return bstr; } static BSTR QName_from_xmlChar(const xmlChar *prefix, const xmlChar *name) { xmlChar *qname; BSTR bstr; if(!name) return NULL; if(!prefix || !*prefix) return bstr_from_xmlChar(name); qname = xmlBuildQName(name, prefix, NULL, 0); bstr = bstr_from_xmlChar(qname); xmlFree(qname); return bstr; } static BSTR pooled_bstr_from_xmlChar(struct bstrpool *pool, const xmlChar *buf) { BSTR pool_entry = bstr_from_xmlChar(buf); if (pool_entry && !bstr_pool_insert(pool, pool_entry)) { SysFreeString(pool_entry); return NULL; } return pool_entry; } static BSTR pooled_bstr_from_xmlCharN(struct bstrpool *pool, const xmlChar *buf, int len) { BSTR pool_entry = bstr_from_xmlCharN(buf, len); if (pool_entry && !bstr_pool_insert(pool, pool_entry)) { SysFreeString(pool_entry); return NULL; } return pool_entry; } static BSTR pooled_QName_from_xmlChar(struct bstrpool *pool, const xmlChar *prefix, const xmlChar *name) { BSTR pool_entry = QName_from_xmlChar(prefix, name); if (pool_entry && !bstr_pool_insert(pool, pool_entry)) { SysFreeString(pool_entry); return NULL; } return pool_entry; } static void format_error_message_from_id(saxlocator *This, HRESULT hr) { xmlStopParser(This->pParserCtxt); This->ret = hr; if(has_error_handler(This)) { WCHAR msg[1024]; if(!FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, 0, msg, sizeof(msg), NULL)) { FIXME("MSXML errors not yet supported.\n"); msg[0] = '\0'; } if(This->vbInterface) { BSTR bstrMsg = SysAllocString(msg); IVBSAXErrorHandler_fatalError(This->saxreader->vberrorHandler, &This->IVBSAXLocator_iface, &bstrMsg, hr); SysFreeString(bstrMsg); } else ISAXErrorHandler_fatalError(This->saxreader->errorHandler, &This->ISAXLocator_iface, msg, hr); } } static void update_position(saxlocator *This, xmlChar *end) { if(This->lastCur == NULL) { This->lastCur = (xmlChar*)This->pParserCtxt->input->base; This->realLine = 1; This->realColumn = 1; } else if(This->lastCur < This->pParserCtxt->input->base) { This->lastCur = (xmlChar*)This->pParserCtxt->input->base; This->realLine = 1; This->realColumn = 1; } if(This->pParserCtxt->input->curlastCur) { This->lastCur = (xmlChar*)This->pParserCtxt->input->base; This->realLine -= 1; This->realColumn = 1; } if(!end) end = (xmlChar*)This->pParserCtxt->input->cur; while(This->lastCur < end) { if(*(This->lastCur) == '\n') { This->realLine++; This->realColumn = 1; } else if(*(This->lastCur) == '\r' && (This->lastCur==This->pParserCtxt->input->end || *(This->lastCur+1)!='\n')) { This->realLine++; This->realColumn = 1; } else This->realColumn++; This->lastCur++; /* Count multibyte UTF8 encoded characters once */ while((*(This->lastCur)&0xC0) == 0x80) This->lastCur++; } This->line = This->realLine; This->column = This->realColumn; } /*** IVBSAXAttributes interface ***/ /*** IUnknown methods ***/ static HRESULT WINAPI ivbsaxattributes_QueryInterface( IVBSAXAttributes* iface, REFIID riid, void **ppvObject) { saxattributes *This = impl_from_IVBSAXAttributes(iface); TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject); *ppvObject = NULL; if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDispatch) || IsEqualGUID(riid, &IID_IVBSAXAttributes)) { *ppvObject = iface; } else { FIXME("interface %s not implemented\n", debugstr_guid(riid)); return E_NOINTERFACE; } IVBSAXAttributes_AddRef(iface); return S_OK; } static ULONG WINAPI ivbsaxattributes_AddRef(IVBSAXAttributes* iface) { saxattributes *This = impl_from_IVBSAXAttributes(iface); return ISAXAttributes_AddRef(&This->ISAXAttributes_iface); } static ULONG WINAPI ivbsaxattributes_Release(IVBSAXAttributes* iface) { saxattributes *This = impl_from_IVBSAXAttributes(iface); return ISAXAttributes_Release(&This->ISAXAttributes_iface); } /*** IDispatch methods ***/ static HRESULT WINAPI ivbsaxattributes_GetTypeInfoCount( IVBSAXAttributes *iface, UINT* pctinfo ) { saxattributes *This = impl_from_IVBSAXAttributes( iface ); TRACE("(%p)->(%p)\n", This, pctinfo); *pctinfo = 1; return S_OK; } static HRESULT WINAPI ivbsaxattributes_GetTypeInfo( IVBSAXAttributes *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo ) { saxattributes *This = impl_from_IVBSAXAttributes( iface ); HRESULT hr; TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); hr = get_typeinfo(IVBSAXAttributes_tid, ppTInfo); return hr; } static HRESULT WINAPI ivbsaxattributes_GetIDsOfNames( IVBSAXAttributes *iface, REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) { saxattributes *This = impl_from_IVBSAXAttributes( iface ); ITypeInfo *typeinfo; HRESULT hr; TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId); if(!rgszNames || cNames == 0 || !rgDispId) return E_INVALIDARG; hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo); if(SUCCEEDED(hr)) { hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId); ITypeInfo_Release(typeinfo); } return hr; } static HRESULT WINAPI ivbsaxattributes_Invoke( IVBSAXAttributes *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) { saxattributes *This = impl_from_IVBSAXAttributes( iface ); ITypeInfo *typeinfo; HRESULT hr; TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo); if(SUCCEEDED(hr)) { hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXAttributes_iface, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); ITypeInfo_Release(typeinfo); } return hr; } /*** IVBSAXAttributes methods ***/ static HRESULT WINAPI ivbsaxattributes_get_length( IVBSAXAttributes* iface, int *nLength) { saxattributes *This = impl_from_IVBSAXAttributes( iface ); return ISAXAttributes_getLength(&This->ISAXAttributes_iface, nLength); } static HRESULT WINAPI ivbsaxattributes_getURI( IVBSAXAttributes* iface, int nIndex, BSTR *uri) { int len; saxattributes *This = impl_from_IVBSAXAttributes( iface ); return ISAXAttributes_getURI(&This->ISAXAttributes_iface, nIndex, (const WCHAR**)uri, &len); } static HRESULT WINAPI ivbsaxattributes_getLocalName( IVBSAXAttributes* iface, int nIndex, BSTR *localName) { int len; saxattributes *This = impl_from_IVBSAXAttributes( iface ); return ISAXAttributes_getLocalName(&This->ISAXAttributes_iface, nIndex, (const WCHAR**)localName, &len); } static HRESULT WINAPI ivbsaxattributes_getQName( IVBSAXAttributes* iface, int nIndex, BSTR *QName) { int len; saxattributes *This = impl_from_IVBSAXAttributes( iface ); return ISAXAttributes_getQName(&This->ISAXAttributes_iface, nIndex, (const WCHAR**)QName, &len); } static HRESULT WINAPI ivbsaxattributes_getIndexFromName( IVBSAXAttributes* iface, BSTR uri, BSTR localName, int *index) { saxattributes *This = impl_from_IVBSAXAttributes( iface ); return ISAXAttributes_getIndexFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri), localName, SysStringLen(localName), index); } static HRESULT WINAPI ivbsaxattributes_getIndexFromQName( IVBSAXAttributes* iface, BSTR QName, int *index) { saxattributes *This = impl_from_IVBSAXAttributes( iface ); return ISAXAttributes_getIndexFromQName(&This->ISAXAttributes_iface, QName, SysStringLen(QName), index); } static HRESULT WINAPI ivbsaxattributes_getType( IVBSAXAttributes* iface, int nIndex, BSTR *type) { int len; saxattributes *This = impl_from_IVBSAXAttributes( iface ); return ISAXAttributes_getType(&This->ISAXAttributes_iface, nIndex, (const WCHAR**)type, &len); } static HRESULT WINAPI ivbsaxattributes_getTypeFromName( IVBSAXAttributes* iface, BSTR uri, BSTR localName, BSTR *type) { int len; saxattributes *This = impl_from_IVBSAXAttributes( iface ); return ISAXAttributes_getTypeFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri), localName, SysStringLen(localName), (const WCHAR**)type, &len); } static HRESULT WINAPI ivbsaxattributes_getTypeFromQName( IVBSAXAttributes* iface, BSTR QName, BSTR *type) { int len; saxattributes *This = impl_from_IVBSAXAttributes( iface ); return ISAXAttributes_getTypeFromQName(&This->ISAXAttributes_iface, QName, SysStringLen(QName), (const WCHAR**)type, &len); } static HRESULT WINAPI ivbsaxattributes_getValue( IVBSAXAttributes* iface, int nIndex, BSTR *value) { int len; saxattributes *This = impl_from_IVBSAXAttributes( iface ); return ISAXAttributes_getValue(&This->ISAXAttributes_iface, nIndex, (const WCHAR**)value, &len); } static HRESULT WINAPI ivbsaxattributes_getValueFromName( IVBSAXAttributes* iface, BSTR uri, BSTR localName, BSTR *value) { int len; saxattributes *This = impl_from_IVBSAXAttributes( iface ); return ISAXAttributes_getValueFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri), localName, SysStringLen(localName), (const WCHAR**)value, &len); } static HRESULT WINAPI ivbsaxattributes_getValueFromQName( IVBSAXAttributes* iface, BSTR QName, BSTR *value) { int len; saxattributes *This = impl_from_IVBSAXAttributes( iface ); return ISAXAttributes_getValueFromQName(&This->ISAXAttributes_iface, QName, SysStringLen(QName), (const WCHAR**)value, &len); } static const struct IVBSAXAttributesVtbl ivbsaxattributes_vtbl = { ivbsaxattributes_QueryInterface, ivbsaxattributes_AddRef, ivbsaxattributes_Release, ivbsaxattributes_GetTypeInfoCount, ivbsaxattributes_GetTypeInfo, ivbsaxattributes_GetIDsOfNames, ivbsaxattributes_Invoke, ivbsaxattributes_get_length, ivbsaxattributes_getURI, ivbsaxattributes_getLocalName, ivbsaxattributes_getQName, ivbsaxattributes_getIndexFromName, ivbsaxattributes_getIndexFromQName, ivbsaxattributes_getType, ivbsaxattributes_getTypeFromName, ivbsaxattributes_getTypeFromQName, ivbsaxattributes_getValue, ivbsaxattributes_getValueFromName, ivbsaxattributes_getValueFromQName }; /*** ISAXAttributes interface ***/ /*** IUnknown methods ***/ static HRESULT WINAPI isaxattributes_QueryInterface( ISAXAttributes* iface, REFIID riid, void **ppvObject) { saxattributes *This = impl_from_ISAXAttributes(iface); TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject); *ppvObject = NULL; if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_ISAXAttributes)) { *ppvObject = iface; } else { FIXME("interface %s not implemented\n", debugstr_guid(riid)); return E_NOINTERFACE; } ISAXAttributes_AddRef(iface); return S_OK; } static ULONG WINAPI isaxattributes_AddRef(ISAXAttributes* iface) { saxattributes *This = impl_from_ISAXAttributes(iface); TRACE("%p\n", This); return InterlockedIncrement(&This->ref); } static ULONG WINAPI isaxattributes_Release(ISAXAttributes* iface) { saxattributes *This = impl_from_ISAXAttributes(iface); LONG ref; TRACE("%p\n", This); ref = InterlockedDecrement(&This->ref); if (ref==0) { int index; for(index=0; indexnb_attributes; index++) { SysFreeString(This->szLocalname[index]); SysFreeString(This->szURI[index]); SysFreeString(This->szValue[index]); SysFreeString(This->szQName[index]); } heap_free(This->szLocalname); heap_free(This->szURI); heap_free(This->szValue); heap_free(This->szQName); heap_free(This); } return ref; } /*** ISAXAttributes methods ***/ static HRESULT WINAPI isaxattributes_getLength( ISAXAttributes* iface, int *length) { saxattributes *This = impl_from_ISAXAttributes( iface ); *length = This->nb_attributes; TRACE("Length set to %d\n", *length); return S_OK; } static HRESULT WINAPI isaxattributes_getURI( ISAXAttributes* iface, int index, const WCHAR **url, int *size) { saxattributes *This = impl_from_ISAXAttributes( iface ); TRACE("(%p)->(%d)\n", This, index); if(index >= This->nb_attributes || index < 0) return E_INVALIDARG; if(!url || !size) return E_POINTER; *size = SysStringLen(This->szURI[index]); *url = This->szURI[index]; TRACE("(%s:%d)\n", debugstr_w(This->szURI[index]), *size); return S_OK; } static HRESULT WINAPI isaxattributes_getLocalName( ISAXAttributes* iface, int nIndex, const WCHAR **pLocalName, int *pLocalNameLength) { saxattributes *This = impl_from_ISAXAttributes( iface ); TRACE("(%p)->(%d)\n", This, nIndex); if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG; if(!pLocalName || !pLocalNameLength) return E_POINTER; *pLocalNameLength = SysStringLen(This->szLocalname[nIndex]); *pLocalName = This->szLocalname[nIndex]; return S_OK; } static HRESULT WINAPI isaxattributes_getQName( ISAXAttributes* iface, int nIndex, const WCHAR **pQName, int *pQNameLength) { saxattributes *This = impl_from_ISAXAttributes( iface ); TRACE("(%p)->(%d)\n", This, nIndex); if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG; if(!pQName || !pQNameLength) return E_POINTER; *pQNameLength = SysStringLen(This->szQName[nIndex]); *pQName = This->szQName[nIndex]; return S_OK; } static HRESULT WINAPI isaxattributes_getName( ISAXAttributes* iface, int index, const WCHAR **uri, int *pUriLength, const WCHAR **localName, int *pLocalNameSize, const WCHAR **QName, int *pQNameLength) { saxattributes *This = impl_from_ISAXAttributes( iface ); TRACE("(%p)->(%d)\n", This, index); if(index>=This->nb_attributes || index<0) return E_INVALIDARG; if(!uri || !pUriLength || !localName || !pLocalNameSize || !QName || !pQNameLength) return E_POINTER; *pUriLength = SysStringLen(This->szURI[index]); *uri = This->szURI[index]; *pLocalNameSize = SysStringLen(This->szLocalname[index]); *localName = This->szLocalname[index]; *pQNameLength = SysStringLen(This->szQName[index]); *QName = This->szQName[index]; TRACE("(%s, %s, %s)\n", debugstr_w(*uri), debugstr_w(*localName), debugstr_w(*QName)); return S_OK; } static HRESULT WINAPI isaxattributes_getIndexFromName( ISAXAttributes* iface, const WCHAR *pUri, int cUriLength, const WCHAR *pLocalName, int cocalNameLength, int *index) { saxattributes *This = impl_from_ISAXAttributes( iface ); int i; TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), cUriLength, debugstr_w(pLocalName), cocalNameLength); if(!pUri || !pLocalName || !index) return E_POINTER; for(i=0; inb_attributes; i++) { if(cUriLength!=SysStringLen(This->szURI[i]) || cocalNameLength!=SysStringLen(This->szLocalname[i])) continue; if(cUriLength && memcmp(pUri, This->szURI[i], sizeof(WCHAR)*cUriLength)) continue; if(cocalNameLength && memcmp(pLocalName, This->szLocalname[i], sizeof(WCHAR)*cocalNameLength)) continue; *index = i; return S_OK; } return E_INVALIDARG; } static HRESULT WINAPI isaxattributes_getIndexFromQName( ISAXAttributes* iface, const WCHAR *pQName, int nQNameLength, int *index) { saxattributes *This = impl_from_ISAXAttributes( iface ); int i; TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQNameLength); if(!pQName || !index) return E_POINTER; if(!nQNameLength) return E_INVALIDARG; for(i=0; inb_attributes; i++) { if(nQNameLength!=SysStringLen(This->szQName[i])) continue; if(memcmp(pQName, This->szQName, sizeof(WCHAR)*nQNameLength)) continue; *index = i; return S_OK; } return E_INVALIDARG; } static HRESULT WINAPI isaxattributes_getType( ISAXAttributes* iface, int nIndex, const WCHAR **pType, int *pTypeLength) { saxattributes *This = impl_from_ISAXAttributes( iface ); FIXME("(%p)->(%d) stub\n", This, nIndex); return E_NOTIMPL; } static HRESULT WINAPI isaxattributes_getTypeFromName( ISAXAttributes* iface, const WCHAR *pUri, int nUri, const WCHAR *pLocalName, int nLocalName, const WCHAR **pType, int *nType) { saxattributes *This = impl_from_ISAXAttributes( iface ); FIXME("(%p)->(%s, %d, %s, %d) stub\n", This, debugstr_w(pUri), nUri, debugstr_w(pLocalName), nLocalName); return E_NOTIMPL; } static HRESULT WINAPI isaxattributes_getTypeFromQName( ISAXAttributes* iface, const WCHAR *pQName, int nQName, const WCHAR **pType, int *nType) { saxattributes *This = impl_from_ISAXAttributes( iface ); FIXME("(%p)->(%s, %d) stub\n", This, debugstr_w(pQName), nQName); return E_NOTIMPL; } static HRESULT WINAPI isaxattributes_getValue( ISAXAttributes* iface, int index, const WCHAR **value, int *nValue) { saxattributes *This = impl_from_ISAXAttributes( iface ); TRACE("(%p)->(%d)\n", This, index); if(index>=This->nb_attributes || index<0) return E_INVALIDARG; if(!value || !nValue) return E_POINTER; *nValue = SysStringLen(This->szValue[index]); *value = This->szValue[index]; TRACE("(%s:%d)\n", debugstr_w(*value), *nValue); return S_OK; } static HRESULT WINAPI isaxattributes_getValueFromName( ISAXAttributes* iface, const WCHAR *pUri, int nUri, const WCHAR *pLocalName, int nLocalName, const WCHAR **pValue, int *nValue) { HRESULT hr; int index; saxattributes *This = impl_from_ISAXAttributes( iface ); TRACE("(%p)->(%s, %d, %s, %d)\n", This, debugstr_w(pUri), nUri, debugstr_w(pLocalName), nLocalName); hr = ISAXAttributes_getIndexFromName(iface, pUri, nUri, pLocalName, nLocalName, &index); if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue); return hr; } static HRESULT WINAPI isaxattributes_getValueFromQName( ISAXAttributes* iface, const WCHAR *pQName, int nQName, const WCHAR **pValue, int *nValue) { HRESULT hr; int index; saxattributes *This = impl_from_ISAXAttributes( iface ); TRACE("(%p)->(%s, %d)\n", This, debugstr_w(pQName), nQName); hr = ISAXAttributes_getIndexFromQName(iface, pQName, nQName, &index); if(hr==S_OK) hr = ISAXAttributes_getValue(iface, index, pValue, nValue); return hr; } static const struct ISAXAttributesVtbl isaxattributes_vtbl = { isaxattributes_QueryInterface, isaxattributes_AddRef, isaxattributes_Release, isaxattributes_getLength, isaxattributes_getURI, isaxattributes_getLocalName, isaxattributes_getQName, isaxattributes_getName, isaxattributes_getIndexFromName, isaxattributes_getIndexFromQName, isaxattributes_getType, isaxattributes_getTypeFromName, isaxattributes_getTypeFromQName, isaxattributes_getValue, isaxattributes_getValueFromName, isaxattributes_getValueFromQName }; static HRESULT SAXAttributes_create(saxattributes **attr, int nb_namespaces, const xmlChar **xmlNamespaces, int nb_attributes, const xmlChar **xmlAttributes) { saxattributes *attributes; int index; static const xmlChar xmlns[] = "xmlns"; attributes = heap_alloc(sizeof(*attributes)); if(!attributes) return E_OUTOFMEMORY; attributes->IVBSAXAttributes_iface.lpVtbl = &ivbsaxattributes_vtbl; attributes->ISAXAttributes_iface.lpVtbl = &isaxattributes_vtbl; attributes->ref = 1; attributes->nb_attributes = nb_namespaces+nb_attributes; attributes->szLocalname = heap_alloc(sizeof(BSTR)*attributes->nb_attributes); attributes->szURI = heap_alloc(sizeof(BSTR)*attributes->nb_attributes); attributes->szValue = heap_alloc(sizeof(BSTR)*attributes->nb_attributes); attributes->szQName = heap_alloc(sizeof(BSTR)*attributes->nb_attributes); if(!attributes->szLocalname || !attributes->szURI || !attributes->szValue || !attributes->szQName) { heap_free(attributes->szLocalname); heap_free(attributes->szURI); heap_free(attributes->szValue); heap_free(attributes->szQName); heap_free(attributes); return E_FAIL; } for(index=0; indexszLocalname[index] = SysAllocStringLen(NULL, 0); attributes->szURI[index] = SysAllocStringLen(NULL, 0); attributes->szValue[index] = bstr_from_xmlChar(xmlNamespaces[2*index+1]); attributes->szQName[index] = QName_from_xmlChar(xmlns, xmlNamespaces[2*index]); } for(index=0; indexszLocalname[nb_namespaces+index] = bstr_from_xmlChar(xmlAttributes[index*5]); attributes->szURI[nb_namespaces+index] = bstr_from_xmlChar(xmlAttributes[index*5+2]); attributes->szValue[nb_namespaces+index] = bstr_from_xmlCharN(xmlAttributes[index*5+3], xmlAttributes[index*5+4]-xmlAttributes[index*5+3]); attributes->szQName[nb_namespaces+index] = QName_from_xmlChar(xmlAttributes[index*5+1], xmlAttributes[index*5]); } *attr = attributes; TRACE("returning %p\n", *attr); return S_OK; } /*** LibXML callbacks ***/ static void libxmlStartDocument(void *ctx) { saxlocator *This = ctx; HRESULT hr; if(has_content_handler(This)) { if(This->vbInterface) hr = IVBSAXContentHandler_startDocument(This->saxreader->vbcontentHandler); else hr = ISAXContentHandler_startDocument(This->saxreader->contentHandler); if(hr != S_OK) format_error_message_from_id(This, hr); } update_position(This, NULL); } static void libxmlEndDocument(void *ctx) { saxlocator *This = ctx; HRESULT hr; This->column = 0; This->line = 0; if(This->ret != S_OK) return; if(has_content_handler(This)) { if(This->vbInterface) hr = IVBSAXContentHandler_endDocument(This->saxreader->vbcontentHandler); else hr = ISAXContentHandler_endDocument(This->saxreader->contentHandler); if(hr != S_OK) format_error_message_from_id(This, hr); } } static void libxmlStartElementNS( void *ctx, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI, int nb_namespaces, const xmlChar **namespaces, int nb_attributes, int nb_defaulted, const xmlChar **attributes) { BSTR NamespaceUri, LocalName, QName, Prefix, Uri; saxlocator *This = ctx; HRESULT hr; saxattributes *attr; int index; if(*(This->pParserCtxt->input->cur) == '/') update_position(This, (xmlChar*)This->pParserCtxt->input->cur+2); else update_position(This, (xmlChar*)This->pParserCtxt->input->cur+1); hr = namespacePush(This, nb_namespaces); if(hr==S_OK && has_content_handler(This)) { for(index=0; indexsaxreader->pool, namespaces[2*index]); Uri = pooled_bstr_from_xmlChar(&This->saxreader->pool, namespaces[2*index+1]); if(This->vbInterface) hr = IVBSAXContentHandler_startPrefixMapping( This->saxreader->vbcontentHandler, &Prefix, &Uri); else hr = ISAXContentHandler_startPrefixMapping( This->saxreader->contentHandler, Prefix, SysStringLen(Prefix), Uri, SysStringLen(Uri)); if(hr != S_OK) { format_error_message_from_id(This, hr); return; } } NamespaceUri = pooled_bstr_from_xmlChar(&This->saxreader->pool, URI); LocalName = pooled_bstr_from_xmlChar(&This->saxreader->pool, localname); QName = pooled_QName_from_xmlChar(&This->saxreader->pool, prefix, localname); hr = SAXAttributes_create(&attr, nb_namespaces, namespaces, nb_attributes, attributes); if(hr == S_OK) { if(This->vbInterface) hr = IVBSAXContentHandler_startElement(This->saxreader->vbcontentHandler, &NamespaceUri, &LocalName, &QName, &attr->IVBSAXAttributes_iface); else hr = ISAXContentHandler_startElement(This->saxreader->contentHandler, NamespaceUri, SysStringLen(NamespaceUri), LocalName, SysStringLen(LocalName), QName, SysStringLen(QName), &attr->ISAXAttributes_iface); ISAXAttributes_Release(&attr->ISAXAttributes_iface); } } if(hr != S_OK) format_error_message_from_id(This, hr); } static void libxmlEndElementNS( void *ctx, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI) { BSTR NamespaceUri, LocalName, QName, Prefix; saxlocator *This = ctx; HRESULT hr; xmlChar *end; int nsNr, index; end = (xmlChar*)This->pParserCtxt->input->cur; if(*(end-1) != '>' || *(end-2) != '/') while(end-2>=This->pParserCtxt->input->base && *(end-2)!='<' && *(end-1)!='/') end--; update_position(This, end); nsNr = namespacePop(This); if(has_content_handler(This)) { NamespaceUri = pooled_bstr_from_xmlChar(&This->saxreader->pool, URI); LocalName = pooled_bstr_from_xmlChar(&This->saxreader->pool, localname); QName = pooled_QName_from_xmlChar(&This->saxreader->pool, prefix, localname); if(This->vbInterface) hr = IVBSAXContentHandler_endElement( This->saxreader->vbcontentHandler, &NamespaceUri, &LocalName, &QName); else hr = ISAXContentHandler_endElement( This->saxreader->contentHandler, NamespaceUri, SysStringLen(NamespaceUri), LocalName, SysStringLen(LocalName), QName, SysStringLen(QName)); if(hr != S_OK) { format_error_message_from_id(This, hr); return; } for(index=This->pParserCtxt->nsNr-2; index>=This->pParserCtxt->nsNr-nsNr*2; index-=2) { Prefix = pooled_bstr_from_xmlChar(&This->saxreader->pool, This->pParserCtxt->nsTab[index]); if(This->vbInterface) hr = IVBSAXContentHandler_endPrefixMapping( This->saxreader->vbcontentHandler, &Prefix); else hr = ISAXContentHandler_endPrefixMapping( This->saxreader->contentHandler, Prefix, SysStringLen(Prefix)); if(hr != S_OK) { format_error_message_from_id(This, hr); return; } } } update_position(This, NULL); } static void libxmlCharacters( void *ctx, const xmlChar *ch, int len) { saxlocator *This = ctx; BSTR Chars; HRESULT hr; xmlChar *cur; xmlChar *end; BOOL lastEvent = FALSE; if(!(has_content_handler(This))) return; cur = (xmlChar*)ch; if(*(ch-1)=='\r') cur--; end = cur; if(chpParserCtxt->input->base || ch>This->pParserCtxt->input->end) This->column++; while(1) { while(end-chsaxreader->pool, cur, end-cur+1); if(This->vbInterface) hr = IVBSAXContentHandler_characters( This->saxreader->vbcontentHandler, &Chars); else hr = ISAXContentHandler_characters( This->saxreader->contentHandler, Chars, SysStringLen(Chars)); if(hr != S_OK) { format_error_message_from_id(This, hr); return; } This->column += end-cur+1; if(lastEvent) break; *end = '\r'; end++; if(*end == '\n') { end++; This->column++; } cur = end; if(end-ch == len) break; } if(chpParserCtxt->input->base || ch>This->pParserCtxt->input->end) This->column = This->realColumn +This->pParserCtxt->input->cur-This->lastCur; } static void libxmlSetDocumentLocator( void *ctx, xmlSAXLocatorPtr loc) { saxlocator *This = ctx; HRESULT hr = S_OK; if(has_content_handler(This)) { if(This->vbInterface) hr = IVBSAXContentHandler_putref_documentLocator(This->saxreader->vbcontentHandler, &This->IVBSAXLocator_iface); else hr = ISAXContentHandler_putDocumentLocator(This->saxreader->contentHandler, &This->ISAXLocator_iface); } if(FAILED(hr)) format_error_message_from_id(This, hr); } static void libxmlComment(void *ctx, const xmlChar *value) { saxlocator *This = ctx; BSTR bValue; HRESULT hr; xmlChar *beg = (xmlChar*)This->pParserCtxt->input->cur; while(beg-4>=This->pParserCtxt->input->base && memcmp(beg-4, "