d3d10: Implement D3D10StateBlockMaskEnableCapture().
[wine] / dlls / msxml3 / stylesheet.c
1 /*
2  *    XSLTemplate/XSLProcessor support
3  *
4  * Copyright 2011 Nikolay Sivov for CodeWeavers
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #define COBJMACROS
22
23 #include "config.h"
24
25 #include <stdarg.h>
26 #ifdef HAVE_LIBXML2
27 # include <libxml/parser.h>
28 # include <libxml/xmlerror.h>
29 #endif
30
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winuser.h"
34 #include "ole2.h"
35 #include "msxml6.h"
36
37 #include "msxml_private.h"
38
39 #include "wine/debug.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
42
43 #ifdef HAVE_LIBXML2
44
45 typedef struct _xsltemplate
46 {
47     IXSLTemplate IXSLTemplate_iface;
48     LONG ref;
49
50     IXMLDOMNode *node;
51 } xsltemplate;
52
53 typedef struct _xslprocessor
54 {
55     IXSLProcessor IXSLProcessor_iface;
56     LONG ref;
57
58     xsltemplate *stylesheet;
59     IXMLDOMNode *input;
60
61     IStream     *output;
62     BSTR         outstr;
63 } xslprocessor;
64
65 static HRESULT XSLProcessor_create(xsltemplate*, IXSLProcessor**);
66
67 static inline xsltemplate *impl_from_IXSLTemplate( IXSLTemplate *iface )
68 {
69     return CONTAINING_RECORD(iface, xsltemplate, IXSLTemplate_iface);
70 }
71
72 static inline xslprocessor *impl_from_IXSLProcessor( IXSLProcessor *iface )
73 {
74     return CONTAINING_RECORD(iface, xslprocessor, IXSLProcessor_iface);
75 }
76
77 static void xsltemplate_set_node( xsltemplate *This, IXMLDOMNode *node )
78 {
79     if (This->node) IXMLDOMNode_Release(This->node);
80     This->node = node;
81     if (node) IXMLDOMNode_AddRef(node);
82 }
83
84 static HRESULT WINAPI xsltemplate_QueryInterface(
85     IXSLTemplate *iface,
86     REFIID riid,
87     void** ppvObject )
88 {
89     xsltemplate *This = impl_from_IXSLTemplate( iface );
90     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
91
92     if ( IsEqualGUID( riid, &IID_IXSLTemplate ) ||
93          IsEqualGUID( riid, &IID_IDispatch ) ||
94          IsEqualGUID( riid, &IID_IUnknown ) )
95     {
96         *ppvObject = iface;
97     }
98     else
99     {
100         FIXME("Unsupported interface %s\n", debugstr_guid(riid));
101         *ppvObject = NULL;
102         return E_NOINTERFACE;
103     }
104
105     IUnknown_AddRef((IUnknown*)*ppvObject);
106     return S_OK;
107 }
108
109 static ULONG WINAPI xsltemplate_AddRef( IXSLTemplate *iface )
110 {
111     xsltemplate *This = impl_from_IXSLTemplate( iface );
112     return InterlockedIncrement( &This->ref );
113 }
114
115 static ULONG WINAPI xsltemplate_Release( IXSLTemplate *iface )
116 {
117     xsltemplate *This = impl_from_IXSLTemplate( iface );
118     ULONG ref;
119
120     ref = InterlockedDecrement( &This->ref );
121     if ( ref == 0 )
122     {
123         if (This->node) IXMLDOMNode_Release( This->node );
124         heap_free( This );
125     }
126
127     return ref;
128 }
129
130 static HRESULT WINAPI xsltemplate_GetTypeInfoCount( IXSLTemplate *iface, UINT* pctinfo )
131 {
132     xsltemplate *This = impl_from_IXSLTemplate( iface );
133
134     TRACE("(%p)->(%p)\n", This, pctinfo);
135
136     *pctinfo = 1;
137     return S_OK;
138 }
139
140 static HRESULT WINAPI xsltemplate_GetTypeInfo(
141     IXSLTemplate *iface,
142     UINT iTInfo, LCID lcid,
143     ITypeInfo** ppTInfo )
144 {
145     xsltemplate *This = impl_from_IXSLTemplate( iface );
146
147     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
148
149     return get_typeinfo(IXSLTemplate_tid, ppTInfo);
150 }
151
152 static HRESULT WINAPI xsltemplate_GetIDsOfNames(
153     IXSLTemplate *iface,
154     REFIID riid, LPOLESTR* rgszNames,
155     UINT cNames, LCID lcid, DISPID* rgDispId )
156 {
157     xsltemplate *This = impl_from_IXSLTemplate( iface );
158     ITypeInfo *typeinfo;
159     HRESULT hr;
160
161     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
162           lcid, rgDispId);
163
164     if(!rgszNames || cNames == 0 || !rgDispId)
165         return E_INVALIDARG;
166
167     hr = get_typeinfo(IXSLTemplate_tid, &typeinfo);
168     if(SUCCEEDED(hr))
169     {
170         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
171         ITypeInfo_Release(typeinfo);
172     }
173
174     return hr;
175 }
176
177 static HRESULT WINAPI xsltemplate_Invoke(
178     IXSLTemplate *iface,
179     DISPID dispIdMember, REFIID riid, LCID lcid,
180     WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
181     EXCEPINFO* pExcepInfo, UINT* puArgErr )
182 {
183     xsltemplate *This = impl_from_IXSLTemplate( iface );
184     ITypeInfo *typeinfo;
185     HRESULT hr;
186
187     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
188           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
189
190     hr = get_typeinfo(IXSLTemplate_tid, &typeinfo);
191     if(SUCCEEDED(hr))
192     {
193        hr = ITypeInfo_Invoke(typeinfo, &This->IXSLTemplate_iface, dispIdMember,
194                 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
195         ITypeInfo_Release(typeinfo);
196     }
197
198     return hr;
199 }
200
201 static HRESULT WINAPI xsltemplate_putref_stylesheet( IXSLTemplate *iface,
202     IXMLDOMNode *node)
203 {
204     xsltemplate *This = impl_from_IXSLTemplate( iface );
205
206     TRACE("(%p)->(%p)\n", This, node);
207
208     if (!node)
209     {
210         xsltemplate_set_node(This, NULL);
211         return S_OK;
212     }
213
214     /* FIXME: test for document type */
215     xsltemplate_set_node(This, node);
216
217     return S_OK;
218 }
219
220 static HRESULT WINAPI xsltemplate_get_stylesheet( IXSLTemplate *iface,
221     IXMLDOMNode **node)
222 {
223     xsltemplate *This = impl_from_IXSLTemplate( iface );
224
225     FIXME("(%p)->(%p): stub\n", This, node);
226     return E_NOTIMPL;
227 }
228
229 static HRESULT WINAPI xsltemplate_createProcessor( IXSLTemplate *iface,
230     IXSLProcessor **processor)
231 {
232     xsltemplate *This = impl_from_IXSLTemplate( iface );
233
234     TRACE("(%p)->(%p)\n", This, processor);
235
236     if (!processor) return E_INVALIDARG;
237
238     return XSLProcessor_create(This, processor);
239 }
240
241 static const struct IXSLTemplateVtbl xsltemplate_vtbl =
242 {
243     xsltemplate_QueryInterface,
244     xsltemplate_AddRef,
245     xsltemplate_Release,
246     xsltemplate_GetTypeInfoCount,
247     xsltemplate_GetTypeInfo,
248     xsltemplate_GetIDsOfNames,
249     xsltemplate_Invoke,
250
251     xsltemplate_putref_stylesheet,
252     xsltemplate_get_stylesheet,
253     xsltemplate_createProcessor
254 };
255
256 HRESULT XSLTemplate_create(IUnknown *pUnkOuter, void **ppObj)
257 {
258     xsltemplate *This;
259
260     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
261
262     if(pUnkOuter) FIXME("support aggregation, outer\n");
263
264     This = heap_alloc( sizeof (*This) );
265     if(!This)
266         return E_OUTOFMEMORY;
267
268     This->IXSLTemplate_iface.lpVtbl = &xsltemplate_vtbl;
269     This->ref = 1;
270     This->node = NULL;
271
272     *ppObj = &This->IXSLTemplate_iface;
273
274     TRACE("returning iface %p\n", *ppObj);
275
276     return S_OK;
277 }
278
279 /*** IXSLProcessor ***/
280 static HRESULT WINAPI xslprocessor_QueryInterface(
281     IXSLProcessor *iface,
282     REFIID riid,
283     void** ppvObject )
284 {
285     xslprocessor *This = impl_from_IXSLProcessor( iface );
286     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
287
288     if ( IsEqualGUID( riid, &IID_IXSLProcessor ) ||
289          IsEqualGUID( riid, &IID_IDispatch ) ||
290          IsEqualGUID( riid, &IID_IUnknown ) )
291     {
292         *ppvObject = iface;
293     }
294     else
295     {
296         FIXME("Unsupported interface %s\n", debugstr_guid(riid));
297         *ppvObject = NULL;
298         return E_NOINTERFACE;
299     }
300
301     IUnknown_AddRef((IUnknown*)*ppvObject);
302     return S_OK;
303 }
304
305 static ULONG WINAPI xslprocessor_AddRef( IXSLProcessor *iface )
306 {
307     xslprocessor *This = impl_from_IXSLProcessor( iface );
308     return InterlockedIncrement( &This->ref );
309 }
310
311 static ULONG WINAPI xslprocessor_Release( IXSLProcessor *iface )
312 {
313     xslprocessor *This = impl_from_IXSLProcessor( iface );
314     ULONG ref;
315
316     ref = InterlockedDecrement( &This->ref );
317     if ( ref == 0 )
318     {
319         if (This->input) IXMLDOMNode_Release(This->input);
320         if (This->output) IStream_Release(This->output);
321         SysFreeString(This->outstr);
322         IXSLTemplate_Release(&This->stylesheet->IXSLTemplate_iface);
323         heap_free( This );
324     }
325
326     return ref;
327 }
328
329 static HRESULT WINAPI xslprocessor_GetTypeInfoCount( IXSLProcessor *iface, UINT* pctinfo )
330 {
331     xslprocessor *This = impl_from_IXSLProcessor( iface );
332
333     TRACE("(%p)->(%p)\n", This, pctinfo);
334
335     *pctinfo = 1;
336     return S_OK;
337 }
338
339 static HRESULT WINAPI xslprocessor_GetTypeInfo(
340     IXSLProcessor *iface,
341     UINT iTInfo, LCID lcid,
342     ITypeInfo** ppTInfo )
343 {
344     xslprocessor *This = impl_from_IXSLProcessor( iface );
345
346     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
347
348     return get_typeinfo(IXSLProcessor_tid, ppTInfo);
349 }
350
351 static HRESULT WINAPI xslprocessor_GetIDsOfNames(
352     IXSLProcessor *iface,
353     REFIID riid, LPOLESTR* rgszNames,
354     UINT cNames, LCID lcid, DISPID* rgDispId )
355 {
356     xslprocessor *This = impl_from_IXSLProcessor( iface );
357     ITypeInfo *typeinfo;
358     HRESULT hr;
359
360     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
361           lcid, rgDispId);
362
363     if(!rgszNames || cNames == 0 || !rgDispId)
364         return E_INVALIDARG;
365
366     hr = get_typeinfo(IXSLProcessor_tid, &typeinfo);
367     if(SUCCEEDED(hr))
368     {
369         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
370         ITypeInfo_Release(typeinfo);
371     }
372
373     return hr;
374 }
375
376 static HRESULT WINAPI xslprocessor_Invoke(
377     IXSLProcessor *iface,
378     DISPID dispIdMember, REFIID riid, LCID lcid,
379     WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
380     EXCEPINFO* pExcepInfo, UINT* puArgErr )
381 {
382     xslprocessor *This = impl_from_IXSLProcessor( iface );
383     ITypeInfo *typeinfo;
384     HRESULT hr;
385
386     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
387           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
388
389     hr = get_typeinfo(IXSLProcessor_tid, &typeinfo);
390     if(SUCCEEDED(hr))
391     {
392        hr = ITypeInfo_Invoke(typeinfo, &This->IXSLProcessor_iface, dispIdMember,
393                 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
394         ITypeInfo_Release(typeinfo);
395     }
396
397     return hr;
398 }
399
400 static HRESULT WINAPI xslprocessor_put_input( IXSLProcessor *iface, VARIANT input )
401 {
402     xslprocessor *This = impl_from_IXSLProcessor( iface );
403     IXMLDOMNode *input_node;
404     HRESULT hr;
405
406     TRACE("(%p)->(%s)\n", This, debugstr_variant(&input));
407
408     /* try IXMLDOMNode directly first */
409     if (V_VT(&input) == VT_UNKNOWN)
410         hr = IUnknown_QueryInterface(V_UNKNOWN(&input), &IID_IXMLDOMNode, (void**)&input_node);
411     else if (V_VT(&input) == VT_DISPATCH)
412         hr = IDispatch_QueryInterface(V_DISPATCH(&input), &IID_IXMLDOMNode, (void**)&input_node);
413     else
414     {
415         IXMLDOMDocument *doc;
416
417         hr = DOMDocument_create(MSXML_DEFAULT, NULL, (void**)&doc);
418         if (hr == S_OK)
419         {
420             VARIANT_BOOL b;
421
422             hr = IXMLDOMDocument_load(doc, input, &b);
423             if (hr == S_OK)
424                 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IXMLDOMNode, (void**)&input_node);
425             IXMLDOMDocument_Release(doc);
426         }
427     }
428
429     if (hr == S_OK)
430     {
431         if (This->input) IXMLDOMNode_Release(This->input);
432         This->input = input_node;
433     }
434
435     return hr;
436 }
437
438 static HRESULT WINAPI xslprocessor_get_input( IXSLProcessor *iface, VARIANT *input )
439 {
440     xslprocessor *This = impl_from_IXSLProcessor( iface );
441
442     FIXME("(%p)->(%p): stub\n", This, input);
443     return E_NOTIMPL;
444 }
445
446 static HRESULT WINAPI xslprocessor_get_ownerTemplate(
447     IXSLProcessor *iface,
448     IXSLTemplate **template)
449 {
450     xslprocessor *This = impl_from_IXSLProcessor( iface );
451
452     FIXME("(%p)->(%p): stub\n", This, template);
453     return E_NOTIMPL;
454 }
455
456 static HRESULT WINAPI xslprocessor_setStartMode(
457     IXSLProcessor *iface,
458     BSTR p,
459     BSTR uri)
460 {
461     xslprocessor *This = impl_from_IXSLProcessor( iface );
462
463     FIXME("(%p)->(%s %s): stub\n", This, wine_dbgstr_w(p), wine_dbgstr_w(uri));
464     return E_NOTIMPL;
465 }
466
467 static HRESULT WINAPI xslprocessor_get_startMode(
468     IXSLProcessor *iface,
469     BSTR *p)
470 {
471     xslprocessor *This = impl_from_IXSLProcessor( iface );
472
473     FIXME("(%p)->(%p): stub\n", This, p);
474     return E_NOTIMPL;
475 }
476
477 static HRESULT WINAPI xslprocessor_get_startModeURI(
478     IXSLProcessor *iface,
479     BSTR *uri)
480 {
481     xslprocessor *This = impl_from_IXSLProcessor( iface );
482
483     FIXME("(%p)->(%p): stub\n", This, uri);
484     return E_NOTIMPL;
485 }
486
487 static HRESULT WINAPI xslprocessor_put_output(
488     IXSLProcessor *iface,
489     VARIANT output)
490 {
491     xslprocessor *This = impl_from_IXSLProcessor( iface );
492     IStream *stream;
493     HRESULT hr;
494
495     FIXME("(%p)->(%s): semi-stub\n", This, debugstr_variant(&output));
496
497     switch (V_VT(&output))
498     {
499       case VT_EMPTY:
500         stream = NULL;
501         hr = S_OK;
502         break;
503       case VT_UNKNOWN:
504         hr = IUnknown_QueryInterface(V_UNKNOWN(&output), &IID_IStream, (void**)&stream);
505         break;
506       default:
507         hr = E_FAIL;
508     }
509
510     if (hr == S_OK)
511     {
512         if (This->output) IStream_Release(This->output);
513         This->output = stream;
514     }
515
516     return hr;
517 }
518
519 static HRESULT WINAPI xslprocessor_get_output(
520     IXSLProcessor *iface,
521     VARIANT *output)
522 {
523     xslprocessor *This = impl_from_IXSLProcessor( iface );
524
525     TRACE("(%p)->(%p)\n", This, output);
526
527     if (!output) return E_INVALIDARG;
528
529     if (This->output)
530     {
531         V_VT(output) = VT_UNKNOWN;
532         V_UNKNOWN(output) = (IUnknown*)This->output;
533         IStream_AddRef(This->output);
534     }
535     else if (This->outstr)
536     {
537         V_VT(output) = VT_BSTR;
538         V_BSTR(output) = SysAllocString(This->outstr);
539     }
540     else
541         V_VT(output) = VT_EMPTY;
542
543     return S_OK;
544 }
545
546 static HRESULT WINAPI xslprocessor_transform(
547     IXSLProcessor *iface,
548     VARIANT_BOOL  *ret)
549 {
550     xslprocessor *This = impl_from_IXSLProcessor( iface );
551     HRESULT hr;
552
553     TRACE("(%p)->(%p)\n", This, ret);
554
555     if (!ret) return E_INVALIDARG;
556
557     SysFreeString(This->outstr);
558     hr = IXMLDOMNode_transformNode(This->input, This->stylesheet->node, &This->outstr);
559     if (hr == S_OK)
560     {
561         if (This->output)
562         {
563             ULONG len = 0;
564
565             /* output to stream */
566             hr = IStream_Write(This->output, This->outstr, SysStringByteLen(This->outstr), &len);
567             *ret = len == SysStringByteLen(This->outstr) ? VARIANT_TRUE : VARIANT_FALSE;
568         }
569     }
570     else
571         *ret = VARIANT_FALSE;
572
573     return hr;
574 }
575
576 static HRESULT WINAPI xslprocessor_reset( IXSLProcessor *iface )
577 {
578     xslprocessor *This = impl_from_IXSLProcessor( iface );
579
580     FIXME("(%p): stub\n", This);
581     return E_NOTIMPL;
582 }
583
584 static HRESULT WINAPI xslprocessor_get_readyState(
585     IXSLProcessor *iface,
586     LONG *state)
587 {
588     xslprocessor *This = impl_from_IXSLProcessor( iface );
589
590     FIXME("(%p)->(%p): stub\n", This, state);
591     return E_NOTIMPL;
592 }
593
594 static HRESULT WINAPI xslprocessor_addParameter(
595     IXSLProcessor *iface,
596     BSTR p,
597     VARIANT var,
598     BSTR uri)
599 {
600     xslprocessor *This = impl_from_IXSLProcessor( iface );
601
602     FIXME("(%p)->(%s %s %s): stub\n", This, wine_dbgstr_w(p), debugstr_variant(&var),
603         wine_dbgstr_w(uri));
604     return E_NOTIMPL;
605 }
606
607 static HRESULT WINAPI xslprocessor_addObject(
608     IXSLProcessor *iface,
609     IDispatch *obj,
610     BSTR uri)
611 {
612     xslprocessor *This = impl_from_IXSLProcessor( iface );
613
614     FIXME("(%p)->(%p %s): stub\n", This, obj, wine_dbgstr_w(uri));
615     return E_NOTIMPL;
616 }
617
618 static HRESULT WINAPI xslprocessor_get_stylesheet(
619     IXSLProcessor *iface,
620     IXMLDOMNode  **node)
621 {
622     xslprocessor *This = impl_from_IXSLProcessor( iface );
623
624     FIXME("(%p)->(%p): stub\n", This, node);
625     return E_NOTIMPL;
626 }
627
628 static const struct IXSLProcessorVtbl xslprocessor_vtbl =
629 {
630     xslprocessor_QueryInterface,
631     xslprocessor_AddRef,
632     xslprocessor_Release,
633     xslprocessor_GetTypeInfoCount,
634     xslprocessor_GetTypeInfo,
635     xslprocessor_GetIDsOfNames,
636     xslprocessor_Invoke,
637
638     xslprocessor_put_input,
639     xslprocessor_get_input,
640     xslprocessor_get_ownerTemplate,
641     xslprocessor_setStartMode,
642     xslprocessor_get_startMode,
643     xslprocessor_get_startModeURI,
644     xslprocessor_put_output,
645     xslprocessor_get_output,
646     xslprocessor_transform,
647     xslprocessor_reset,
648     xslprocessor_get_readyState,
649     xslprocessor_addParameter,
650     xslprocessor_addObject,
651     xslprocessor_get_stylesheet
652 };
653
654 HRESULT XSLProcessor_create(xsltemplate *template, IXSLProcessor **ppObj)
655 {
656     xslprocessor *This;
657
658     TRACE("(%p)\n", ppObj);
659
660     This = heap_alloc( sizeof (*This) );
661     if(!This)
662         return E_OUTOFMEMORY;
663
664     This->IXSLProcessor_iface.lpVtbl = &xslprocessor_vtbl;
665     This->ref = 1;
666     This->input = NULL;
667     This->output = NULL;
668     This->outstr = NULL;
669     This->stylesheet = template;
670     IXSLTemplate_AddRef(&template->IXSLTemplate_iface);
671
672     *ppObj = &This->IXSLProcessor_iface;
673
674     TRACE("returning iface %p\n", *ppObj);
675
676     return S_OK;
677 }
678
679 #else
680
681 HRESULT XSLTemplate_create(IUnknown *pUnkOuter, void **ppObj)
682 {
683     MESSAGE("This program tried to use a XSLTemplate object, but\n"
684             "libxml2 support was not present at compile time.\n");
685     return E_NOTIMPL;
686 }
687
688 #endif