/* * 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 #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 #include #include 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; } 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); } 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 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 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 nIndex, const WCHAR **pUrl, int *pUriSize) { saxattributes *This = impl_from_ISAXAttributes( iface ); TRACE("(%p)->(%d)\n", This, nIndex); if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG; if(!pUrl || !pUriSize) return E_POINTER; *pUriSize = SysStringLen(This->szURI[nIndex]); *pUrl = This->szURI[nIndex]; 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 nIndex, const WCHAR **pUri, int *pUriLength, const WCHAR **pLocalName, int *pLocalNameSize, 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(!pUri || !pUriLength || !pLocalName || !pLocalNameSize || !pQName || !pQNameLength) return E_POINTER; *pUriLength = SysStringLen(This->szURI[nIndex]); *pUri = This->szURI[nIndex]; *pLocalNameSize = SysStringLen(This->szLocalname[nIndex]); *pLocalName = This->szLocalname[nIndex]; *pQNameLength = SysStringLen(This->szQName[nIndex]); *pQName = This->szQName[nIndex]; 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 nIndex, const WCHAR **pValue, int *nValue) { saxattributes *This = impl_from_ISAXAttributes( iface ); TRACE("(%p)->(%d)\n", This, nIndex); if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG; if(!pValue || !nValue) return E_POINTER; *nValue = SysStringLen(This->szValue[nIndex]); *pValue = This->szValue[nIndex]; 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; indexvbInterface) hr = IVBSAXContentHandler_startPrefixMapping( This->saxreader->vbcontentHandler, &Prefix, &Uri); else hr = ISAXContentHandler_startPrefixMapping( This->saxreader->contentHandler, Prefix, SysStringLen(Prefix), Uri, SysStringLen(Uri)); SysFreeString(Prefix); SysFreeString(Uri); if(hr != S_OK) { format_error_message_from_id(This, hr); return; } } NamespaceUri = bstr_from_xmlChar(URI); LocalName = bstr_from_xmlChar(localname); QName = QName_from_xmlChar(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); } SysFreeString(NamespaceUri); SysFreeString(LocalName); SysFreeString(QName); } 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 = bstr_from_xmlChar(URI); LocalName = bstr_from_xmlChar(localname); QName = QName_from_xmlChar(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)); SysFreeString(NamespaceUri); SysFreeString(LocalName); SysFreeString(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 = bstr_from_xmlChar(This->pParserCtxt->nsTab[index]); if(This->vbInterface) hr = IVBSAXContentHandler_endPrefixMapping( This->saxreader->vbcontentHandler, &Prefix); else hr = ISAXContentHandler_endPrefixMapping( This->saxreader->contentHandler, Prefix, SysStringLen(Prefix)); SysFreeString(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-chvbInterface) hr = IVBSAXContentHandler_characters( This->saxreader->vbcontentHandler, &Chars); else hr = ISAXContentHandler_characters( This->saxreader->contentHandler, Chars, SysStringLen(Chars)); SysFreeString(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, "