From cebed397c335490c57389245b6e365b651a2f796 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Tue, 28 Mar 2017 00:04:33 +0300 Subject: [PATCH] msxml3: Added support for setting IResponse as xsl processor output. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/msxml3/stylesheet.c | 72 ++++++++++++++++++++++++++++++++++++++++------ dlls/msxml3/tests/domdoc.c | 22 ++++++++++++-- 2 files changed, 84 insertions(+), 10 deletions(-) diff --git a/dlls/msxml3/stylesheet.c b/dlls/msxml3/stylesheet.c index 74a91808f8e..4c4f60ee0fa 100644 --- a/dlls/msxml3/stylesheet.c +++ b/dlls/msxml3/stylesheet.c @@ -36,6 +36,9 @@ #include "msxml_private.h" +#include "initguid.h" +#include "asptlb.h" + #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(msxml); @@ -54,6 +57,7 @@ enum output_type PROCESSOR_OUTPUT_NOT_SET, PROCESSOR_OUTPUT_STREAM, /* IStream or ISequentialStream */ PROCESSOR_OUTPUT_PERSISTSTREAM, /* IPersistStream or IPersistStreamInit */ + PROCESSOR_OUTPUT_RESPONSE, /* IResponse */ }; typedef struct @@ -70,6 +74,7 @@ typedef struct IUnknown *unk; ISequentialStream *stream; IPersistStream *persiststream; + IResponse *response; } output; enum output_type output_type; BSTR outstr; @@ -493,7 +498,11 @@ static HRESULT WINAPI xslprocessor_put_output( hr = IUnknown_QueryInterface(V_UNKNOWN(&var), &IID_IStream, (void **)&output); if (FAILED(hr)) hr = IUnknown_QueryInterface(V_UNKNOWN(&var), &IID_ISequentialStream, (void **)&output); - /* FIXME: try IResponse */ + if (FAILED(hr)) + { + output_type = PROCESSOR_OUTPUT_RESPONSE; + hr = IUnknown_QueryInterface(V_UNKNOWN(&var), &IID_IResponse, (void **)&output); + } if (FAILED(hr)) { output_type = PROCESSOR_OUTPUT_PERSISTSTREAM; @@ -570,20 +579,67 @@ static HRESULT WINAPI xslprocessor_transform( stream = This->output.stream; ISequentialStream_AddRef(stream); } - else if (This->output_type == PROCESSOR_OUTPUT_PERSISTSTREAM) + else if (This->output_type == PROCESSOR_OUTPUT_PERSISTSTREAM || + This->output_type == PROCESSOR_OUTPUT_RESPONSE) + { 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) + if (SUCCEEDED(hr)) { 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); + switch (This->output_type) + { + case PROCESSOR_OUTPUT_PERSISTSTREAM: + { + 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); + break; + } + case PROCESSOR_OUTPUT_RESPONSE: + { + SAFEARRAYBOUND bound; + SAFEARRAY *array; + HGLOBAL hglobal; + VARIANT bin; + DWORD size; + void *dest; + + GetHGlobalFromStream(src, &hglobal); + size = GlobalSize(hglobal); + + bound.lLbound = 0; + bound.cElements = size; + if (!(array = SafeArrayCreate(VT_UI1, 1, &bound))) + break; + + V_VT(&bin) = VT_ARRAY | VT_UI1; + V_ARRAY(&bin) = array; + + hr = SafeArrayAccessData(array, &dest); + if (hr == S_OK) + { + void *data = GlobalLock(hglobal); + memcpy(dest, data, size); + GlobalUnlock(hglobal); + SafeArrayUnaccessData(array); + + IResponse_BinaryWrite(This->output.response, bin); + } + + VariantClear(&bin); + break; + } + default: + ; + } } if (stream) diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c index 371349011fd..4bac5a1ccf2 100644 --- a/dlls/msxml3/tests/domdoc.c +++ b/dlls/msxml3/tests/domdoc.c @@ -361,7 +361,6 @@ static HRESULT WINAPI response_QI(IResponse *iface, REFIID riid, void **obj) } if (!IsEqualIID(&IID_IStream, riid) && !IsEqualIID(&IID_ISequentialStream, riid)) -todo_wine ok(0, "unexpected call\n"); return E_NOINTERFACE; } @@ -488,7 +487,25 @@ static HRESULT WINAPI response_AppendToLog(IResponse *iface, BSTR bstrLogEntry) static HRESULT WINAPI response_BinaryWrite(IResponse *iface, VARIANT input) { + HRESULT hr; + LONG bound; + UINT dim; + ok(V_VT(&input) == (VT_ARRAY | VT_UI1), "got wrong input type %x\n", V_VT(&input)); + + dim = SafeArrayGetDim(V_ARRAY(&input)); + ok(dim == 1, "got wrong array dimensions %u\n", dim); + + bound = 1; + hr = SafeArrayGetLBound(V_ARRAY(&input), 1, &bound); + ok(hr == S_OK, "got %#x\n", hr); + ok(bound == 0, "wrong array low bound %d\n", bound); + + bound = 0; + hr = SafeArrayGetUBound(V_ARRAY(&input), 1, &bound); + ok(hr == S_OK, "got %#x\n", hr); + ok(bound > 0, "wrong array high bound %d\n", bound); + return E_NOTIMPL; } @@ -8977,11 +8994,12 @@ todo_wine { V_VT(&v) = VT_UNKNOWN; V_UNKNOWN(&v) = (IUnknown *)&testresponse; hr = IXSLProcessor_put_output(processor, v); -todo_wine ok(hr == S_OK, "got 0x%08x\n", hr); + b = VARIANT_FALSE; hr = IXSLProcessor_transform(processor, &b); ok(hr == S_OK, "got 0x%08x\n", hr); + ok(b == VARIANT_TRUE, "got %x\n", b); IXSLProcessor_Release(processor); IXMLDOMDocument_Release(doc2); -- 2.11.4.GIT