Commit df08e9b4 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

msxml3: Store document event handler for ready state notification.

parent 01a6286b
...@@ -105,6 +105,13 @@ struct ConnectionPoint ...@@ -105,6 +105,13 @@ struct ConnectionPoint
DWORD sinks_size; DWORD sinks_size;
}; };
typedef enum {
EVENTID_READYSTATECHANGE = 0,
EVENTID_DATAAVAILABLE,
EVENTID_TRANSFORMNODE,
EVENTID_LAST
} eventid_t;
struct domdoc struct domdoc
{ {
xmlnode node; xmlnode node;
...@@ -136,8 +143,37 @@ struct domdoc ...@@ -136,8 +143,37 @@ struct domdoc
ConnectionPoint cp_domdocevents; ConnectionPoint cp_domdocevents;
ConnectionPoint cp_propnotif; ConnectionPoint cp_propnotif;
ConnectionPoint cp_dispatch; ConnectionPoint cp_dispatch;
/* events */
IDispatch *events[EVENTID_LAST];
}; };
static HRESULT set_doc_event(domdoc *doc, eventid_t eid, const VARIANT *v)
{
IDispatch *disp;
switch (V_VT(v))
{
case VT_UNKNOWN:
if (V_UNKNOWN(v))
IUnknown_QueryInterface(V_UNKNOWN(v), &IID_IDispatch, (void**)&disp);
else
disp = NULL;
break;
case VT_DISPATCH:
disp = V_DISPATCH(v);
if (disp) IDispatch_AddRef(disp);
break;
default:
return DISP_E_TYPEMISMATCH;
}
if (doc->events[eid]) IDispatch_Release(doc->events[eid]);
doc->events[eid] = disp;
return S_OK;
}
static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface) static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface)
{ {
return (ConnectionPoint *)((char*)iface - FIELD_OFFSET(ConnectionPoint, lpVtblConnectionPoint)); return (ConnectionPoint *)((char*)iface - FIELD_OFFSET(ConnectionPoint, lpVtblConnectionPoint));
...@@ -909,6 +945,8 @@ static ULONG WINAPI domdoc_Release( ...@@ -909,6 +945,8 @@ static ULONG WINAPI domdoc_Release(
if ( ref == 0 ) if ( ref == 0 )
{ {
int eid;
if(This->bsc) if(This->bsc)
detach_bsc(This->bsc); detach_bsc(This->bsc);
...@@ -917,6 +955,10 @@ static ULONG WINAPI domdoc_Release( ...@@ -917,6 +955,10 @@ static ULONG WINAPI domdoc_Release(
destroy_xmlnode(&This->node); destroy_xmlnode(&This->node);
if (This->stream) if (This->stream)
IStream_Release(This->stream); IStream_Release(This->stream);
for (eid = 0; eid < EVENTID_LAST; eid++)
if (This->events[eid]) IDispatch_Release(This->events[eid]);
heap_free(This); heap_free(This);
} }
...@@ -2470,13 +2512,14 @@ static HRESULT WINAPI domdoc_put_preserveWhiteSpace( ...@@ -2470,13 +2512,14 @@ static HRESULT WINAPI domdoc_put_preserveWhiteSpace(
} }
static HRESULT WINAPI domdoc_put_onReadyStateChange( static HRESULT WINAPI domdoc_put_onreadystatechange(
IXMLDOMDocument3 *iface, IXMLDOMDocument3 *iface,
VARIANT readyStateChangeSink ) VARIANT event )
{ {
domdoc *This = impl_from_IXMLDOMDocument3( iface ); domdoc *This = impl_from_IXMLDOMDocument3( iface );
FIXME("%p\n", This);
return E_NOTIMPL; TRACE("(%p)->(%s)\n", This, debugstr_variant(&event));
return set_doc_event(This, EVENTID_READYSTATECHANGE, &event);
} }
...@@ -3040,7 +3083,7 @@ static const struct IXMLDOMDocument3Vtbl domdoc_vtbl = ...@@ -3040,7 +3083,7 @@ static const struct IXMLDOMDocument3Vtbl domdoc_vtbl =
domdoc_put_resolveExternals, domdoc_put_resolveExternals,
domdoc_get_preserveWhiteSpace, domdoc_get_preserveWhiteSpace,
domdoc_put_preserveWhiteSpace, domdoc_put_preserveWhiteSpace,
domdoc_put_onReadyStateChange, domdoc_put_onreadystatechange,
domdoc_put_onDataAvailable, domdoc_put_onDataAvailable,
domdoc_put_onTransformNode, domdoc_put_onTransformNode,
domdoc_get_namespaces, domdoc_get_namespaces,
...@@ -3402,6 +3445,7 @@ HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **docu ...@@ -3402,6 +3445,7 @@ HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **docu
doc->safeopt = 0; doc->safeopt = 0;
doc->bsc = NULL; doc->bsc = NULL;
doc->cp_list = NULL; doc->cp_list = NULL;
memset(doc->events, 0, sizeof(doc->events));
/* events connection points */ /* events connection points */
ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch); ConnectionPoint_Init(&doc->cp_dispatch, doc, &IID_IDispatch);
......
...@@ -7530,6 +7530,9 @@ static void test_events(void) ...@@ -7530,6 +7530,9 @@ static void test_events(void)
IConnectionPoint *point; IConnectionPoint *point;
IXMLDOMDocument *doc; IXMLDOMDocument *doc;
HRESULT hr; HRESULT hr;
VARIANT v;
IDispatch *event;
ULONG ref;
doc = create_document(&IID_IXMLDOMDocument); doc = create_document(&IID_IXMLDOMDocument);
if (!doc) return; if (!doc) return;
...@@ -7549,6 +7552,54 @@ static void test_events(void) ...@@ -7549,6 +7552,54 @@ static void test_events(void)
IConnectionPointContainer_Release(conn); IConnectionPointContainer_Release(conn);
/* ready state callback */
VariantInit(&v);
hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
ok(hr == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hr);
event = create_dispevent();
V_VT(&v) = VT_UNKNOWN;
V_UNKNOWN(&v) = (IUnknown*)event;
hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
ok(hr == S_OK, "got 0x%08x\n", hr);
ref = IDispatch_AddRef(event);
IDispatch_Release(event);
ok(ref == 3, "got %d\n", ref);
V_VT(&v) = VT_DISPATCH;
V_DISPATCH(&v) = event;
hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
ok(hr == S_OK, "got 0x%08x\n", hr);
ref = IDispatch_AddRef(event);
IDispatch_Release(event);
ok(ref == 3, "got %d\n", ref);
/* VT_NULL doesn't reset event handler */
V_VT(&v) = VT_NULL;
hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
ok(hr == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hr);
ref = IDispatch_AddRef(event);
IDispatch_Release(event);
ok(ref == 3, "got %d\n", ref);
V_VT(&v) = VT_DISPATCH;
V_DISPATCH(&v) = NULL;
hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
ok(hr == S_OK, "got 0x%08x\n", hr);
ref = IDispatch_AddRef(event);
IDispatch_Release(event);
ok(ref == 2, "got %d\n", ref);
V_VT(&v) = VT_UNKNOWN;
V_DISPATCH(&v) = NULL;
hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
ok(hr == S_OK, "got 0x%08x\n", hr);
IDispatch_Release(event);
IXMLDOMDocument_Release(doc); IXMLDOMDocument_Release(doc);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment