| /* | |
| * XSLTemplate/XSLProcessor support | |
| * | |
| * Copyright 2011 Nikolay Sivov for CodeWeavers | |
| * | |
| * 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 <stdarg.h> | |
| #ifdef HAVE_LIBXML2 | |
| # include <libxml/parser.h> | |
| # include <libxml/xmlerror.h> | |
| #endif | |
| #include "windef.h" | |
| #include "winbase.h" | |
| #include "winuser.h" | |
| #include "ole2.h" | |
| #include "msxml6.h" | |
| #include "msxml_private.h" | |
| #include "initguid.h" | |
| #include "asptlb.h" | |
| #include "wine/debug.h" | |
| WINE_DEFAULT_DEBUG_CHANNEL(msxml); | |
| typedef struct | |
| { | |
| DispatchEx dispex; | |
| IXSLTemplate IXSLTemplate_iface; | |
| LONG ref; | |
| IXMLDOMNode *node; | |
| } xsltemplate; | |
| enum output_type | |
| { | |
| PROCESSOR_OUTPUT_NOT_SET, | |
| PROCESSOR_OUTPUT_STREAM, /* IStream or ISequentialStream */ | |
| PROCESSOR_OUTPUT_PERSISTSTREAM, /* IPersistStream or IPersistStreamInit */ | |
| PROCESSOR_OUTPUT_RESPONSE, /* IResponse */ | |
| }; | |
| typedef struct | |
| { | |
| DispatchEx dispex; | |
| IXSLProcessor IXSLProcessor_iface; | |
| LONG ref; | |
| xsltemplate *stylesheet; | |
| IXMLDOMNode *input; | |
| union | |
| { | |
| IUnknown *unk; | |
| ISequentialStream *stream; | |
| IPersistStream *persiststream; | |
| IResponse *response; | |
| } output; | |
| enum output_type output_type; | |
| BSTR outstr; | |
| struct xslprocessor_params params; | |
| } xslprocessor; | |
| static HRESULT XSLProcessor_create(xsltemplate*, IXSLProcessor**); | |
| static inline xsltemplate *impl_from_IXSLTemplate( IXSLTemplate *iface ) | |
| { | |
| return CONTAINING_RECORD(iface, xsltemplate, IXSLTemplate_iface); | |
| } | |
| static inline xslprocessor *impl_from_IXSLProcessor( IXSLProcessor *iface ) | |
| { | |
| return CONTAINING_RECORD(iface, xslprocessor, IXSLProcessor_iface); | |
| } | |
| static void xslprocessor_par_free(struct xslprocessor_params *params, struct xslprocessor_par *par) | |
| { | |
| params->count--; | |
| list_remove(&par->entry); | |
| SysFreeString(par->name); | |
| SysFreeString(par->value); | |
| heap_free(par); | |
| } | |
| static void xsltemplate_set_node( xsltemplate *This, IXMLDOMNode *node ) | |
| { | |
| if (This->node) IXMLDOMNode_Release(This->node); | |
| This->node = node; | |
| if (node) IXMLDOMNode_AddRef(node); | |
| } | |
| static HRESULT WINAPI xsltemplate_QueryInterface( | |
| IXSLTemplate *iface, | |
| REFIID riid, | |
| void** ppvObject ) | |
| { | |
| xsltemplate *This = impl_from_IXSLTemplate( iface ); | |
| TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject); | |
| if ( IsEqualGUID( riid, &IID_IXSLTemplate ) || | |
| IsEqualGUID( riid, &IID_IDispatch ) || | |
| IsEqualGUID( riid, &IID_IUnknown ) ) | |
| { | |
| *ppvObject = iface; | |
| } | |
| else if (dispex_query_interface(&This->dispex, riid, ppvObject)) | |
| { | |
| return *ppvObject ? S_OK : E_NOINTERFACE; | |
| } | |
| else | |
| { | |
| FIXME("Unsupported interface %s\n", debugstr_guid(riid)); | |
| *ppvObject = NULL; | |
| return E_NOINTERFACE; | |
| } | |
| IUnknown_AddRef((IUnknown*)*ppvObject); | |
| return S_OK; | |
| } | |
| static ULONG WINAPI xsltemplate_AddRef( IXSLTemplate *iface ) | |
| { | |
| xsltemplate *This = impl_from_IXSLTemplate( iface ); | |
| ULONG ref = InterlockedIncrement( &This->ref ); | |
| TRACE("(%p)->(%d)\n", This, ref); | |
| return ref; | |
| } | |
| static ULONG WINAPI xsltemplate_Release( IXSLTemplate *iface ) | |
| { | |
| xsltemplate *This = impl_from_IXSLTemplate( iface ); | |
| ULONG ref = InterlockedDecrement( &This->ref ); | |
| TRACE("(%p)->(%d)\n", This, ref); | |
| if ( ref == 0 ) | |
| { | |
| if (This->node) IXMLDOMNode_Release( This->node ); | |
| heap_free( This ); | |
| } | |
| return ref; | |
| } | |
| static HRESULT WINAPI xsltemplate_GetTypeInfoCount( IXSLTemplate *iface, UINT* pctinfo ) | |
| { | |
| xsltemplate *This = impl_from_IXSLTemplate( iface ); | |
| return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo); | |
| } | |
| static HRESULT WINAPI xsltemplate_GetTypeInfo( | |
| IXSLTemplate *iface, | |
| UINT iTInfo, LCID lcid, | |
| ITypeInfo** ppTInfo ) | |
| { | |
| xsltemplate *This = impl_from_IXSLTemplate( iface ); | |
| return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, | |
| iTInfo, lcid, ppTInfo); | |
| } | |
| static HRESULT WINAPI xsltemplate_GetIDsOfNames( | |
| IXSLTemplate *iface, | |
| REFIID riid, LPOLESTR* rgszNames, | |
| UINT cNames, LCID lcid, DISPID* rgDispId ) | |
| { | |
| xsltemplate *This = impl_from_IXSLTemplate( iface ); | |
| return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, | |
| riid, rgszNames, cNames, lcid, rgDispId); | |
| } | |
| static HRESULT WINAPI xsltemplate_Invoke( | |
| IXSLTemplate *iface, | |
| DISPID dispIdMember, REFIID riid, LCID lcid, | |
| WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, | |
| EXCEPINFO* pExcepInfo, UINT* puArgErr ) | |
| { | |
| xsltemplate *This = impl_from_IXSLTemplate( iface ); | |
| return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, | |
| dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); | |
| } | |
| static HRESULT WINAPI xsltemplate_putref_stylesheet( IXSLTemplate *iface, | |
| IXMLDOMNode *node) | |
| { | |
| xsltemplate *This = impl_from_IXSLTemplate( iface ); | |
| TRACE("(%p)->(%p)\n", This, node); | |
| if (!node) | |
| { | |
| xsltemplate_set_node(This, NULL); | |
| return S_OK; | |
| } | |
| /* FIXME: test for document type */ | |
| xsltemplate_set_node(This, node); | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI xsltemplate_get_stylesheet( IXSLTemplate *iface, | |
| IXMLDOMNode **node) | |
| { | |
| xsltemplate *This = impl_from_IXSLTemplate( iface ); | |
| FIXME("(%p)->(%p): stub\n", This, node); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI xsltemplate_createProcessor( IXSLTemplate *iface, | |
| IXSLProcessor **processor) | |
| { | |
| xsltemplate *This = impl_from_IXSLTemplate( iface ); | |
| TRACE("(%p)->(%p)\n", This, processor); | |
| if (!processor) return E_INVALIDARG; | |
| return XSLProcessor_create(This, processor); | |
| } | |
| static const struct IXSLTemplateVtbl XSLTemplateVtbl = | |
| { | |
| xsltemplate_QueryInterface, | |
| xsltemplate_AddRef, | |
| xsltemplate_Release, | |
| xsltemplate_GetTypeInfoCount, | |
| xsltemplate_GetTypeInfo, | |
| xsltemplate_GetIDsOfNames, | |
| xsltemplate_Invoke, | |
| xsltemplate_putref_stylesheet, | |
| xsltemplate_get_stylesheet, | |
| xsltemplate_createProcessor | |
| }; | |
| static const tid_t xsltemplate_iface_tids[] = { | |
| IXSLTemplate_tid, | |
| 0 | |
| }; | |
| static dispex_static_data_t xsltemplate_dispex = { | |
| NULL, | |
| IXSLTemplate_tid, | |
| NULL, | |
| xsltemplate_iface_tids | |
| }; | |
| HRESULT XSLTemplate_create(void **ppObj) | |
| { | |
| xsltemplate *This; | |
| TRACE("(%p)\n", ppObj); | |
| This = heap_alloc( sizeof (*This) ); | |
| if(!This) | |
| return E_OUTOFMEMORY; | |
| This->IXSLTemplate_iface.lpVtbl = &XSLTemplateVtbl; | |
| This->ref = 1; | |
| This->node = NULL; | |
| init_dispex(&This->dispex, (IUnknown*)&This->IXSLTemplate_iface, &xsltemplate_dispex); | |
| *ppObj = &This->IXSLTemplate_iface; | |
| TRACE("returning iface %p\n", *ppObj); | |
| return S_OK; | |
| } | |
| /*** IXSLProcessor ***/ | |
| static HRESULT WINAPI xslprocessor_QueryInterface( | |
| IXSLProcessor *iface, | |
| REFIID riid, | |
| void** ppvObject ) | |
| { | |
| xslprocessor *This = impl_from_IXSLProcessor( iface ); | |
| TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject); | |
| if ( IsEqualGUID( riid, &IID_IXSLProcessor ) || | |
| IsEqualGUID( riid, &IID_IDispatch ) || | |
| IsEqualGUID( riid, &IID_IUnknown ) ) | |
| { | |
| *ppvObject = iface; | |
| } | |
| else if (dispex_query_interface(&This->dispex, riid, ppvObject)) | |
| { | |
| return *ppvObject ? S_OK : E_NOINTERFACE; | |
| } | |
| else | |
| { | |
| FIXME("Unsupported interface %s\n", debugstr_guid(riid)); | |
| *ppvObject = NULL; | |
| return E_NOINTERFACE; | |
| } | |
| IUnknown_AddRef((IUnknown*)*ppvObject); | |
| return S_OK; | |
| } | |
| static ULONG WINAPI xslprocessor_AddRef( IXSLProcessor *iface ) | |
| { | |
| xslprocessor *This = impl_from_IXSLProcessor( iface ); | |
| ULONG ref = InterlockedIncrement( &This->ref ); | |
| TRACE("(%p)->(%d)\n", This, ref); | |
| return ref; | |
| } | |
| static ULONG WINAPI xslprocessor_Release( IXSLProcessor *iface ) | |
| { | |
| xslprocessor *This = impl_from_IXSLProcessor( iface ); | |
| ULONG ref = InterlockedDecrement( &This->ref ); | |
| TRACE("(%p)->(%d)\n", This, ref); | |
| if ( ref == 0 ) | |
| { | |
| struct xslprocessor_par *par, *par2; | |
| if (This->input) IXMLDOMNode_Release(This->input); | |
| if (This->output.unk) | |
| IUnknown_Release(This->output.unk); | |
| SysFreeString(This->outstr); | |
| LIST_FOR_EACH_ENTRY_SAFE(par, par2, &This->params.list, struct xslprocessor_par, entry) | |
| xslprocessor_par_free(&This->params, par); | |
| IXSLTemplate_Release(&This->stylesheet->IXSLTemplate_iface); | |
| heap_free( This ); | |
| } | |
| return ref; | |
| } | |
| static HRESULT WINAPI xslprocessor_GetTypeInfoCount( IXSLProcessor *iface, UINT* pctinfo ) | |
| { | |
| xslprocessor *This = impl_from_IXSLProcessor( iface ); | |
| return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo); | |
| } | |
| static HRESULT WINAPI xslprocessor_GetTypeInfo( | |
| IXSLProcessor *iface, | |
| UINT iTInfo, LCID lcid, | |
| ITypeInfo** ppTInfo ) | |
| { | |
| xslprocessor *This = impl_from_IXSLProcessor( iface ); | |
| return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, | |
| iTInfo, lcid, ppTInfo); | |
| } | |
| static HRESULT WINAPI xslprocessor_GetIDsOfNames( | |
| IXSLProcessor *iface, | |
| REFIID riid, LPOLESTR* rgszNames, | |
| UINT cNames, LCID lcid, DISPID* rgDispId ) | |
| { | |
| xslprocessor *This = impl_from_IXSLProcessor( iface ); | |
| return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, | |
| riid, rgszNames, cNames, lcid, rgDispId); | |
| } | |
| static HRESULT WINAPI xslprocessor_Invoke( | |
| IXSLProcessor *iface, | |
| DISPID dispIdMember, REFIID riid, LCID lcid, | |
| WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, | |
| EXCEPINFO* pExcepInfo, UINT* puArgErr ) | |
| { | |
| xslprocessor *This = impl_from_IXSLProcessor( iface ); | |
| return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, | |
| dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); | |
| } | |
| static HRESULT WINAPI xslprocessor_put_input( IXSLProcessor *iface, VARIANT input ) | |
| { | |
| xslprocessor *This = impl_from_IXSLProcessor( iface ); | |
| IXMLDOMNode *input_node; | |
| HRESULT hr; | |
| TRACE("(%p)->(%s)\n", This, debugstr_variant(&input)); | |
| /* try IXMLDOMNode directly first */ | |
| if (V_VT(&input) == VT_UNKNOWN) | |
| hr = IUnknown_QueryInterface(V_UNKNOWN(&input), &IID_IXMLDOMNode, (void**)&input_node); | |
| else if (V_VT(&input) == VT_DISPATCH) | |
| hr = IDispatch_QueryInterface(V_DISPATCH(&input), &IID_IXMLDOMNode, (void**)&input_node); | |
| else | |
| { | |
| IXMLDOMDocument *doc; | |
| hr = DOMDocument_create(MSXML_DEFAULT, (void**)&doc); | |
| if (hr == S_OK) | |
| { | |
| VARIANT_BOOL b; | |
| hr = IXMLDOMDocument_load(doc, input, &b); | |
| if (hr == S_OK) | |
| hr = IXMLDOMDocument_QueryInterface(doc, &IID_IXMLDOMNode, (void**)&input_node); | |
| IXMLDOMDocument_Release(doc); | |
| } | |
| } | |
| if (hr == S_OK) | |
| { | |
| if (This->input) IXMLDOMNode_Release(This->input); | |
| This->input = input_node; | |
| } | |
| return hr; | |
| } | |
| static HRESULT WINAPI xslprocessor_get_input( IXSLProcessor *iface, VARIANT *input ) | |
| { | |
| xslprocessor *This = impl_from_IXSLProcessor( iface ); | |
| FIXME("(%p)->(%p): stub\n", This, input); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI xslprocessor_get_ownerTemplate( | |
| IXSLProcessor *iface, | |
| IXSLTemplate **template) | |
| { | |
| xslprocessor *This = impl_from_IXSLProcessor( iface ); | |
| FIXME("(%p)->(%p): stub\n", This, template); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI xslprocessor_setStartMode( | |
| IXSLProcessor *iface, | |
| BSTR p, | |
| BSTR uri) | |
| { | |
| xslprocessor *This = impl_from_IXSLProcessor( iface ); | |
| FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(p), debugstr_w(uri)); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI xslprocessor_get_startMode( | |
| IXSLProcessor *iface, | |
| BSTR *p) | |
| { | |
| xslprocessor *This = impl_from_IXSLProcessor( iface ); | |
| FIXME("(%p)->(%p): stub\n", This, p); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI xslprocessor_get_startModeURI( | |
| IXSLProcessor *iface, | |
| BSTR *uri) | |
| { | |
| xslprocessor *This = impl_from_IXSLProcessor( iface ); | |
| FIXME("(%p)->(%p): stub\n", This, uri); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI xslprocessor_put_output( | |
| IXSLProcessor *iface, | |
| VARIANT var) | |
| { | |
| xslprocessor *This = impl_from_IXSLProcessor( iface ); | |
| enum output_type output_type = PROCESSOR_OUTPUT_NOT_SET; | |
| IUnknown *output = NULL; | |
| HRESULT hr = S_OK; | |
| TRACE("(%p)->(%s)\n", This, debugstr_variant(&var)); | |
| switch (V_VT(&var)) | |
| { | |
| case VT_EMPTY: | |
| break; | |
| case VT_UNKNOWN: | |
| case VT_DISPATCH: | |
| if (!V_UNKNOWN(&var)) | |
| break; | |
| output_type = PROCESSOR_OUTPUT_STREAM; | |
| hr = IUnknown_QueryInterface(V_UNKNOWN(&var), &IID_IStream, (void **)&output); | |
| if (FAILED(hr)) | |
| hr = IUnknown_QueryInterface(V_UNKNOWN(&var), &IID_ISequentialStream, (void **)&output); | |
| if (FAILED(hr)) | |
| { | |
| output_type = PROCESSOR_OUTPUT_RESPONSE; | |
| hr = IUnknown_QueryInterface(V_UNKNOWN(&var), &IID_IResponse, (void **)&output); | |
| } | |
| if (FAILED(hr)) | |
| { | |
| output_type = PROCESSOR_OUTPUT_PERSISTSTREAM; | |
| hr = IUnknown_QueryInterface(V_UNKNOWN(&var), &IID_IPersistStream, (void **)&output); | |
| } | |
| if (FAILED(hr)) | |
| hr = IUnknown_QueryInterface(V_UNKNOWN(&var), &IID_IPersistStreamInit, (void **)&output); | |
| if (FAILED(hr)) | |
| { | |
| output_type = PROCESSOR_OUTPUT_NOT_SET; | |
| WARN("failed to get output interface, 0x%08x\n", hr); | |
| } | |
| break; | |
| default: | |
| FIXME("output type %d not handled\n", V_VT(&var)); | |
| hr = E_FAIL; | |
| } | |
| if (hr == S_OK) | |
| { | |
| if (This->output.unk) | |
| IUnknown_Release(This->output.unk); | |
| This->output.unk = output; | |
| This->output_type = output_type; | |
| } | |
| return hr; | |
| } | |
| static HRESULT WINAPI xslprocessor_get_output( | |
| IXSLProcessor *iface, | |
| VARIANT *output) | |
| { | |
| xslprocessor *This = impl_from_IXSLProcessor( iface ); | |
| TRACE("(%p)->(%p)\n", This, output); | |
| if (!output) return E_INVALIDARG; | |
| if (This->output.unk) | |
| { | |
| V_VT(output) = VT_UNKNOWN; | |
| V_UNKNOWN(output) = This->output.unk; | |
| IUnknown_AddRef(This->output.unk); | |
| } | |
| else if (This->outstr) | |
| { | |
| V_VT(output) = VT_BSTR; | |
| V_BSTR(output) = SysAllocString(This->outstr); | |
| } | |
| else | |
| V_VT(output) = VT_EMPTY; | |
| return S_OK; | |
| } | |
| static HRESULT WINAPI xslprocessor_transform( | |
| IXSLProcessor *iface, | |
| VARIANT_BOOL *ret) | |
| { | |
| #ifdef HAVE_LIBXML2 | |
| xslprocessor *This = impl_from_IXSLProcessor( iface ); | |
| ISequentialStream *stream = NULL; | |
| HRESULT hr; | |
| TRACE("(%p)->(%p)\n", This, ret); | |
| if (!ret) | |
| return E_INVALIDARG; | |
| if (This->output_type == PROCESSOR_OUTPUT_STREAM) | |
| { | |
| stream = This->output.stream; | |
| ISequentialStream_AddRef(stream); | |
| } | |
| else if (This->output_type == PROCESSOR_OUTPUT_PERSISTSTREAM || | |
| This->output_type == PROCESSOR_OUTPUT_RESPONSE) | |
| { | |
| if (FAILED(hr = CreateStreamOnHGlobal(NULL, TRUE, (IStream **)&stream))) | |
| return hr; | |
| } | |
| SysFreeString(This->outstr); | |
| hr = node_transform_node_params(get_node_obj(This->input), This->stylesheet->node, | |
| &This->outstr, stream, &This->params); | |
| if (SUCCEEDED(hr)) | |
| { | |
| IStream *src = (IStream *)stream; | |
| switch (This->output_type) | |
| { | |
| case PROCESSOR_OUTPUT_PERSISTSTREAM: | |
| { | |
| LARGE_INTEGER zero; | |
| /* for IPersistStream* output seekable stream is used */ | |
| zero.QuadPart = 0; | |
| IStream_Seek(src, zero, STREAM_SEEK_SET, NULL); | |
| hr = IPersistStream_Load(This->output.persiststream, src); | |
| break; | |
| } | |
| case PROCESSOR_OUTPUT_RESPONSE: | |
| { | |
| SAFEARRAYBOUND bound; | |
| SAFEARRAY *array; | |
| HGLOBAL hglobal; | |
| VARIANT bin; | |
| DWORD size; | |
| void *dest; | |
| if (FAILED(hr = GetHGlobalFromStream(src, &hglobal))) | |
| break; | |
| size = GlobalSize(hglobal); | |
| bound.lLbound = 0; | |
| bound.cElements = size; | |
| if (!(array = SafeArrayCreate(VT_UI1, 1, &bound))) | |
| break; | |
| V_VT(&bin) = VT_ARRAY | VT_UI1; | |
| V_ARRAY(&bin) = array; | |
| hr = SafeArrayAccessData(array, &dest); | |
| if (hr == S_OK) | |
| { | |
| void *data = GlobalLock(hglobal); | |
| memcpy(dest, data, size); | |
| GlobalUnlock(hglobal); | |
| SafeArrayUnaccessData(array); | |
| IResponse_BinaryWrite(This->output.response, bin); | |
| } | |
| VariantClear(&bin); | |
| break; | |
| } | |
| default: | |
| ; | |
| } | |
| } | |
| if (stream) | |
| ISequentialStream_Release(stream); | |
| *ret = hr == S_OK ? VARIANT_TRUE : VARIANT_FALSE; | |
| return hr; | |
| #else | |
| FIXME("libxml2 is required but wasn't present at compile time\n"); | |
| return E_NOTIMPL; | |
| #endif | |
| } | |
| static HRESULT WINAPI xslprocessor_reset( IXSLProcessor *iface ) | |
| { | |
| xslprocessor *This = impl_from_IXSLProcessor( iface ); | |
| FIXME("(%p): stub\n", This); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI xslprocessor_get_readyState( | |
| IXSLProcessor *iface, | |
| LONG *state) | |
| { | |
| xslprocessor *This = impl_from_IXSLProcessor( iface ); | |
| FIXME("(%p)->(%p): stub\n", This, state); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT xslprocessor_set_parvalue(const VARIANT *var, struct xslprocessor_par *par) | |
| { | |
| HRESULT hr = S_OK; | |
| switch (V_VT(var)) | |
| { | |
| case VT_BSTR: | |
| { | |
| par->value = SysAllocString(V_BSTR(var)); | |
| if (!par->value) hr = E_OUTOFMEMORY; | |
| break; | |
| } | |
| default: | |
| FIXME("value type %d not handled\n", V_VT(var)); | |
| hr = E_NOTIMPL; | |
| } | |
| return hr; | |
| } | |
| static HRESULT WINAPI xslprocessor_addParameter( | |
| IXSLProcessor *iface, | |
| BSTR p, | |
| VARIANT var, | |
| BSTR uri) | |
| { | |
| xslprocessor *This = impl_from_IXSLProcessor( iface ); | |
| struct xslprocessor_par *cur, *par = NULL; | |
| HRESULT hr; | |
| TRACE("(%p)->(%s %s %s)\n", This, debugstr_w(p), debugstr_variant(&var), | |
| debugstr_w(uri)); | |
| if (uri && *uri) | |
| FIXME("namespace uri is not supported\n"); | |
| /* search for existing parameter first */ | |
| LIST_FOR_EACH_ENTRY(cur, &This->params.list, struct xslprocessor_par, entry) | |
| { | |
| if (!strcmpW(cur->name, p)) | |
| { | |
| par = cur; | |
| break; | |
| } | |
| } | |
| /* override with new value or add new parameter */ | |
| if (par) | |
| { | |
| if (V_VT(&var) == VT_NULL || V_VT(&var) == VT_EMPTY) | |
| { | |
| /* remove parameter */ | |
| xslprocessor_par_free(&This->params, par); | |
| return S_OK; | |
| } | |
| SysFreeString(par->value); | |
| par->value = NULL; | |
| } | |
| else | |
| { | |
| /* new parameter */ | |
| par = heap_alloc(sizeof(struct xslprocessor_par)); | |
| if (!par) return E_OUTOFMEMORY; | |
| par->name = SysAllocString(p); | |
| if (!par->name) | |
| { | |
| heap_free(par); | |
| return E_OUTOFMEMORY; | |
| } | |
| list_add_tail(&This->params.list, &par->entry); | |
| This->params.count++; | |
| } | |
| hr = xslprocessor_set_parvalue(&var, par); | |
| if (FAILED(hr)) | |
| xslprocessor_par_free(&This->params, par); | |
| return hr; | |
| } | |
| static HRESULT WINAPI xslprocessor_addObject( | |
| IXSLProcessor *iface, | |
| IDispatch *obj, | |
| BSTR uri) | |
| { | |
| xslprocessor *This = impl_from_IXSLProcessor( iface ); | |
| FIXME("(%p)->(%p %s): stub\n", This, obj, debugstr_w(uri)); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI xslprocessor_get_stylesheet( | |
| IXSLProcessor *iface, | |
| IXMLDOMNode **node) | |
| { | |
| xslprocessor *This = impl_from_IXSLProcessor( iface ); | |
| FIXME("(%p)->(%p): stub\n", This, node); | |
| return E_NOTIMPL; | |
| } | |
| static const struct IXSLProcessorVtbl XSLProcessorVtbl = | |
| { | |
| xslprocessor_QueryInterface, | |
| xslprocessor_AddRef, | |
| xslprocessor_Release, | |
| xslprocessor_GetTypeInfoCount, | |
| xslprocessor_GetTypeInfo, | |
| xslprocessor_GetIDsOfNames, | |
| xslprocessor_Invoke, | |
| xslprocessor_put_input, | |
| xslprocessor_get_input, | |
| xslprocessor_get_ownerTemplate, | |
| xslprocessor_setStartMode, | |
| xslprocessor_get_startMode, | |
| xslprocessor_get_startModeURI, | |
| xslprocessor_put_output, | |
| xslprocessor_get_output, | |
| xslprocessor_transform, | |
| xslprocessor_reset, | |
| xslprocessor_get_readyState, | |
| xslprocessor_addParameter, | |
| xslprocessor_addObject, | |
| xslprocessor_get_stylesheet | |
| }; | |
| static const tid_t xslprocessor_iface_tids[] = { | |
| IXSLProcessor_tid, | |
| 0 | |
| }; | |
| static dispex_static_data_t xslprocessor_dispex = { | |
| NULL, | |
| IXSLProcessor_tid, | |
| NULL, | |
| xslprocessor_iface_tids | |
| }; | |
| HRESULT XSLProcessor_create(xsltemplate *template, IXSLProcessor **ppObj) | |
| { | |
| xslprocessor *This; | |
| TRACE("(%p)\n", ppObj); | |
| This = heap_alloc( sizeof (*This) ); | |
| if(!This) | |
| return E_OUTOFMEMORY; | |
| This->IXSLProcessor_iface.lpVtbl = &XSLProcessorVtbl; | |
| This->ref = 1; | |
| This->input = NULL; | |
| This->output.unk = NULL; | |
| This->output_type = PROCESSOR_OUTPUT_NOT_SET; | |
| This->outstr = NULL; | |
| list_init(&This->params.list); | |
| This->params.count = 0; | |
| This->stylesheet = template; | |
| IXSLTemplate_AddRef(&template->IXSLTemplate_iface); | |
| init_dispex(&This->dispex, (IUnknown*)&This->IXSLProcessor_iface, &xslprocessor_dispex); | |
| *ppObj = &This->IXSLProcessor_iface; | |
| TRACE("returning iface %p\n", *ppObj); | |
| return S_OK; | |
| } |