From: Daniel Lehman Subject: [PATCH] msxml3: Don't QI for IPersistStream in internal_parse Message-Id: <31db48f9173746c5af9b9021a582124e@RED-INF-MXMB-P4.esri.com> Date: Mon, 13 Mar 2017 20:53:39 +0000 From a02eef95d61a877eb19f116ba7a9a02a70c0b3d5 Mon Sep 17 00:00:00 2001 From: Daniel Lehman Date: Mon, 13 Mar 2017 11:28:18 -0700 Subject: [PATCH] msxml3: Don't QI for IPersistStream in internal_parse internal_parse QIs for IPersistStream and calls Save to convert to an IStream in memory. but IPersistStream::Save might not be implemented in a way that writes readable XML Windows doesn't appear to query for IPersistStream and returns E_INVALIDARG from "parse Method1" in ISAXXMLReader interface docs on MSDN: https://msdn.microsoft.com/en-us/library/ms764729.aspx " Parameters varInput A variant (or a reference to one) containing the input source to parse from. The following VARIANT types are supported: ... - VT_UNKNOWN or VT_DISPATCH, which can contain a value in the form of either an IStream, ISequentialStream, or IXMLDOMDocument " Signed-off-by: Daniel Lehman --- dlls/msxml3/saxreader.c | 32 ++--------- dlls/msxml3/tests/saxreader.c | 127 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 28 deletions(-) diff --git a/dlls/msxml3/saxreader.c b/dlls/msxml3/saxreader.c index 78cfe08..82241ad 100644 --- a/dlls/msxml3/saxreader.c +++ b/dlls/msxml3/saxreader.c @@ -2661,7 +2661,6 @@ static HRESULT internal_parse( } case VT_UNKNOWN: case VT_DISPATCH: { - IPersistStream *persistStream; ISequentialStream *stream = NULL; IXMLDOMDocument *xmlDoc; @@ -2678,34 +2677,11 @@ static HRESULT internal_parse( break; } - if(IUnknown_QueryInterface(V_UNKNOWN(&varInput), - &IID_IPersistStream, (void**)&persistStream) == S_OK) - { - IStream *stream_copy; - - hr = CreateStreamOnHGlobal(NULL, TRUE, &stream_copy); - if(hr != S_OK) - { - IPersistStream_Release(persistStream); - return hr; - } - - hr = IPersistStream_Save(persistStream, stream_copy, TRUE); - IPersistStream_Release(persistStream); - if(hr == S_OK) - IStream_QueryInterface(stream_copy, &IID_ISequentialStream, (void**)&stream); - - IStream_Release(stream_copy); - } - /* try base interface first */ - if(!stream) - { - IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_ISequentialStream, (void**)&stream); - if (!stream) - /* this should never happen if IStream is implemented properly, but just in case */ - IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_IStream, (void**)&stream); - } + IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_ISequentialStream, (void**)&stream); + if (!stream) + /* this should never happen if IStream is implemented properly, but just in case */ + IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_IStream, (void**)&stream); if(stream) { diff --git a/dlls/msxml3/tests/saxreader.c b/dlls/msxml3/tests/saxreader.c index 5fc62b7..04bbd41 100644 --- a/dlls/msxml3/tests/saxreader.c +++ b/dlls/msxml3/tests/saxreader.c @@ -5619,6 +5619,132 @@ static void test_mxwriter_indent(void) free_bstrs(); } +typedef struct +{ + IPersistStream IPersistStream_iface; + LONG ref; +} ipstream; + +static inline ipstream *impl_from_IPersistStream( IPersistStream *iface ) +{ + return CONTAINING_RECORD(iface, ipstream, IPersistStream_iface); +} + +static HRESULT WINAPI ipstream_QueryInterface(IPersistStream *iface, REFIID riid, void **ppvObject) +{ + *ppvObject = NULL; + + if(IsEqualGUID(riid, &IID_IUnknown) || + IsEqualGUID(riid, &IID_IPersistStream)) + *ppvObject = iface; + else + return E_NOINTERFACE; + + return S_OK; +} + +static ULONG WINAPI ipstream_AddRef(IPersistStream *iface) +{ + ipstream *This = impl_from_IPersistStream( iface ); + return InterlockedIncrement( &This->ref ); +} + +static ULONG WINAPI ipstream_Release(IPersistStream *iface) +{ + ipstream *This = impl_from_IPersistStream( iface ); + ULONG ref = InterlockedDecrement( &This->ref ); + + if (ref == 0) + HeapFree(GetProcessHeap(), 0, This); + + return ref; +} + +static HRESULT WINAPI ipstream_GetClassID(IPersistStream *iface, CLSID *clsid) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ipstream_IsDirty(IPersistStream *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ipstream_Load(IPersistStream *iface, IStream *stream) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ipstream_Save(IPersistStream *iface, IStream *stream, BOOL clear) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ipstream_GetSizeMax(IPersistStream *iface, ULARGE_INTEGER *size) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const IPersistStreamVtbl saxreaderipstreamVtbl = +{ + ipstream_QueryInterface, + ipstream_AddRef, + ipstream_Release, + ipstream_GetClassID, + ipstream_IsDirty, + ipstream_Load, + ipstream_Save, + ipstream_GetSizeMax +}; + +static IPersistStream *create_ipstream(void) +{ + ipstream *ipstream = HeapAlloc(GetProcessHeap(), 0, sizeof(*ipstream)); + + ipstream->IPersistStream_iface.lpVtbl = &saxreaderipstreamVtbl; + ipstream->ref = 1; + + return &ipstream->IPersistStream_iface; +} + +static void test_saxreader_ipersiststream(void) +{ + const struct msxmlsupported_data_t *table = reader_support_data; + IPersistStream *persist; + ISAXXMLReader *reader; + VARIANT var; + HRESULT hr; + + while (table->clsid) + { + if (!is_clsid_supported(table->clsid, reader_support_data)) + { + table++; + continue; + } + + hr = CoCreateInstance(table->clsid, NULL, CLSCTX_INPROC_SERVER, &IID_ISAXXMLReader, (void**)&reader); + EXPECT_HR(hr, S_OK); + + persist = create_ipstream(); + V_VT(&var) = VT_UNKNOWN; + V_UNKNOWN(&var) = (IUnknown*)persist; + + hr = ISAXXMLReader_parse(reader, var); + EXPECT_HR(hr, E_INVALIDARG); + + IPersistStream_Release(persist); + + ISAXXMLReader_Release(reader); + table++; + } +} + START_TEST(saxreader) { ISAXXMLReader *reader; @@ -5647,6 +5773,7 @@ START_TEST(saxreader) test_saxreader_features(); test_saxreader_encoding(); test_saxreader_dispex(); + test_saxreader_ipersiststream(); /* MXXMLWriter tests */ get_class_support_data(mxwriter_support_data, &IID_IMXWriter); -- 1.9.5