[PATCH 3/5] Add basic bind callback for moniker binding

Nikolay Sivov nsivov at codeweavers.com
Sat Sep 25 13:15:58 CDT 2010


---
 dlls/msxml3/httprequest.c   |  334 ++++++++++++++++++++++++++++++++++++++++---
 dlls/msxml3/msxml_private.h |    3 +
 dlls/msxml3/tests/domdoc.c  |    8 +
 3 files changed, 325 insertions(+), 20 deletions(-)

diff --git a/dlls/msxml3/httprequest.c b/dlls/msxml3/httprequest.c
index f7c200c..e626838 100644
--- a/dlls/msxml3/httprequest.c
+++ b/dlls/msxml3/httprequest.c
@@ -41,23 +41,9 @@ static const WCHAR MethodGetW[] = {'G','E','T',0};
 static const WCHAR MethodPutW[] = {'P','U','T',0};
 static const WCHAR MethodPostW[] = {'P','O','S','T',0};
 
-struct reqheader
-{
-    struct list entry;
-    BSTR header;
-    BSTR value;
-};
+typedef struct BindStatusCallback BindStatusCallback;
 
-enum READYSTATE
-{
-    STATE_UNINITIALIZED = 0,
-    STATE_LOADING       = 1,
-    STATE_LOADED        = 2,
-    STATE_INTERACTIVE   = 3,
-    STATE_COMPLETED     = 4
-};
-
-typedef struct _httprequest
+typedef struct
 {
     const struct IXMLHTTPRequestVtbl *lpVtbl;
     LONG ref;
@@ -73,8 +59,301 @@ typedef struct _httprequest
     /* credentials */
     BSTR user;
     BSTR password;
+
+    /* bind callback */
+    BindStatusCallback *bsc;
 } httprequest;
 
+struct BindStatusCallback
+{
+    const IBindStatusCallbackVtbl *lpBindStatusCallbackVtbl;
+    const IHttpNegotiateVtbl      *lpHttpNegotiateVtbl;
+    LONG ref;
+
+    const httprequest *request;
+};
+
+#define STATUSCLB(x)     ((IBindStatusCallback*)  &(x)->lpBindStatusCallbackVtbl)
+
+#define STATUSCLB_THIS(iface) DEFINE_THIS(BindStatusCallback, BindStatusCallback, iface)
+
+void BindStatusCallback_Detach(BindStatusCallback *bsc)
+{
+    if (bsc)
+    {
+        bsc->request = NULL;
+        IBindStatusCallback_Release(STATUSCLB(bsc));
+    }
+}
+
+static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface,
+        REFIID riid, void **ppv)
+{
+    BindStatusCallback *This = STATUSCLB_THIS(iface);
+
+    *ppv = NULL;
+
+    TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
+
+    if (IsEqualGUID(&IID_IUnknown, riid) ||
+        IsEqualGUID(&IID_IBindStatusCallback, riid))
+    {
+        *ppv = &This->lpBindStatusCallbackVtbl;
+    }
+
+    if (*ppv)
+    {
+        IBindStatusCallback_AddRef(iface);
+        return S_OK;
+    }
+
+    FIXME("Unsupported riid = %s\n", debugstr_guid(riid));
+
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface)
+{
+    BindStatusCallback *This = STATUSCLB_THIS(iface);
+    LONG ref = InterlockedIncrement(&This->ref);
+    TRACE("(%p) ref = %d\n", This, ref);
+    return ref;
+}
+
+static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface)
+{
+    BindStatusCallback *This = STATUSCLB_THIS(iface);
+    LONG ref = InterlockedDecrement(&This->ref);
+
+    TRACE("(%p) ref = %d\n", This, ref);
+
+    if (!ref) {
+        heap_free(This);
+    }
+
+    return ref;
+}
+
+static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface,
+        DWORD dwReserved, IBinding *pbind)
+{
+    BindStatusCallback *This = STATUSCLB_THIS(iface);
+
+    TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pPriority)
+{
+    BindStatusCallback *This = STATUSCLB_THIS(iface);
+    TRACE("(%p)->(%p)\n", This, pPriority);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
+{
+    BindStatusCallback *This = STATUSCLB_THIS(iface);
+    TRACE("(%p)->(%d)\n", This, reserved);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
+        ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
+{
+    BindStatusCallback *This = STATUSCLB_THIS(iface);
+
+    TRACE("%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode,
+            debugstr_w(szStatusText));
+
+    return S_OK;
+}
+
+static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface,
+        HRESULT hr, LPCWSTR error)
+{
+    BindStatusCallback *This = STATUSCLB_THIS(iface);
+
+    TRACE("(%p)->(0x%08x %s)\n", This, hr, debugstr_w(error));
+
+    return S_OK;
+}
+
+static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface,
+        DWORD *bind_flags, BINDINFO *pbindinfo)
+{
+    BindStatusCallback *This = STATUSCLB_THIS(iface);
+
+    TRACE("(%p)->(%p %p)\n", This, bind_flags, pbindinfo);
+
+    *bind_flags = BINDF_FROMURLMON;
+    if (This->request->async) *bind_flags |= BINDF_ASYNCHRONOUS;
+
+    if (This->request->verb != BINDVERB_GET)
+    {
+        FIXME("only GET verb supported. Got %d\n", This->request->verb);
+        return E_FAIL;
+    }
+
+    pbindinfo->dwBindVerb = This->request->verb;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface,
+        DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
+{
+    BindStatusCallback *This = STATUSCLB_THIS(iface);
+
+    TRACE("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface,
+        REFIID riid, IUnknown *punk)
+{
+    BindStatusCallback *This = STATUSCLB_THIS(iface);
+
+    TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk);
+
+    return E_NOTIMPL;
+}
+
+#undef STATUSCLB_THIS
+
+static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
+    BindStatusCallback_QueryInterface,
+    BindStatusCallback_AddRef,
+    BindStatusCallback_Release,
+    BindStatusCallback_OnStartBinding,
+    BindStatusCallback_GetPriority,
+    BindStatusCallback_OnLowResource,
+    BindStatusCallback_OnProgress,
+    BindStatusCallback_OnStopBinding,
+    BindStatusCallback_GetBindInfo,
+    BindStatusCallback_OnDataAvailable,
+    BindStatusCallback_OnObjectAvailable
+};
+
+#define HTTPNEG_THIS(iface) DEFINE_THIS(BindStatusCallback, HttpNegotiate, iface)
+
+static HRESULT WINAPI BSCHttpNegotiate_QueryInterface(IHttpNegotiate *iface,
+        REFIID riid, void **ppv)
+{
+    BindStatusCallback *This = HTTPNEG_THIS(iface);
+    return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv);
+}
+
+static ULONG WINAPI BSCHttpNegotiate_AddRef(IHttpNegotiate *iface)
+{
+    BindStatusCallback *This = HTTPNEG_THIS(iface);
+    return IBindStatusCallback_AddRef(STATUSCLB(This));
+}
+
+static ULONG WINAPI BSCHttpNegotiate_Release(IHttpNegotiate *iface)
+{
+    BindStatusCallback *This = HTTPNEG_THIS(iface);
+    return IBindStatusCallback_Release(STATUSCLB(This));
+}
+
+static HRESULT WINAPI BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate *iface,
+        LPCWSTR url, LPCWSTR headers, DWORD reserved, LPWSTR *add_headers)
+{
+    BindStatusCallback *This = HTTPNEG_THIS(iface);
+
+    TRACE("(%p)->(%s %s %d %p)\n", This, debugstr_w(url), debugstr_w(headers), reserved, add_headers);
+
+    *add_headers = NULL;
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BSCHttpNegotiate_OnResponse(IHttpNegotiate *iface, DWORD code,
+        LPCWSTR resp_headers, LPCWSTR req_headers, LPWSTR *add_reqheaders)
+{
+    BindStatusCallback *This = HTTPNEG_THIS(iface);
+
+    TRACE("(%p)->(%d %s %s %p)\n", This, code, debugstr_w(resp_headers),
+          debugstr_w(req_headers), add_reqheaders);
+
+    return S_OK;
+}
+
+#undef HTTPNEG2_THIS
+
+static const IHttpNegotiateVtbl BSCHttpNegotiateVtbl = {
+    BSCHttpNegotiate_QueryInterface,
+    BSCHttpNegotiate_AddRef,
+    BSCHttpNegotiate_Release,
+    BSCHttpNegotiate_BeginningTransaction,
+    BSCHttpNegotiate_OnResponse
+};
+
+static HRESULT BindStatusCallback_create(const httprequest* This, BindStatusCallback **obj)
+{
+    BindStatusCallback *bsc;
+    IBindCtx *pbc;
+    HRESULT hr;
+
+    hr = CreateBindCtx(0, &pbc);
+    if (hr != S_OK) return hr;
+
+    bsc = heap_alloc(sizeof(*bsc));
+    if (!bsc)
+    {
+        IBindCtx_Release(pbc);
+        return E_OUTOFMEMORY;
+    }
+
+    bsc->lpBindStatusCallbackVtbl = &BindStatusCallbackVtbl;
+    bsc->lpHttpNegotiateVtbl = &BSCHttpNegotiateVtbl;
+    bsc->ref = 1;
+    bsc->request = This;
+
+    hr = RegisterBindStatusCallback(pbc, STATUSCLB(bsc), NULL, 0);
+    if (hr == S_OK)
+    {
+        IMoniker *moniker;
+
+        hr = CreateURLMoniker(NULL, This->url, &moniker);
+        if (hr == S_OK)
+        {
+            IStream *stream;
+
+            hr = IMoniker_BindToStorage(moniker, pbc, NULL, &IID_IStream, (void**)&stream);
+            IMoniker_Release(moniker);
+            if (stream) IStream_Release(stream);
+        }
+        IBindCtx_Release(pbc);
+    }
+
+    if (FAILED(hr))
+    {
+        IBindStatusCallback_Release(STATUSCLB(bsc));
+        bsc = NULL;
+    }
+
+    *obj = bsc;
+    return hr;
+}
+
+struct reqheader
+{
+    struct list entry;
+    BSTR header;
+    BSTR value;
+};
+
+enum READYSTATE
+{
+    STATE_UNINITIALIZED = 0,
+    STATE_LOADING       = 1,
+    STATE_LOADED        = 2,
+    STATE_INTERACTIVE   = 3,
+    STATE_COMPLETED     = 4
+};
+
 static inline httprequest *impl_from_IXMLHTTPRequest( IXMLHTTPRequest *iface )
 {
     return (httprequest *)((char*)iface - FIELD_OFFSET(httprequest, lpVtbl));
@@ -136,6 +415,9 @@ static ULONG WINAPI httprequest_Release(IXMLHTTPRequest *iface)
             SysFreeString(header->value);
         }
 
+        /* detach callback object */
+        BindStatusCallback_Detach(This->bsc);
+
         heap_free( This );
     }
 
@@ -314,10 +596,21 @@ static HRESULT WINAPI httprequest_getAllResponseHeaders(IXMLHTTPRequest *iface,
 static HRESULT WINAPI httprequest_send(IXMLHTTPRequest *iface, VARIANT varBody)
 {
     httprequest *This = impl_from_IXMLHTTPRequest( iface );
+    BindStatusCallback *bsc = NULL;
+    HRESULT hr;
 
-    FIXME("stub (%p)\n", This);
+    TRACE("(%p)\n", This);
 
-    return E_NOTIMPL;
+    if (This->state != STATE_LOADING) return E_FAIL;
+
+    hr = BindStatusCallback_create(This, &bsc);
+    if (FAILED(hr)) return hr;
+
+    ERR("%x\n", hr);
+    BindStatusCallback_Detach(This->bsc);
+    This->bsc = bsc;
+
+    return hr;
 }
 
 static HRESULT WINAPI httprequest_abort(IXMLHTTPRequest *iface)
@@ -429,7 +722,7 @@ static const struct IXMLHTTPRequestVtbl dimimpl_vtbl =
     httprequest_put_onreadystatechange
 };
 
-HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, LPVOID *ppObj)
+HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, void **ppObj)
 {
     httprequest *req;
     HRESULT hr = S_OK;
@@ -447,6 +740,7 @@ HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, LPVOID *ppObj)
     req->verb = -1;
     req->url = req->user = req->password = NULL;
     req->state = STATE_UNINITIALIZED;
+    req->bsc = NULL;
     list_init(&req->reqheaders);
 
     *ppObj = &req->lpVtbl;
@@ -458,7 +752,7 @@ HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, LPVOID *ppObj)
 
 #else
 
-HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, LPVOID *ppObj)
+HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, void **ppObj)
 {
     MESSAGE("This program tried to use a XMLHTTPRequest object, but\n"
             "libxml2 support was not present at compile time.\n");
diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h
index a1b3b9d..8fe7dfd 100644
--- a/dlls/msxml3/msxml_private.h
+++ b/dlls/msxml3/msxml_private.h
@@ -106,6 +106,9 @@ BOOL dispex_query_interface(DispatchEx*,REFIID,void**);
 #include <libxml/parser.h>
 #endif
 
+#define DEFINE_THIS2(cls,ifc,iface) ((cls*)((BYTE*)(iface)-offsetof(cls,ifc)))
+#define DEFINE_THIS(cls,ifc,iface) DEFINE_THIS2(cls,lp ## ifc ## Vtbl,iface)
+
 /* constructors */
 extern IUnknown         *create_domdoc( xmlNodePtr document );
 extern IUnknown         *create_xmldoc( void );
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index fac5173..f3ebf63 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -2909,6 +2909,10 @@ static void test_XMLHTTP(void)
     method = SysAllocString(wszPOST);
     url = SysAllocString(wszUrl);
 
+    /* send before open */
+    hr = IXMLHttpRequest_send(pXMLHttpRequest, dummy);
+    ok(hr == E_FAIL, "got 0x%08x\n", hr);
+
     /* invalid parameters */
     hr = IXMLHttpRequest_open(pXMLHttpRequest, NULL, NULL, async, dummy, dummy);
     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
@@ -2970,6 +2974,10 @@ static void test_XMLHTTP(void)
         return;
     }
     todo_wine ok(hr == S_OK, "IXMLHttpRequest_send should have succeeded instead of failing with 0x%08x\n", hr);
+
+    hr = IXMLHttpRequest_send(pXMLHttpRequest, varbody);
+    ok(hr == E_FAIL, "got 0x%08x\n", hr);
+
     VariantClear(&varbody);
 
     hr = IXMLHttpRequest_get_responseText(pXMLHttpRequest, &bstrResponse);
-- 
1.5.6.5



--------------060203060809060209030906--



More information about the wine-patches mailing list