msxml3: Query for handler interface instead of using what was passed in Variant directly
Nikolay Sivov
nsivov at codeweavers.com
Thu Apr 26 15:24:53 CDT 2012
Fix for a crash from http://bugs.winehq.org/show_bug.cgi?id=30513
-------------- next part --------------
>From ef0178c3c32e1eeb73da07ab8655d88be8a59161 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov at codeweavers.com>
Date: Thu, 26 Apr 2012 23:54:22 +0400
Subject: [PATCH 1/1] Query for handler interface instead of using what was passed in Variant directly
---
dlls/msxml3/saxreader.c | 31 ++++++---
dlls/msxml3/tests/saxreader.c | 138 +++++++++++++++++++++++++++++++++--------
2 files changed, 132 insertions(+), 37 deletions(-)
diff --git a/dlls/msxml3/saxreader.c b/dlls/msxml3/saxreader.c
index 913eeaf..090f70c 100644
--- a/dlls/msxml3/saxreader.c
+++ b/dlls/msxml3/saxreader.c
@@ -2575,8 +2575,6 @@ static HRESULT internal_putProperty(
}
break;
case VT_UNKNOWN:
- if (V_UNKNOWN(&value)) IUnknown_AddRef(V_UNKNOWN(&value));
-
if ((vbInterface && This->vbdeclHandler) ||
(!vbInterface && This->declHandler))
{
@@ -2586,10 +2584,17 @@ static HRESULT internal_putProperty(
ISAXDeclHandler_Release(This->declHandler);
}
- if (vbInterface)
- This->vbdeclHandler = (IVBSAXDeclHandler*)V_UNKNOWN(&value);
+ if (V_UNKNOWN(&value))
+ {
+ return vbInterface ?
+ IVBSAXDeclHandler_QueryInterface(V_UNKNOWN(&value), &IID_IVBSAXDeclHandler, (void**)&This->vbdeclHandler) :
+ ISAXDeclHandler_QueryInterface(V_UNKNOWN(&value), &IID_ISAXDeclHandler, (void**)&This->declHandler);
+ }
else
- This->declHandler = (ISAXDeclHandler*)V_UNKNOWN(&value);
+ {
+ This->vbdeclHandler = NULL;
+ This->declHandler = NULL;
+ }
break;
default:
return E_INVALIDARG;
@@ -2621,8 +2626,6 @@ static HRESULT internal_putProperty(
}
break;
case VT_UNKNOWN:
- if (V_UNKNOWN(&value)) IUnknown_AddRef(V_UNKNOWN(&value));
-
if ((vbInterface && This->vblexicalHandler) ||
(!vbInterface && This->lexicalHandler))
{
@@ -2632,10 +2635,18 @@ static HRESULT internal_putProperty(
ISAXLexicalHandler_Release(This->lexicalHandler);
}
- if (vbInterface)
- This->vblexicalHandler = (IVBSAXLexicalHandler*)V_UNKNOWN(&value);
+ if (V_UNKNOWN(&value))
+ {
+ return vbInterface ?
+ IVBSAXLexicalHandler_QueryInterface(V_UNKNOWN(&value), &IID_IVBSAXLexicalHandler, (void**)&This->vblexicalHandler) :
+ ISAXLexicalHandler_QueryInterface(V_UNKNOWN(&value), &IID_ISAXLexicalHandler, (void**)&This->lexicalHandler);
+ }
else
- This->lexicalHandler = (ISAXLexicalHandler*)V_UNKNOWN(&value);
+ {
+ This->vblexicalHandler = NULL;
+ This->lexicalHandler = NULL;
+ }
+
break;
default:
return E_INVALIDARG;
diff --git a/dlls/msxml3/tests/saxreader.c b/dlls/msxml3/tests/saxreader.c
index ebb9d89..cb1a088 100644
--- a/dlls/msxml3/tests/saxreader.c
+++ b/dlls/msxml3/tests/saxreader.c
@@ -46,6 +46,16 @@ static void _expect_ref(IUnknown* obj, ULONG ref, int line)
ok_(__FILE__,line)(rc-1 == ref, "expected refcount %d, got %d\n", ref, rc-1);
}
+static LONG get_refcount(void *iface)
+{
+ IUnknown *unk = iface;
+ LONG ref;
+
+ ref = IUnknown_AddRef(unk);
+ IUnknown_Release(unk);
+ return ref-1;
+}
+
struct msxmlsupported_data_t
{
const GUID *clsid;
@@ -1465,34 +1475,54 @@ static const ISAXAttributesVtbl SAXAttributesVtbl =
static ISAXAttributes saxattributes = { &SAXAttributesVtbl };
-static int handler_addrefcalled;
+struct saxlexicalhandler
+{
+ ISAXLexicalHandler ISAXLexicalHandler_iface;
+ LONG ref;
-static HRESULT WINAPI isaxlexical_QueryInterface(ISAXLexicalHandler* iface, REFIID riid, void **ppvObject)
+ HRESULT qi_hr; /* ret value for QueryInterface for handler riid */
+};
+
+static inline struct saxlexicalhandler *impl_from_ISAXLexicalHandler( ISAXLexicalHandler *iface )
{
- *ppvObject = NULL;
+ return CONTAINING_RECORD(iface, struct saxlexicalhandler, ISAXLexicalHandler_iface);
+}
+
+static HRESULT WINAPI isaxlexical_QueryInterface(ISAXLexicalHandler* iface, REFIID riid, void **out)
+{
+ struct saxlexicalhandler *handler = impl_from_ISAXLexicalHandler(iface);
+
+ *out = NULL;
- if(IsEqualGUID(riid, &IID_IUnknown) ||
- IsEqualGUID(riid, &IID_ISAXLexicalHandler))
+ if (IsEqualGUID(riid, &IID_IUnknown))
{
- *ppvObject = iface;
+ *out = iface;
+ ok(0, "got unexpected IID_IUnknown query\n");
}
- else
+ else if (IsEqualGUID(riid, &IID_ISAXLexicalHandler))
{
- return E_NOINTERFACE;
+ if (handler->qi_hr == E_NOINTERFACE) return handler->qi_hr;
+ *out = iface;
}
+ if (*out)
+ ISAXLexicalHandler_AddRef(iface);
+ else
+ return E_NOINTERFACE;
+
return S_OK;
}
static ULONG WINAPI isaxlexical_AddRef(ISAXLexicalHandler* iface)
{
- handler_addrefcalled++;
- return 2;
+ struct saxlexicalhandler *handler = impl_from_ISAXLexicalHandler(iface);
+ return InterlockedIncrement(&handler->ref);
}
static ULONG WINAPI isaxlexical_Release(ISAXLexicalHandler* iface)
{
- return 1;
+ struct saxlexicalhandler *handler = impl_from_ISAXLexicalHandler(iface);
+ return InterlockedDecrement(&handler->ref);
}
static HRESULT WINAPI isaxlexical_startDTD(ISAXLexicalHandler* iface,
@@ -1556,34 +1586,61 @@ static const ISAXLexicalHandlerVtbl SAXLexicalHandlerVtbl =
isaxlexical_comment
};
-static ISAXLexicalHandler saxlexicalhandler = { &SAXLexicalHandlerVtbl };
+static void init_saxlexicalhandler(struct saxlexicalhandler *handler, HRESULT hr)
+{
+ handler->ISAXLexicalHandler_iface.lpVtbl = &SAXLexicalHandlerVtbl;
+ handler->ref = 1;
+ handler->qi_hr = hr;
+}
-static HRESULT WINAPI isaxdecl_QueryInterface(ISAXDeclHandler* iface, REFIID riid, void **ppvObject)
+struct saxdeclhandler
{
- *ppvObject = NULL;
+ ISAXDeclHandler ISAXDeclHandler_iface;
+ LONG ref;
+
+ HRESULT qi_hr; /* ret value for QueryInterface for handler riid */
+};
- if(IsEqualGUID(riid, &IID_IUnknown) ||
- IsEqualGUID(riid, &IID_ISAXDeclHandler))
+static inline struct saxdeclhandler *impl_from_ISAXDeclHandler( ISAXDeclHandler *iface )
+{
+ return CONTAINING_RECORD(iface, struct saxdeclhandler, ISAXDeclHandler_iface);
+}
+
+static HRESULT WINAPI isaxdecl_QueryInterface(ISAXDeclHandler* iface, REFIID riid, void **out)
+{
+ struct saxdeclhandler *handler = impl_from_ISAXDeclHandler(iface);
+
+ *out = NULL;
+
+ if (IsEqualGUID(riid, &IID_IUnknown))
{
- *ppvObject = iface;
+ *out = iface;
+ ok(0, "got unexpected IID_IUnknown query\n");
}
- else
+ else if (IsEqualGUID(riid, &IID_ISAXDeclHandler))
{
- return E_NOINTERFACE;
+ if (handler->qi_hr == E_NOINTERFACE) return handler->qi_hr;
+ *out = iface;
}
+ if (*out)
+ ISAXDeclHandler_AddRef(iface);
+ else
+ return E_NOINTERFACE;
+
return S_OK;
}
static ULONG WINAPI isaxdecl_AddRef(ISAXDeclHandler* iface)
{
- handler_addrefcalled++;
- return 2;
+ struct saxdeclhandler *handler = impl_from_ISAXDeclHandler(iface);
+ return InterlockedIncrement(&handler->ref);
}
static ULONG WINAPI isaxdecl_Release(ISAXDeclHandler* iface)
{
- return 1;
+ struct saxdeclhandler *handler = impl_from_ISAXDeclHandler(iface);
+ return InterlockedDecrement(&handler->ref);
}
static HRESULT WINAPI isaxdecl_elementDecl(ISAXDeclHandler* iface,
@@ -1628,7 +1685,12 @@ static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl =
isaxdecl_externalEntityDecl
};
-static ISAXDeclHandler saxdeclhandler = { &SAXDeclHandlerVtbl };
+static void init_saxdeclhandler(struct saxdeclhandler *handler, HRESULT hr)
+{
+ handler->ISAXDeclHandler_iface.lpVtbl = &SAXDeclHandlerVtbl;
+ handler->ref = 1;
+ handler->qi_hr = hr;
+}
typedef struct mxwriter_write_test_t {
BOOL last;
@@ -2121,9 +2183,12 @@ struct saxreader_props_test_t
IUnknown *iface;
};
+static struct saxlexicalhandler lexicalhandler;
+static struct saxdeclhandler declhandler;
+
static const struct saxreader_props_test_t props_test_data[] = {
- { "http://xml.org/sax/properties/lexical-handler", (IUnknown*)&saxlexicalhandler },
- { "http://xml.org/sax/properties/declaration-handler", (IUnknown*)&saxdeclhandler },
+ { "http://xml.org/sax/properties/lexical-handler", (IUnknown*)&lexicalhandler.ISAXLexicalHandler_iface },
+ { "http://xml.org/sax/properties/declaration-handler", (IUnknown*)&declhandler.ISAXDeclHandler_iface },
{ 0 }
};
@@ -2143,6 +2208,10 @@ static void test_saxreader_properties(void)
while (ptr->prop_name)
{
VARIANT v;
+ LONG ref;
+
+ init_saxlexicalhandler(&lexicalhandler, S_OK);
+ init_saxdeclhandler(&declhandler, S_OK);
V_VT(&v) = VT_EMPTY;
V_UNKNOWN(&v) = (IUnknown*)0xdeadbeef;
@@ -2153,17 +2222,20 @@ static void test_saxreader_properties(void)
V_VT(&v) = VT_UNKNOWN;
V_UNKNOWN(&v) = ptr->iface;
+ ref = get_refcount(ptr->iface);
hr = ISAXXMLReader_putProperty(reader, _bstr_(ptr->prop_name), v);
EXPECT_HR(hr, S_OK);
+ ok(ref < get_refcount(ptr->iface), "expected inreased refcount\n");
V_VT(&v) = VT_EMPTY;
V_UNKNOWN(&v) = (IUnknown*)0xdeadbeef;
- handler_addrefcalled = 0;
+
+ ref = get_refcount(ptr->iface);
hr = ISAXXMLReader_getProperty(reader, _bstr_(ptr->prop_name), &v);
EXPECT_HR(hr, S_OK);
ok(V_VT(&v) == VT_UNKNOWN, "got %d\n", V_VT(&v));
ok(V_UNKNOWN(&v) == ptr->iface, "got %p\n", V_UNKNOWN(&v));
- ok(handler_addrefcalled == 1, "AddRef called %d times\n", handler_addrefcalled);
+ ok(ref < get_refcount(ptr->iface), "expected inreased refcount\n");
VariantClear(&v);
V_VT(&v) = VT_EMPTY;
@@ -2209,6 +2281,18 @@ static void test_saxreader_properties(void)
ok(V_VT(&v) == VT_UNKNOWN, "got %d\n", V_VT(&v));
ok(V_UNKNOWN(&v) == NULL, "got %p\n", V_UNKNOWN(&v));
+ /* block QueryInterface on handler riid */
+ init_saxlexicalhandler(&lexicalhandler, E_NOINTERFACE);
+ init_saxdeclhandler(&declhandler, E_NOINTERFACE);
+
+ V_VT(&v) = VT_UNKNOWN;
+ V_UNKNOWN(&v) = ptr->iface;
+ EXPECT_REF(ptr->iface, 1);
+ ref = get_refcount(ptr->iface);
+ hr = ISAXXMLReader_putProperty(reader, _bstr_(ptr->prop_name), v);
+ EXPECT_HR(hr, E_NOINTERFACE);
+ EXPECT_REF(ptr->iface, 1);
+
ptr++;
}
--
1.5.6.5
More information about the wine-patches
mailing list