strmbase: Separate BaseFilter destructor from Release.
[wine.git] / dlls / msxml3 / stylesheet.c
blob000199f2aaa4090d22699202908da686a3f1ca1d
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 heap_free( This );
144 return ref;
147 static HRESULT WINAPI xsltemplate_GetTypeInfoCount( IXSLTemplate *iface, UINT* pctinfo )
149 xsltemplate *This = impl_from_IXSLTemplate( iface );
150 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
153 static HRESULT WINAPI xsltemplate_GetTypeInfo(
154 IXSLTemplate *iface,
155 UINT iTInfo, LCID lcid,
156 ITypeInfo** ppTInfo )
158 xsltemplate *This = impl_from_IXSLTemplate( iface );
159 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
160 iTInfo, lcid, ppTInfo);
163 static HRESULT WINAPI xsltemplate_GetIDsOfNames(
164 IXSLTemplate *iface,
165 REFIID riid, LPOLESTR* rgszNames,
166 UINT cNames, LCID lcid, DISPID* rgDispId )
168 xsltemplate *This = impl_from_IXSLTemplate( iface );
169 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
170 riid, rgszNames, cNames, lcid, rgDispId);
173 static HRESULT WINAPI xsltemplate_Invoke(
174 IXSLTemplate *iface,
175 DISPID dispIdMember, REFIID riid, LCID lcid,
176 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
177 EXCEPINFO* pExcepInfo, UINT* puArgErr )
179 xsltemplate *This = impl_from_IXSLTemplate( iface );
180 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
181 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
184 static HRESULT WINAPI xsltemplate_putref_stylesheet( IXSLTemplate *iface,
185 IXMLDOMNode *node)
187 xsltemplate *This = impl_from_IXSLTemplate( iface );
189 TRACE("(%p)->(%p)\n", This, node);
191 if (!node)
193 xsltemplate_set_node(This, NULL);
194 return S_OK;
197 /* FIXME: test for document type */
198 xsltemplate_set_node(This, node);
200 return S_OK;
203 static HRESULT WINAPI xsltemplate_get_stylesheet( IXSLTemplate *iface,
204 IXMLDOMNode **node)
206 xsltemplate *This = impl_from_IXSLTemplate( iface );
208 FIXME("(%p)->(%p): stub\n", This, node);
209 return E_NOTIMPL;
212 static HRESULT WINAPI xsltemplate_createProcessor( IXSLTemplate *iface,
213 IXSLProcessor **processor)
215 xsltemplate *This = impl_from_IXSLTemplate( iface );
217 TRACE("(%p)->(%p)\n", This, processor);
219 if (!processor) return E_INVALIDARG;
221 return XSLProcessor_create(This, processor);
224 static const struct IXSLTemplateVtbl XSLTemplateVtbl =
226 xsltemplate_QueryInterface,
227 xsltemplate_AddRef,
228 xsltemplate_Release,
229 xsltemplate_GetTypeInfoCount,
230 xsltemplate_GetTypeInfo,
231 xsltemplate_GetIDsOfNames,
232 xsltemplate_Invoke,
233 xsltemplate_putref_stylesheet,
234 xsltemplate_get_stylesheet,
235 xsltemplate_createProcessor
238 static const tid_t xsltemplate_iface_tids[] = {
239 IXSLTemplate_tid,
243 static dispex_static_data_t xsltemplate_dispex = {
244 NULL,
245 IXSLTemplate_tid,
246 NULL,
247 xsltemplate_iface_tids
250 HRESULT XSLTemplate_create(void **ppObj)
252 xsltemplate *This;
254 TRACE("(%p)\n", ppObj);
256 This = heap_alloc( sizeof (*This) );
257 if(!This)
258 return E_OUTOFMEMORY;
260 This->IXSLTemplate_iface.lpVtbl = &XSLTemplateVtbl;
261 This->ref = 1;
262 This->node = NULL;
263 init_dispex(&This->dispex, (IUnknown*)&This->IXSLTemplate_iface, &xsltemplate_dispex);
265 *ppObj = &This->IXSLTemplate_iface;
267 TRACE("returning iface %p\n", *ppObj);
269 return S_OK;
272 /*** IXSLProcessor ***/
273 static HRESULT WINAPI xslprocessor_QueryInterface(
274 IXSLProcessor *iface,
275 REFIID riid,
276 void** ppvObject )
278 xslprocessor *This = impl_from_IXSLProcessor( iface );
279 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
281 if ( IsEqualGUID( riid, &IID_IXSLProcessor ) ||
282 IsEqualGUID( riid, &IID_IDispatch ) ||
283 IsEqualGUID( riid, &IID_IUnknown ) )
285 *ppvObject = iface;
287 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
289 return *ppvObject ? S_OK : E_NOINTERFACE;
291 else
293 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
294 *ppvObject = NULL;
295 return E_NOINTERFACE;
298 IUnknown_AddRef((IUnknown*)*ppvObject);
299 return S_OK;
302 static ULONG WINAPI xslprocessor_AddRef( IXSLProcessor *iface )
304 xslprocessor *This = impl_from_IXSLProcessor( iface );
305 ULONG ref = InterlockedIncrement( &This->ref );
306 TRACE("(%p)->(%d)\n", This, ref);
307 return ref;
310 static ULONG WINAPI xslprocessor_Release( IXSLProcessor *iface )
312 xslprocessor *This = impl_from_IXSLProcessor( iface );
313 ULONG ref = InterlockedDecrement( &This->ref );
315 TRACE("(%p)->(%d)\n", This, ref);
316 if ( ref == 0 )
318 struct xslprocessor_par *par, *par2;
320 if (This->input) IXMLDOMNode_Release(This->input);
321 if (This->output) IStream_Release(This->output);
322 SysFreeString(This->outstr);
324 LIST_FOR_EACH_ENTRY_SAFE(par, par2, &This->params.list, struct xslprocessor_par, entry)
325 xslprocessor_par_free(&This->params, par);
327 IXSLTemplate_Release(&This->stylesheet->IXSLTemplate_iface);
328 heap_free( This );
331 return ref;
334 static HRESULT WINAPI xslprocessor_GetTypeInfoCount( IXSLProcessor *iface, UINT* pctinfo )
336 xslprocessor *This = impl_from_IXSLProcessor( iface );
337 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
340 static HRESULT WINAPI xslprocessor_GetTypeInfo(
341 IXSLProcessor *iface,
342 UINT iTInfo, LCID lcid,
343 ITypeInfo** ppTInfo )
345 xslprocessor *This = impl_from_IXSLProcessor( iface );
346 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
347 iTInfo, lcid, ppTInfo);
350 static HRESULT WINAPI xslprocessor_GetIDsOfNames(
351 IXSLProcessor *iface,
352 REFIID riid, LPOLESTR* rgszNames,
353 UINT cNames, LCID lcid, DISPID* rgDispId )
355 xslprocessor *This = impl_from_IXSLProcessor( iface );
356 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
357 riid, rgszNames, cNames, lcid, rgDispId);
360 static HRESULT WINAPI xslprocessor_Invoke(
361 IXSLProcessor *iface,
362 DISPID dispIdMember, REFIID riid, LCID lcid,
363 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
364 EXCEPINFO* pExcepInfo, UINT* puArgErr )
366 xslprocessor *This = impl_from_IXSLProcessor( iface );
367 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
368 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
371 static HRESULT WINAPI xslprocessor_put_input( IXSLProcessor *iface, VARIANT input )
373 xslprocessor *This = impl_from_IXSLProcessor( iface );
374 IXMLDOMNode *input_node;
375 HRESULT hr;
377 TRACE("(%p)->(%s)\n", This, debugstr_variant(&input));
379 /* try IXMLDOMNode directly first */
380 if (V_VT(&input) == VT_UNKNOWN)
381 hr = IUnknown_QueryInterface(V_UNKNOWN(&input), &IID_IXMLDOMNode, (void**)&input_node);
382 else if (V_VT(&input) == VT_DISPATCH)
383 hr = IDispatch_QueryInterface(V_DISPATCH(&input), &IID_IXMLDOMNode, (void**)&input_node);
384 else
386 IXMLDOMDocument *doc;
388 hr = DOMDocument_create(MSXML_DEFAULT, (void**)&doc);
389 if (hr == S_OK)
391 VARIANT_BOOL b;
393 hr = IXMLDOMDocument_load(doc, input, &b);
394 if (hr == S_OK)
395 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IXMLDOMNode, (void**)&input_node);
396 IXMLDOMDocument_Release(doc);
400 if (hr == S_OK)
402 if (This->input) IXMLDOMNode_Release(This->input);
403 This->input = input_node;
406 return hr;
409 static HRESULT WINAPI xslprocessor_get_input( IXSLProcessor *iface, VARIANT *input )
411 xslprocessor *This = impl_from_IXSLProcessor( iface );
413 FIXME("(%p)->(%p): stub\n", This, input);
414 return E_NOTIMPL;
417 static HRESULT WINAPI xslprocessor_get_ownerTemplate(
418 IXSLProcessor *iface,
419 IXSLTemplate **template)
421 xslprocessor *This = impl_from_IXSLProcessor( iface );
423 FIXME("(%p)->(%p): stub\n", This, template);
424 return E_NOTIMPL;
427 static HRESULT WINAPI xslprocessor_setStartMode(
428 IXSLProcessor *iface,
429 BSTR p,
430 BSTR uri)
432 xslprocessor *This = impl_from_IXSLProcessor( iface );
434 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(p), debugstr_w(uri));
435 return E_NOTIMPL;
438 static HRESULT WINAPI xslprocessor_get_startMode(
439 IXSLProcessor *iface,
440 BSTR *p)
442 xslprocessor *This = impl_from_IXSLProcessor( iface );
444 FIXME("(%p)->(%p): stub\n", This, p);
445 return E_NOTIMPL;
448 static HRESULT WINAPI xslprocessor_get_startModeURI(
449 IXSLProcessor *iface,
450 BSTR *uri)
452 xslprocessor *This = impl_from_IXSLProcessor( iface );
454 FIXME("(%p)->(%p): stub\n", This, uri);
455 return E_NOTIMPL;
458 static HRESULT WINAPI xslprocessor_put_output(
459 IXSLProcessor *iface,
460 VARIANT output)
462 xslprocessor *This = impl_from_IXSLProcessor( iface );
463 IStream *stream;
464 HRESULT hr;
466 TRACE("(%p)->(%s)\n", This, debugstr_variant(&output));
468 switch (V_VT(&output))
470 case VT_EMPTY:
471 stream = NULL;
472 hr = S_OK;
473 break;
474 case VT_UNKNOWN:
475 hr = IUnknown_QueryInterface(V_UNKNOWN(&output), &IID_IStream, (void**)&stream);
476 if (FAILED(hr))
477 WARN("failed to get IStream from output, 0x%08x\n", hr);
478 break;
479 default:
480 FIXME("output type %d not handled\n", V_VT(&output));
481 hr = E_FAIL;
484 if (hr == S_OK)
486 if (This->output) IStream_Release(This->output);
487 This->output = stream;
490 return hr;
493 static HRESULT WINAPI xslprocessor_get_output(
494 IXSLProcessor *iface,
495 VARIANT *output)
497 xslprocessor *This = impl_from_IXSLProcessor( iface );
499 TRACE("(%p)->(%p)\n", This, output);
501 if (!output) return E_INVALIDARG;
503 if (This->output)
505 V_VT(output) = VT_UNKNOWN;
506 V_UNKNOWN(output) = (IUnknown*)This->output;
507 IStream_AddRef(This->output);
509 else if (This->outstr)
511 V_VT(output) = VT_BSTR;
512 V_BSTR(output) = SysAllocString(This->outstr);
514 else
515 V_VT(output) = VT_EMPTY;
517 return S_OK;
520 static HRESULT WINAPI xslprocessor_transform(
521 IXSLProcessor *iface,
522 VARIANT_BOOL *ret)
524 #ifdef HAVE_LIBXML2
525 xslprocessor *This = impl_from_IXSLProcessor( iface );
526 HRESULT hr;
528 TRACE("(%p)->(%p)\n", This, ret);
530 if (!ret) return E_INVALIDARG;
532 SysFreeString(This->outstr);
533 hr = node_transform_node_params(get_node_obj(This->input), This->stylesheet->node, &This->outstr, This->output, &This->params);
534 *ret = hr == S_OK ? VARIANT_TRUE : VARIANT_FALSE;
535 return hr;
536 #else
537 FIXME("libxml2 is required but wasn't present at compile time\n");
538 return E_NOTIMPL;
539 #endif
542 static HRESULT WINAPI xslprocessor_reset( IXSLProcessor *iface )
544 xslprocessor *This = impl_from_IXSLProcessor( iface );
546 FIXME("(%p): stub\n", This);
547 return E_NOTIMPL;
550 static HRESULT WINAPI xslprocessor_get_readyState(
551 IXSLProcessor *iface,
552 LONG *state)
554 xslprocessor *This = impl_from_IXSLProcessor( iface );
556 FIXME("(%p)->(%p): stub\n", This, state);
557 return E_NOTIMPL;
560 static HRESULT xslprocessor_set_parvalue(const VARIANT *var, struct xslprocessor_par *par)
562 HRESULT hr = S_OK;
564 switch (V_VT(var))
566 case VT_BSTR:
568 par->value = SysAllocString(V_BSTR(var));
569 if (!par->value) hr = E_OUTOFMEMORY;
570 break;
572 default:
573 FIXME("value type %d not handled\n", V_VT(var));
574 hr = E_NOTIMPL;
577 return hr;
580 static HRESULT WINAPI xslprocessor_addParameter(
581 IXSLProcessor *iface,
582 BSTR p,
583 VARIANT var,
584 BSTR uri)
586 xslprocessor *This = impl_from_IXSLProcessor( iface );
587 struct xslprocessor_par *cur, *par = NULL;
588 HRESULT hr;
590 TRACE("(%p)->(%s %s %s)\n", This, debugstr_w(p), debugstr_variant(&var),
591 debugstr_w(uri));
593 if (uri && *uri)
594 FIXME("namespace uri is not supported\n");
596 /* search for existing parameter first */
597 LIST_FOR_EACH_ENTRY(cur, &This->params.list, struct xslprocessor_par, entry)
599 if (!strcmpW(cur->name, p))
601 par = cur;
602 break;
606 /* override with new value or add new parameter */
607 if (par)
609 if (V_VT(&var) == VT_NULL || V_VT(&var) == VT_EMPTY)
611 /* remove parameter */
612 xslprocessor_par_free(&This->params, par);
613 return S_OK;
615 SysFreeString(par->value);
616 par->value = NULL;
618 else
620 /* new parameter */
621 par = heap_alloc(sizeof(struct xslprocessor_par));
622 if (!par) return E_OUTOFMEMORY;
624 par->name = SysAllocString(p);
625 if (!par->name)
627 heap_free(par);
628 return E_OUTOFMEMORY;
630 list_add_tail(&This->params.list, &par->entry);
631 This->params.count++;
634 hr = xslprocessor_set_parvalue(&var, par);
635 if (FAILED(hr))
636 xslprocessor_par_free(&This->params, par);
638 return hr;
641 static HRESULT WINAPI xslprocessor_addObject(
642 IXSLProcessor *iface,
643 IDispatch *obj,
644 BSTR uri)
646 xslprocessor *This = impl_from_IXSLProcessor( iface );
648 FIXME("(%p)->(%p %s): stub\n", This, obj, debugstr_w(uri));
649 return E_NOTIMPL;
652 static HRESULT WINAPI xslprocessor_get_stylesheet(
653 IXSLProcessor *iface,
654 IXMLDOMNode **node)
656 xslprocessor *This = impl_from_IXSLProcessor( iface );
658 FIXME("(%p)->(%p): stub\n", This, node);
659 return E_NOTIMPL;
662 static const struct IXSLProcessorVtbl XSLProcessorVtbl =
664 xslprocessor_QueryInterface,
665 xslprocessor_AddRef,
666 xslprocessor_Release,
667 xslprocessor_GetTypeInfoCount,
668 xslprocessor_GetTypeInfo,
669 xslprocessor_GetIDsOfNames,
670 xslprocessor_Invoke,
671 xslprocessor_put_input,
672 xslprocessor_get_input,
673 xslprocessor_get_ownerTemplate,
674 xslprocessor_setStartMode,
675 xslprocessor_get_startMode,
676 xslprocessor_get_startModeURI,
677 xslprocessor_put_output,
678 xslprocessor_get_output,
679 xslprocessor_transform,
680 xslprocessor_reset,
681 xslprocessor_get_readyState,
682 xslprocessor_addParameter,
683 xslprocessor_addObject,
684 xslprocessor_get_stylesheet
687 static const tid_t xslprocessor_iface_tids[] = {
688 IXSLProcessor_tid,
692 static dispex_static_data_t xslprocessor_dispex = {
693 NULL,
694 IXSLProcessor_tid,
695 NULL,
696 xslprocessor_iface_tids
699 HRESULT XSLProcessor_create(xsltemplate *template, IXSLProcessor **ppObj)
701 xslprocessor *This;
703 TRACE("(%p)\n", ppObj);
705 This = heap_alloc( sizeof (*This) );
706 if(!This)
707 return E_OUTOFMEMORY;
709 This->IXSLProcessor_iface.lpVtbl = &XSLProcessorVtbl;
710 This->ref = 1;
711 This->input = NULL;
712 This->output = NULL;
713 This->outstr = NULL;
714 list_init(&This->params.list);
715 This->params.count = 0;
716 This->stylesheet = template;
717 IXSLTemplate_AddRef(&template->IXSLTemplate_iface);
718 init_dispex(&This->dispex, (IUnknown*)&This->IXSLProcessor_iface, &xslprocessor_dispex);
720 *ppObj = &This->IXSLProcessor_iface;
722 TRACE("returning iface %p\n", *ppObj);
724 return S_OK;