msxml3: Pass XSL processor parameters to libxml2.
[wine.git] / dlls / msxml3 / stylesheet.c
blob8073dde34980c09d578aa916177c64fb3ea3037f
1 /*
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
21 #define COBJMACROS
23 #include "config.h"
25 #include <stdarg.h>
26 #ifdef HAVE_LIBXML2
27 # include <libxml/parser.h>
28 # include <libxml/xmlerror.h>
29 #endif
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winuser.h"
34 #include "ole2.h"
35 #include "msxml6.h"
37 #include "msxml_private.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
43 typedef struct
45 DispatchEx dispex;
46 IXSLTemplate IXSLTemplate_iface;
47 LONG ref;
49 IXMLDOMNode *node;
50 } xsltemplate;
52 typedef struct
54 DispatchEx dispex;
55 IXSLProcessor IXSLProcessor_iface;
56 LONG ref;
58 xsltemplate *stylesheet;
59 IXMLDOMNode *input;
61 IStream *output;
62 BSTR outstr;
64 struct xslprocessor_params params;
65 } xslprocessor;
67 static HRESULT XSLProcessor_create(xsltemplate*, IXSLProcessor**);
69 static inline xsltemplate *impl_from_IXSLTemplate( IXSLTemplate *iface )
71 return CONTAINING_RECORD(iface, xsltemplate, IXSLTemplate_iface);
74 static inline xslprocessor *impl_from_IXSLProcessor( IXSLProcessor *iface )
76 return CONTAINING_RECORD(iface, xslprocessor, IXSLProcessor_iface);
79 static void xslprocessor_par_free(struct xslprocessor_params *params, struct xslprocessor_par *par)
81 params->count--;
82 list_remove(&par->entry);
83 SysFreeString(par->name);
84 SysFreeString(par->value);
85 heap_free(par);
88 static void xsltemplate_set_node( xsltemplate *This, IXMLDOMNode *node )
90 if (This->node) IXMLDOMNode_Release(This->node);
91 This->node = node;
92 if (node) IXMLDOMNode_AddRef(node);
95 static HRESULT WINAPI xsltemplate_QueryInterface(
96 IXSLTemplate *iface,
97 REFIID riid,
98 void** ppvObject )
100 xsltemplate *This = impl_from_IXSLTemplate( iface );
101 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
103 if ( IsEqualGUID( riid, &IID_IXSLTemplate ) ||
104 IsEqualGUID( riid, &IID_IDispatch ) ||
105 IsEqualGUID( riid, &IID_IUnknown ) )
107 *ppvObject = iface;
109 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
111 return *ppvObject ? S_OK : E_NOINTERFACE;
113 else
115 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
116 *ppvObject = NULL;
117 return E_NOINTERFACE;
120 IUnknown_AddRef((IUnknown*)*ppvObject);
121 return S_OK;
124 static ULONG WINAPI xsltemplate_AddRef( IXSLTemplate *iface )
126 xsltemplate *This = impl_from_IXSLTemplate( iface );
127 ULONG ref = InterlockedIncrement( &This->ref );
128 TRACE("(%p)->(%d)\n", This, ref);
129 return ref;
132 static ULONG WINAPI xsltemplate_Release( IXSLTemplate *iface )
134 xsltemplate *This = impl_from_IXSLTemplate( iface );
135 ULONG ref = InterlockedDecrement( &This->ref );
137 TRACE("(%p)->(%d)\n", This, ref);
138 if ( ref == 0 )
140 if (This->node) IXMLDOMNode_Release( This->node );
141 release_dispex(&This->dispex);
142 heap_free( This );
145 return ref;
148 static HRESULT WINAPI xsltemplate_GetTypeInfoCount( IXSLTemplate *iface, UINT* pctinfo )
150 xsltemplate *This = impl_from_IXSLTemplate( iface );
151 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
154 static HRESULT WINAPI xsltemplate_GetTypeInfo(
155 IXSLTemplate *iface,
156 UINT iTInfo, LCID lcid,
157 ITypeInfo** ppTInfo )
159 xsltemplate *This = impl_from_IXSLTemplate( iface );
160 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
161 iTInfo, lcid, ppTInfo);
164 static HRESULT WINAPI xsltemplate_GetIDsOfNames(
165 IXSLTemplate *iface,
166 REFIID riid, LPOLESTR* rgszNames,
167 UINT cNames, LCID lcid, DISPID* rgDispId )
169 xsltemplate *This = impl_from_IXSLTemplate( iface );
170 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
171 riid, rgszNames, cNames, lcid, rgDispId);
174 static HRESULT WINAPI xsltemplate_Invoke(
175 IXSLTemplate *iface,
176 DISPID dispIdMember, REFIID riid, LCID lcid,
177 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
178 EXCEPINFO* pExcepInfo, UINT* puArgErr )
180 xsltemplate *This = impl_from_IXSLTemplate( iface );
181 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
182 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
185 static HRESULT WINAPI xsltemplate_putref_stylesheet( IXSLTemplate *iface,
186 IXMLDOMNode *node)
188 xsltemplate *This = impl_from_IXSLTemplate( iface );
190 TRACE("(%p)->(%p)\n", This, node);
192 if (!node)
194 xsltemplate_set_node(This, NULL);
195 return S_OK;
198 /* FIXME: test for document type */
199 xsltemplate_set_node(This, node);
201 return S_OK;
204 static HRESULT WINAPI xsltemplate_get_stylesheet( IXSLTemplate *iface,
205 IXMLDOMNode **node)
207 xsltemplate *This = impl_from_IXSLTemplate( iface );
209 FIXME("(%p)->(%p): stub\n", This, node);
210 return E_NOTIMPL;
213 static HRESULT WINAPI xsltemplate_createProcessor( IXSLTemplate *iface,
214 IXSLProcessor **processor)
216 xsltemplate *This = impl_from_IXSLTemplate( iface );
218 TRACE("(%p)->(%p)\n", This, processor);
220 if (!processor) return E_INVALIDARG;
222 return XSLProcessor_create(This, processor);
225 static const struct IXSLTemplateVtbl XSLTemplateVtbl =
227 xsltemplate_QueryInterface,
228 xsltemplate_AddRef,
229 xsltemplate_Release,
230 xsltemplate_GetTypeInfoCount,
231 xsltemplate_GetTypeInfo,
232 xsltemplate_GetIDsOfNames,
233 xsltemplate_Invoke,
234 xsltemplate_putref_stylesheet,
235 xsltemplate_get_stylesheet,
236 xsltemplate_createProcessor
239 static const tid_t xsltemplate_iface_tids[] = {
240 IXSLTemplate_tid,
244 static dispex_static_data_t xsltemplate_dispex = {
245 NULL,
246 IXSLTemplate_tid,
247 NULL,
248 xsltemplate_iface_tids
251 HRESULT XSLTemplate_create(void **ppObj)
253 xsltemplate *This;
255 TRACE("(%p)\n", ppObj);
257 This = heap_alloc( sizeof (*This) );
258 if(!This)
259 return E_OUTOFMEMORY;
261 This->IXSLTemplate_iface.lpVtbl = &XSLTemplateVtbl;
262 This->ref = 1;
263 This->node = NULL;
264 init_dispex(&This->dispex, (IUnknown*)&This->IXSLTemplate_iface, &xsltemplate_dispex);
266 *ppObj = &This->IXSLTemplate_iface;
268 TRACE("returning iface %p\n", *ppObj);
270 return S_OK;
273 /*** IXSLProcessor ***/
274 static HRESULT WINAPI xslprocessor_QueryInterface(
275 IXSLProcessor *iface,
276 REFIID riid,
277 void** ppvObject )
279 xslprocessor *This = impl_from_IXSLProcessor( iface );
280 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
282 if ( IsEqualGUID( riid, &IID_IXSLProcessor ) ||
283 IsEqualGUID( riid, &IID_IDispatch ) ||
284 IsEqualGUID( riid, &IID_IUnknown ) )
286 *ppvObject = iface;
288 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
290 return *ppvObject ? S_OK : E_NOINTERFACE;
292 else
294 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
295 *ppvObject = NULL;
296 return E_NOINTERFACE;
299 IUnknown_AddRef((IUnknown*)*ppvObject);
300 return S_OK;
303 static ULONG WINAPI xslprocessor_AddRef( IXSLProcessor *iface )
305 xslprocessor *This = impl_from_IXSLProcessor( iface );
306 ULONG ref = InterlockedIncrement( &This->ref );
307 TRACE("(%p)->(%d)\n", This, ref);
308 return ref;
311 static ULONG WINAPI xslprocessor_Release( IXSLProcessor *iface )
313 xslprocessor *This = impl_from_IXSLProcessor( iface );
314 ULONG ref = InterlockedDecrement( &This->ref );
316 TRACE("(%p)->(%d)\n", This, ref);
317 if ( ref == 0 )
319 struct xslprocessor_par *par, *par2;
321 if (This->input) IXMLDOMNode_Release(This->input);
322 if (This->output) IStream_Release(This->output);
323 SysFreeString(This->outstr);
325 LIST_FOR_EACH_ENTRY_SAFE(par, par2, &This->params.list, struct xslprocessor_par, entry)
326 xslprocessor_par_free(&This->params, par);
328 IXSLTemplate_Release(&This->stylesheet->IXSLTemplate_iface);
329 release_dispex(&This->dispex);
330 heap_free( This );
333 return ref;
336 static HRESULT WINAPI xslprocessor_GetTypeInfoCount( IXSLProcessor *iface, UINT* pctinfo )
338 xslprocessor *This = impl_from_IXSLProcessor( iface );
339 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
342 static HRESULT WINAPI xslprocessor_GetTypeInfo(
343 IXSLProcessor *iface,
344 UINT iTInfo, LCID lcid,
345 ITypeInfo** ppTInfo )
347 xslprocessor *This = impl_from_IXSLProcessor( iface );
348 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
349 iTInfo, lcid, ppTInfo);
352 static HRESULT WINAPI xslprocessor_GetIDsOfNames(
353 IXSLProcessor *iface,
354 REFIID riid, LPOLESTR* rgszNames,
355 UINT cNames, LCID lcid, DISPID* rgDispId )
357 xslprocessor *This = impl_from_IXSLProcessor( iface );
358 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
359 riid, rgszNames, cNames, lcid, rgDispId);
362 static HRESULT WINAPI xslprocessor_Invoke(
363 IXSLProcessor *iface,
364 DISPID dispIdMember, REFIID riid, LCID lcid,
365 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
366 EXCEPINFO* pExcepInfo, UINT* puArgErr )
368 xslprocessor *This = impl_from_IXSLProcessor( iface );
369 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
370 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
373 static HRESULT WINAPI xslprocessor_put_input( IXSLProcessor *iface, VARIANT input )
375 xslprocessor *This = impl_from_IXSLProcessor( iface );
376 IXMLDOMNode *input_node;
377 HRESULT hr;
379 TRACE("(%p)->(%s)\n", This, debugstr_variant(&input));
381 /* try IXMLDOMNode directly first */
382 if (V_VT(&input) == VT_UNKNOWN)
383 hr = IUnknown_QueryInterface(V_UNKNOWN(&input), &IID_IXMLDOMNode, (void**)&input_node);
384 else if (V_VT(&input) == VT_DISPATCH)
385 hr = IDispatch_QueryInterface(V_DISPATCH(&input), &IID_IXMLDOMNode, (void**)&input_node);
386 else
388 IXMLDOMDocument *doc;
390 hr = DOMDocument_create(MSXML_DEFAULT, (void**)&doc);
391 if (hr == S_OK)
393 VARIANT_BOOL b;
395 hr = IXMLDOMDocument_load(doc, input, &b);
396 if (hr == S_OK)
397 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IXMLDOMNode, (void**)&input_node);
398 IXMLDOMDocument_Release(doc);
402 if (hr == S_OK)
404 if (This->input) IXMLDOMNode_Release(This->input);
405 This->input = input_node;
408 return hr;
411 static HRESULT WINAPI xslprocessor_get_input( IXSLProcessor *iface, VARIANT *input )
413 xslprocessor *This = impl_from_IXSLProcessor( iface );
415 FIXME("(%p)->(%p): stub\n", This, input);
416 return E_NOTIMPL;
419 static HRESULT WINAPI xslprocessor_get_ownerTemplate(
420 IXSLProcessor *iface,
421 IXSLTemplate **template)
423 xslprocessor *This = impl_from_IXSLProcessor( iface );
425 FIXME("(%p)->(%p): stub\n", This, template);
426 return E_NOTIMPL;
429 static HRESULT WINAPI xslprocessor_setStartMode(
430 IXSLProcessor *iface,
431 BSTR p,
432 BSTR uri)
434 xslprocessor *This = impl_from_IXSLProcessor( iface );
436 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(p), debugstr_w(uri));
437 return E_NOTIMPL;
440 static HRESULT WINAPI xslprocessor_get_startMode(
441 IXSLProcessor *iface,
442 BSTR *p)
444 xslprocessor *This = impl_from_IXSLProcessor( iface );
446 FIXME("(%p)->(%p): stub\n", This, p);
447 return E_NOTIMPL;
450 static HRESULT WINAPI xslprocessor_get_startModeURI(
451 IXSLProcessor *iface,
452 BSTR *uri)
454 xslprocessor *This = impl_from_IXSLProcessor( iface );
456 FIXME("(%p)->(%p): stub\n", This, uri);
457 return E_NOTIMPL;
460 static HRESULT WINAPI xslprocessor_put_output(
461 IXSLProcessor *iface,
462 VARIANT output)
464 xslprocessor *This = impl_from_IXSLProcessor( iface );
465 IStream *stream;
466 HRESULT hr;
468 FIXME("(%p)->(%s): semi-stub\n", This, debugstr_variant(&output));
470 switch (V_VT(&output))
472 case VT_EMPTY:
473 stream = NULL;
474 hr = S_OK;
475 break;
476 case VT_UNKNOWN:
477 hr = IUnknown_QueryInterface(V_UNKNOWN(&output), &IID_IStream, (void**)&stream);
478 break;
479 default:
480 hr = E_FAIL;
483 if (hr == S_OK)
485 if (This->output) IStream_Release(This->output);
486 This->output = stream;
489 return hr;
492 static HRESULT WINAPI xslprocessor_get_output(
493 IXSLProcessor *iface,
494 VARIANT *output)
496 xslprocessor *This = impl_from_IXSLProcessor( iface );
498 TRACE("(%p)->(%p)\n", This, output);
500 if (!output) return E_INVALIDARG;
502 if (This->output)
504 V_VT(output) = VT_UNKNOWN;
505 V_UNKNOWN(output) = (IUnknown*)This->output;
506 IStream_AddRef(This->output);
508 else if (This->outstr)
510 V_VT(output) = VT_BSTR;
511 V_BSTR(output) = SysAllocString(This->outstr);
513 else
514 V_VT(output) = VT_EMPTY;
516 return S_OK;
519 static HRESULT WINAPI xslprocessor_transform(
520 IXSLProcessor *iface,
521 VARIANT_BOOL *ret)
523 #ifdef HAVE_LIBXML2
524 xslprocessor *This = impl_from_IXSLProcessor( iface );
525 HRESULT hr;
527 TRACE("(%p)->(%p)\n", This, ret);
529 if (!ret) return E_INVALIDARG;
531 SysFreeString(This->outstr);
533 hr = node_transform_node_params(get_node_obj(This->input), This->stylesheet->node, &This->outstr, &This->params);
534 if (hr == S_OK)
536 if (This->output)
538 ULONG len = 0;
540 /* output to stream */
541 hr = IStream_Write(This->output, This->outstr, SysStringByteLen(This->outstr), &len);
542 *ret = len == SysStringByteLen(This->outstr) ? VARIANT_TRUE : VARIANT_FALSE;
545 else
546 *ret = VARIANT_FALSE;
548 return hr;
549 #else
550 FIXME("libxml2 is required but wasn't present at compile time\n");
551 return E_NOTIMPL;
552 #endif
555 static HRESULT WINAPI xslprocessor_reset( IXSLProcessor *iface )
557 xslprocessor *This = impl_from_IXSLProcessor( iface );
559 FIXME("(%p): stub\n", This);
560 return E_NOTIMPL;
563 static HRESULT WINAPI xslprocessor_get_readyState(
564 IXSLProcessor *iface,
565 LONG *state)
567 xslprocessor *This = impl_from_IXSLProcessor( iface );
569 FIXME("(%p)->(%p): stub\n", This, state);
570 return E_NOTIMPL;
573 static HRESULT xslprocessor_set_parvalue(const VARIANT *var, struct xslprocessor_par *par)
575 HRESULT hr = S_OK;
577 switch (V_VT(var))
579 case VT_BSTR:
581 par->value = SysAllocString(V_BSTR(var));
582 if (!par->value) hr = E_OUTOFMEMORY;
583 break;
585 default:
586 FIXME("value type %d not handled\n", V_VT(var));
587 hr = E_NOTIMPL;
590 return hr;
593 static HRESULT WINAPI xslprocessor_addParameter(
594 IXSLProcessor *iface,
595 BSTR p,
596 VARIANT var,
597 BSTR uri)
599 xslprocessor *This = impl_from_IXSLProcessor( iface );
600 struct xslprocessor_par *cur, *par = NULL;
601 HRESULT hr;
603 TRACE("(%p)->(%s %s %s)\n", This, debugstr_w(p), debugstr_variant(&var),
604 debugstr_w(uri));
606 if (uri && *uri)
607 FIXME("namespace uri is not supported\n");
609 /* search for existing parameter first */
610 LIST_FOR_EACH_ENTRY(cur, &This->params.list, struct xslprocessor_par, entry)
612 if (!strcmpW(cur->name, p))
614 par = cur;
615 break;
619 /* override with new value or add new parameter */
620 if (par)
622 if (V_VT(&var) == VT_NULL || V_VT(&var) == VT_EMPTY)
624 /* remove parameter */
625 xslprocessor_par_free(&This->params, par);
626 return S_OK;
628 SysFreeString(par->value);
629 par->value = NULL;
631 else
633 /* new parameter */
634 par = heap_alloc(sizeof(struct xslprocessor_par));
635 if (!par) return E_OUTOFMEMORY;
637 par->name = SysAllocString(p);
638 if (!par->name)
640 heap_free(par);
641 return E_OUTOFMEMORY;
643 list_add_tail(&This->params.list, &par->entry);
644 This->params.count++;
647 hr = xslprocessor_set_parvalue(&var, par);
648 if (FAILED(hr))
649 xslprocessor_par_free(&This->params, par);
651 return hr;
654 static HRESULT WINAPI xslprocessor_addObject(
655 IXSLProcessor *iface,
656 IDispatch *obj,
657 BSTR uri)
659 xslprocessor *This = impl_from_IXSLProcessor( iface );
661 FIXME("(%p)->(%p %s): stub\n", This, obj, debugstr_w(uri));
662 return E_NOTIMPL;
665 static HRESULT WINAPI xslprocessor_get_stylesheet(
666 IXSLProcessor *iface,
667 IXMLDOMNode **node)
669 xslprocessor *This = impl_from_IXSLProcessor( iface );
671 FIXME("(%p)->(%p): stub\n", This, node);
672 return E_NOTIMPL;
675 static const struct IXSLProcessorVtbl XSLProcessorVtbl =
677 xslprocessor_QueryInterface,
678 xslprocessor_AddRef,
679 xslprocessor_Release,
680 xslprocessor_GetTypeInfoCount,
681 xslprocessor_GetTypeInfo,
682 xslprocessor_GetIDsOfNames,
683 xslprocessor_Invoke,
684 xslprocessor_put_input,
685 xslprocessor_get_input,
686 xslprocessor_get_ownerTemplate,
687 xslprocessor_setStartMode,
688 xslprocessor_get_startMode,
689 xslprocessor_get_startModeURI,
690 xslprocessor_put_output,
691 xslprocessor_get_output,
692 xslprocessor_transform,
693 xslprocessor_reset,
694 xslprocessor_get_readyState,
695 xslprocessor_addParameter,
696 xslprocessor_addObject,
697 xslprocessor_get_stylesheet
700 static const tid_t xslprocessor_iface_tids[] = {
701 IXSLProcessor_tid,
705 static dispex_static_data_t xslprocessor_dispex = {
706 NULL,
707 IXSLProcessor_tid,
708 NULL,
709 xslprocessor_iface_tids
712 HRESULT XSLProcessor_create(xsltemplate *template, IXSLProcessor **ppObj)
714 xslprocessor *This;
716 TRACE("(%p)\n", ppObj);
718 This = heap_alloc( sizeof (*This) );
719 if(!This)
720 return E_OUTOFMEMORY;
722 This->IXSLProcessor_iface.lpVtbl = &XSLProcessorVtbl;
723 This->ref = 1;
724 This->input = NULL;
725 This->output = NULL;
726 This->outstr = NULL;
727 list_init(&This->params.list);
728 This->params.count = 0;
729 This->stylesheet = template;
730 IXSLTemplate_AddRef(&template->IXSLTemplate_iface);
731 init_dispex(&This->dispex, (IUnknown*)&This->IXSLProcessor_iface, &xslprocessor_dispex);
733 *ppObj = &This->IXSLProcessor_iface;
735 TRACE("returning iface %p\n", *ppObj);
737 return S_OK;