msxml3: Support IPersistStream* as IXSLProcessor output.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
7019347409
commit
ea9b797409
|
@ -358,7 +358,8 @@ extern HRESULT node_get_text(const xmlnode*,BSTR*) DECLSPEC_HIDDEN;
|
|||
extern HRESULT node_select_nodes(const xmlnode*,BSTR,IXMLDOMNodeList**) DECLSPEC_HIDDEN;
|
||||
extern HRESULT node_select_singlenode(const xmlnode*,BSTR,IXMLDOMNode**) DECLSPEC_HIDDEN;
|
||||
extern HRESULT node_transform_node(const xmlnode*,IXMLDOMNode*,BSTR*) DECLSPEC_HIDDEN;
|
||||
extern HRESULT node_transform_node_params(const xmlnode*,IXMLDOMNode*,BSTR*,IStream*,const struct xslprocessor_params*) DECLSPEC_HIDDEN;
|
||||
extern HRESULT node_transform_node_params(const xmlnode*,IXMLDOMNode*,BSTR*,ISequentialStream*,
|
||||
const struct xslprocessor_params*) DECLSPEC_HIDDEN;
|
||||
extern HRESULT node_create_supporterrorinfo(const tid_t*,void**) DECLSPEC_HIDDEN;
|
||||
|
||||
extern HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -1035,7 +1035,7 @@ static void xml_write_quotedstring(xmlOutputBufferPtr buf, const xmlChar *string
|
|||
static int XMLCALL transform_to_stream_write(void *context, const char *buffer, int len)
|
||||
{
|
||||
DWORD written;
|
||||
HRESULT hr = IStream_Write((IStream*)context, buffer, len, &written);
|
||||
HRESULT hr = ISequentialStream_Write((ISequentialStream *)context, buffer, len, &written);
|
||||
return hr == S_OK ? written : -1;
|
||||
}
|
||||
|
||||
|
@ -1280,7 +1280,7 @@ static HRESULT node_transform_write_to_bstr(xsltStylesheetPtr style, xmlDocPtr r
|
|||
return *str ? hr : E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
static HRESULT node_transform_write_to_stream(xsltStylesheetPtr style, xmlDocPtr result, IStream *stream)
|
||||
static HRESULT node_transform_write_to_stream(xsltStylesheetPtr style, xmlDocPtr result, ISequentialStream *stream)
|
||||
{
|
||||
static const xmlChar *utf16 = (const xmlChar*)"UTF-16";
|
||||
xmlOutputBufferPtr output;
|
||||
|
@ -1316,7 +1316,7 @@ static HRESULT node_transform_write_to_stream(xsltStylesheetPtr style, xmlDocPtr
|
|||
#endif
|
||||
|
||||
HRESULT node_transform_node_params(const xmlnode *This, IXMLDOMNode *stylesheet, BSTR *p,
|
||||
IStream *stream, const struct xslprocessor_params *params)
|
||||
ISequentialStream *stream, const struct xslprocessor_params *params)
|
||||
{
|
||||
#ifdef SONAME_LIBXSLT
|
||||
xsltStylesheetPtr xsltSS;
|
||||
|
|
|
@ -49,6 +49,13 @@ typedef struct
|
|||
IXMLDOMNode *node;
|
||||
} xsltemplate;
|
||||
|
||||
enum output_type
|
||||
{
|
||||
PROCESSOR_OUTPUT_NOT_SET,
|
||||
PROCESSOR_OUTPUT_STREAM, /* IStream or ISequentialStream */
|
||||
PROCESSOR_OUTPUT_PERSISTSTREAM, /* IPersistStream or IPersistStreamInit */
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DispatchEx dispex;
|
||||
|
@ -58,8 +65,14 @@ typedef struct
|
|||
xsltemplate *stylesheet;
|
||||
IXMLDOMNode *input;
|
||||
|
||||
IStream *output;
|
||||
BSTR outstr;
|
||||
union
|
||||
{
|
||||
IUnknown *unk;
|
||||
ISequentialStream *stream;
|
||||
IPersistStream *persiststream;
|
||||
} output;
|
||||
enum output_type output_type;
|
||||
BSTR outstr;
|
||||
|
||||
struct xslprocessor_params params;
|
||||
} xslprocessor;
|
||||
|
@ -318,7 +331,8 @@ static ULONG WINAPI xslprocessor_Release( IXSLProcessor *iface )
|
|||
struct xslprocessor_par *par, *par2;
|
||||
|
||||
if (This->input) IXMLDOMNode_Release(This->input);
|
||||
if (This->output) IStream_Release(This->output);
|
||||
if (This->output.unk)
|
||||
IUnknown_Release(This->output.unk);
|
||||
SysFreeString(This->outstr);
|
||||
|
||||
LIST_FOR_EACH_ENTRY_SAFE(par, par2, &This->params.list, struct xslprocessor_par, entry)
|
||||
|
@ -457,34 +471,53 @@ static HRESULT WINAPI xslprocessor_get_startModeURI(
|
|||
|
||||
static HRESULT WINAPI xslprocessor_put_output(
|
||||
IXSLProcessor *iface,
|
||||
VARIANT output)
|
||||
VARIANT var)
|
||||
{
|
||||
xslprocessor *This = impl_from_IXSLProcessor( iface );
|
||||
IStream *stream;
|
||||
HRESULT hr;
|
||||
enum output_type output_type = PROCESSOR_OUTPUT_NOT_SET;
|
||||
IUnknown *output = NULL;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
TRACE("(%p)->(%s)\n", This, debugstr_variant(&output));
|
||||
TRACE("(%p)->(%s)\n", This, debugstr_variant(&var));
|
||||
|
||||
switch (V_VT(&output))
|
||||
switch (V_VT(&var))
|
||||
{
|
||||
case VT_EMPTY:
|
||||
stream = NULL;
|
||||
hr = S_OK;
|
||||
case VT_EMPTY:
|
||||
break;
|
||||
case VT_UNKNOWN:
|
||||
hr = IUnknown_QueryInterface(V_UNKNOWN(&output), &IID_IStream, (void**)&stream);
|
||||
case VT_UNKNOWN:
|
||||
case VT_DISPATCH:
|
||||
if (!V_UNKNOWN(&var))
|
||||
break;
|
||||
|
||||
output_type = PROCESSOR_OUTPUT_STREAM;
|
||||
hr = IUnknown_QueryInterface(V_UNKNOWN(&var), &IID_IStream, (void **)&output);
|
||||
if (FAILED(hr))
|
||||
WARN("failed to get IStream from output, 0x%08x\n", hr);
|
||||
hr = IUnknown_QueryInterface(V_UNKNOWN(&var), &IID_ISequentialStream, (void **)&output);
|
||||
/* FIXME: try IResponse */
|
||||
if (FAILED(hr))
|
||||
{
|
||||
output_type = PROCESSOR_OUTPUT_PERSISTSTREAM;
|
||||
hr = IUnknown_QueryInterface(V_UNKNOWN(&var), &IID_IPersistStream, (void **)&output);
|
||||
}
|
||||
if (FAILED(hr))
|
||||
hr = IUnknown_QueryInterface(V_UNKNOWN(&var), &IID_IPersistStreamInit, (void **)&output);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
output_type = PROCESSOR_OUTPUT_NOT_SET;
|
||||
WARN("failed to get output interface, 0x%08x\n", hr);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
FIXME("output type %d not handled\n", V_VT(&output));
|
||||
default:
|
||||
FIXME("output type %d not handled\n", V_VT(&var));
|
||||
hr = E_FAIL;
|
||||
}
|
||||
|
||||
if (hr == S_OK)
|
||||
{
|
||||
if (This->output) IStream_Release(This->output);
|
||||
This->output = stream;
|
||||
if (This->output.unk)
|
||||
IUnknown_Release(This->output.unk);
|
||||
This->output.unk = output;
|
||||
This->output_type = output_type;
|
||||
}
|
||||
|
||||
return hr;
|
||||
|
@ -500,11 +533,11 @@ static HRESULT WINAPI xslprocessor_get_output(
|
|||
|
||||
if (!output) return E_INVALIDARG;
|
||||
|
||||
if (This->output)
|
||||
if (This->output.unk)
|
||||
{
|
||||
V_VT(output) = VT_UNKNOWN;
|
||||
V_UNKNOWN(output) = (IUnknown*)This->output;
|
||||
IStream_AddRef(This->output);
|
||||
V_UNKNOWN(output) = This->output.unk;
|
||||
IUnknown_AddRef(This->output.unk);
|
||||
}
|
||||
else if (This->outstr)
|
||||
{
|
||||
|
@ -523,6 +556,7 @@ static HRESULT WINAPI xslprocessor_transform(
|
|||
{
|
||||
#ifdef HAVE_LIBXML2
|
||||
xslprocessor *This = impl_from_IXSLProcessor( iface );
|
||||
ISequentialStream *stream = NULL;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%p)->(%p)\n", This, ret);
|
||||
|
@ -530,7 +564,31 @@ static HRESULT WINAPI xslprocessor_transform(
|
|||
if (!ret) return E_INVALIDARG;
|
||||
|
||||
SysFreeString(This->outstr);
|
||||
hr = node_transform_node_params(get_node_obj(This->input), This->stylesheet->node, &This->outstr, This->output, &This->params);
|
||||
|
||||
if (This->output_type == PROCESSOR_OUTPUT_STREAM)
|
||||
{
|
||||
stream = This->output.stream;
|
||||
ISequentialStream_AddRef(stream);
|
||||
}
|
||||
else if (This->output_type == PROCESSOR_OUTPUT_PERSISTSTREAM)
|
||||
CreateStreamOnHGlobal(NULL, TRUE, (IStream **)&stream);
|
||||
|
||||
hr = node_transform_node_params(get_node_obj(This->input), This->stylesheet->node,
|
||||
&This->outstr, stream, &This->params);
|
||||
if (SUCCEEDED(hr) && This->output_type == PROCESSOR_OUTPUT_PERSISTSTREAM)
|
||||
{
|
||||
IStream *src = (IStream *)stream;
|
||||
LARGE_INTEGER zero;
|
||||
|
||||
/* for IPersistStream* output seekable stream is used */
|
||||
zero.QuadPart = 0;
|
||||
IStream_Seek(src, zero, STREAM_SEEK_SET, NULL);
|
||||
hr = IPersistStream_Load(This->output.persiststream, src);
|
||||
}
|
||||
|
||||
if (stream)
|
||||
ISequentialStream_Release(stream);
|
||||
|
||||
*ret = hr == S_OK ? VARIANT_TRUE : VARIANT_FALSE;
|
||||
return hr;
|
||||
#else
|
||||
|
@ -709,7 +767,8 @@ HRESULT XSLProcessor_create(xsltemplate *template, IXSLProcessor **ppObj)
|
|||
This->IXSLProcessor_iface.lpVtbl = &XSLProcessorVtbl;
|
||||
This->ref = 1;
|
||||
This->input = NULL;
|
||||
This->output = NULL;
|
||||
This->output.unk = NULL;
|
||||
This->output_type = PROCESSOR_OUTPUT_NOT_SET;
|
||||
This->outstr = NULL;
|
||||
list_init(&This->params.list);
|
||||
This->params.count = 0;
|
||||
|
|
|
@ -8496,14 +8496,15 @@ static void test_get_xml(void)
|
|||
|
||||
static void test_xsltemplate(void)
|
||||
{
|
||||
IXMLDOMDocument *doc, *doc2, *doc3;
|
||||
IXSLTemplate *template;
|
||||
IXSLProcessor *processor;
|
||||
IXMLDOMDocument *doc, *doc2;
|
||||
IStream *stream;
|
||||
VARIANT_BOOL b;
|
||||
HRESULT hr;
|
||||
ULONG ref1, ref2;
|
||||
VARIANT v;
|
||||
BSTR str;
|
||||
|
||||
if (!is_clsid_supported(&CLSID_XSLTemplate, &IID_IXSLTemplate)) return;
|
||||
template = create_xsltemplate(&IID_IXSLTemplate);
|
||||
|
@ -8583,6 +8584,16 @@ todo_wine {
|
|||
hr = IXSLProcessor_put_output(processor, v);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
|
||||
V_VT(&v) = VT_UNKNOWN;
|
||||
V_UNKNOWN(&v) = NULL;
|
||||
hr = IXSLProcessor_put_output(processor, v);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
|
||||
V_VT(&v) = VT_UNKNOWN;
|
||||
V_DISPATCH(&v) = NULL;
|
||||
hr = IXSLProcessor_put_output(processor, v);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
|
||||
hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
EXPECT_REF(stream, 1);
|
||||
|
@ -8619,7 +8630,7 @@ todo_wine {
|
|||
/* no output interface set, check output */
|
||||
doc2 = create_document(&IID_IXMLDOMDocument);
|
||||
|
||||
b = VARIANT_TRUE;
|
||||
b = VARIANT_FALSE;
|
||||
hr = IXMLDOMDocument_loadXML( doc2, _bstr_("<a>test</a>"), &b );
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok( b == VARIANT_TRUE, "got %d\n", b);
|
||||
|
@ -8637,10 +8648,47 @@ todo_wine {
|
|||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(V_VT(&v) == VT_BSTR, "got type %d\n", V_VT(&v));
|
||||
ok(*V_BSTR(&v) == 0, "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
|
||||
IXMLDOMDocument_Release(doc2);
|
||||
VariantClear(&v);
|
||||
|
||||
/* transform to document */
|
||||
b = VARIANT_FALSE;
|
||||
hr = IXMLDOMDocument_loadXML(doc2, _bstr_(szTransformXML), &b);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(b == VARIANT_TRUE, "got %d\n", b);
|
||||
|
||||
V_VT(&v) = VT_UNKNOWN;
|
||||
V_UNKNOWN(&v) = (IUnknown*)doc2;
|
||||
hr = IXSLProcessor_put_input(processor, v);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
|
||||
doc3 = create_document(&IID_IXMLDOMDocument);
|
||||
V_VT(&v) = VT_UNKNOWN;
|
||||
V_UNKNOWN(&v) = (IUnknown *)doc3;
|
||||
hr = IXSLProcessor_put_output(processor, v);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
|
||||
hr = IXMLDOMDocument_get_xml(doc3, &str);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(!*str, "Expected empty document\n");
|
||||
SysFreeString(str);
|
||||
|
||||
hr = IXSLProcessor_transform(processor, &b);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
|
||||
V_VT(&v) = VT_EMPTY;
|
||||
hr = IXSLProcessor_get_output(processor, &v);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(V_VT(&v) == VT_UNKNOWN, "got type %d\n", V_VT(&v));
|
||||
VariantClear(&v);
|
||||
|
||||
hr = IXMLDOMDocument_get_xml(doc3, &str);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(!!*str, "Expected document\n");
|
||||
SysFreeString(str);
|
||||
|
||||
IXSLProcessor_Release(processor);
|
||||
IXMLDOMDocument_Release(doc2);
|
||||
IXMLDOMDocument_Release(doc3);
|
||||
|
||||
/* drop reference */
|
||||
hr = IXSLTemplate_putref_stylesheet(template, NULL);
|
||||
|
|
Loading…
Reference in New Issue