[PATCH 3/3] Implement ready state change callback

Nikolay Sivov nsivov at codeweavers.com
Tue Oct 5 19:44:00 CDT 2010


---
 dlls/msxml3/httprequest.c  |   24 ++++++-
 dlls/msxml3/tests/domdoc.c |  139 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 158 insertions(+), 5 deletions(-)

diff --git a/dlls/msxml3/httprequest.c b/dlls/msxml3/httprequest.c
index f1a93f6..7deae26 100644
--- a/dlls/msxml3/httprequest.c
+++ b/dlls/msxml3/httprequest.c
@@ -60,6 +60,7 @@ typedef struct
     LONG ref;
 
     READYSTATE state;
+    IDispatch *sink;
 
     /* request */
     BINDVERB verb;
@@ -415,10 +416,17 @@ static HRESULT BindStatusCallback_create(httprequest* This, BindStatusCallback *
     return hr;
 }
 
-/* TODO: process OnChange callback */
 static void httprequest_setreadystate(httprequest *This, READYSTATE state)
 {
     This->state = state;
+
+    if (This->sink)
+    {
+        DISPPARAMS params;
+
+        memset(&params, 0, sizeof(params));
+        IDispatch_Invoke(This->sink, 0, &IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &params, 0, 0, 0);
+    }
 }
 
 static HRESULT WINAPI httprequest_QueryInterface(IXMLHTTPRequest *iface, REFIID riid, void **ppvObject)
@@ -477,6 +485,8 @@ static ULONG WINAPI httprequest_Release(IXMLHTTPRequest *iface)
         /* detach callback object */
         BindStatusCallback_Detach(This->bsc);
 
+        if (This->sink) IDispatch_Release(This->sink);
+
         heap_free( This );
     }
 
@@ -768,13 +778,16 @@ static HRESULT WINAPI httprequest_get_readyState(IXMLHTTPRequest *iface, LONG *s
     return S_OK;
 }
 
-static HRESULT WINAPI httprequest_put_onreadystatechange(IXMLHTTPRequest *iface, IDispatch *pReadyStateSink)
+static HRESULT WINAPI httprequest_put_onreadystatechange(IXMLHTTPRequest *iface, IDispatch *sink)
 {
     httprequest *This = impl_from_IXMLHTTPRequest( iface );
 
-    FIXME("stub %p %p\n", This, pReadyStateSink);
+    TRACE("(%p)->(%p)\n", This, sink);
 
-    return E_NOTIMPL;
+    if (This->sink) IDispatch_Release(This->sink);
+    if ((This->sink = sink)) IDispatch_AddRef(This->sink);
+
+    return S_OK;
 }
 
 static const struct IXMLHTTPRequestVtbl dimimpl_vtbl =
@@ -819,7 +832,10 @@ HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, void **ppObj)
     req->async = FALSE;
     req->verb = -1;
     req->url = req->user = req->password = NULL;
+
     req->state = READYSTATE_UNINITIALIZED;
+    req->sink = NULL;
+
     req->bsc = NULL;
     req->status = 0;
     req->reqheader_size = 0;
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index 2c261fe..bcc9842 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -40,6 +40,117 @@
 DEFINE_GUID(IID_IObjectSafety, 0xcb5bdc81, 0x93c1, 0x11cf, 0x8f,0x20, 0x00,0x80,0x5f,0x2c,0xd0,0x64);
 DEFINE_GUID(CLSID_DOMDocument60, 0x88d96a05, 0xf192, 0x11d4, 0xa6,0x5f, 0x00,0x40,0x96,0x32,0x51,0xe5);
 
+static int g_unexpectedcall, g_expectedcall;
+
+typedef struct
+{
+    const struct IDispatchVtbl *lpVtbl;
+    LONG ref;
+} dispevent;
+
+static inline dispevent *impl_from_IDispatch( IDispatch *iface )
+{
+    return (dispevent *)((char*)iface - FIELD_OFFSET(dispevent, lpVtbl));
+}
+
+static HRESULT WINAPI dispevent_QueryInterface(IDispatch *iface, REFIID riid, void **ppvObject)
+{
+    *ppvObject = NULL;
+
+    if ( IsEqualGUID( riid, &IID_IDispatch) ||
+         IsEqualGUID( riid, &IID_IUnknown) )
+    {
+        *ppvObject = iface;
+    }
+    else
+        return E_NOINTERFACE;
+
+    IDispatch_AddRef( iface );
+
+    return S_OK;
+}
+
+static ULONG WINAPI dispevent_AddRef(IDispatch *iface)
+{
+    dispevent *This = impl_from_IDispatch( iface );
+    return InterlockedIncrement( &This->ref );
+}
+
+static ULONG WINAPI dispevent_Release(IDispatch *iface)
+{
+    dispevent *This = impl_from_IDispatch( iface );
+    ULONG ref = InterlockedDecrement( &This->ref );
+
+    if (ref == 0)
+        HeapFree(GetProcessHeap(), 0, This);
+
+    return ref;
+}
+
+static HRESULT WINAPI dispevent_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
+{
+    g_unexpectedcall++;
+    *pctinfo = 0;
+    return S_OK;
+}
+
+static HRESULT WINAPI dispevent_GetTypeInfo(IDispatch *iface, UINT iTInfo,
+        LCID lcid, ITypeInfo **ppTInfo)
+{
+    g_unexpectedcall++;
+    return S_OK;
+}
+
+static HRESULT WINAPI dispevent_GetIDsOfNames(IDispatch *iface, REFIID riid,
+        LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
+{
+    g_unexpectedcall++;
+    return S_OK;
+}
+
+static HRESULT WINAPI dispevent_Invoke(IDispatch *iface, DISPID member, REFIID riid,
+        LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result,
+        EXCEPINFO *excepInfo, UINT *argErr)
+{
+    ok(member == 0, "expected 0 member, got %d\n", member);
+    ok(lcid == LOCALE_SYSTEM_DEFAULT, "expected LOCALE_SYSTEM_DEFAULT, got lcid %x\n", lcid);
+    ok(flags == DISPATCH_METHOD, "expected DISPATCH_METHOD, got %d\n", flags);
+
+    ok(params->cArgs == 0, "got %d\n", params->cArgs);
+    ok(params->cNamedArgs == 0, "got %d\n", params->cNamedArgs);
+    ok(params->rgvarg == NULL, "got %p\n", params->rgvarg);
+    ok(params->rgdispidNamedArgs == NULL, "got %p\n", params->rgdispidNamedArgs);
+
+    ok(result == NULL, "got %p\n", result);
+    ok(excepInfo == NULL, "got %p\n", excepInfo);
+    ok(argErr == NULL, "got %p\n", argErr);
+
+    g_expectedcall++;
+    return E_FAIL;
+}
+
+static const IDispatchVtbl dispeventVtbl =
+{
+    dispevent_QueryInterface,
+    dispevent_AddRef,
+    dispevent_Release,
+    dispevent_GetTypeInfoCount,
+    dispevent_GetTypeInfo,
+    dispevent_GetIDsOfNames,
+    dispevent_Invoke
+};
+
+static IDispatch* create_dispevent(void)
+{
+    dispevent *event = HeapAlloc(GetProcessHeap(), 0, sizeof(*event));
+
+    event->lpVtbl = &dispeventVtbl;
+    event->ref = 1;
+
+    return (IDispatch*)&event->lpVtbl;
+}
+
+
 static const WCHAR szEmpty[] = { 0 };
 static const WCHAR szIncomplete[] = {
     '<','?','x','m','l',' ',
@@ -3082,7 +3193,8 @@ static void test_XMLHTTP(void)
     VARIANT dummy;
     VARIANT async;
     VARIANT varbody;
-    LONG state, status;
+    LONG state, status, ref;
+    IDispatch *event;
     HRESULT hr = CoCreateInstance(&CLSID_XMLHTTPRequest, NULL,
                                   CLSCTX_INPROC_SERVER, &IID_IXMLHttpRequest,
                                   (void **)&pXMLHttpRequest);
@@ -3104,6 +3216,13 @@ static void test_XMLHTTP(void)
     method = SysAllocString(wszPOST);
     url = SysAllocString(wszUrl);
 
+if (0)
+{
+    /* crashes on win98 */
+    hr = IXMLHttpRequest_put_onreadystatechange(pXMLHttpRequest, NULL);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+}
+
     /* send before open */
     hr = IXMLHttpRequest_send(pXMLHttpRequest, dummy);
     ok(hr == E_FAIL || broken(hr == E_UNEXPECTED) /* win9x, win2k */, "got 0x%08x\n", hr);
@@ -3147,9 +3266,26 @@ static void test_XMLHTTP(void)
     ok(hr == S_OK, "got 0x%08x\n", hr);
     ok(state == 0, "got %d, expected 0\n", state);
 
+    event = create_dispevent();
+    ref = IDispatch_AddRef(event);
+    ok(ref == 2, "got %d\n", ref);
+    IDispatch_Release(event);
+
+    hr = IXMLHttpRequest_put_onreadystatechange(pXMLHttpRequest, event);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    ref = IDispatch_AddRef(event);
+    ok(ref == 3, "got %d\n", ref);
+    IDispatch_Release(event);
+
+    g_unexpectedcall = g_expectedcall = 0;
+
     hr = IXMLHttpRequest_open(pXMLHttpRequest, method, url, async, dummy, dummy);
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
+    ok(g_unexpectedcall == 0, "unexpected disp event call\n");
+    ok(g_expectedcall == 1 || broken(g_expectedcall == 0) /* win2k */, "no expected disp event call\n");
+
     /* status code after ::open() */
     status = 0xdeadbeef;
     hr = IXMLHttpRequest_get_status(pXMLHttpRequest, &status);
@@ -3225,6 +3361,7 @@ todo_wine {
 
     SysFreeString(url);
 
+    IDispatch_Release(event);
     IXMLHttpRequest_Release(pXMLHttpRequest);
     free_bstrs();
 }
-- 
1.5.6.5



--------------020408020109060304070405--



More information about the wine-patches mailing list