Nikolay Sivov : msxml3/httprequest: Implement IXMLHttpRequest:: setRequestHeader().

Alexandre Julliard julliard at winehq.org
Wed Sep 29 12:00:17 CDT 2010


Module: wine
Branch: master
Commit: 1ac256a5885fcb7a26e5d617f1599b2761f765e2
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=1ac256a5885fcb7a26e5d617f1599b2761f765e2

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Wed Sep 29 02:50:37 2010 +0400

msxml3/httprequest: Implement IXMLHttpRequest::setRequestHeader().

---

 dlls/msxml3/httprequest.c  |   80 ++++++++++++++++++++++++++++++++++++++++---
 dlls/msxml3/tests/domdoc.c |   36 ++++++++++++++++++++
 2 files changed, 110 insertions(+), 6 deletions(-)

diff --git a/dlls/msxml3/httprequest.c b/dlls/msxml3/httprequest.c
index 21bd80c..e0f7701 100644
--- a/dlls/msxml3/httprequest.c
+++ b/dlls/msxml3/httprequest.c
@@ -31,6 +31,7 @@
 #include "msxml_private.h"
 
 #include "wine/debug.h"
+#include "wine/list.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
 
@@ -40,14 +41,34 @@ 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;
+};
+
+enum READYSTATE
+{
+    STATE_UNINITIALIZED = 0,
+    STATE_LOADING       = 1,
+    STATE_LOADED        = 2,
+    STATE_INTERACTIVE   = 3,
+    STATE_COMPLETED     = 4
+};
+
 typedef struct _httprequest
 {
     const struct IXMLHTTPRequestVtbl *lpVtbl;
     LONG ref;
 
+    READYSTATE state;
+
+    /* request */
     BINDVERB verb;
     BSTR url;
     BOOL async;
+    struct list reqheaders;
 
     /* credentials */
     BSTR user;
@@ -59,6 +80,12 @@ static inline httprequest *impl_from_IXMLHTTPRequest( IXMLHTTPRequest *iface )
     return (httprequest *)((char*)iface - FIELD_OFFSET(httprequest, lpVtbl));
 }
 
+/* TODO: process OnChange callback */
+static void httprequest_setreadystate(httprequest *This, READYSTATE state)
+{
+    This->state = state;
+}
+
 static HRESULT WINAPI httprequest_QueryInterface(IXMLHTTPRequest *iface, REFIID riid, void **ppvObject)
 {
     httprequest *This = impl_from_IXMLHTTPRequest( iface );
@@ -95,9 +122,20 @@ static ULONG WINAPI httprequest_Release(IXMLHTTPRequest *iface)
     ref = InterlockedDecrement( &This->ref );
     if ( ref == 0 )
     {
+        struct reqheader *header, *header2;
+
         SysFreeString(This->url);
         SysFreeString(This->user);
         SysFreeString(This->password);
+
+        /* request headers */
+        LIST_FOR_EACH_ENTRY_SAFE(header, header2, &This->reqheaders, struct reqheader, entry)
+        {
+            list_remove(&header->entry);
+            SysFreeString(header->header);
+            SysFreeString(header->value);
+        }
+
         heap_free( This );
     }
 
@@ -223,16 +261,41 @@ static HRESULT WINAPI httprequest_open(IXMLHTTPRequest *iface, BSTR method, BSTR
     if (hr == S_OK)
         This->password = V_BSTR(&str);
 
+    httprequest_setreadystate(This, STATE_LOADING);
+
     return S_OK;
 }
 
-static HRESULT WINAPI httprequest_setRequestHeader(IXMLHTTPRequest *iface, BSTR bstrHeader, BSTR bstrValue)
+static HRESULT WINAPI httprequest_setRequestHeader(IXMLHTTPRequest *iface, BSTR header, BSTR value)
 {
     httprequest *This = impl_from_IXMLHTTPRequest( iface );
+    struct reqheader *entry;
 
-    FIXME("stub (%p) %s %s\n", This, debugstr_w(bstrHeader), debugstr_w(bstrValue));
+    TRACE("(%p)->(%s %s)\n", This, debugstr_w(header), debugstr_w(value));
 
-    return E_NOTIMPL;
+    if (!header || !*header) return E_INVALIDARG;
+    if (This->state != STATE_LOADING) return E_FAIL;
+    if (!value) return E_INVALIDARG;
+
+    /* replace existing header value if already added */
+    LIST_FOR_EACH_ENTRY(entry, &This->reqheaders, struct reqheader, entry)
+    {
+        if (lstrcmpW(entry->header, header) == 0)
+        {
+            return SysReAllocString(&entry->value, value) ? S_OK : E_OUTOFMEMORY;
+        }
+    }
+
+    entry = heap_alloc(sizeof(*entry));
+    if (!entry) return E_OUTOFMEMORY;
+
+    /* new header */
+    entry->header = SysAllocString(header);
+    entry->value  = SysAllocString(value);
+
+    list_add_head(&This->reqheaders, &entry->entry);
+
+    return S_OK;
 }
 
 static HRESULT WINAPI httprequest_getResponseHeader(IXMLHTTPRequest *iface, BSTR bstrHeader, BSTR *pbstrValue)
@@ -325,13 +388,16 @@ static HRESULT WINAPI httprequest_get_responseStream(IXMLHTTPRequest *iface, VAR
     return E_NOTIMPL;
 }
 
-static HRESULT WINAPI httprequest_get_readyState(IXMLHTTPRequest *iface, LONG *plState)
+static HRESULT WINAPI httprequest_get_readyState(IXMLHTTPRequest *iface, LONG *state)
 {
     httprequest *This = impl_from_IXMLHTTPRequest( iface );
 
-    FIXME("stub %p %p\n", This, plState);
+    TRACE("(%p)->(%p)\n", This, state);
 
-    return E_NOTIMPL;
+    if (!state) return E_INVALIDARG;
+
+    *state = This->state;
+    return S_OK;
 }
 
 static HRESULT WINAPI httprequest_put_onreadystatechange(IXMLHTTPRequest *iface, IDispatch *pReadyStateSink)
@@ -385,6 +451,8 @@ HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, LPVOID *ppObj)
     req->async = FALSE;
     req->verb = -1;
     req->url = req->user = req->password = NULL;
+    req->state = STATE_UNINITIALIZED;
+    list_init(&req->reqheaders);
 
     *ppObj = &req->lpVtbl;
 
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index 008c6b7..d9587a0 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -2887,6 +2887,7 @@ static void test_XMLHTTP(void)
     VARIANT dummy;
     VARIANT async;
     VARIANT varbody;
+    LONG state;
     HRESULT hr = CoCreateInstance(&CLSID_XMLHTTPRequest, NULL,
                                   CLSCTX_INPROC_SERVER, &IID_IXMLHttpRequest,
                                   (void **)&pXMLHttpRequest);
@@ -2918,9 +2919,43 @@ static void test_XMLHTTP(void)
     hr = IXMLHttpRequest_open(pXMLHttpRequest, NULL, url, async, dummy, dummy);
     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
 
+    hr = IXMLHttpRequest_setRequestHeader(pXMLHttpRequest, NULL, NULL);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+
+    hr = IXMLHttpRequest_setRequestHeader(pXMLHttpRequest, _bstr_("header1"), NULL);
+    ok(hr == E_FAIL || broken(hr == E_UNEXPECTED) /* win9x, win2k */, "got 0x%08x\n", hr);
+
+    hr = IXMLHttpRequest_setRequestHeader(pXMLHttpRequest, NULL, _bstr_("value1"));
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+
+    hr = IXMLHttpRequest_setRequestHeader(pXMLHttpRequest, _bstr_("header1"), _bstr_("value1"));
+    ok(hr == E_FAIL || broken(hr == E_UNEXPECTED) /* win9x, win2k */, "got 0x%08x\n", hr);
+
+    hr = IXMLHttpRequest_get_readyState(pXMLHttpRequest, NULL);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+
+    state = -1;
+    hr = IXMLHttpRequest_get_readyState(pXMLHttpRequest, &state);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(state == 0, "got %d, expected 0\n", state);
+
     hr = IXMLHttpRequest_open(pXMLHttpRequest, method, url, async, dummy, dummy);
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
+    state = -1;
+    hr = IXMLHttpRequest_get_readyState(pXMLHttpRequest, &state);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(state == 1, "got %d, expected 1\n", state);
+
+    hr = IXMLHttpRequest_setRequestHeader(pXMLHttpRequest, _bstr_("header1"), _bstr_("value1"));
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = IXMLHttpRequest_setRequestHeader(pXMLHttpRequest, NULL, _bstr_("value1"));
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+
+    hr = IXMLHttpRequest_setRequestHeader(pXMLHttpRequest, _bstr_(""), _bstr_("value1"));
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+
     SysFreeString(method);
     SysFreeString(url);
 
@@ -2945,6 +2980,7 @@ static void test_XMLHTTP(void)
     }
 
     IXMLHttpRequest_Release(pXMLHttpRequest);
+    free_bstrs();
 }
 
 static void test_IXMLDOMDocument2(void)




More information about the wine-cvs mailing list