2020-09-14 18:15:32 -07:00
|
|
|
From 849e198c39ce81b2e99505486859ee305d9f6fed Mon Sep 17 00:00:00 2001
|
2020-09-08 19:37:05 -07:00
|
|
|
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
|
|
|
|
Date: Tue, 8 Sep 2020 18:43:52 +0200
|
2020-09-14 18:15:32 -07:00
|
|
|
Subject: [PATCH 3/3] msxml3: Implement FreeThreadedXMLHTTP60.
|
2020-09-08 19:37:05 -07:00
|
|
|
|
|
|
|
---
|
|
|
|
dlls/msxml3/Makefile.in | 2 +-
|
|
|
|
dlls/msxml3/httprequest.c | 493 +++++++++++++++++++++++++++++++++++-
|
|
|
|
dlls/msxml3/msxml_private.h | 1 +
|
|
|
|
dlls/msxml3/tests/httpreq.c | 395 ++++++++++++++++++++++++++++-
|
2020-09-14 18:15:32 -07:00
|
|
|
dlls/msxml3/tests/schema.c | 5 +
|
|
|
|
dlls/msxml3/uuid.c | 3 +
|
|
|
|
6 files changed, 894 insertions(+), 5 deletions(-)
|
2020-09-08 19:37:05 -07:00
|
|
|
|
|
|
|
diff --git a/dlls/msxml3/Makefile.in b/dlls/msxml3/Makefile.in
|
|
|
|
index 936c745895..f9e629f89b 100644
|
|
|
|
--- a/dlls/msxml3/Makefile.in
|
|
|
|
+++ b/dlls/msxml3/Makefile.in
|
|
|
|
@@ -1,5 +1,5 @@
|
|
|
|
MODULE = msxml3.dll
|
|
|
|
-IMPORTS = uuid urlmon shlwapi oleaut32 ole32 user32 advapi32
|
|
|
|
+IMPORTS = uuid urlmon shlwapi oleaut32 ole32 user32 advapi32 rtworkq
|
|
|
|
EXTRALIBS = $(XML2_LIBS)
|
|
|
|
EXTRAINCL = $(XML2_CFLAGS) $(XSLT_CFLAGS)
|
|
|
|
|
|
|
|
diff --git a/dlls/msxml3/httprequest.c b/dlls/msxml3/httprequest.c
|
|
|
|
index 7286eb97bb..ad74260193 100644
|
|
|
|
--- a/dlls/msxml3/httprequest.c
|
|
|
|
+++ b/dlls/msxml3/httprequest.c
|
|
|
|
@@ -44,13 +44,16 @@
|
|
|
|
#include "docobj.h"
|
|
|
|
#include "shlwapi.h"
|
|
|
|
|
|
|
|
+#include "initguid.h"
|
|
|
|
+#include "rtworkq.h"
|
|
|
|
+
|
|
|
|
#include "msxml_private.h"
|
|
|
|
|
|
|
|
#include "wine/debug.h"
|
|
|
|
|
|
|
|
#ifdef HAVE_LIBXML2
|
|
|
|
|
|
|
|
-WINE_DEFAULT_DEBUG_CHANNEL(msxml);
|
|
|
|
+WINE_DEFAULT_DEBUG_CHANNEL(xmlhttp);
|
|
|
|
|
|
|
|
static const WCHAR colspaceW[] = {':',' ',0};
|
|
|
|
static const WCHAR crlfW[] = {'\r','\n',0};
|
|
|
|
@@ -2031,6 +2034,458 @@ static const struct IServerXMLHTTPRequestVtbl ServerXMLHTTPRequestVtbl =
|
|
|
|
ServerXMLHTTPRequest_setOption
|
|
|
|
};
|
|
|
|
|
|
|
|
+static DWORD xhr2_work_queue;
|
|
|
|
+
|
|
|
|
+struct xml_http_request_2
|
|
|
|
+{
|
|
|
|
+ httprequest req;
|
|
|
|
+ IXMLHTTPRequest2 IXMLHTTPRequest2_iface;
|
|
|
|
+ IRtwqAsyncCallback IRtwqAsyncCallback_iface;
|
|
|
|
+ IDispatch IDispatch_iface;
|
|
|
|
+
|
|
|
|
+ IXMLHTTPRequest2Callback *callback;
|
|
|
|
+ IXMLHTTPRequest3Callback *callback3;
|
|
|
|
+ ISequentialStream *response_body;
|
|
|
|
+ ISequentialStream *request_body;
|
|
|
|
+ ULONGLONG request_body_size;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static inline struct xml_http_request_2 *impl_from_IXMLHTTPRequest2(IXMLHTTPRequest2 *iface)
|
|
|
|
+{
|
|
|
|
+ return CONTAINING_RECORD(iface, struct xml_http_request_2, IXMLHTTPRequest2_iface);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static inline struct xml_http_request_2 *xml_http_request_2_from_IRtwqAsyncCallback(IRtwqAsyncCallback *iface)
|
|
|
|
+{
|
|
|
|
+ return CONTAINING_RECORD(iface, struct xml_http_request_2, IRtwqAsyncCallback_iface);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static inline struct xml_http_request_2 *xml_http_request_2_from_IDispatch(IDispatch *iface)
|
|
|
|
+{
|
|
|
|
+ return CONTAINING_RECORD(iface, struct xml_http_request_2, IDispatch_iface);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xml_http_request_2_QueryInterface(IXMLHTTPRequest2 *iface, REFIID riid, void **obj)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = impl_from_IXMLHTTPRequest2(iface);
|
|
|
|
+
|
|
|
|
+ TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
|
|
|
|
+
|
|
|
|
+ if (IsEqualGUID(riid, &IID_IXMLHTTPRequest2) || IsEqualGUID(riid, &IID_IUnknown))
|
|
|
|
+ {
|
|
|
|
+ IXMLHTTPRequest2_AddRef(iface);
|
|
|
|
+ *obj = iface;
|
|
|
|
+ return S_OK;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ FIXME("Unsupported interface %s\n", debugstr_guid(riid));
|
|
|
|
+ *obj = NULL;
|
|
|
|
+ return E_NOINTERFACE;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static ULONG WINAPI xml_http_request_2_AddRef(IXMLHTTPRequest2 *iface)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = impl_from_IXMLHTTPRequest2(iface);
|
|
|
|
+ ULONG ref = InterlockedIncrement(&This->req.ref);
|
|
|
|
+ TRACE("(%p)->(%u)\n", This, ref);
|
|
|
|
+ return ref;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static ULONG WINAPI xml_http_request_2_Release(IXMLHTTPRequest2 *iface)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = impl_from_IXMLHTTPRequest2(iface);
|
|
|
|
+ ULONG ref = InterlockedDecrement(&This->req.ref);
|
|
|
|
+
|
|
|
|
+ TRACE("(%p)->(%u)\n", This, ref);
|
|
|
|
+
|
|
|
|
+ if (ref == 0)
|
|
|
|
+ {
|
|
|
|
+ /* do not call httprequest_put_onreadystatechange to avoid ref cycle */
|
|
|
|
+ This->req.sink = NULL;
|
|
|
|
+ if (This->response_body) ISequentialStream_Release(This->response_body);
|
|
|
|
+ if (This->request_body) ISequentialStream_Release(This->request_body);
|
|
|
|
+ if (This->callback3) IXMLHTTPRequest3Callback_Release(This->callback3);
|
|
|
|
+ if (This->callback) IXMLHTTPRequest2Callback_Release(This->callback);
|
|
|
|
+ heap_free(This);
|
|
|
|
+ RtwqShutdown();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return ref;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xml_http_request_2_Open(IXMLHTTPRequest2 *iface, const WCHAR *method,
|
|
|
|
+ const WCHAR *url, IXMLHTTPRequest2Callback *callback,
|
|
|
|
+ const WCHAR *username, const WCHAR *password,
|
|
|
|
+ const WCHAR *proxy_username, const WCHAR *proxy_password)
|
|
|
|
+{
|
|
|
|
+ static const WCHAR accept_encoding[] = {'A','c','c','e','p','t','-','E','n','c','o','d','i','n','g',0};
|
|
|
|
+ static const WCHAR empty = 0;
|
|
|
|
+ struct xml_http_request_2 *This = impl_from_IXMLHTTPRequest2(iface);
|
|
|
|
+ VARIANT async_v, username_v, password_v;
|
|
|
|
+ HRESULT hr;
|
|
|
|
+
|
|
|
|
+ TRACE("(%p)->(%s %s %p %s %s %s %s)\n", This, debugstr_w(method), debugstr_w(url), callback,
|
|
|
|
+ debugstr_w(username), debugstr_w(password), debugstr_w(proxy_username), debugstr_w(proxy_password));
|
|
|
|
+
|
|
|
|
+ if (This->callback) IXMLHTTPRequest2Callback_Release(This->callback);
|
|
|
|
+ if (This->callback3) IXMLHTTPRequest3Callback_Release(This->callback3);
|
|
|
|
+ IXMLHTTPRequest2Callback_AddRef(callback);
|
|
|
|
+ This->callback = callback;
|
|
|
|
+ if (FAILED(IXMLHTTPRequest2Callback_QueryInterface(callback, &IID_IXMLHTTPRequest3Callback, (void **)&This->callback3)))
|
|
|
|
+ This->callback3 = NULL;
|
|
|
|
+
|
|
|
|
+ if (proxy_username || proxy_password) FIXME("proxy credentials not implemented\n");
|
|
|
|
+
|
|
|
|
+ VariantInit(&async_v);
|
|
|
|
+ V_VT(&async_v) = VT_BOOL;
|
|
|
|
+ V_BOOL(&async_v) = FALSE; /* FIXME: TRUE needs a RTWQ_WINDOW_WORKQUEUE */
|
|
|
|
+
|
|
|
|
+ VariantInit(&username_v);
|
|
|
|
+ V_VT(&username_v) = VT_BSTR;
|
|
|
|
+ if (username) V_BSTR(&username_v) = SysAllocString(username);
|
|
|
|
+ else V_BSTR(&username_v) = SysAllocString(&empty);
|
|
|
|
+
|
|
|
|
+ VariantInit(&password_v);
|
|
|
|
+ V_VT(&password_v) = VT_BSTR;
|
|
|
|
+ if (password) V_BSTR(&password_v) = SysAllocString(password);
|
|
|
|
+ else V_BSTR(&password_v) = SysAllocString(&empty);
|
|
|
|
+
|
|
|
|
+ if (FAILED(hr = httprequest_open(&This->req, (BSTR)method, (BSTR)url, async_v, username_v, password_v)))
|
|
|
|
+ return hr;
|
|
|
|
+ return httprequest_setRequestHeader(&This->req, (BSTR)accept_encoding, (BSTR)&empty);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xml_http_request_2_Send(IXMLHTTPRequest2 *iface, ISequentialStream *body, ULONGLONG body_size)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = impl_from_IXMLHTTPRequest2(iface);
|
|
|
|
+ IRtwqAsyncResult *result;
|
|
|
|
+ HRESULT hr;
|
|
|
|
+
|
|
|
|
+ TRACE("(%p)->(%p %s)\n", This, body, wine_dbgstr_longlong( body_size ));
|
|
|
|
+
|
|
|
|
+ if (body_size)
|
|
|
|
+ {
|
|
|
|
+ ISequentialStream_AddRef(body);
|
|
|
|
+ This->request_body = body;
|
|
|
|
+ This->request_body_size = body_size;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (FAILED(hr = RtwqCreateAsyncResult(NULL, &This->IRtwqAsyncCallback_iface, NULL, &result)))
|
|
|
|
+ return hr;
|
|
|
|
+ // IRtwqAsyncCallback_Invoke(&This->IRtwqAsyncCallback_iface, result);
|
|
|
|
+ hr = RtwqPutWorkItem(xhr2_work_queue, 0, result);
|
|
|
|
+ if (result) IRtwqAsyncResult_Release(result);
|
|
|
|
+
|
|
|
|
+ return hr;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xml_http_request_2_Abort(IXMLHTTPRequest2 *iface)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = impl_from_IXMLHTTPRequest2(iface);
|
|
|
|
+ TRACE("(%p) stub!\n", This);
|
|
|
|
+ return E_NOTIMPL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xml_http_request_2_SetCookie(IXMLHTTPRequest2 *iface, const XHR_COOKIE *cookie, DWORD *state)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = impl_from_IXMLHTTPRequest2(iface);
|
|
|
|
+ FIXME("(%p)->(%p %p) stub!\n", This, cookie, state);
|
|
|
|
+ return E_NOTIMPL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xml_http_request_2_SetCustomResponseStream(IXMLHTTPRequest2 *iface, ISequentialStream *stream)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = impl_from_IXMLHTTPRequest2(iface);
|
|
|
|
+ FIXME("(%p)->(%p) stub!\n", This, stream);
|
|
|
|
+ return E_NOTIMPL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xml_http_request_2_SetProperty(IXMLHTTPRequest2 *iface, XHR_PROPERTY property, ULONGLONG value)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = impl_from_IXMLHTTPRequest2(iface);
|
|
|
|
+ FIXME("(%p)->(%#x %s) stub!\n", This, property, wine_dbgstr_longlong( value ));
|
|
|
|
+ return E_NOTIMPL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xml_http_request_2_SetRequestHeader(IXMLHTTPRequest2 *iface,
|
|
|
|
+ const WCHAR *header, const WCHAR *value)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = impl_from_IXMLHTTPRequest2(iface);
|
|
|
|
+ TRACE("(%p)->(%s %s)\n", This, debugstr_w(header), debugstr_w(value));
|
|
|
|
+ return httprequest_setRequestHeader(&This->req, (BSTR)header, (BSTR)value);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xml_http_request_2_GetAllResponseHeaders(IXMLHTTPRequest2 *iface, WCHAR **headers)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = impl_from_IXMLHTTPRequest2(iface);
|
|
|
|
+ FIXME("(%p)->(%p) stub!\n", This, headers);
|
|
|
|
+ return E_NOTIMPL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xml_http_request_2_GetCookie(IXMLHTTPRequest2 *iface, const WCHAR *url,
|
|
|
|
+ const WCHAR *name, DWORD flags,
|
|
|
|
+ ULONG *cookies_count, XHR_COOKIE **cookies)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = impl_from_IXMLHTTPRequest2(iface);
|
|
|
|
+ FIXME("(%p)->(%s %s %d %p %p) stub!\n", This, debugstr_w(url), debugstr_w(name), flags, cookies_count, cookies);
|
|
|
|
+ return E_NOTIMPL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xml_http_request_2_GetResponseHeader(IXMLHTTPRequest2 *iface,
|
|
|
|
+ const WCHAR *header, WCHAR **value)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = impl_from_IXMLHTTPRequest2(iface);
|
|
|
|
+ HRESULT hr;
|
|
|
|
+
|
|
|
|
+ TRACE("(%p)->(%s %p)\n", This, debugstr_w(header), value);
|
|
|
|
+
|
|
|
|
+ if (FAILED(hr = httprequest_getResponseHeader(&This->req, (BSTR)header, value)))
|
|
|
|
+ return hr;
|
|
|
|
+
|
|
|
|
+#define E_FILE_NOT_FOUND _HRESULT_TYPEDEF_(0x80070002)
|
|
|
|
+
|
|
|
|
+ if (hr == S_FALSE)
|
|
|
|
+ {
|
|
|
|
+ *value = NULL;
|
|
|
|
+ return E_FILE_NOT_FOUND;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return hr;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static const struct IXMLHTTPRequest2Vtbl XMLHTTPRequest2Vtbl = {
|
|
|
|
+ /* IUnknown methods */
|
|
|
|
+ xml_http_request_2_QueryInterface,
|
|
|
|
+ xml_http_request_2_AddRef,
|
|
|
|
+ xml_http_request_2_Release,
|
|
|
|
+ /* IXMLHTTPRequest2 methods */
|
|
|
|
+ xml_http_request_2_Open,
|
|
|
|
+ xml_http_request_2_Send,
|
|
|
|
+ xml_http_request_2_Abort,
|
|
|
|
+ xml_http_request_2_SetCookie,
|
|
|
|
+ xml_http_request_2_SetCustomResponseStream,
|
|
|
|
+ xml_http_request_2_SetProperty,
|
|
|
|
+ xml_http_request_2_SetRequestHeader,
|
|
|
|
+ xml_http_request_2_GetAllResponseHeaders,
|
|
|
|
+ xml_http_request_2_GetCookie,
|
|
|
|
+ xml_http_request_2_GetResponseHeader,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xml_http_request_2_IRtwqAsyncCallback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = xml_http_request_2_from_IRtwqAsyncCallback(iface);
|
|
|
|
+ TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
|
|
|
|
+
|
|
|
|
+ if (IsEqualGUID(riid, &IID_IRtwqAsyncCallback) || IsEqualGUID(riid, &IID_IUnknown))
|
|
|
|
+ {
|
|
|
|
+ IRtwqAsyncCallback_AddRef(iface);
|
|
|
|
+ *obj = iface;
|
|
|
|
+ return S_OK;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ FIXME("Unsupported interface %s\n", debugstr_guid(riid));
|
|
|
|
+ *obj = NULL;
|
|
|
|
+ return E_NOINTERFACE;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static ULONG WINAPI xml_http_request_2_IRtwqAsyncCallback_AddRef(IRtwqAsyncCallback *iface)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = xml_http_request_2_from_IRtwqAsyncCallback(iface);
|
|
|
|
+ TRACE("(%p)\n", This);
|
|
|
|
+ return xml_http_request_2_AddRef(&This->IXMLHTTPRequest2_iface);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static ULONG WINAPI xml_http_request_2_IRtwqAsyncCallback_Release(IRtwqAsyncCallback *iface)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = xml_http_request_2_from_IRtwqAsyncCallback(iface);
|
|
|
|
+ TRACE("(%p)\n", This);
|
|
|
|
+ return xml_http_request_2_Release(&This->IXMLHTTPRequest2_iface);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xml_http_request_2_IRtwqAsyncCallback_GetParameters(IRtwqAsyncCallback *iface,
|
|
|
|
+ DWORD *flags, DWORD *queue)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = xml_http_request_2_from_IRtwqAsyncCallback(iface);
|
|
|
|
+
|
|
|
|
+ TRACE("(%p)->(%p %p)\n", This, flags, queue);
|
|
|
|
+
|
|
|
|
+ *flags = 0;
|
|
|
|
+ *queue = xhr2_work_queue;
|
|
|
|
+ return S_OK;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xml_http_request_2_IRtwqAsyncCallback_Invoke(IRtwqAsyncCallback *iface,
|
|
|
|
+ IRtwqAsyncResult *result)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = xml_http_request_2_from_IRtwqAsyncCallback(iface);
|
|
|
|
+ VARIANT body_v;
|
|
|
|
+ HRESULT hr;
|
|
|
|
+ ULONG read;
|
|
|
|
+
|
|
|
|
+ TRACE("(%p)->(%p)\n", This, result);
|
|
|
|
+
|
|
|
|
+ VariantInit(&body_v);
|
|
|
|
+
|
|
|
|
+ if (This->request_body)
|
|
|
|
+ {
|
|
|
|
+ V_VT(&body_v) = VT_BSTR;
|
|
|
|
+ V_BSTR(&body_v) = CoTaskMemAlloc(This->request_body_size);
|
|
|
|
+
|
|
|
|
+ if (FAILED(hr = ISequentialStream_Read(This->request_body, V_BSTR(&body_v), This->request_body_size, &read)) ||
|
|
|
|
+ read < This->request_body_size)
|
|
|
|
+ {
|
|
|
|
+ ERR("Failed to allocate request body memory, hr %#x\n", hr);
|
|
|
|
+ CoTaskMemFree(V_BSTR(&body_v));
|
|
|
|
+ goto done;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ISequentialStream_Release(This->request_body);
|
|
|
|
+ This->request_body = NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ hr = httprequest_send(&This->req, body_v);
|
|
|
|
+
|
|
|
|
+done:
|
|
|
|
+ return IRtwqAsyncResult_SetStatus(result, hr);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static const struct IRtwqAsyncCallbackVtbl xml_http_request_2_IRtwqAsyncCallbackVtbl = {
|
|
|
|
+ /* IUnknown methods */
|
|
|
|
+ xml_http_request_2_IRtwqAsyncCallback_QueryInterface,
|
|
|
|
+ xml_http_request_2_IRtwqAsyncCallback_AddRef,
|
|
|
|
+ xml_http_request_2_IRtwqAsyncCallback_Release,
|
|
|
|
+ /* IRtwqAsyncCallback methods */
|
|
|
|
+ xml_http_request_2_IRtwqAsyncCallback_GetParameters,
|
|
|
|
+ xml_http_request_2_IRtwqAsyncCallback_Invoke,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xml_http_request_2_IDispatch_QueryInterface(IDispatch *iface, REFIID riid, void **obj)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = xml_http_request_2_from_IDispatch(iface);
|
|
|
|
+ TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
|
|
|
|
+
|
|
|
|
+ if (IsEqualGUID(riid, &IID_IDispatch) || IsEqualGUID(riid, &IID_IUnknown))
|
|
|
|
+ {
|
|
|
|
+ IDispatch_AddRef(iface);
|
|
|
|
+ *obj = iface;
|
|
|
|
+ return S_OK;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ FIXME("Unsupported interface %s\n", debugstr_guid(riid));
|
|
|
|
+ *obj = NULL;
|
|
|
|
+ return E_NOINTERFACE;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static ULONG WINAPI xml_http_request_2_IDispatch_AddRef(IDispatch *iface)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = xml_http_request_2_from_IDispatch(iface);
|
|
|
|
+ TRACE("(%p)\n", This);
|
|
|
|
+ return xml_http_request_2_AddRef(&This->IXMLHTTPRequest2_iface);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static ULONG WINAPI xml_http_request_2_IDispatch_Release(IDispatch *iface)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = xml_http_request_2_from_IDispatch(iface);
|
|
|
|
+ TRACE("(%p)\n", This);
|
|
|
|
+ return xml_http_request_2_Release(&This->IXMLHTTPRequest2_iface);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xml_http_request_2_IDispatch_GetTypeInfoCount(IDispatch *iface, UINT *value)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = xml_http_request_2_from_IDispatch(iface);
|
|
|
|
+ FIXME("(%p)->(%p) stub!\n", This, value);
|
|
|
|
+ *value = 0;
|
|
|
|
+ return S_OK;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xml_http_request_2_IDispatch_GetTypeInfo(IDispatch *iface, UINT index,
|
|
|
|
+ LCID lcid, ITypeInfo **value)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = xml_http_request_2_from_IDispatch(iface);
|
|
|
|
+ FIXME("(%p)->(%d %u %p) stub!\n", This, index, lcid, value);
|
|
|
|
+ *value = NULL;
|
|
|
|
+ return S_OK;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xml_http_request_2_IDispatch_GetIDsOfNames(IDispatch *iface, REFIID riid,
|
|
|
|
+ OLECHAR **names, UINT names_count,
|
|
|
|
+ LCID lcid, DISPID *disp_ids)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = xml_http_request_2_from_IDispatch(iface);
|
|
|
|
+ FIXME("(%p)->(%s %p %d %u %p) stub!\n", This, debugstr_guid(riid), names, names_count, lcid, disp_ids);
|
|
|
|
+ return S_OK;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xml_http_request_2_IDispatch_Invoke(IDispatch *iface, DISPID id, REFIID riid,
|
|
|
|
+ LCID lcid, WORD flags, DISPPARAMS *params,
|
|
|
|
+ VARIANT *result, EXCEPINFO *exception, UINT *arg_err)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *This = xml_http_request_2_from_IDispatch(iface);
|
|
|
|
+ IXMLHTTPRequest2 *xhr2_iface = &This->IXMLHTTPRequest2_iface;
|
|
|
|
+ HRESULT hr;
|
|
|
|
+ LONG status;
|
|
|
|
+ BSTR status_str = NULL;
|
|
|
|
+
|
|
|
|
+ TRACE("(%p)->(%d %s %u %d %p %p %p %p) stub!\n", This, id, debugstr_guid(riid), lcid, flags,
|
|
|
|
+ params, result, exception, arg_err);
|
|
|
|
+
|
|
|
|
+ if (This->req.state == READYSTATE_COMPLETE)
|
|
|
|
+ {
|
|
|
|
+ VARIANT body_v;
|
|
|
|
+ VariantInit(&body_v);
|
|
|
|
+
|
|
|
|
+ IXMLHTTPRequest2Callback_AddRef(This->callback);
|
|
|
|
+ if (This->callback3)
|
|
|
|
+ {
|
|
|
|
+ IXMLHTTPRequest3Callback_AddRef(This->callback3);
|
|
|
|
+ IXMLHTTPRequest3Callback_OnServerCertificateReceived(This->callback3, (IXMLHTTPRequest3 *)xhr2_iface, 0, 1, NULL);
|
|
|
|
+ IXMLHTTPRequest3Callback_Release(This->callback3);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (FAILED(hr = httprequest_get_status(&This->req, &status)) ||
|
|
|
|
+ FAILED(hr = httprequest_get_statusText(&This->req, &status_str)))
|
|
|
|
+ {
|
|
|
|
+ WARN("failed to get response status, error %#x\n", hr);
|
|
|
|
+ IXMLHTTPRequest2Callback_OnError(This->callback, xhr2_iface, hr);
|
|
|
|
+ IXMLHTTPRequest2Callback_Release(This->callback);
|
|
|
|
+ return S_OK;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ IXMLHTTPRequest2Callback_OnHeadersAvailable(This->callback, xhr2_iface, status, status_str);
|
|
|
|
+ SysFreeString(status_str);
|
|
|
|
+
|
|
|
|
+ if (This->response_body) ISequentialStream_Release(This->response_body);
|
|
|
|
+ This->response_body = NULL;
|
|
|
|
+
|
|
|
|
+ if (FAILED(hr = httprequest_get_responseStream(&This->req, &body_v)) ||
|
|
|
|
+ FAILED(hr = IUnknown_QueryInterface(V_UNKNOWN(&body_v), &IID_ISequentialStream, (void **)&This->response_body)))
|
|
|
|
+ {
|
|
|
|
+ WARN("failed to get response stream, error %#x\n", hr);
|
|
|
|
+ IXMLHTTPRequest2Callback_OnError(This->callback, xhr2_iface, hr);
|
|
|
|
+ IXMLHTTPRequest2Callback_Release(This->callback);
|
|
|
|
+ return S_OK;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ IXMLHTTPRequest2Callback_OnDataAvailable(This->callback, xhr2_iface, This->response_body);
|
|
|
|
+ IXMLHTTPRequest2Callback_OnResponseReceived(This->callback, xhr2_iface, This->response_body);
|
|
|
|
+ IXMLHTTPRequest2Callback_Release(This->callback);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return S_OK;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static const struct IDispatchVtbl xml_http_request_2_IDispatchVtbl = {
|
|
|
|
+ /* IUnknown methods */
|
|
|
|
+ xml_http_request_2_IDispatch_QueryInterface,
|
|
|
|
+ xml_http_request_2_IDispatch_AddRef,
|
|
|
|
+ xml_http_request_2_IDispatch_Release,
|
|
|
|
+ /* IDispatch methods */
|
|
|
|
+ xml_http_request_2_IDispatch_GetTypeInfoCount,
|
|
|
|
+ xml_http_request_2_IDispatch_GetTypeInfo,
|
|
|
|
+ xml_http_request_2_IDispatch_GetIDsOfNames,
|
|
|
|
+ xml_http_request_2_IDispatch_Invoke,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
static void init_httprequest(httprequest *req)
|
|
|
|
{
|
|
|
|
req->IXMLHTTPRequest_iface.lpVtbl = &XMLHTTPRequestVtbl;
|
|
|
|
@@ -2080,6 +2535,35 @@ HRESULT XMLHTTPRequest_create(void **obj)
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
+HRESULT XMLHTTPRequest2_create(void **obj)
|
|
|
|
+{
|
|
|
|
+ struct xml_http_request_2 *xhr2;
|
|
|
|
+ TRACE("(%p)\n", obj);
|
|
|
|
+
|
|
|
|
+ if (!(xhr2 = heap_alloc(sizeof(*xhr2)))) return E_OUTOFMEMORY;
|
|
|
|
+
|
|
|
|
+ init_httprequest(&xhr2->req);
|
|
|
|
+ xhr2->IXMLHTTPRequest2_iface.lpVtbl = &XMLHTTPRequest2Vtbl;
|
|
|
|
+ xhr2->IRtwqAsyncCallback_iface.lpVtbl = &xml_http_request_2_IRtwqAsyncCallbackVtbl;
|
|
|
|
+ xhr2->IDispatch_iface.lpVtbl = &xml_http_request_2_IDispatchVtbl;
|
|
|
|
+
|
|
|
|
+ /* do not call httprequest_put_onreadystatechange to avoid ref cycle */
|
|
|
|
+ xhr2->req.sink = &xhr2->IDispatch_iface;
|
|
|
|
+
|
|
|
|
+ xhr2->callback = NULL;
|
|
|
|
+ xhr2->callback3 = NULL;
|
|
|
|
+ xhr2->request_body = NULL;
|
|
|
|
+ xhr2->response_body = NULL;
|
|
|
|
+
|
|
|
|
+ /* for async http requests we need window message queue */
|
|
|
|
+ RtwqStartup();
|
|
|
|
+ if (!xhr2_work_queue) RtwqAllocateWorkQueue(RTWQ_MULTITHREADED_WORKQUEUE, &xhr2_work_queue);
|
|
|
|
+
|
|
|
|
+ *obj = &xhr2->IXMLHTTPRequest2_iface;
|
|
|
|
+ TRACE("returning iface %p\n", *obj);
|
|
|
|
+ return S_OK;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
HRESULT ServerXMLHTTP_create(void **obj)
|
|
|
|
{
|
|
|
|
serverhttp *req;
|
|
|
|
@@ -2109,6 +2593,13 @@ HRESULT XMLHTTPRequest_create(void **ppObj)
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
+HRESULT XMLHTTPRequest2_create(void **ppObj)
|
|
|
|
+{
|
|
|
|
+ MESSAGE("This program tried to use a XMLHTTPRequest object, but\n"
|
|
|
|
+ "libxml2 support was not present at compile time.\n");
|
|
|
|
+ return E_NOTIMPL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
HRESULT ServerXMLHTTP_create(void **obj)
|
|
|
|
{
|
|
|
|
MESSAGE("This program tried to use a ServerXMLHTTP object, but\n"
|
|
|
|
diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h
|
2020-09-14 18:15:32 -07:00
|
|
|
index a59e00bf2b..9797f96f3c 100644
|
2020-09-08 19:37:05 -07:00
|
|
|
--- a/dlls/msxml3/msxml_private.h
|
|
|
|
+++ b/dlls/msxml3/msxml_private.h
|
2020-09-14 18:15:32 -07:00
|
|
|
@@ -501,6 +501,7 @@ extern HRESULT XMLDocument_create(void**) DECLSPEC_HIDDEN;
|
2020-09-08 19:37:05 -07:00
|
|
|
extern HRESULT SAXXMLReader_create(MSXML_VERSION, void**) DECLSPEC_HIDDEN;
|
|
|
|
extern HRESULT SAXAttributes_create(MSXML_VERSION, void**) DECLSPEC_HIDDEN;
|
|
|
|
extern HRESULT XMLHTTPRequest_create(void **) DECLSPEC_HIDDEN;
|
|
|
|
+extern HRESULT XMLHTTPRequest2_create(void **) DECLSPEC_HIDDEN;
|
|
|
|
extern HRESULT ServerXMLHTTP_create(void **) DECLSPEC_HIDDEN;
|
|
|
|
extern HRESULT XSLTemplate_create(void**) DECLSPEC_HIDDEN;
|
|
|
|
extern HRESULT MXWriter_create(MSXML_VERSION, void**) DECLSPEC_HIDDEN;
|
|
|
|
diff --git a/dlls/msxml3/tests/httpreq.c b/dlls/msxml3/tests/httpreq.c
|
2020-09-14 18:15:32 -07:00
|
|
|
index 74c302d5eb..25e6922c31 100644
|
2020-09-08 19:37:05 -07:00
|
|
|
--- a/dlls/msxml3/tests/httpreq.c
|
|
|
|
+++ b/dlls/msxml3/tests/httpreq.c
|
2020-09-14 18:15:32 -07:00
|
|
|
@@ -26,9 +26,9 @@
|
|
|
|
#include <assert.h>
|
2020-09-08 19:37:05 -07:00
|
|
|
|
|
|
|
#include "windows.h"
|
2020-09-14 18:15:32 -07:00
|
|
|
-
|
|
|
|
#include "msxml2.h"
|
2020-09-08 19:37:05 -07:00
|
|
|
-#include "msxml2did.h"
|
|
|
|
+#include "msxml6.h"
|
|
|
|
+#include "msxml6did.h"
|
|
|
|
#include "dispex.h"
|
|
|
|
|
|
|
|
#include "initguid.h"
|
|
|
|
@@ -1334,6 +1334,17 @@ static IXMLHttpRequest *create_xhr(void)
|
|
|
|
return SUCCEEDED(hr) ? ret : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
+static IXMLHTTPRequest2 *create_xhr2(void)
|
|
|
|
+{
|
|
|
|
+ IXMLHTTPRequest2 *ret;
|
|
|
|
+ HRESULT hr;
|
|
|
|
+
|
|
|
|
+ hr = CoCreateInstance(&CLSID_FreeThreadedXMLHTTP60, NULL, CLSCTX_INPROC_SERVER,
|
|
|
|
+ &IID_IXMLHTTPRequest2, (void**)&ret);
|
|
|
|
+
|
|
|
|
+ return SUCCEEDED(hr) ? ret : NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
static IServerXMLHTTPRequest *create_server_xhr(void)
|
|
|
|
{
|
|
|
|
IServerXMLHTTPRequest *ret;
|
|
|
|
@@ -1893,11 +1904,388 @@ static void test_supporterrorinfo(void)
|
|
|
|
IServerXMLHTTPRequest_Release(server_xhr);
|
|
|
|
}
|
|
|
|
|
|
|
|
+struct xhr3_callback
|
|
|
|
+{
|
|
|
|
+ IXMLHTTPRequest3Callback IXMLHTTPRequest3Callback_iface;
|
|
|
|
+ LONG ref;
|
|
|
|
+ HANDLE event;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static inline struct xhr3_callback *xhr3_callback_from_IXMLHTTPRequest3Callback(IXMLHTTPRequest3Callback *iface)
|
|
|
|
+{
|
|
|
|
+ return CONTAINING_RECORD(iface, struct xhr3_callback, IXMLHTTPRequest3Callback_iface);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xhr3_callback_QueryInterface(IXMLHTTPRequest3Callback *iface, REFIID riid, void **obj)
|
|
|
|
+{
|
|
|
|
+ struct xhr3_callback *This = xhr3_callback_from_IXMLHTTPRequest3Callback(iface);
|
|
|
|
+ trace("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
|
|
|
|
+
|
|
|
|
+ if (IsEqualGUID(riid, &IID_IXMLHTTPRequest3Callback) || IsEqualGUID(riid, &IID_IXMLHTTPRequest2Callback) || IsEqualGUID(riid, &IID_IUnknown))
|
|
|
|
+ {
|
|
|
|
+ IXMLHTTPRequest3Callback_AddRef(iface);
|
|
|
|
+ *obj = iface;
|
|
|
|
+ return S_OK;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ok(0, "unexpected interface %s\n", debugstr_guid(riid));
|
|
|
|
+ return E_NOINTERFACE;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static ULONG WINAPI xhr3_callback_AddRef(IXMLHTTPRequest3Callback *iface)
|
|
|
|
+{
|
|
|
|
+ struct xhr3_callback *This = xhr3_callback_from_IXMLHTTPRequest3Callback(iface);
|
|
|
|
+ ULONG ref = InterlockedIncrement(&This->ref);
|
|
|
|
+ trace("(%p)->(%u)\n", This, ref);
|
|
|
|
+ return ref;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static ULONG WINAPI xhr3_callback_Release(IXMLHTTPRequest3Callback *iface)
|
|
|
|
+{
|
|
|
|
+ struct xhr3_callback *This = xhr3_callback_from_IXMLHTTPRequest3Callback(iface);
|
|
|
|
+ ULONG ref = InterlockedDecrement(&This->ref);
|
|
|
|
+ trace("(%p)->(%u)\n", This, ref);
|
|
|
|
+ if (ref == 0) HeapFree(GetProcessHeap(), 0, This);
|
|
|
|
+ return ref;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xhr3_callback_OnRedirect(IXMLHTTPRequest3Callback *iface,
|
|
|
|
+ IXMLHTTPRequest2 *request, const WCHAR* redirect_url)
|
|
|
|
+{
|
|
|
|
+ struct xhr3_callback *This = xhr3_callback_from_IXMLHTTPRequest3Callback(iface);
|
|
|
|
+ trace("(%p)->(%p %s)\n", This, request, debugstr_w(redirect_url));
|
|
|
|
+ return S_OK;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xhr3_callback_OnHeadersAvailable(IXMLHTTPRequest3Callback *iface,
|
|
|
|
+ IXMLHTTPRequest2 *request, DWORD status, const WCHAR *status_str)
|
|
|
|
+{
|
|
|
|
+ struct xhr3_callback *This = xhr3_callback_from_IXMLHTTPRequest3Callback(iface);
|
|
|
|
+ WCHAR *header = NULL;
|
|
|
|
+ HRESULT hr;
|
|
|
|
+
|
|
|
|
+ trace("(%p)->(%p %d %s)\n", This, request, status, debugstr_w(status_str));
|
|
|
|
+
|
|
|
|
+ header = (void *)0xdeadbeef;
|
|
|
|
+ hr = IXMLHTTPRequest2_GetResponseHeader(request, L"Content-Length", &header);
|
|
|
|
+ trace("Content-Length: %p (%s), hr %#x\n", header, debugstr_w(header), hr);
|
|
|
|
+
|
|
|
|
+ return S_OK;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xhr3_callback_OnDataAvailable(IXMLHTTPRequest3Callback *iface,
|
|
|
|
+ IXMLHTTPRequest2 *request, ISequentialStream *response)
|
|
|
|
+{
|
|
|
|
+ struct xhr3_callback *This = xhr3_callback_from_IXMLHTTPRequest3Callback(iface);
|
|
|
|
+ trace("(%p)->(%p %p)\n", This, request, response);
|
|
|
|
+ return S_OK;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xhr3_callback_OnResponseReceived(IXMLHTTPRequest3Callback *iface,
|
|
|
|
+ IXMLHTTPRequest2 *request, ISequentialStream *response)
|
|
|
|
+{
|
|
|
|
+ struct xhr3_callback *This = xhr3_callback_from_IXMLHTTPRequest3Callback(iface);
|
|
|
|
+ WCHAR *header = NULL;
|
|
|
|
+ char *buffer = HeapAlloc( GetProcessHeap(), 0, 256 );
|
|
|
|
+ ULONG read_size = 0;
|
|
|
|
+ HRESULT hr;
|
|
|
|
+
|
|
|
|
+ memset(buffer, '?', 256);
|
|
|
|
+ buffer[255] = 0;
|
|
|
|
+
|
|
|
|
+ trace("(%p)->(%p %p)\n", This, request, response);
|
|
|
|
+
|
|
|
|
+ header = (void *)0xdeadbeef;
|
|
|
|
+ hr = IXMLHTTPRequest2_GetResponseHeader(request, L"Cache-Control", &header);
|
|
|
|
+ trace("Cache-Control: %p (%s), hr %#x\n", header, debugstr_w(header), hr);
|
|
|
|
+
|
|
|
|
+ header = (void *)0xdeadbeef;
|
|
|
|
+ hr = IXMLHTTPRequest2_GetResponseHeader(request, L"Expires", &header);
|
|
|
|
+ trace("Expires: %p (%s), hr %#x\n", header, debugstr_w(header), hr);
|
|
|
|
+
|
|
|
|
+ header = (void *)0xdeadbeef;
|
|
|
|
+ hr = IXMLHTTPRequest2_GetResponseHeader(request, L"Content-Type", &header);
|
|
|
|
+ trace("Content-Type: %p (%s), hr %#x\n", header, debugstr_w(header), hr);
|
|
|
|
+
|
|
|
|
+ read_size = 0xdeadbeef;
|
|
|
|
+ hr = ISequentialStream_Read(response, buffer, 214, &read_size);
|
|
|
|
+ trace("Response: (%d) %s, hr %#x\n", read_size, debugstr_a(buffer), hr);
|
|
|
|
+
|
|
|
|
+ read_size = 0xdeadbeef;
|
|
|
|
+ hr = ISequentialStream_Read(response, buffer, 1, &read_size);
|
|
|
|
+ trace("Response: (%d) %s, hr %#x\n", read_size, debugstr_a(buffer), hr);
|
|
|
|
+
|
|
|
|
+ HeapFree( GetProcessHeap(), 0, buffer );
|
|
|
|
+ SetEvent(This->event);
|
|
|
|
+
|
|
|
|
+ return S_OK;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xhr3_callback_OnError(IXMLHTTPRequest3Callback *iface,
|
|
|
|
+ IXMLHTTPRequest2 *request, HRESULT error)
|
|
|
|
+{
|
|
|
|
+ struct xhr3_callback *This = xhr3_callback_from_IXMLHTTPRequest3Callback(iface);
|
|
|
|
+ trace("(%p)->(%p %#x)\n", This, request, error);
|
|
|
|
+ SetEvent(This->event);
|
|
|
|
+ return S_OK;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xhr3_callback_OnServerCertificateReceived(IXMLHTTPRequest3Callback *iface,
|
|
|
|
+ IXMLHTTPRequest3 *request, DWORD errors, DWORD chain_size, const XHR_CERT *chain)
|
|
|
|
+{
|
|
|
|
+ struct xhr3_callback *This = xhr3_callback_from_IXMLHTTPRequest3Callback(iface);
|
|
|
|
+ trace("(%p)->(%p %u %u %p)\n", This, request, errors, chain_size, chain);
|
|
|
|
+ return S_OK;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xhr3_callback_OnClientCertificateRequested(IXMLHTTPRequest3Callback *iface,
|
|
|
|
+ IXMLHTTPRequest3 *request, DWORD issuers_size, const WCHAR **issuers)
|
|
|
|
+{
|
|
|
|
+ struct xhr3_callback *This = xhr3_callback_from_IXMLHTTPRequest3Callback(iface);
|
|
|
|
+ trace("(%p)->(%p %u %p)\n", This, request, issuers_size, issuers);
|
|
|
|
+ return S_OK;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static const IXMLHTTPRequest3CallbackVtbl xhr3_callback_vtbl =
|
|
|
|
+{
|
|
|
|
+ xhr3_callback_QueryInterface,
|
|
|
|
+ xhr3_callback_AddRef,
|
|
|
|
+ xhr3_callback_Release,
|
|
|
|
+ /* IXMLHTTPRequest2Callback methods */
|
|
|
|
+ xhr3_callback_OnRedirect,
|
|
|
|
+ xhr3_callback_OnHeadersAvailable,
|
|
|
|
+ xhr3_callback_OnDataAvailable,
|
|
|
|
+ xhr3_callback_OnResponseReceived,
|
|
|
|
+ xhr3_callback_OnError,
|
|
|
|
+ /* IXMLHTTPRequest3Callback methods */
|
|
|
|
+ xhr3_callback_OnServerCertificateReceived,
|
|
|
|
+ xhr3_callback_OnClientCertificateRequested,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static IXMLHTTPRequest2Callback* xhr3_callback_create(HANDLE event)
|
|
|
|
+{
|
|
|
|
+ struct xhr3_callback *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
|
|
|
|
+ ok(This != NULL, "failed to allocate object\n");
|
|
|
|
+ if (!This) return NULL;
|
|
|
|
+
|
|
|
|
+ This->IXMLHTTPRequest3Callback_iface.lpVtbl = &xhr3_callback_vtbl;
|
|
|
|
+ This->ref = 1;
|
|
|
|
+ This->event = event;
|
|
|
|
+
|
|
|
|
+ return (IXMLHTTPRequest2Callback*)&This->IXMLHTTPRequest3Callback_iface;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+struct xhr2_stream
|
|
|
|
+{
|
|
|
|
+ IStream IStream_iface;
|
|
|
|
+ LONG ref;
|
|
|
|
+ IStream *stream;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static inline struct xhr2_stream *xhr2_stream_from_IStream(IStream *iface)
|
|
|
|
+{
|
|
|
|
+ return CONTAINING_RECORD(iface, struct xhr2_stream, IStream_iface);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xhr2_stream_QueryInterface(IStream *iface, REFIID riid, void **obj)
|
|
|
|
+{
|
|
|
|
+ struct xhr2_stream *This = xhr2_stream_from_IStream(iface);
|
|
|
|
+ trace("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
|
|
|
|
+
|
|
|
|
+ if (IsEqualGUID(riid, &IID_IStream) || IsEqualGUID(riid, &IID_ISequentialStream) || IsEqualGUID(riid, &IID_IUnknown))
|
|
|
|
+ {
|
|
|
|
+ IStream_AddRef(iface);
|
|
|
|
+ *obj = iface;
|
|
|
|
+ return S_OK;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ok(0, "unexpected interface %s\n", debugstr_guid(riid));
|
|
|
|
+ return E_NOINTERFACE;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static ULONG WINAPI xhr2_stream_AddRef(IStream *iface)
|
|
|
|
+{
|
|
|
|
+ struct xhr2_stream *This = xhr2_stream_from_IStream(iface);
|
|
|
|
+ ULONG ref = InterlockedIncrement(&This->ref);
|
|
|
|
+ trace("(%p)->(%u)\n", This, ref);
|
|
|
|
+ return ref;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static ULONG WINAPI xhr2_stream_Release(IStream *iface)
|
|
|
|
+{
|
|
|
|
+ struct xhr2_stream *This = xhr2_stream_from_IStream(iface);
|
|
|
|
+ ULONG ref = InterlockedDecrement(&This->ref);
|
|
|
|
+ trace("(%p)->(%u)\n", This, ref);
|
|
|
|
+ if (ref == 0)
|
|
|
|
+ {
|
|
|
|
+ IStream_Release(This->stream);
|
|
|
|
+ HeapFree(GetProcessHeap(), 0, This);
|
|
|
|
+ }
|
|
|
|
+ return ref;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xhr2_stream_Read(IStream *iface, void *pv, ULONG cb,
|
|
|
|
+ ULONG *pcbRead)
|
|
|
|
+{
|
|
|
|
+ struct xhr2_stream *This = xhr2_stream_from_IStream(iface);
|
|
|
|
+ trace("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
|
|
|
|
+ return IStream_Read(This->stream, pv, cb, pcbRead);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xhr2_stream_Write(IStream *iface, const void *pv,
|
|
|
|
+ ULONG cb, ULONG *pcbWritten)
|
|
|
|
+{
|
|
|
|
+ struct xhr2_stream *This = xhr2_stream_from_IStream(iface);
|
|
|
|
+ trace("(%p)->(%p %u %p)\n", This, pv, cb, pcbWritten);
|
|
|
|
+ return IStream_Write(This->stream, pv, cb, pcbWritten);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xhr2_stream_Seek(IStream *iface, LARGE_INTEGER dlibMove,
|
|
|
|
+ DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
|
|
|
|
+{
|
|
|
|
+ struct xhr2_stream *This = xhr2_stream_from_IStream(iface);
|
|
|
|
+ trace("(%p)->(%lu, %u %p)\n", This, dlibMove.QuadPart, dwOrigin, plibNewPosition);
|
|
|
|
+ return IStream_Seek(This->stream, dlibMove, dwOrigin, plibNewPosition);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xhr2_stream_SetSize(IStream *iface, ULARGE_INTEGER libNewSize)
|
|
|
|
+{
|
|
|
|
+ struct xhr2_stream *This = xhr2_stream_from_IStream(iface);
|
|
|
|
+ trace("(%p)->(%lu)\n", This, libNewSize.QuadPart);
|
|
|
|
+ return IStream_SetSize(This->stream, libNewSize);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xhr2_stream_CopyTo(IStream *iface, IStream *pstm,
|
|
|
|
+ ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
|
|
|
|
+{
|
|
|
|
+ struct xhr2_stream *This = xhr2_stream_from_IStream(iface);
|
|
|
|
+ trace("(%p)->(%p %lu %p %p)\n", This, pstm, cb.QuadPart, pcbRead, pcbWritten);
|
|
|
|
+ return IStream_CopyTo(This->stream, pstm, cb, pcbRead, pcbWritten);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xhr2_stream_Commit(IStream *iface, DWORD grfCommitFlags)
|
|
|
|
+{
|
|
|
|
+ struct xhr2_stream *This = xhr2_stream_from_IStream(iface);
|
|
|
|
+ trace("(%p)->(%#x)\n", This, grfCommitFlags);
|
|
|
|
+ return IStream_Commit(This->stream, grfCommitFlags);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xhr2_stream_Revert(IStream *iface)
|
|
|
|
+{
|
|
|
|
+ struct xhr2_stream *This = xhr2_stream_from_IStream(iface);
|
|
|
|
+ trace("(%p)->()\n", This);
|
|
|
|
+ return IStream_Revert(This->stream);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xhr2_stream_LockRegion(IStream *iface, ULARGE_INTEGER libOffset,
|
|
|
|
+ ULARGE_INTEGER cb, DWORD dwLockType)
|
|
|
|
+{
|
|
|
|
+ struct xhr2_stream *This = xhr2_stream_from_IStream(iface);
|
|
|
|
+ trace("(%p)->(%lu %lu %u)\n", This, libOffset.QuadPart, cb.QuadPart, dwLockType);
|
|
|
|
+ return IStream_LockRegion(This->stream, libOffset, cb, dwLockType);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xhr2_stream_UnlockRegion(IStream *iface, ULARGE_INTEGER libOffset,
|
|
|
|
+ ULARGE_INTEGER cb, DWORD dwLockType)
|
|
|
|
+{
|
|
|
|
+ struct xhr2_stream *This = xhr2_stream_from_IStream(iface);
|
|
|
|
+ trace("(%p)->(%lu %lu %u)\n", This, libOffset.QuadPart, cb.QuadPart, dwLockType);
|
|
|
|
+ return IStream_UnlockRegion(This->stream, libOffset, cb, dwLockType);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xhr2_stream_Stat(IStream *iface, STATSTG *pstatstg, DWORD grfStatFlag)
|
|
|
|
+{
|
|
|
|
+ struct xhr2_stream *This = xhr2_stream_from_IStream(iface);
|
|
|
|
+ trace("(%p)->(%p %#x)\n", This, pstatstg, grfStatFlag);
|
|
|
|
+ return IStream_Stat(This->stream, pstatstg, grfStatFlag);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI xhr2_stream_Clone(IStream *iface, IStream **ppstm)
|
|
|
|
+{
|
|
|
|
+ struct xhr2_stream *This = xhr2_stream_from_IStream(iface);
|
|
|
|
+ trace("(%p)->(%p)\n", This, ppstm);
|
|
|
|
+ return IStream_Clone(This->stream, ppstm);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static const IStreamVtbl xhr2_stream_vtbl =
|
|
|
|
+{
|
|
|
|
+ xhr2_stream_QueryInterface,
|
|
|
|
+ xhr2_stream_AddRef,
|
|
|
|
+ xhr2_stream_Release,
|
|
|
|
+ /* IStream methods */
|
|
|
|
+ xhr2_stream_Read,
|
|
|
|
+ xhr2_stream_Write,
|
|
|
|
+ xhr2_stream_Seek,
|
|
|
|
+ xhr2_stream_SetSize,
|
|
|
|
+ xhr2_stream_CopyTo,
|
|
|
|
+ xhr2_stream_Commit,
|
|
|
|
+ xhr2_stream_Revert,
|
|
|
|
+ xhr2_stream_LockRegion,
|
|
|
|
+ xhr2_stream_UnlockRegion,
|
|
|
|
+ xhr2_stream_Stat,
|
|
|
|
+ xhr2_stream_Clone
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static ISequentialStream *xhr2_stream_create(void)
|
|
|
|
+{
|
|
|
|
+ struct xhr2_stream *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
|
|
|
|
+ ok(This != NULL, "failed to allocate object\n");
|
|
|
|
+ if (!This) return NULL;
|
|
|
|
+
|
|
|
|
+ This->IStream_iface.lpVtbl = &xhr2_stream_vtbl;
|
|
|
|
+ This->ref = 1;
|
|
|
|
+ CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
|
|
|
|
+
|
|
|
|
+ return (ISequentialStream*)&This->IStream_iface;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void test_IXMLHTTPRequest2(void)
|
|
|
|
+{
|
|
|
|
+ IXMLHTTPRequest2 *xhr2[16];
|
|
|
|
+ IXMLHTTPRequest2Callback *xhr3_callback;
|
|
|
|
+ ISequentialStream *stream;
|
|
|
|
+ HANDLE events[16];
|
|
|
|
+ HRESULT hr;
|
|
|
|
+ int i = 0;
|
|
|
|
+
|
|
|
|
+ if (!(xhr2[i] = create_xhr2()))
|
|
|
|
+ {
|
|
|
|
+ win_skip("IXMLHTTPRequest2 is not available\n");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ events[i] = CreateEventW(NULL, FALSE, FALSE, NULL);
|
|
|
|
+ if (!(xhr3_callback = xhr3_callback_create(events[i])))
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ trace("IXMLHTTPRequest2_Open (%p)->(L\"GET\", L\"http://test.winehq.org/\", xhr3_callback, NULL, NULL, NULL, NULL)\n", GetCurrentThreadId(), xhr2[i]);
|
|
|
|
+ hr = IXMLHTTPRequest2_Open(xhr2[i], L"GET", L"http://test.winehq.org/", xhr3_callback, NULL, NULL, NULL, NULL);
|
|
|
|
+ ok(SUCCEEDED(hr), "IXMLHTTPRequest2_Send failed %#x\n", hr);
|
|
|
|
+
|
|
|
|
+ if ((stream = xhr2_stream_create()))
|
|
|
|
+ {
|
|
|
|
+ trace("IXMLHTTPRequest2_Send (%p)->(%p 0)\n", GetCurrentThreadId(), xhr2[i], stream);
|
|
|
|
+ hr = IXMLHTTPRequest2_Send(xhr2[i], stream, 0);
|
|
|
|
+ ok(SUCCEEDED(hr), "IXMLHTTPRequest2_Send failed %#x\n", hr);
|
|
|
|
+
|
|
|
|
+ ISequentialStream_Release(stream);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ IXMLHTTPRequest2Callback_Release(xhr3_callback);
|
|
|
|
+ i++;
|
|
|
|
+
|
|
|
|
+ while (i--)
|
|
|
|
+ {
|
|
|
|
+ WaitForSingleObject(events[i], INFINITE);
|
|
|
|
+ IXMLHTTPRequest2_Release(xhr2[i]);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
START_TEST(httpreq)
|
|
|
|
{
|
|
|
|
IXMLHttpRequest *xhr;
|
|
|
|
|
|
|
|
- CoInitialize(NULL);
|
|
|
|
+ CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
|
|
|
|
|
|
|
if (!(xhr = create_xhr()))
|
|
|
|
{
|
|
|
|
@@ -1912,6 +2300,7 @@ START_TEST(httpreq)
|
|
|
|
test_server_xhr();
|
|
|
|
test_safe_httpreq();
|
|
|
|
test_supporterrorinfo();
|
|
|
|
+ test_IXMLHTTPRequest2();
|
|
|
|
|
|
|
|
CoUninitialize();
|
|
|
|
}
|
2020-09-14 18:15:32 -07:00
|
|
|
diff --git a/dlls/msxml3/tests/schema.c b/dlls/msxml3/tests/schema.c
|
|
|
|
index 805f05cb71..f9c64c50ec 100644
|
|
|
|
--- a/dlls/msxml3/tests/schema.c
|
|
|
|
+++ b/dlls/msxml3/tests/schema.c
|
|
|
|
@@ -32,10 +32,15 @@
|
|
|
|
#include "dispex.h"
|
|
|
|
#include "cguid.h"
|
|
|
|
|
|
|
|
+DEFINE_GUID(CLSID_FreeThreadedDOMDocument60, 0x88d96a06, 0xf192, 0x11d4, 0xa6,0x5f, 0x00,0x40,0x96,0x32,0x51,0xe5);
|
|
|
|
+DEFINE_GUID(CLSID_FreeThreadedXMLHTTP60, 0x88d96a09, 0xf192, 0x11d4, 0xa6,0x5f, 0x00,0x40,0x96,0x32,0x51,0xe5);
|
|
|
|
DEFINE_GUID(CLSID_MXXMLWriter60, 0x88d96a0f, 0xf192, 0x11d4, 0xa6,0x5f, 0x00,0x40,0x96,0x32,0x51,0xe5);
|
|
|
|
DEFINE_GUID(CLSID_SAXAttributes60, 0x88d96a0e, 0xf192, 0x11d4, 0xa6,0x5f, 0x00,0x40,0x96,0x32,0x51,0xe5);
|
|
|
|
DEFINE_GUID(CLSID_SAXXMLReader60, 0x88d96a0c, 0xf192, 0x11d4, 0xa6,0x5f, 0x00,0x40,0x96,0x32,0x51,0xe5);
|
|
|
|
DEFINE_GUID(CLSID_XMLSchemaCache60, 0x88d96a07, 0xf192, 0x11d4, 0xa6,0x5f, 0x00,0x40,0x96,0x32,0x51,0xe5);
|
|
|
|
+DEFINE_GUID(IID_IXMLHTTPRequest2, 0xe5d37dc0, 0x552a, 0x4d52, 0x9c,0xc0, 0xa1,0x4d,0x54,0x6f,0xbd,0x04);
|
|
|
|
+DEFINE_GUID(IID_IXMLHTTPRequest2Callback, 0xa44a9299, 0xe321, 0x40de, 0x88,0x66, 0x34,0x1b,0x41,0x66,0x91,0x62);
|
|
|
|
+DEFINE_GUID(IID_IXMLHTTPRequest3Callback, 0xb9e57830, 0x8c6c, 0x4a6f, 0x9c,0x13, 0x47,0x77,0x2b,0xb0,0x47,0xbb);
|
|
|
|
|
|
|
|
#include "wine/test.h"
|
|
|
|
|
|
|
|
diff --git a/dlls/msxml3/uuid.c b/dlls/msxml3/uuid.c
|
|
|
|
index 333d4f3d3c..2b995d5acc 100644
|
|
|
|
--- a/dlls/msxml3/uuid.c
|
|
|
|
+++ b/dlls/msxml3/uuid.c
|
|
|
|
@@ -51,6 +51,9 @@ DEFINE_GUID(CLSID_ServerXMLHTTP60, 0x88d96a0b, 0xf192, 0x11d4, 0xa6,0x5f, 0x00,0
|
|
|
|
DEFINE_GUID(CLSID_XMLHTTP60, 0x88d96a0a, 0xf192, 0x11d4, 0xa6,0x5f, 0x00,0x40,0x96,0x32,0x51,0xe5);
|
|
|
|
DEFINE_GUID(CLSID_XMLSchemaCache60, 0x88d96a07, 0xf192, 0x11d4, 0xa6,0x5f, 0x00,0x40,0x96,0x32,0x51,0xe5);
|
|
|
|
DEFINE_GUID(CLSID_XSLTemplate60, 0x88d96a08, 0xf192, 0x11d4, 0xa6,0x5f, 0x00,0x40,0x96,0x32,0x51,0xe5);
|
|
|
|
+DEFINE_GUID(IID_IXMLHTTPRequest2, 0xe5d37dc0, 0x552a, 0x4d52, 0x9c,0xc0, 0xa1,0x4d,0x54,0x6f,0xbd,0x04);
|
|
|
|
+DEFINE_GUID(IID_IXMLHTTPRequest2Callback, 0xa44a9299, 0xe321, 0x40de, 0x88,0x66, 0x34,0x1b,0x41,0x66,0x91,0x62);
|
|
|
|
+DEFINE_GUID(IID_IXMLHTTPRequest3Callback, 0xb9e57830, 0x8c6c, 0x4a6f, 0x9c,0x13, 0x47,0x77,0x2b,0xb0,0x47,0xbb);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Note that because of a #define in msxml2.h, we end up initializing
|
2020-09-08 19:37:05 -07:00
|
|
|
--
|
|
|
|
2.28.0
|
|
|
|
|