[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