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 "initguid.h"
40 #include "asptlb.h"
41
42 #include "wine/debug.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
45
46 typedef struct
47 {
48 DispatchEx dispex;
49 IXSLTemplate IXSLTemplate_iface;
50 LONG ref;
51
52 IXMLDOMNode *node;
53 } xsltemplate;
54
55 enum output_type
56 {
57 PROCESSOR_OUTPUT_NOT_SET,
58 PROCESSOR_OUTPUT_STREAM, /* IStream or ISequentialStream */
59 PROCESSOR_OUTPUT_PERSISTSTREAM, /* IPersistStream or IPersistStreamInit */
60 PROCESSOR_OUTPUT_RESPONSE, /* IResponse */
61 };
62
63 typedef struct
64 {
65 DispatchEx dispex;
66 IXSLProcessor IXSLProcessor_iface;
67 LONG ref;
68
69 xsltemplate *stylesheet;
70 IXMLDOMNode *input;
71
72 union
73 {
74 IUnknown *unk;
75 ISequentialStream *stream;
76 IPersistStream *persiststream;
77 IResponse *response;
78 } output;
79 enum output_type output_type;
80 BSTR outstr;
81
82 struct xslprocessor_params params;
83 } xslprocessor;
84
85 static HRESULT XSLProcessor_create(xsltemplate*, IXSLProcessor**);
86
impl_from_IXSLTemplate(IXSLTemplate * iface)87 static inline xsltemplate *impl_from_IXSLTemplate( IXSLTemplate *iface )
88 {
89 return CONTAINING_RECORD(iface, xsltemplate, IXSLTemplate_iface);
90 }
91
impl_from_IXSLProcessor(IXSLProcessor * iface)92 static inline xslprocessor *impl_from_IXSLProcessor( IXSLProcessor *iface )
93 {
94 return CONTAINING_RECORD(iface, xslprocessor, IXSLProcessor_iface);
95 }
96
xslprocessor_par_free(struct xslprocessor_params * params,struct xslprocessor_par * par)97 static void xslprocessor_par_free(struct xslprocessor_params *params, struct xslprocessor_par *par)
98 {
99 params->count--;
100 list_remove(&par->entry);
101 SysFreeString(par->name);
102 SysFreeString(par->value);
103 heap_free(par);
104 }
105
xsltemplate_set_node(xsltemplate * This,IXMLDOMNode * node)106 static void xsltemplate_set_node( xsltemplate *This, IXMLDOMNode *node )
107 {
108 if (This->node) IXMLDOMNode_Release(This->node);
109 This->node = node;
110 if (node) IXMLDOMNode_AddRef(node);
111 }
112
xsltemplate_QueryInterface(IXSLTemplate * iface,REFIID riid,void ** ppvObject)113 static HRESULT WINAPI xsltemplate_QueryInterface(
114 IXSLTemplate *iface,
115 REFIID riid,
116 void** ppvObject )
117 {
118 xsltemplate *This = impl_from_IXSLTemplate( iface );
119 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
120
121 if ( IsEqualGUID( riid, &IID_IXSLTemplate ) ||
122 IsEqualGUID( riid, &IID_IDispatch ) ||
123 IsEqualGUID( riid, &IID_IUnknown ) )
124 {
125 *ppvObject = iface;
126 }
127 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
128 {
129 return *ppvObject ? S_OK : E_NOINTERFACE;
130 }
131 else
132 {
133 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
134 *ppvObject = NULL;
135 return E_NOINTERFACE;
136 }
137
138 IUnknown_AddRef((IUnknown*)*ppvObject);
139 return S_OK;
140 }
141
xsltemplate_AddRef(IXSLTemplate * iface)142 static ULONG WINAPI xsltemplate_AddRef( IXSLTemplate *iface )
143 {
144 xsltemplate *This = impl_from_IXSLTemplate( iface );
145 ULONG ref = InterlockedIncrement( &This->ref );
146 TRACE("(%p)->(%d)\n", This, ref);
147 return ref;
148 }
149
xsltemplate_Release(IXSLTemplate * iface)150 static ULONG WINAPI xsltemplate_Release( IXSLTemplate *iface )
151 {
152 xsltemplate *This = impl_from_IXSLTemplate( iface );
153 ULONG ref = InterlockedDecrement( &This->ref );
154
155 TRACE("(%p)->(%d)\n", This, ref);
156 if ( ref == 0 )
157 {
158 if (This->node) IXMLDOMNode_Release( This->node );
159 heap_free( This );
160 }
161
162 return ref;
163 }
164
xsltemplate_GetTypeInfoCount(IXSLTemplate * iface,UINT * pctinfo)165 static HRESULT WINAPI xsltemplate_GetTypeInfoCount( IXSLTemplate *iface, UINT* pctinfo )
166 {
167 xsltemplate *This = impl_from_IXSLTemplate( iface );
168 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
169 }
170
xsltemplate_GetTypeInfo(IXSLTemplate * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)171 static HRESULT WINAPI xsltemplate_GetTypeInfo(
172 IXSLTemplate *iface,
173 UINT iTInfo, LCID lcid,
174 ITypeInfo** ppTInfo )
175 {
176 xsltemplate *This = impl_from_IXSLTemplate( iface );
177 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
178 iTInfo, lcid, ppTInfo);
179 }
180
xsltemplate_GetIDsOfNames(IXSLTemplate * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)181 static HRESULT WINAPI xsltemplate_GetIDsOfNames(
182 IXSLTemplate *iface,
183 REFIID riid, LPOLESTR* rgszNames,
184 UINT cNames, LCID lcid, DISPID* rgDispId )
185 {
186 xsltemplate *This = impl_from_IXSLTemplate( iface );
187 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
188 riid, rgszNames, cNames, lcid, rgDispId);
189 }
190
xsltemplate_Invoke(IXSLTemplate * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)191 static HRESULT WINAPI xsltemplate_Invoke(
192 IXSLTemplate *iface,
193 DISPID dispIdMember, REFIID riid, LCID lcid,
194 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
195 EXCEPINFO* pExcepInfo, UINT* puArgErr )
196 {
197 xsltemplate *This = impl_from_IXSLTemplate( iface );
198 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
199 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
200 }
201
xsltemplate_putref_stylesheet(IXSLTemplate * iface,IXMLDOMNode * node)202 static HRESULT WINAPI xsltemplate_putref_stylesheet( IXSLTemplate *iface,
203 IXMLDOMNode *node)
204 {
205 xsltemplate *This = impl_from_IXSLTemplate( iface );
206
207 TRACE("(%p)->(%p)\n", This, node);
208
209 if (!node)
210 {
211 xsltemplate_set_node(This, NULL);
212 return S_OK;
213 }
214
215 /* FIXME: test for document type */
216 xsltemplate_set_node(This, node);
217
218 return S_OK;
219 }
220
xsltemplate_get_stylesheet(IXSLTemplate * iface,IXMLDOMNode ** node)221 static HRESULT WINAPI xsltemplate_get_stylesheet( IXSLTemplate *iface,
222 IXMLDOMNode **node)
223 {
224 xsltemplate *This = impl_from_IXSLTemplate( iface );
225
226 FIXME("(%p)->(%p): stub\n", This, node);
227 return E_NOTIMPL;
228 }
229
xsltemplate_createProcessor(IXSLTemplate * iface,IXSLProcessor ** processor)230 static HRESULT WINAPI xsltemplate_createProcessor( IXSLTemplate *iface,
231 IXSLProcessor **processor)
232 {
233 xsltemplate *This = impl_from_IXSLTemplate( iface );
234
235 TRACE("(%p)->(%p)\n", This, processor);
236
237 if (!processor) return E_INVALIDARG;
238
239 return XSLProcessor_create(This, processor);
240 }
241
242 static const struct IXSLTemplateVtbl XSLTemplateVtbl =
243 {
244 xsltemplate_QueryInterface,
245 xsltemplate_AddRef,
246 xsltemplate_Release,
247 xsltemplate_GetTypeInfoCount,
248 xsltemplate_GetTypeInfo,
249 xsltemplate_GetIDsOfNames,
250 xsltemplate_Invoke,
251 xsltemplate_putref_stylesheet,
252 xsltemplate_get_stylesheet,
253 xsltemplate_createProcessor
254 };
255
256 static const tid_t xsltemplate_iface_tids[] = {
257 IXSLTemplate_tid,
258 0
259 };
260
261 static dispex_static_data_t xsltemplate_dispex = {
262 NULL,
263 IXSLTemplate_tid,
264 NULL,
265 xsltemplate_iface_tids
266 };
267
XSLTemplate_create(void ** ppObj)268 HRESULT XSLTemplate_create(void **ppObj)
269 {
270 xsltemplate *This;
271
272 TRACE("(%p)\n", ppObj);
273
274 This = heap_alloc( sizeof (*This) );
275 if(!This)
276 return E_OUTOFMEMORY;
277
278 This->IXSLTemplate_iface.lpVtbl = &XSLTemplateVtbl;
279 This->ref = 1;
280 This->node = NULL;
281 init_dispex(&This->dispex, (IUnknown*)&This->IXSLTemplate_iface, &xsltemplate_dispex);
282
283 *ppObj = &This->IXSLTemplate_iface;
284
285 TRACE("returning iface %p\n", *ppObj);
286
287 return S_OK;
288 }
289
290 /*** IXSLProcessor ***/
xslprocessor_QueryInterface(IXSLProcessor * iface,REFIID riid,void ** ppvObject)291 static HRESULT WINAPI xslprocessor_QueryInterface(
292 IXSLProcessor *iface,
293 REFIID riid,
294 void** ppvObject )
295 {
296 xslprocessor *This = impl_from_IXSLProcessor( iface );
297 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
298
299 if ( IsEqualGUID( riid, &IID_IXSLProcessor ) ||
300 IsEqualGUID( riid, &IID_IDispatch ) ||
301 IsEqualGUID( riid, &IID_IUnknown ) )
302 {
303 *ppvObject = iface;
304 }
305 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
306 {
307 return *ppvObject ? S_OK : E_NOINTERFACE;
308 }
309 else
310 {
311 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
312 *ppvObject = NULL;
313 return E_NOINTERFACE;
314 }
315
316 IUnknown_AddRef((IUnknown*)*ppvObject);
317 return S_OK;
318 }
319
xslprocessor_AddRef(IXSLProcessor * iface)320 static ULONG WINAPI xslprocessor_AddRef( IXSLProcessor *iface )
321 {
322 xslprocessor *This = impl_from_IXSLProcessor( iface );
323 ULONG ref = InterlockedIncrement( &This->ref );
324 TRACE("(%p)->(%d)\n", This, ref);
325 return ref;
326 }
327
xslprocessor_Release(IXSLProcessor * iface)328 static ULONG WINAPI xslprocessor_Release( IXSLProcessor *iface )
329 {
330 xslprocessor *This = impl_from_IXSLProcessor( iface );
331 ULONG ref = InterlockedDecrement( &This->ref );
332
333 TRACE("(%p)->(%d)\n", This, ref);
334 if ( ref == 0 )
335 {
336 struct xslprocessor_par *par, *par2;
337
338 if (This->input) IXMLDOMNode_Release(This->input);
339 if (This->output.unk)
340 IUnknown_Release(This->output.unk);
341 SysFreeString(This->outstr);
342
343 LIST_FOR_EACH_ENTRY_SAFE(par, par2, &This->params.list, struct xslprocessor_par, entry)
344 xslprocessor_par_free(&This->params, par);
345
346 IXSLTemplate_Release(&This->stylesheet->IXSLTemplate_iface);
347 heap_free( This );
348 }
349
350 return ref;
351 }
352
xslprocessor_GetTypeInfoCount(IXSLProcessor * iface,UINT * pctinfo)353 static HRESULT WINAPI xslprocessor_GetTypeInfoCount( IXSLProcessor *iface, UINT* pctinfo )
354 {
355 xslprocessor *This = impl_from_IXSLProcessor( iface );
356 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
357 }
358
xslprocessor_GetTypeInfo(IXSLProcessor * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)359 static HRESULT WINAPI xslprocessor_GetTypeInfo(
360 IXSLProcessor *iface,
361 UINT iTInfo, LCID lcid,
362 ITypeInfo** ppTInfo )
363 {
364 xslprocessor *This = impl_from_IXSLProcessor( iface );
365 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
366 iTInfo, lcid, ppTInfo);
367 }
368
xslprocessor_GetIDsOfNames(IXSLProcessor * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)369 static HRESULT WINAPI xslprocessor_GetIDsOfNames(
370 IXSLProcessor *iface,
371 REFIID riid, LPOLESTR* rgszNames,
372 UINT cNames, LCID lcid, DISPID* rgDispId )
373 {
374 xslprocessor *This = impl_from_IXSLProcessor( iface );
375 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
376 riid, rgszNames, cNames, lcid, rgDispId);
377 }
378
xslprocessor_Invoke(IXSLProcessor * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)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 )
384 {
385 xslprocessor *This = impl_from_IXSLProcessor( iface );
386 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
387 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
388 }
389
xslprocessor_put_input(IXSLProcessor * iface,VARIANT input)390 static HRESULT WINAPI xslprocessor_put_input( IXSLProcessor *iface, VARIANT input )
391 {
392 xslprocessor *This = impl_from_IXSLProcessor( iface );
393 IXMLDOMNode *input_node;
394 HRESULT hr;
395
396 TRACE("(%p)->(%s)\n", This, debugstr_variant(&input));
397
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);
403 else
404 {
405 IXMLDOMDocument *doc;
406
407 hr = DOMDocument_create(MSXML_DEFAULT, (void**)&doc);
408 if (hr == S_OK)
409 {
410 VARIANT_BOOL b;
411
412 hr = IXMLDOMDocument_load(doc, input, &b);
413 if (hr == S_OK)
414 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IXMLDOMNode, (void**)&input_node);
415 IXMLDOMDocument_Release(doc);
416 }
417 }
418
419 if (hr == S_OK)
420 {
421 if (This->input) IXMLDOMNode_Release(This->input);
422 This->input = input_node;
423 }
424
425 return hr;
426 }
427
xslprocessor_get_input(IXSLProcessor * iface,VARIANT * input)428 static HRESULT WINAPI xslprocessor_get_input( IXSLProcessor *iface, VARIANT *input )
429 {
430 xslprocessor *This = impl_from_IXSLProcessor( iface );
431
432 FIXME("(%p)->(%p): stub\n", This, input);
433 return E_NOTIMPL;
434 }
435
xslprocessor_get_ownerTemplate(IXSLProcessor * iface,IXSLTemplate ** template)436 static HRESULT WINAPI xslprocessor_get_ownerTemplate(
437 IXSLProcessor *iface,
438 IXSLTemplate **template)
439 {
440 xslprocessor *This = impl_from_IXSLProcessor( iface );
441
442 FIXME("(%p)->(%p): stub\n", This, template);
443 return E_NOTIMPL;
444 }
445
xslprocessor_setStartMode(IXSLProcessor * iface,BSTR p,BSTR uri)446 static HRESULT WINAPI xslprocessor_setStartMode(
447 IXSLProcessor *iface,
448 BSTR p,
449 BSTR uri)
450 {
451 xslprocessor *This = impl_from_IXSLProcessor( iface );
452
453 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(p), debugstr_w(uri));
454 return E_NOTIMPL;
455 }
456
xslprocessor_get_startMode(IXSLProcessor * iface,BSTR * p)457 static HRESULT WINAPI xslprocessor_get_startMode(
458 IXSLProcessor *iface,
459 BSTR *p)
460 {
461 xslprocessor *This = impl_from_IXSLProcessor( iface );
462
463 FIXME("(%p)->(%p): stub\n", This, p);
464 return E_NOTIMPL;
465 }
466
xslprocessor_get_startModeURI(IXSLProcessor * iface,BSTR * uri)467 static HRESULT WINAPI xslprocessor_get_startModeURI(
468 IXSLProcessor *iface,
469 BSTR *uri)
470 {
471 xslprocessor *This = impl_from_IXSLProcessor( iface );
472
473 FIXME("(%p)->(%p): stub\n", This, uri);
474 return E_NOTIMPL;
475 }
476
xslprocessor_put_output(IXSLProcessor * iface,VARIANT var)477 static HRESULT WINAPI xslprocessor_put_output(
478 IXSLProcessor *iface,
479 VARIANT var)
480 {
481 xslprocessor *This = impl_from_IXSLProcessor( iface );
482 enum output_type output_type = PROCESSOR_OUTPUT_NOT_SET;
483 IUnknown *output = NULL;
484 HRESULT hr = S_OK;
485
486 TRACE("(%p)->(%s)\n", This, debugstr_variant(&var));
487
488 switch (V_VT(&var))
489 {
490 case VT_EMPTY:
491 break;
492 case VT_UNKNOWN:
493 case VT_DISPATCH:
494 if (!V_UNKNOWN(&var))
495 break;
496
497 output_type = PROCESSOR_OUTPUT_STREAM;
498 hr = IUnknown_QueryInterface(V_UNKNOWN(&var), &IID_IStream, (void **)&output);
499 if (FAILED(hr))
500 hr = IUnknown_QueryInterface(V_UNKNOWN(&var), &IID_ISequentialStream, (void **)&output);
501 if (FAILED(hr))
502 {
503 output_type = PROCESSOR_OUTPUT_RESPONSE;
504 hr = IUnknown_QueryInterface(V_UNKNOWN(&var), &IID_IResponse, (void **)&output);
505 }
506 if (FAILED(hr))
507 {
508 output_type = PROCESSOR_OUTPUT_PERSISTSTREAM;
509 hr = IUnknown_QueryInterface(V_UNKNOWN(&var), &IID_IPersistStream, (void **)&output);
510 }
511 if (FAILED(hr))
512 hr = IUnknown_QueryInterface(V_UNKNOWN(&var), &IID_IPersistStreamInit, (void **)&output);
513 if (FAILED(hr))
514 {
515 output_type = PROCESSOR_OUTPUT_NOT_SET;
516 WARN("failed to get output interface, 0x%08x\n", hr);
517 }
518 break;
519 default:
520 FIXME("output type %d not handled\n", V_VT(&var));
521 hr = E_FAIL;
522 }
523
524 if (hr == S_OK)
525 {
526 if (This->output.unk)
527 IUnknown_Release(This->output.unk);
528 This->output.unk = output;
529 This->output_type = output_type;
530 }
531
532 return hr;
533 }
534
xslprocessor_get_output(IXSLProcessor * iface,VARIANT * output)535 static HRESULT WINAPI xslprocessor_get_output(
536 IXSLProcessor *iface,
537 VARIANT *output)
538 {
539 xslprocessor *This = impl_from_IXSLProcessor( iface );
540
541 TRACE("(%p)->(%p)\n", This, output);
542
543 if (!output) return E_INVALIDARG;
544
545 if (This->output.unk)
546 {
547 V_VT(output) = VT_UNKNOWN;
548 V_UNKNOWN(output) = This->output.unk;
549 IUnknown_AddRef(This->output.unk);
550 }
551 else if (This->outstr)
552 {
553 V_VT(output) = VT_BSTR;
554 V_BSTR(output) = SysAllocString(This->outstr);
555 }
556 else
557 V_VT(output) = VT_EMPTY;
558
559 return S_OK;
560 }
561
xslprocessor_transform(IXSLProcessor * iface,VARIANT_BOOL * ret)562 static HRESULT WINAPI xslprocessor_transform(
563 IXSLProcessor *iface,
564 VARIANT_BOOL *ret)
565 {
566 #ifdef HAVE_LIBXML2
567 xslprocessor *This = impl_from_IXSLProcessor( iface );
568 ISequentialStream *stream = NULL;
569 HRESULT hr;
570
571 TRACE("(%p)->(%p)\n", This, ret);
572
573 if (!ret)
574 return E_INVALIDARG;
575
576 if (This->output_type == PROCESSOR_OUTPUT_STREAM)
577 {
578 stream = This->output.stream;
579 ISequentialStream_AddRef(stream);
580 }
581 else if (This->output_type == PROCESSOR_OUTPUT_PERSISTSTREAM ||
582 This->output_type == PROCESSOR_OUTPUT_RESPONSE)
583 {
584 if (FAILED(hr = CreateStreamOnHGlobal(NULL, TRUE, (IStream **)&stream)))
585 return hr;
586 }
587
588 SysFreeString(This->outstr);
589
590 hr = node_transform_node_params(get_node_obj(This->input), This->stylesheet->node,
591 &This->outstr, stream, &This->params);
592 if (SUCCEEDED(hr))
593 {
594 IStream *src = (IStream *)stream;
595
596 switch (This->output_type)
597 {
598 case PROCESSOR_OUTPUT_PERSISTSTREAM:
599 {
600 LARGE_INTEGER zero;
601
602 /* for IPersistStream* output seekable stream is used */
603 zero.QuadPart = 0;
604 IStream_Seek(src, zero, STREAM_SEEK_SET, NULL);
605 hr = IPersistStream_Load(This->output.persiststream, src);
606 break;
607 }
608 case PROCESSOR_OUTPUT_RESPONSE:
609 {
610 SAFEARRAYBOUND bound;
611 SAFEARRAY *array;
612 HGLOBAL hglobal;
613 VARIANT bin;
614 DWORD size;
615 void *dest;
616
617 if (FAILED(hr = GetHGlobalFromStream(src, &hglobal)))
618 break;
619 size = GlobalSize(hglobal);
620
621 bound.lLbound = 0;
622 bound.cElements = size;
623 if (!(array = SafeArrayCreate(VT_UI1, 1, &bound)))
624 break;
625
626 V_VT(&bin) = VT_ARRAY | VT_UI1;
627 V_ARRAY(&bin) = array;
628
629 hr = SafeArrayAccessData(array, &dest);
630 if (hr == S_OK)
631 {
632 void *data = GlobalLock(hglobal);
633 memcpy(dest, data, size);
634 GlobalUnlock(hglobal);
635 SafeArrayUnaccessData(array);
636
637 IResponse_BinaryWrite(This->output.response, bin);
638 }
639
640 VariantClear(&bin);
641 break;
642 }
643 default:
644 ;
645 }
646 }
647
648 if (stream)
649 ISequentialStream_Release(stream);
650
651 *ret = hr == S_OK ? VARIANT_TRUE : VARIANT_FALSE;
652 return hr;
653 #else
654 FIXME("libxml2 is required but wasn't present at compile time\n");
655 return E_NOTIMPL;
656 #endif
657 }
658
xslprocessor_reset(IXSLProcessor * iface)659 static HRESULT WINAPI xslprocessor_reset( IXSLProcessor *iface )
660 {
661 xslprocessor *This = impl_from_IXSLProcessor( iface );
662
663 FIXME("(%p): stub\n", This);
664 return E_NOTIMPL;
665 }
666
xslprocessor_get_readyState(IXSLProcessor * iface,LONG * state)667 static HRESULT WINAPI xslprocessor_get_readyState(
668 IXSLProcessor *iface,
669 LONG *state)
670 {
671 xslprocessor *This = impl_from_IXSLProcessor( iface );
672
673 FIXME("(%p)->(%p): stub\n", This, state);
674 return E_NOTIMPL;
675 }
676
xslprocessor_set_parvalue(const VARIANT * var,struct xslprocessor_par * par)677 static HRESULT xslprocessor_set_parvalue(const VARIANT *var, struct xslprocessor_par *par)
678 {
679 HRESULT hr = S_OK;
680
681 switch (V_VT(var))
682 {
683 case VT_BSTR:
684 {
685 par->value = SysAllocString(V_BSTR(var));
686 if (!par->value) hr = E_OUTOFMEMORY;
687 break;
688 }
689 default:
690 FIXME("value type %d not handled\n", V_VT(var));
691 hr = E_NOTIMPL;
692 }
693
694 return hr;
695 }
696
xslprocessor_addParameter(IXSLProcessor * iface,BSTR p,VARIANT var,BSTR uri)697 static HRESULT WINAPI xslprocessor_addParameter(
698 IXSLProcessor *iface,
699 BSTR p,
700 VARIANT var,
701 BSTR uri)
702 {
703 xslprocessor *This = impl_from_IXSLProcessor( iface );
704 struct xslprocessor_par *cur, *par = NULL;
705 HRESULT hr;
706
707 TRACE("(%p)->(%s %s %s)\n", This, debugstr_w(p), debugstr_variant(&var),
708 debugstr_w(uri));
709
710 if (uri && *uri)
711 FIXME("namespace uri is not supported\n");
712
713 /* search for existing parameter first */
714 LIST_FOR_EACH_ENTRY(cur, &This->params.list, struct xslprocessor_par, entry)
715 {
716 if (!strcmpW(cur->name, p))
717 {
718 par = cur;
719 break;
720 }
721 }
722
723 /* override with new value or add new parameter */
724 if (par)
725 {
726 if (V_VT(&var) == VT_NULL || V_VT(&var) == VT_EMPTY)
727 {
728 /* remove parameter */
729 xslprocessor_par_free(&This->params, par);
730 return S_OK;
731 }
732 SysFreeString(par->value);
733 par->value = NULL;
734 }
735 else
736 {
737 /* new parameter */
738 par = heap_alloc(sizeof(struct xslprocessor_par));
739 if (!par) return E_OUTOFMEMORY;
740
741 par->name = SysAllocString(p);
742 if (!par->name)
743 {
744 heap_free(par);
745 return E_OUTOFMEMORY;
746 }
747 list_add_tail(&This->params.list, &par->entry);
748 This->params.count++;
749 }
750
751 hr = xslprocessor_set_parvalue(&var, par);
752 if (FAILED(hr))
753 xslprocessor_par_free(&This->params, par);
754
755 return hr;
756 }
757
xslprocessor_addObject(IXSLProcessor * iface,IDispatch * obj,BSTR uri)758 static HRESULT WINAPI xslprocessor_addObject(
759 IXSLProcessor *iface,
760 IDispatch *obj,
761 BSTR uri)
762 {
763 xslprocessor *This = impl_from_IXSLProcessor( iface );
764
765 FIXME("(%p)->(%p %s): stub\n", This, obj, debugstr_w(uri));
766 return E_NOTIMPL;
767 }
768
xslprocessor_get_stylesheet(IXSLProcessor * iface,IXMLDOMNode ** node)769 static HRESULT WINAPI xslprocessor_get_stylesheet(
770 IXSLProcessor *iface,
771 IXMLDOMNode **node)
772 {
773 xslprocessor *This = impl_from_IXSLProcessor( iface );
774
775 FIXME("(%p)->(%p): stub\n", This, node);
776 return E_NOTIMPL;
777 }
778
779 static const struct IXSLProcessorVtbl XSLProcessorVtbl =
780 {
781 xslprocessor_QueryInterface,
782 xslprocessor_AddRef,
783 xslprocessor_Release,
784 xslprocessor_GetTypeInfoCount,
785 xslprocessor_GetTypeInfo,
786 xslprocessor_GetIDsOfNames,
787 xslprocessor_Invoke,
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,
797 xslprocessor_reset,
798 xslprocessor_get_readyState,
799 xslprocessor_addParameter,
800 xslprocessor_addObject,
801 xslprocessor_get_stylesheet
802 };
803
804 static const tid_t xslprocessor_iface_tids[] = {
805 IXSLProcessor_tid,
806 0
807 };
808
809 static dispex_static_data_t xslprocessor_dispex = {
810 NULL,
811 IXSLProcessor_tid,
812 NULL,
813 xslprocessor_iface_tids
814 };
815
XSLProcessor_create(xsltemplate * template,IXSLProcessor ** ppObj)816 HRESULT XSLProcessor_create(xsltemplate *template, IXSLProcessor **ppObj)
817 {
818 xslprocessor *This;
819
820 TRACE("(%p)\n", ppObj);
821
822 This = heap_alloc( sizeof (*This) );
823 if(!This)
824 return E_OUTOFMEMORY;
825
826 This->IXSLProcessor_iface.lpVtbl = &XSLProcessorVtbl;
827 This->ref = 1;
828 This->input = NULL;
829 This->output.unk = NULL;
830 This->output_type = PROCESSOR_OUTPUT_NOT_SET;
831 This->outstr = NULL;
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);
837
838 *ppObj = &This->IXSLProcessor_iface;
839
840 TRACE("returning iface %p\n", *ppObj);
841
842 return S_OK;
843 }
844