msxml3: Query for handler interface instead of using what was passed in Variant directly.

oldstable
Nikolay Sivov 2012-04-26 23:54:22 +04:00 committed by Alexandre Julliard
parent 3ef92af6a8
commit 28335fb39b
2 changed files with 134 additions and 39 deletions

View File

@ -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;

View File

@ -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;
static HRESULT WINAPI isaxlexical_QueryInterface(ISAXLexicalHandler* iface, REFIID riid, void **ppvObject)
struct saxlexicalhandler
{
*ppvObject = NULL;
ISAXLexicalHandler ISAXLexicalHandler_iface;
LONG ref;
if(IsEqualGUID(riid, &IID_IUnknown) ||
IsEqualGUID(riid, &IID_ISAXLexicalHandler))
HRESULT qi_hr; /* ret value for QueryInterface for handler riid */
};
static inline struct saxlexicalhandler *impl_from_ISAXLexicalHandler( ISAXLexicalHandler *iface )
{
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))
{
*ppvObject = iface;
*out = iface;
ok(0, "got unexpected IID_IUnknown query\n");
}
else if (IsEqualGUID(riid, &IID_ISAXLexicalHandler))
{
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 HRESULT WINAPI isaxdecl_QueryInterface(ISAXDeclHandler* iface, REFIID riid, void **ppvObject)
static void init_saxlexicalhandler(struct saxlexicalhandler *handler, HRESULT hr)
{
*ppvObject = NULL;
handler->ISAXLexicalHandler_iface.lpVtbl = &SAXLexicalHandlerVtbl;
handler->ref = 1;
handler->qi_hr = hr;
}
if(IsEqualGUID(riid, &IID_IUnknown) ||
IsEqualGUID(riid, &IID_ISAXDeclHandler))
struct saxdeclhandler
{
ISAXDeclHandler ISAXDeclHandler_iface;
LONG ref;
HRESULT qi_hr; /* ret value for QueryInterface for handler riid */
};
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 if (IsEqualGUID(riid, &IID_ISAXDeclHandler))
{
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++;
}