2 * XSLTemplate/XSLProcessor support
4 * Copyright 2011 Nikolay Sivov for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 # include <libxml/parser.h>
28 # include <libxml/xmlerror.h>
37 #include "msxml_private.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
49 IXSLTemplate IXSLTemplate_iface
;
57 PROCESSOR_OUTPUT_NOT_SET
,
58 PROCESSOR_OUTPUT_STREAM
, /* IStream or ISequentialStream */
59 PROCESSOR_OUTPUT_PERSISTSTREAM
, /* IPersistStream or IPersistStreamInit */
60 PROCESSOR_OUTPUT_RESPONSE
, /* IResponse */
66 IXSLProcessor IXSLProcessor_iface
;
69 xsltemplate
*stylesheet
;
75 ISequentialStream
*stream
;
76 IPersistStream
*persiststream
;
79 enum output_type output_type
;
82 struct xslprocessor_params params
;
85 static HRESULT
XSLProcessor_create(xsltemplate
*, IXSLProcessor
**);
87 static inline xsltemplate
*impl_from_IXSLTemplate( IXSLTemplate
*iface
)
89 return CONTAINING_RECORD(iface
, xsltemplate
, IXSLTemplate_iface
);
92 static inline xslprocessor
*impl_from_IXSLProcessor( IXSLProcessor
*iface
)
94 return CONTAINING_RECORD(iface
, xslprocessor
, IXSLProcessor_iface
);
97 static void xslprocessor_par_free(struct xslprocessor_params
*params
, struct xslprocessor_par
*par
)
100 list_remove(&par
->entry
);
101 SysFreeString(par
->name
);
102 SysFreeString(par
->value
);
106 static void xsltemplate_set_node( xsltemplate
*This
, IXMLDOMNode
*node
)
108 if (This
->node
) IXMLDOMNode_Release(This
->node
);
110 if (node
) IXMLDOMNode_AddRef(node
);
113 static HRESULT WINAPI
xsltemplate_QueryInterface(
118 xsltemplate
*This
= impl_from_IXSLTemplate( iface
);
119 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
121 if ( IsEqualGUID( riid
, &IID_IXSLTemplate
) ||
122 IsEqualGUID( riid
, &IID_IDispatch
) ||
123 IsEqualGUID( riid
, &IID_IUnknown
) )
127 else if (dispex_query_interface(&This
->dispex
, riid
, ppvObject
))
129 return *ppvObject
? S_OK
: E_NOINTERFACE
;
133 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
135 return E_NOINTERFACE
;
138 IUnknown_AddRef((IUnknown
*)*ppvObject
);
142 static ULONG WINAPI
xsltemplate_AddRef( IXSLTemplate
*iface
)
144 xsltemplate
*This
= impl_from_IXSLTemplate( iface
);
145 ULONG ref
= InterlockedIncrement( &This
->ref
);
146 TRACE("(%p)->(%d)\n", This
, ref
);
150 static ULONG WINAPI
xsltemplate_Release( IXSLTemplate
*iface
)
152 xsltemplate
*This
= impl_from_IXSLTemplate( iface
);
153 ULONG ref
= InterlockedDecrement( &This
->ref
);
155 TRACE("(%p)->(%d)\n", This
, ref
);
158 if (This
->node
) IXMLDOMNode_Release( This
->node
);
165 static HRESULT WINAPI
xsltemplate_GetTypeInfoCount( IXSLTemplate
*iface
, UINT
* pctinfo
)
167 xsltemplate
*This
= impl_from_IXSLTemplate( iface
);
168 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
171 static HRESULT WINAPI
xsltemplate_GetTypeInfo(
173 UINT iTInfo
, LCID lcid
,
174 ITypeInfo
** ppTInfo
)
176 xsltemplate
*This
= impl_from_IXSLTemplate( iface
);
177 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
,
178 iTInfo
, lcid
, ppTInfo
);
181 static HRESULT WINAPI
xsltemplate_GetIDsOfNames(
183 REFIID riid
, LPOLESTR
* rgszNames
,
184 UINT cNames
, LCID lcid
, DISPID
* rgDispId
)
186 xsltemplate
*This
= impl_from_IXSLTemplate( iface
);
187 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
,
188 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
191 static HRESULT WINAPI
xsltemplate_Invoke(
193 DISPID dispIdMember
, REFIID riid
, LCID lcid
,
194 WORD wFlags
, DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
195 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
197 xsltemplate
*This
= impl_from_IXSLTemplate( iface
);
198 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
,
199 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
202 static HRESULT WINAPI
xsltemplate_putref_stylesheet( IXSLTemplate
*iface
,
205 xsltemplate
*This
= impl_from_IXSLTemplate( iface
);
207 TRACE("(%p)->(%p)\n", This
, node
);
211 xsltemplate_set_node(This
, NULL
);
215 /* FIXME: test for document type */
216 xsltemplate_set_node(This
, node
);
221 static HRESULT WINAPI
xsltemplate_get_stylesheet( IXSLTemplate
*iface
,
224 xsltemplate
*This
= impl_from_IXSLTemplate( iface
);
226 FIXME("(%p)->(%p): stub\n", This
, node
);
230 static HRESULT WINAPI
xsltemplate_createProcessor( IXSLTemplate
*iface
,
231 IXSLProcessor
**processor
)
233 xsltemplate
*This
= impl_from_IXSLTemplate( iface
);
235 TRACE("(%p)->(%p)\n", This
, processor
);
237 if (!processor
) return E_INVALIDARG
;
239 return XSLProcessor_create(This
, processor
);
242 static const struct IXSLTemplateVtbl XSLTemplateVtbl
=
244 xsltemplate_QueryInterface
,
247 xsltemplate_GetTypeInfoCount
,
248 xsltemplate_GetTypeInfo
,
249 xsltemplate_GetIDsOfNames
,
251 xsltemplate_putref_stylesheet
,
252 xsltemplate_get_stylesheet
,
253 xsltemplate_createProcessor
256 static const tid_t xsltemplate_iface_tids
[] = {
261 static dispex_static_data_t xsltemplate_dispex
= {
265 xsltemplate_iface_tids
268 HRESULT
XSLTemplate_create(void **ppObj
)
272 TRACE("(%p)\n", ppObj
);
274 This
= heap_alloc( sizeof (*This
) );
276 return E_OUTOFMEMORY
;
278 This
->IXSLTemplate_iface
.lpVtbl
= &XSLTemplateVtbl
;
281 init_dispex(&This
->dispex
, (IUnknown
*)&This
->IXSLTemplate_iface
, &xsltemplate_dispex
);
283 *ppObj
= &This
->IXSLTemplate_iface
;
285 TRACE("returning iface %p\n", *ppObj
);
290 /*** IXSLProcessor ***/
291 static HRESULT WINAPI
xslprocessor_QueryInterface(
292 IXSLProcessor
*iface
,
296 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
297 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
299 if ( IsEqualGUID( riid
, &IID_IXSLProcessor
) ||
300 IsEqualGUID( riid
, &IID_IDispatch
) ||
301 IsEqualGUID( riid
, &IID_IUnknown
) )
305 else if (dispex_query_interface(&This
->dispex
, riid
, ppvObject
))
307 return *ppvObject
? S_OK
: E_NOINTERFACE
;
311 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
313 return E_NOINTERFACE
;
316 IUnknown_AddRef((IUnknown
*)*ppvObject
);
320 static ULONG WINAPI
xslprocessor_AddRef( IXSLProcessor
*iface
)
322 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
323 ULONG ref
= InterlockedIncrement( &This
->ref
);
324 TRACE("(%p)->(%d)\n", This
, ref
);
328 static ULONG WINAPI
xslprocessor_Release( IXSLProcessor
*iface
)
330 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
331 ULONG ref
= InterlockedDecrement( &This
->ref
);
333 TRACE("(%p)->(%d)\n", This
, ref
);
336 struct xslprocessor_par
*par
, *par2
;
338 if (This
->input
) IXMLDOMNode_Release(This
->input
);
339 if (This
->output
.unk
)
340 IUnknown_Release(This
->output
.unk
);
341 SysFreeString(This
->outstr
);
343 LIST_FOR_EACH_ENTRY_SAFE(par
, par2
, &This
->params
.list
, struct xslprocessor_par
, entry
)
344 xslprocessor_par_free(&This
->params
, par
);
346 IXSLTemplate_Release(&This
->stylesheet
->IXSLTemplate_iface
);
353 static HRESULT WINAPI
xslprocessor_GetTypeInfoCount( IXSLProcessor
*iface
, UINT
* pctinfo
)
355 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
356 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
359 static HRESULT WINAPI
xslprocessor_GetTypeInfo(
360 IXSLProcessor
*iface
,
361 UINT iTInfo
, LCID lcid
,
362 ITypeInfo
** ppTInfo
)
364 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
365 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
,
366 iTInfo
, lcid
, ppTInfo
);
369 static HRESULT WINAPI
xslprocessor_GetIDsOfNames(
370 IXSLProcessor
*iface
,
371 REFIID riid
, LPOLESTR
* rgszNames
,
372 UINT cNames
, LCID lcid
, DISPID
* rgDispId
)
374 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
375 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
,
376 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
379 static HRESULT WINAPI
xslprocessor_Invoke(
380 IXSLProcessor
*iface
,
381 DISPID dispIdMember
, REFIID riid
, LCID lcid
,
382 WORD wFlags
, DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
383 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
385 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
386 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
,
387 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
390 static HRESULT WINAPI
xslprocessor_put_input( IXSLProcessor
*iface
, VARIANT input
)
392 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
393 IXMLDOMNode
*input_node
;
396 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&input
));
398 /* try IXMLDOMNode directly first */
399 if (V_VT(&input
) == VT_UNKNOWN
)
400 hr
= IUnknown_QueryInterface(V_UNKNOWN(&input
), &IID_IXMLDOMNode
, (void**)&input_node
);
401 else if (V_VT(&input
) == VT_DISPATCH
)
402 hr
= IDispatch_QueryInterface(V_DISPATCH(&input
), &IID_IXMLDOMNode
, (void**)&input_node
);
405 IXMLDOMDocument
*doc
;
407 hr
= DOMDocument_create(MSXML_DEFAULT
, (void**)&doc
);
412 hr
= IXMLDOMDocument_load(doc
, input
, &b
);
414 hr
= IXMLDOMDocument_QueryInterface(doc
, &IID_IXMLDOMNode
, (void**)&input_node
);
415 IXMLDOMDocument_Release(doc
);
421 if (This
->input
) IXMLDOMNode_Release(This
->input
);
422 This
->input
= input_node
;
428 static HRESULT WINAPI
xslprocessor_get_input( IXSLProcessor
*iface
, VARIANT
*input
)
430 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
432 FIXME("(%p)->(%p): stub\n", This
, input
);
436 static HRESULT WINAPI
xslprocessor_get_ownerTemplate(
437 IXSLProcessor
*iface
,
438 IXSLTemplate
**template)
440 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
442 FIXME("(%p)->(%p): stub\n", This
, template);
446 static HRESULT WINAPI
xslprocessor_setStartMode(
447 IXSLProcessor
*iface
,
451 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
453 FIXME("(%p)->(%s %s): stub\n", This
, debugstr_w(p
), debugstr_w(uri
));
457 static HRESULT WINAPI
xslprocessor_get_startMode(
458 IXSLProcessor
*iface
,
461 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
463 FIXME("(%p)->(%p): stub\n", This
, p
);
467 static HRESULT WINAPI
xslprocessor_get_startModeURI(
468 IXSLProcessor
*iface
,
471 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
473 FIXME("(%p)->(%p): stub\n", This
, uri
);
477 static HRESULT WINAPI
xslprocessor_put_output(
478 IXSLProcessor
*iface
,
481 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
482 enum output_type output_type
= PROCESSOR_OUTPUT_NOT_SET
;
483 IUnknown
*output
= NULL
;
486 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&var
));
494 if (!V_UNKNOWN(&var
))
497 output_type
= PROCESSOR_OUTPUT_STREAM
;
498 hr
= IUnknown_QueryInterface(V_UNKNOWN(&var
), &IID_IStream
, (void **)&output
);
500 hr
= IUnknown_QueryInterface(V_UNKNOWN(&var
), &IID_ISequentialStream
, (void **)&output
);
503 output_type
= PROCESSOR_OUTPUT_RESPONSE
;
504 hr
= IUnknown_QueryInterface(V_UNKNOWN(&var
), &IID_IResponse
, (void **)&output
);
508 output_type
= PROCESSOR_OUTPUT_PERSISTSTREAM
;
509 hr
= IUnknown_QueryInterface(V_UNKNOWN(&var
), &IID_IPersistStream
, (void **)&output
);
512 hr
= IUnknown_QueryInterface(V_UNKNOWN(&var
), &IID_IPersistStreamInit
, (void **)&output
);
515 output_type
= PROCESSOR_OUTPUT_NOT_SET
;
516 WARN("failed to get output interface, 0x%08x\n", hr
);
520 FIXME("output type %d not handled\n", V_VT(&var
));
526 if (This
->output
.unk
)
527 IUnknown_Release(This
->output
.unk
);
528 This
->output
.unk
= output
;
529 This
->output_type
= output_type
;
535 static HRESULT WINAPI
xslprocessor_get_output(
536 IXSLProcessor
*iface
,
539 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
541 TRACE("(%p)->(%p)\n", This
, output
);
543 if (!output
) return E_INVALIDARG
;
545 if (This
->output
.unk
)
547 V_VT(output
) = VT_UNKNOWN
;
548 V_UNKNOWN(output
) = This
->output
.unk
;
549 IUnknown_AddRef(This
->output
.unk
);
551 else if (This
->outstr
)
553 V_VT(output
) = VT_BSTR
;
554 V_BSTR(output
) = SysAllocString(This
->outstr
);
557 V_VT(output
) = VT_EMPTY
;
562 static HRESULT WINAPI
xslprocessor_transform(
563 IXSLProcessor
*iface
,
567 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
568 ISequentialStream
*stream
= NULL
;
571 TRACE("(%p)->(%p)\n", This
, ret
);
576 if (This
->output_type
== PROCESSOR_OUTPUT_STREAM
)
578 stream
= This
->output
.stream
;
579 ISequentialStream_AddRef(stream
);
581 else if (This
->output_type
== PROCESSOR_OUTPUT_PERSISTSTREAM
||
582 This
->output_type
== PROCESSOR_OUTPUT_RESPONSE
)
584 if (FAILED(hr
= CreateStreamOnHGlobal(NULL
, TRUE
, (IStream
**)&stream
)))
588 SysFreeString(This
->outstr
);
590 hr
= node_transform_node_params(get_node_obj(This
->input
), This
->stylesheet
->node
,
591 &This
->outstr
, stream
, &This
->params
);
594 IStream
*src
= (IStream
*)stream
;
596 switch (This
->output_type
)
598 case PROCESSOR_OUTPUT_PERSISTSTREAM
:
602 /* for IPersistStream* output seekable stream is used */
604 IStream_Seek(src
, zero
, STREAM_SEEK_SET
, NULL
);
605 hr
= IPersistStream_Load(This
->output
.persiststream
, src
);
608 case PROCESSOR_OUTPUT_RESPONSE
:
610 SAFEARRAYBOUND bound
;
617 if (FAILED(hr
= GetHGlobalFromStream(src
, &hglobal
)))
619 size
= GlobalSize(hglobal
);
622 bound
.cElements
= size
;
623 if (!(array
= SafeArrayCreate(VT_UI1
, 1, &bound
)))
626 V_VT(&bin
) = VT_ARRAY
| VT_UI1
;
627 V_ARRAY(&bin
) = array
;
629 hr
= SafeArrayAccessData(array
, &dest
);
632 void *data
= GlobalLock(hglobal
);
633 memcpy(dest
, data
, size
);
634 GlobalUnlock(hglobal
);
635 SafeArrayUnaccessData(array
);
637 IResponse_BinaryWrite(This
->output
.response
, bin
);
649 ISequentialStream_Release(stream
);
651 *ret
= hr
== S_OK
? VARIANT_TRUE
: VARIANT_FALSE
;
654 FIXME("libxml2 is required but wasn't present at compile time\n");
659 static HRESULT WINAPI
xslprocessor_reset( IXSLProcessor
*iface
)
661 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
663 FIXME("(%p): stub\n", This
);
667 static HRESULT WINAPI
xslprocessor_get_readyState(
668 IXSLProcessor
*iface
,
671 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
673 FIXME("(%p)->(%p): stub\n", This
, state
);
677 static HRESULT
xslprocessor_set_parvalue(const VARIANT
*var
, struct xslprocessor_par
*par
)
685 par
->value
= SysAllocString(V_BSTR(var
));
686 if (!par
->value
) hr
= E_OUTOFMEMORY
;
690 FIXME("value type %d not handled\n", V_VT(var
));
697 static HRESULT WINAPI
xslprocessor_addParameter(
698 IXSLProcessor
*iface
,
703 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
704 struct xslprocessor_par
*cur
, *par
= NULL
;
707 TRACE("(%p)->(%s %s %s)\n", This
, debugstr_w(p
), debugstr_variant(&var
),
711 FIXME("namespace uri is not supported\n");
713 /* search for existing parameter first */
714 LIST_FOR_EACH_ENTRY(cur
, &This
->params
.list
, struct xslprocessor_par
, entry
)
716 if (!strcmpW(cur
->name
, p
))
723 /* override with new value or add new parameter */
726 if (V_VT(&var
) == VT_NULL
|| V_VT(&var
) == VT_EMPTY
)
728 /* remove parameter */
729 xslprocessor_par_free(&This
->params
, par
);
732 SysFreeString(par
->value
);
738 par
= heap_alloc(sizeof(struct xslprocessor_par
));
739 if (!par
) return E_OUTOFMEMORY
;
741 par
->name
= SysAllocString(p
);
745 return E_OUTOFMEMORY
;
747 list_add_tail(&This
->params
.list
, &par
->entry
);
748 This
->params
.count
++;
751 hr
= xslprocessor_set_parvalue(&var
, par
);
753 xslprocessor_par_free(&This
->params
, par
);
758 static HRESULT WINAPI
xslprocessor_addObject(
759 IXSLProcessor
*iface
,
763 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
765 FIXME("(%p)->(%p %s): stub\n", This
, obj
, debugstr_w(uri
));
769 static HRESULT WINAPI
xslprocessor_get_stylesheet(
770 IXSLProcessor
*iface
,
773 xslprocessor
*This
= impl_from_IXSLProcessor( iface
);
775 FIXME("(%p)->(%p): stub\n", This
, node
);
779 static const struct IXSLProcessorVtbl XSLProcessorVtbl
=
781 xslprocessor_QueryInterface
,
783 xslprocessor_Release
,
784 xslprocessor_GetTypeInfoCount
,
785 xslprocessor_GetTypeInfo
,
786 xslprocessor_GetIDsOfNames
,
788 xslprocessor_put_input
,
789 xslprocessor_get_input
,
790 xslprocessor_get_ownerTemplate
,
791 xslprocessor_setStartMode
,
792 xslprocessor_get_startMode
,
793 xslprocessor_get_startModeURI
,
794 xslprocessor_put_output
,
795 xslprocessor_get_output
,
796 xslprocessor_transform
,
798 xslprocessor_get_readyState
,
799 xslprocessor_addParameter
,
800 xslprocessor_addObject
,
801 xslprocessor_get_stylesheet
804 static const tid_t xslprocessor_iface_tids
[] = {
809 static dispex_static_data_t xslprocessor_dispex
= {
813 xslprocessor_iface_tids
816 HRESULT
XSLProcessor_create(xsltemplate
*template, IXSLProcessor
**ppObj
)
820 TRACE("(%p)\n", ppObj
);
822 This
= heap_alloc( sizeof (*This
) );
824 return E_OUTOFMEMORY
;
826 This
->IXSLProcessor_iface
.lpVtbl
= &XSLProcessorVtbl
;
829 This
->output
.unk
= NULL
;
830 This
->output_type
= PROCESSOR_OUTPUT_NOT_SET
;
832 list_init(&This
->params
.list
);
833 This
->params
.count
= 0;
834 This
->stylesheet
= template;
835 IXSLTemplate_AddRef(&template->IXSLTemplate_iface
);
836 init_dispex(&This
->dispex
, (IUnknown
*)&This
->IXSLProcessor_iface
, &xslprocessor_dispex
);
838 *ppObj
= &This
->IXSLProcessor_iface
;
840 TRACE("returning iface %p\n", *ppObj
);