2 * Copyright 2015 Zhenbo Li
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "wine/test.h"
31 #define DEFINE_EXPECT(func) \
32 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
34 #define SET_EXPECT(func) \
35 do { called_ ## func = FALSE; expect_ ## func = TRUE; } while(0)
37 #define CHECK_EXPECT2(func) \
40 ok(expect_ ##func, "unexpected call " #func "\n"); \
41 called_ ## func = TRUE; \
44 #define CHECK_EXPECT(func) \
46 CHECK_EXPECT2(func); \
47 expect_ ## func = FALSE; \
50 #define CHECK_CALLED(func) \
52 ok(called_ ## func, "expected " #func "\n"); \
53 expect_ ## func = called_ ## func = FALSE; \
56 static IHTMLXMLHttpRequest
*xhr
= NULL
;
57 static BSTR content_type
= NULL
;
58 static int loading_cnt
= 0;
59 static int readystatechange_cnt
= 0;
61 DEFINE_EXPECT(xmlhttprequest_onreadystatechange_opened
);
62 DEFINE_EXPECT(xmlhttprequest_onreadystatechange_headers_received
);
63 DEFINE_EXPECT(xmlhttprequest_onreadystatechange_loading
);
64 DEFINE_EXPECT(xmlhttprequest_onreadystatechange_done
);
66 #define test_disp(u,id) _test_disp(__LINE__,u,id)
67 static void _test_disp(unsigned line
, IUnknown
*unk
, const IID
*diid
, const IID
*broken_diid
)
74 hres
= IUnknown_QueryInterface(unk
, &IID_IDispatchEx
, (void**)&dispex
);
75 ok_(__FILE__
,line
) (hres
== S_OK
, "Could not get IDispatch: %08x\n", hres
);
80 hres
= IDispatchEx_GetTypeInfoCount(dispex
, &ticnt
);
81 ok_(__FILE__
,line
) (hres
== S_OK
, "GetTypeInfoCount failed: %08x\n", hres
);
82 ok_(__FILE__
,line
) (ticnt
== 1, "ticnt=%u\n", ticnt
);
84 hres
= IDispatchEx_GetTypeInfo(dispex
, 0, 0, &typeinfo
);
85 ok_(__FILE__
,line
) (hres
== S_OK
, "GetTypeInfo failed: %08x\n", hres
);
90 hres
= ITypeInfo_GetTypeAttr(typeinfo
, &type_attr
);
91 ok_(__FILE__
,line
) (hres
== S_OK
, "GetTypeAttr failed: %08x\n", hres
);
92 ok_(__FILE__
,line
) (IsEqualGUID(&type_attr
->guid
, diid
)
93 || broken(broken_diid
&& IsEqualGUID(&type_attr
->guid
, broken_diid
)),
94 "unexpected guid %s\n", wine_dbgstr_guid(&type_attr
->guid
));
96 ITypeInfo_ReleaseTypeAttr(typeinfo
, type_attr
);
97 ITypeInfo_Release(typeinfo
);
100 IDispatchEx_Release(dispex
);
103 #define test_event_args(a,b,c,d,e,f,g,h) _test_event_args(__LINE__,a,b,c,d,e,f,g,h)
104 static void _test_event_args(unsigned line
, const IID
*dispiid
, const IID
*broken_dispiid
, DISPID id
, WORD wFlags
,
105 DISPPARAMS
*pdp
, VARIANT
*pvarRes
, EXCEPINFO
*pei
, IServiceProvider
*pspCaller
)
107 ok_(__FILE__
,line
) (id
== DISPID_VALUE
, "id = %d\n", id
);
108 ok_(__FILE__
,line
) (wFlags
== DISPATCH_METHOD
, "wFlags = %x\n", wFlags
);
109 ok_(__FILE__
,line
) (pdp
!= NULL
, "pdp == NULL\n");
110 ok_(__FILE__
,line
) (pdp
->cArgs
== 1, "pdp->cArgs = %d\n", pdp
->cArgs
);
111 ok_(__FILE__
,line
) (pdp
->cNamedArgs
== 1, "pdp->cNamedArgs = %d\n", pdp
->cNamedArgs
);
112 ok_(__FILE__
,line
) (pdp
->rgdispidNamedArgs
[0] == DISPID_THIS
, "pdp->rgdispidNamedArgs[0] = %d\n",
113 pdp
->rgdispidNamedArgs
[0]);
114 ok_(__FILE__
,line
) (V_VT(pdp
->rgvarg
) == VT_DISPATCH
, "V_VT(rgvarg) = %d\n", V_VT(pdp
->rgvarg
));
115 ok_(__FILE__
,line
) (pvarRes
!= NULL
, "pvarRes == NULL\n");
116 ok_(__FILE__
,line
) (pei
!= NULL
, "pei == NULL\n");
117 ok_(__FILE__
,line
) (!pspCaller
, "pspCaller != NULL\n");
120 _test_disp(line
, (IUnknown
*)V_DISPATCH(pdp
->rgvarg
), dispiid
, broken_dispiid
);
123 static HRESULT WINAPI
DispatchEx_QueryInterface(IDispatchEx
*iface
, REFIID riid
, void **ppv
)
125 if(!IsEqualGUID(riid
, &IID_IUnknown
)
126 && !IsEqualGUID(riid
, &IID_IDispatch
)
127 && !IsEqualGUID(riid
, &IID_IDispatchEx
)) {
129 return E_NOINTERFACE
;
136 static ULONG WINAPI
DispatchEx_AddRef(IDispatchEx
*iface
)
141 static ULONG WINAPI
DispatchEx_Release(IDispatchEx
*iface
)
146 static HRESULT WINAPI
DispatchEx_GetTypeInfoCount(IDispatchEx
*iface
, UINT
*pctinfo
)
148 ok(0, "unexpected call\n");
152 static HRESULT WINAPI
DispatchEx_GetTypeInfo(IDispatchEx
*iface
, UINT iTInfo
,
153 LCID lcid
, ITypeInfo
**ppTInfo
)
155 ok(0, "unexpected call\n");
159 static HRESULT WINAPI
DispatchEx_GetIDsOfNames(IDispatchEx
*iface
, REFIID riid
,
160 LPOLESTR
*rgszNames
, UINT cNames
,
161 LCID lcid
, DISPID
*rgDispId
)
163 ok(0, "unexpected call\n");
167 static HRESULT WINAPI
DispatchEx_Invoke(IDispatchEx
*iface
, DISPID dispIdMember
,
168 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
169 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
171 ok(0, "unexpected call\n");
175 static HRESULT WINAPI
DispatchEx_GetDispID(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
, DISPID
*pid
)
177 ok(0, "unexpected call\n");
181 static HRESULT WINAPI
DispatchEx_DeleteMemberByName(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
)
183 ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName
), grfdex
);
187 static HRESULT WINAPI
DispatchEx_DeleteMemberByDispID(IDispatchEx
*iface
, DISPID id
)
189 ok(0, "unexpected call\n");
193 static HRESULT WINAPI
DispatchEx_GetMemberProperties(IDispatchEx
*iface
, DISPID id
, DWORD grfdexFetch
, DWORD
*pgrfdex
)
195 ok(0, "unexpected call\n");
199 static HRESULT WINAPI
DispatchEx_GetMemberName(IDispatchEx
*iface
, DISPID id
, BSTR
*pbstrName
)
201 ok(0, "unexpected call\n");
205 static HRESULT WINAPI
DispatchEx_GetNextDispID(IDispatchEx
*iface
, DWORD grfdex
, DISPID id
, DISPID
*pid
)
207 ok(0, "unexpected call\n");
211 static HRESULT WINAPI
DispatchEx_GetNameSpaceParent(IDispatchEx
*iface
, IUnknown
**ppunk
)
213 ok(0, "unexpected call\n");
217 static HRESULT WINAPI
xmlhttprequest_onreadystatechange(IDispatchEx
*iface
, DISPID id
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pdp
,
218 VARIANT
*pvarRes
, EXCEPINFO
*pei
, IServiceProvider
*pspCaller
)
223 test_event_args(&DIID_DispHTMLXMLHttpRequest
, &IID_IHTMLXMLHttpRequest
, id
, wFlags
, pdp
, pvarRes
, pei
, pspCaller
);
225 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
226 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
227 readystatechange_cnt
++;
231 CHECK_EXPECT(xmlhttprequest_onreadystatechange_opened
);
234 CHECK_EXPECT(xmlhttprequest_onreadystatechange_headers_received
);
238 CHECK_EXPECT2(xmlhttprequest_onreadystatechange_loading
);
241 CHECK_EXPECT(xmlhttprequest_onreadystatechange_done
);
244 ok(0, "unexpected readyState: %d\n", val
);
249 static IDispatchExVtbl xmlhttprequest_onreadystatechangeFuncVtbl
= {
250 DispatchEx_QueryInterface
,
253 DispatchEx_GetTypeInfoCount
,
254 DispatchEx_GetTypeInfo
,
255 DispatchEx_GetIDsOfNames
,
257 DispatchEx_GetDispID
,
258 xmlhttprequest_onreadystatechange
,
259 DispatchEx_DeleteMemberByName
,
260 DispatchEx_DeleteMemberByDispID
,
261 DispatchEx_GetMemberProperties
,
262 DispatchEx_GetMemberName
,
263 DispatchEx_GetNextDispID
,
264 DispatchEx_GetNameSpaceParent
266 static IDispatchEx xmlhttprequest_onreadystatechange_obj
= { &xmlhttprequest_onreadystatechangeFuncVtbl
};
268 static BOOL doc_complete
;
269 static IHTMLDocument2
*notif_doc
;
271 static HRESULT WINAPI
PropertyNotifySink_QueryInterface(IPropertyNotifySink
*iface
,
272 REFIID riid
, void**ppv
)
274 if(IsEqualGUID(&IID_IPropertyNotifySink
, riid
)) {
279 ok(0, "unexpected call\n");
280 return E_NOINTERFACE
;
283 static ULONG WINAPI
PropertyNotifySink_AddRef(IPropertyNotifySink
*iface
)
288 static ULONG WINAPI
PropertyNotifySink_Release(IPropertyNotifySink
*iface
)
293 static HRESULT WINAPI
PropertyNotifySink_OnChanged(IPropertyNotifySink
*iface
, DISPID dispID
)
295 if(dispID
== DISPID_READYSTATE
){
299 hres
= IHTMLDocument2_get_readyState(notif_doc
, &state
);
300 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
302 if(!lstrcmpW(state
, L
"complete"))
305 SysFreeString(state
);
311 static HRESULT WINAPI
PropertyNotifySink_OnRequestEdit(IPropertyNotifySink
*iface
, DISPID dispID
)
313 ok(0, "unexpected call\n");
317 static IPropertyNotifySinkVtbl PropertyNotifySinkVtbl
= {
318 PropertyNotifySink_QueryInterface
,
319 PropertyNotifySink_AddRef
,
320 PropertyNotifySink_Release
,
321 PropertyNotifySink_OnChanged
,
322 PropertyNotifySink_OnRequestEdit
325 static IPropertyNotifySink PropertyNotifySink
= { &PropertyNotifySinkVtbl
};
327 static void do_advise(IUnknown
*unk
, REFIID riid
, IUnknown
*unk_advise
)
329 IConnectionPointContainer
*container
;
330 IConnectionPoint
*cp
;
334 hres
= IUnknown_QueryInterface(unk
, &IID_IConnectionPointContainer
, (void**)&container
);
335 ok(hres
== S_OK
, "QueryInterface(IID_IConnectionPointContainer) failed: %08x\n", hres
);
337 hres
= IConnectionPointContainer_FindConnectionPoint(container
, riid
, &cp
);
338 IConnectionPointContainer_Release(container
);
339 ok(hres
== S_OK
, "FindConnectionPoint failed: %08x\n", hres
);
341 hres
= IConnectionPoint_Advise(cp
, unk_advise
, &cookie
);
342 IConnectionPoint_Release(cp
);
343 ok(hres
== S_OK
, "Advise failed: %08x\n", hres
);
346 static void pump_msgs(BOOL
*b
)
351 while(!*b
&& GetMessageW(&msg
, NULL
, 0, 0)) {
352 TranslateMessage(&msg
);
353 DispatchMessageW(&msg
);
356 while(PeekMessageW(&msg
, NULL
, 0, 0, PM_REMOVE
)) {
357 TranslateMessage(&msg
);
358 DispatchMessageW(&msg
);
369 static void create_xmlhttprequest(IHTMLDocument2
*doc
)
371 IHTMLWindow2
*window
;
372 IHTMLWindow5
*window5
;
374 IHTMLXMLHttpRequestFactory
*factory
;
377 hres
= IHTMLDocument2_get_parentWindow(doc
, &window
);
378 ok(hres
== S_OK
, "get_parentWindow failed: %08x\n", hres
);
379 ok(window
!= NULL
, "window == NULL\n");
381 hres
= IHTMLWindow2_QueryInterface(window
, &IID_IHTMLWindow5
, (void**)&window5
);
382 IHTMLWindow2_Release(window
);
384 win_skip("IHTMLWindow5 not supported\n");
389 hres
= IHTMLWindow5_get_XMLHttpRequest(window5
, &var
);
390 IHTMLWindow5_Release(window5
);
391 ok(hres
== S_OK
, "get_XMLHttpRequest failed: %08x\n", hres
);
392 ok(V_VT(&var
) == VT_DISPATCH
, "V_VT(&var) is %08x, expected VT_DISPATCH\n", V_VT(&var
));
394 hres
= IDispatch_QueryInterface(V_DISPATCH(&var
), &IID_IHTMLXMLHttpRequestFactory
, (void**)&factory
);
396 ok(hres
== S_OK
, "QueryInterface(IID_IHTMLXMLHttpRequestFactory) failed: %08x\n", hres
);
397 ok(factory
!= NULL
, "factory == NULL\n");
399 hres
= IHTMLXMLHttpRequestFactory_create(factory
, &xhr
);
400 IHTMLXMLHttpRequestFactory_Release(factory
);
401 ok(hres
== S_OK
, "create failed: %08x\n", hres
);
402 ok(xhr
!= NULL
, "xhr == NULL\n");
405 static void test_header(const struct HEADER_TYPE expect
[], int num
)
413 hres
= IHTMLXMLHttpRequest_getAllResponseHeaders(xhr
, &all
);
414 ok(hres
== S_OK
, "getAllResponseHeader failed: %08x\n", hres
);
415 ok(all
!= NULL
, "all == NULL\n");
417 for(i
= 0; i
< num
; ++i
) {
419 key
= SysAllocString(expect
[i
].key
);
420 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, key
, &text
);
421 ok(hres
== S_OK
, "getResponseHeader failed, got %08x\n", hres
);
422 ok(text
!= NULL
, "text == NULL\n");
423 ok(!lstrcmpW(text
, expect
[i
].value
),
424 "Expect %s: %s, got %s\n", wine_dbgstr_w(expect
[i
].key
), wine_dbgstr_w(expect
[i
].value
),
425 wine_dbgstr_w(text
));
429 wsprintfW(buf
, L
"%s: %s", expect
[i
].key
, expect
[i
].value
);
430 ok(wcsstr(all
, buf
) != NULL
, "AllResponseHeaders(%s) don't have expected substr(%s)\n",
431 wine_dbgstr_w(all
), wine_dbgstr_w(buf
));
437 static void test_illegal_xml(IXMLDOMDocument
*xmldom
)
439 IXMLDOMNode
*first
, *last
;
444 hres
= IXMLDOMDocument_get_baseName(xmldom
, NULL
);
445 ok(hres
== E_INVALIDARG
, "Expect E_INVALIDARG, got %08x\n", hres
);
446 hres
= IXMLDOMDocument_get_baseName(xmldom
, &bstr
);
447 ok(hres
== S_FALSE
, "get_baseName failed: %08x\n", hres
);
448 ok(bstr
== NULL
, "bstr(%p): %s\n", bstr
, wine_dbgstr_w(bstr
));
451 hres
= IXMLDOMDocument_get_dataType(xmldom
, NULL
);
452 ok(hres
== E_INVALIDARG
, "Expect E_INVALIDARG, got %08x\n", hres
);
453 hres
= IXMLDOMDocument_get_dataType(xmldom
, &variant
);
454 ok(hres
== S_FALSE
, "get_dataType failed: %08x\n", hres
);
455 ok(V_VT(&variant
) == VT_NULL
, "got %s\n", wine_dbgstr_variant(&variant
));
456 VariantClear(&variant
);
458 hres
= IXMLDOMDocument_get_text(xmldom
, &bstr
);
459 ok(!lstrcmpW(bstr
, L
""), "text = %s\n", wine_dbgstr_w(bstr
));
462 hres
= IXMLDOMDocument_get_firstChild(xmldom
, NULL
);
463 ok(hres
== E_INVALIDARG
, "Expect E_INVALIDARG, got %08x\n", hres
);
465 first
= (void*)0xdeadbeef;
466 hres
= IXMLDOMDocument_get_firstChild(xmldom
, &first
);
467 ok(hres
== S_FALSE
, "get_firstChild failed: %08x\n", hres
);
468 ok(first
== NULL
, "first != NULL\n");
470 last
= (void*)0xdeadbeef;
471 hres
= IXMLDOMDocument_get_lastChild(xmldom
, &last
);
472 ok(hres
== S_FALSE
, "get_lastChild failed: %08x\n", hres
);
473 ok(last
== NULL
, "last != NULL\n");
476 #define set_request_header(a,b,c) _set_request_header(__LINE__,a,b,c)
477 static void _set_request_header(unsigned line
, IHTMLXMLHttpRequest
*xhr
, const WCHAR
*header_w
, const WCHAR
*value_w
)
479 BSTR header
= SysAllocString(header_w
), value
= SysAllocString(value_w
);
482 hres
= IHTMLXMLHttpRequest_setRequestHeader(xhr
, header
, value
);
483 ok_(__FILE__
,line
)(hres
== S_OK
, "setRequestHeader failed: %08x\n", hres
);
485 SysFreeString(header
);
486 SysFreeString(value
);
489 static void test_responseXML(const WCHAR
*expect_text
)
492 IXMLDOMDocument
*xmldom
;
493 IObjectSafety
*safety
;
494 DWORD enabled
= 0, supported
= 0;
498 hres
= IHTMLXMLHttpRequest_get_responseXML(xhr
, &disp
);
499 ok(hres
== S_OK
, "get_responseXML failed: %08x\n", hres
);
500 ok(disp
!= NULL
, "disp == NULL\n");
503 hres
= IDispatch_QueryInterface(disp
, &IID_IXMLDOMDocument
, (void**)&xmldom
);
504 ok(hres
== S_OK
, "QueryInterface(IXMLDOMDocument) failed: %08x\n", hres
);
505 ok(xmldom
!= NULL
, "xmldom == NULL\n");
507 hres
= IXMLDOMDocument_QueryInterface(xmldom
, &IID_IObjectSafety
, (void**)&safety
);
508 ok(hres
== S_OK
, "QueryInterface IObjectSafety failed: %08x\n", hres
);
509 hres
= IObjectSafety_GetInterfaceSafetyOptions(safety
, NULL
, &supported
, &enabled
);
510 ok(hres
== S_OK
, "GetInterfaceSafetyOptions failed: %08x\n", hres
);
511 ok(broken(supported
== (INTERFACESAFE_FOR_UNTRUSTED_CALLER
| INTERFACESAFE_FOR_UNTRUSTED_DATA
)) ||
512 supported
== (INTERFACESAFE_FOR_UNTRUSTED_CALLER
| INTERFACESAFE_FOR_UNTRUSTED_DATA
| INTERFACE_USES_SECURITY_MANAGER
) /* msxml3 SP8+ */,
513 "Expected supported: (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER), got %08x\n", supported
);
514 ok(enabled
== ((INTERFACESAFE_FOR_UNTRUSTED_CALLER
| INTERFACESAFE_FOR_UNTRUSTED_DATA
| INTERFACE_USES_SECURITY_MANAGER
) & supported
),
515 "Expected enabled: (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER), got 0x%08x\n", enabled
);
516 IObjectSafety_Release(safety
);
519 test_illegal_xml(xmldom
);
521 IXMLDOMDocument_Release(xmldom
);
522 IDispatch_Release(disp
);
525 #define xhr_open(a,b) _xhr_open(__LINE__,a,b)
526 static HRESULT
_xhr_open(unsigned line
, const WCHAR
*url_w
, const WCHAR
*method_w
)
528 BSTR method
= SysAllocString(method_w
);
529 BSTR url
= SysAllocString(url_w
);
530 VARIANT async
, empty
;
533 V_VT(&async
) = VT_BOOL
;
534 V_BOOL(&async
) = VARIANT_TRUE
;
535 V_VT(&empty
) = VT_EMPTY
;
537 hres
= IHTMLXMLHttpRequest_open(xhr
, method
, url
, async
, empty
, empty
);
538 ok_(__FILE__
,line
)(hres
== S_OK
, "open failed: %08x\n", hres
);
540 SysFreeString(method
);
545 #define test_response_text(a) _test_response_text(__LINE__,a)
546 static void _test_response_text(unsigned line
, const WCHAR
*expect_text
)
551 hres
= IHTMLXMLHttpRequest_get_responseText(xhr
, &text
);
552 ok(hres
== S_OK
, "get_responseText failed: %08x\n", hres
);
553 ok(text
!= NULL
, "test == NULL\n");
556 /* Some recent version of IE strip trailing '\n' from post.php response, while others don't. */
557 len
= SysStringLen(text
);
558 if(text
[len
-1] == '\n')
560 ok_(__FILE__
,line
)(!lstrcmpW(text
, expect_text
), "expect %s, got %s\n",
561 wine_dbgstr_w(expect_text
), wine_dbgstr_w(text
));
566 static void test_sync_xhr(IHTMLDocument2
*doc
, const WCHAR
*xml_url
, const WCHAR
*expect_text
)
568 VARIANT vbool
, vempty
, var
;
573 static const struct HEADER_TYPE expect_headers
[] = {
574 {L
"Content-Length", L
"51"},
575 {L
"Content-Type", L
"application/xml"}
578 trace("test_sync_xhr\n");
580 create_xmlhttprequest(doc
);
584 V_VT(&var
) = VT_EMPTY
;
585 hres
= IHTMLXMLHttpRequest_get_onreadystatechange(xhr
, &var
);
586 ok(hres
== S_OK
, "get_onreadystatechange failed: %08x\n", hres
);
587 ok(V_VT(&var
) == VT_NULL
, "V_VT(onreadystatechange) = %d\n", V_VT(&var
));
589 V_VT(&var
) = VT_DISPATCH
;
590 V_DISPATCH(&var
) = (IDispatch
*)&xmlhttprequest_onreadystatechange_obj
;
591 hres
= IHTMLXMLHttpRequest_put_onreadystatechange(xhr
, var
);
592 ok(hres
== S_OK
, "put_onreadystatechange failed: %08x\n", hres
);
594 V_VT(&var
) = VT_EMPTY
;
595 hres
= IHTMLXMLHttpRequest_get_onreadystatechange(xhr
, &var
);
596 ok(hres
== S_OK
, "get_onreadystatechange failed: %08x\n", hres
);
597 ok(V_VT(&var
) == VT_DISPATCH
, "V_VT(onreadystatechange) = %d\n", V_VT(&var
));
598 ok(V_DISPATCH(&var
) == (IDispatch
*)&xmlhttprequest_onreadystatechange_obj
, "unexpected onreadystatechange value\n");
600 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, NULL
);
601 ok(hres
== E_POINTER
, "Expect E_POINTER, got %08x\n", hres
);
604 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
605 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
606 ok(val
== 0, "Expect UNSENT, got %d\n", val
);
608 hres
= IHTMLXMLHttpRequest_get_status(xhr
, NULL
);
609 ok(hres
== E_POINTER
, "Expect E_POINTER, got %08x\n", hres
);
612 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
613 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
614 ok(val
== 0, "Expect 0, got %d\n", val
);
616 hres
= IHTMLXMLHttpRequest_get_statusText(xhr
, NULL
);
617 ok(hres
== E_POINTER
, "Expect E_POINTER, got %08x\n", hres
);
619 hres
= IHTMLXMLHttpRequest_get_statusText(xhr
, &text
);
620 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
621 ok(text
== NULL
, "Expect NULL, got %p\n", text
);
623 text
= (BSTR
)0xdeadbeef;
624 hres
= IHTMLXMLHttpRequest_getAllResponseHeaders(xhr
, &text
);
625 ok(hres
== E_FAIL
, "got %08x\n", hres
);
626 ok(text
== NULL
, "text = %p\n", text
);
628 text
= (BSTR
)0xdeadbeef;
629 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, content_type
, &text
);
630 ok(hres
== E_FAIL
, "got %08x\n", hres
);
631 ok(text
== NULL
, "text = %p\n", text
);
633 method
= SysAllocString(L
"GET");
634 url
= SysAllocString(xml_url
);
635 V_VT(&vbool
) = VT_BOOL
;
636 V_BOOL(&vbool
) = VARIANT_FALSE
;
637 V_VT(&vempty
) = VT_EMPTY
;
639 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
640 hres
= IHTMLXMLHttpRequest_open(xhr
, method
, url
, vbool
, vempty
, vempty
);
641 todo_wine
ok(hres
== S_OK
, "open failed: %08x\n", hres
); /* Gecko 30+ only supports async */
642 todo_wine
CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
644 SysFreeString(method
);
648 IHTMLXMLHttpRequest_Release(xhr
);
653 text
= (BSTR
)0xdeadbeef;
654 hres
= IHTMLXMLHttpRequest_getAllResponseHeaders(xhr
, &text
);
655 ok(hres
== E_FAIL
, "got %08x\n", hres
);
656 ok(text
== NULL
, "text = %p\n", text
);
658 text
= (BSTR
)0xdeadbeef;
659 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, content_type
, &text
);
660 ok(hres
== E_FAIL
, "got %08x\n", hres
);
661 ok(text
== NULL
, "text = %p\n", text
);
664 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
665 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
666 ok(val
== 0, "Expect 0, got %d\n", val
);
668 hres
= IHTMLXMLHttpRequest_get_statusText(xhr
, &text
);
669 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
670 ok(text
== NULL
, "Expect NULL, got %p\n", text
);
673 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
674 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
675 ok(val
== 1, "Expect OPENED, got %d\n", val
);
677 set_request_header(xhr
, L
"x-wine-test", L
"sync-test");
679 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
680 SET_EXPECT(xmlhttprequest_onreadystatechange_headers_received
);
681 SET_EXPECT(xmlhttprequest_onreadystatechange_loading
);
682 SET_EXPECT(xmlhttprequest_onreadystatechange_done
);
684 hres
= IHTMLXMLHttpRequest_send(xhr
, vempty
);
685 ok(hres
== S_OK
, "send failed: %08x\n", hres
);
686 CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
687 CHECK_CALLED(xmlhttprequest_onreadystatechange_headers_received
);
688 CHECK_CALLED(xmlhttprequest_onreadystatechange_loading
);
689 CHECK_CALLED(xmlhttprequest_onreadystatechange_done
);
690 ok(loading_cnt
== 1, "loading_cnt = %d\n", loading_cnt
);
693 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, content_type
, &text
);
694 ok(hres
== S_OK
, "getResponseHeader failed, got %08x\n", hres
);
695 ok(text
!= NULL
, "text == NULL\n");
699 test_header(expect_headers
, ARRAY_SIZE(expect_headers
));
702 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
703 ok(hres
== S_OK
, "get_status failed: %08x\n", hres
);
704 ok(val
== 200, "Expect 200, got %d\n", val
);
706 hres
= IHTMLXMLHttpRequest_get_statusText(xhr
, &text
);
707 ok(hres
== S_OK
, "get_statusText failed: %08x\n", hres
);
708 ok(text
!= NULL
, "text == NULL\n");
709 ok(!lstrcmpW(text
, L
"OK"),
710 "Expected \"OK\", got %s\n", wine_dbgstr_w(text
));
714 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
715 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
716 ok(val
== 4, "Expect DONE, got %d\n", val
);
718 test_response_text(expect_text
);
719 test_responseXML(expect_text
);
721 IHTMLXMLHttpRequest_Release(xhr
);
725 static void test_async_xhr(IHTMLDocument2
*doc
, const WCHAR
*xml_url
, const WCHAR
*expect_text
)
731 static const struct HEADER_TYPE expect_headers
[] = {
732 {L
"Content-Length", L
"51"},
733 {L
"Content-Type", L
"application/xml"}
736 create_xmlhttprequest(doc
);
740 V_VT(&var
) = VT_DISPATCH
;
741 V_DISPATCH(&var
) = (IDispatch
*)&xmlhttprequest_onreadystatechange_obj
;
742 hres
= IHTMLXMLHttpRequest_put_onreadystatechange(xhr
, var
);
743 ok(hres
== S_OK
, "put_onreadystatechange failed: %08x\n", hres
);
745 V_VT(&var
) = VT_EMPTY
;
746 hres
= IHTMLXMLHttpRequest_get_onreadystatechange(xhr
, &var
);
747 ok(hres
== S_OK
, "get_onreadystatechange failed: %08x\n", hres
);
748 ok(V_VT(&var
) == VT_DISPATCH
, "V_VT(onreadystatechange) = %d\n", V_VT(&var
));
749 ok(V_DISPATCH(&var
) == (IDispatch
*)&xmlhttprequest_onreadystatechange_obj
, "unexpected onreadystatechange value\n");
751 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, NULL
, &text
);
752 ok(hres
== E_INVALIDARG
, "Expect E_INVALIDARG, got %08x\n", hres
);
754 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, content_type
, NULL
);
755 ok(hres
== E_POINTER
, "Expect E_POINTER, got %08x\n", hres
);
757 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, NULL
, NULL
);
758 ok(hres
== E_POINTER
|| broken(hres
== E_INVALIDARG
), /* Vista and before */
759 "Expect E_POINTER, got %08x\n", hres
);
761 text
= (BSTR
)0xdeadbeef;
762 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, content_type
, &text
);
763 ok(hres
== E_FAIL
, "got %08x\n", hres
);
764 ok(text
== NULL
, "text = %p\n", text
);
766 hres
= IHTMLXMLHttpRequest_getAllResponseHeaders(xhr
, NULL
);
767 ok(hres
== E_POINTER
, "Expect E_POINTER, got %08x\n", hres
);
769 text
= (BSTR
)0xdeadbeef;
770 hres
= IHTMLXMLHttpRequest_getAllResponseHeaders(xhr
, &text
);
771 ok(hres
== E_FAIL
, "got %08x\n", hres
);
772 ok(text
== NULL
, "text = %p\n", text
);
775 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
776 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
777 ok(val
== 0, "Expect 0, got %d\n", val
);
779 text
= (BSTR
)0xdeadbeef;
780 hres
= IHTMLXMLHttpRequest_get_statusText(xhr
, &text
);
781 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
782 ok(text
== NULL
, "Expect NULL, got %p\n", text
);
785 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
786 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
787 ok(val
== 0, "Expect UNSENT, got %d\n", val
);
789 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
790 hres
= xhr_open(xml_url
, L
"GET");
791 CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
794 IHTMLXMLHttpRequest_Release(xhr
);
799 text
= (BSTR
)0xdeadbeef;
800 hres
= IHTMLXMLHttpRequest_getAllResponseHeaders(xhr
, &text
);
801 ok(hres
== E_FAIL
, "got %08x\n", hres
);
802 ok(text
== NULL
, "text = %p\n", text
);
804 text
= (BSTR
)0xdeadbeef;
805 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, content_type
, &text
);
806 ok(hres
== E_FAIL
, "got %08x\n", hres
);
807 ok(text
== NULL
, "text = %p\n", text
);
810 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
811 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
812 ok(val
== 0, "Expect 0, got %d\n", val
);
814 hres
= IHTMLXMLHttpRequest_get_statusText(xhr
, &text
);
815 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
816 ok(text
== NULL
, "Expect NULL, got %p\n", text
);
819 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
820 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
821 ok(val
== 1, "Expect OPENED, got %d\n", val
);
823 set_request_header(xhr
, L
"x-wine-test", L
"async-test");
825 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
826 SET_EXPECT(xmlhttprequest_onreadystatechange_headers_received
);
827 SET_EXPECT(xmlhttprequest_onreadystatechange_loading
);
828 SET_EXPECT(xmlhttprequest_onreadystatechange_done
);
830 V_VT(&vempty
) = VT_EMPTY
;
831 hres
= IHTMLXMLHttpRequest_send(xhr
, vempty
);
833 ok(hres
== S_OK
, "send failed: %08x\n", hres
);
835 pump_msgs(&called_xmlhttprequest_onreadystatechange_done
);
836 todo_wine
CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
837 CHECK_CALLED(xmlhttprequest_onreadystatechange_headers_received
);
838 CHECK_CALLED(xmlhttprequest_onreadystatechange_loading
);
839 CHECK_CALLED(xmlhttprequest_onreadystatechange_done
);
840 /* Workaround for loading large files */
841 todo_wine_if(!expect_text
)
842 ok(loading_cnt
== 1, "loading_cnt = %d\n", loading_cnt
);
845 IHTMLXMLHttpRequest_Release(xhr
);
851 hres
= IHTMLXMLHttpRequest_getAllResponseHeaders(xhr
, &text
);
852 ok(hres
== S_OK
, "getAllResponseHeader failed, got %08x\n", hres
);
853 ok(text
!= NULL
, "text == NULL\n");
857 test_header(expect_headers
, ARRAY_SIZE(expect_headers
));
860 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
861 ok(hres
== S_OK
, "get_status failed: %08x\n", hres
);
862 ok(val
== 200, "Expect 200, got %d\n", val
);
865 hres
= IHTMLXMLHttpRequest_get_statusText(xhr
, &text
);
866 ok(hres
== S_OK
, "get_statusText failed: %08x\n", hres
);
867 ok(text
!= NULL
, "text == NULL\n");
868 ok(!lstrcmpW(text
, L
"OK"), "Expected \"OK\", got %s\n", wine_dbgstr_w(text
));
872 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
873 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
874 ok(val
== 4, "Expect DONE, got %d\n", val
);
876 test_response_text(expect_text
);
877 test_responseXML(expect_text
);
879 IHTMLXMLHttpRequest_Release(xhr
);
883 static void test_async_xhr_abort(IHTMLDocument2
*doc
, const WCHAR
*xml_url
)
889 V_VT(&vempty
) = VT_EMPTY
;
891 trace("abort before send() is fired\n");
892 create_xmlhttprequest(doc
);
896 V_VT(&var
) = VT_DISPATCH
;
897 V_DISPATCH(&var
) = (IDispatch
*)&xmlhttprequest_onreadystatechange_obj
;
898 hres
= IHTMLXMLHttpRequest_put_onreadystatechange(xhr
, var
);
900 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
901 xhr_open(xml_url
, L
"GET");
902 CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
904 hres
= IHTMLXMLHttpRequest_abort(xhr
);
905 ok(hres
== S_OK
, "abort failed: %08x\n", hres
);
907 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
908 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
909 ok(val
== 0, "Expect 0, got %d\n", val
);
911 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
912 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
913 ok(val
== 0, "Expect UNSENT, got %d\n", val
);
915 IHTMLXMLHttpRequest_Release(xhr
);
918 trace("abort after send() is fired\n");
919 create_xmlhttprequest(doc
);
920 V_VT(&var
) = VT_DISPATCH
;
921 V_DISPATCH(&var
) = (IDispatch
*)&xmlhttprequest_onreadystatechange_obj
;
922 hres
= IHTMLXMLHttpRequest_put_onreadystatechange(xhr
, var
);
924 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
925 xhr_open(xml_url
, L
"GET");
926 CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
929 readystatechange_cnt
= 0;
930 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
931 SET_EXPECT(xmlhttprequest_onreadystatechange_done
);
932 hres
= IHTMLXMLHttpRequest_send(xhr
, vempty
);
933 ok(hres
== S_OK
, "send failed: %08x\n", hres
);
934 todo_wine
CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
936 hres
= IHTMLXMLHttpRequest_abort(xhr
);
937 ok(hres
== S_OK
, "abort failed: %08x\n", hres
);
938 CHECK_CALLED(xmlhttprequest_onreadystatechange_done
);
940 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
941 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
942 ok(val
== 0, "Expect UNSENT, got %d\n", val
);
944 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
945 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
946 ok(val
== 0, "Expect 0, got %d\n", val
);
948 ok(loading_cnt
== 0, "loading_cnt = %d, expect 0, loading_cnt\n", loading_cnt
);
949 todo_wine
ok(readystatechange_cnt
== 2, "readystatechange_cnt = %d, expect 2\n", readystatechange_cnt
);
951 IHTMLXMLHttpRequest_Release(xhr
);
955 static void test_xhr_post(IHTMLDocument2
*doc
)
960 trace("send string...\n");
962 create_xmlhttprequest(doc
);
966 V_VT(&v
) = VT_DISPATCH
;
967 V_DISPATCH(&v
) = (IDispatch
*)&xmlhttprequest_onreadystatechange_obj
;
968 hres
= IHTMLXMLHttpRequest_put_onreadystatechange(xhr
, v
);
969 ok(hres
== S_OK
, "put_onreadystatechange failed: %08x\n", hres
);
971 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
972 xhr_open(L
"http://test.winehq.org/tests/post.php", L
"POST");
973 CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
975 set_request_header(xhr
, L
"Content-Type", L
"application/x-www-form-urlencoded");
978 V_BSTR(&v
) = SysAllocString(L
"X=Testing");
981 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
982 SET_EXPECT(xmlhttprequest_onreadystatechange_headers_received
);
983 SET_EXPECT(xmlhttprequest_onreadystatechange_loading
);
984 SET_EXPECT(xmlhttprequest_onreadystatechange_done
);
986 hres
= IHTMLXMLHttpRequest_send(xhr
, v
);
987 ok(hres
== S_OK
, "send failed: %08x\n", hres
);
989 pump_msgs(&called_xmlhttprequest_onreadystatechange_done
);
991 todo_wine
CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
992 CHECK_CALLED(xmlhttprequest_onreadystatechange_headers_received
);
993 CHECK_CALLED(xmlhttprequest_onreadystatechange_loading
);
994 CHECK_CALLED(xmlhttprequest_onreadystatechange_done
);
995 ok(loading_cnt
== 1, "loading_cnt = %d\n", loading_cnt
);
997 SysFreeString(V_BSTR(&v
));
999 test_response_text(L
"X => Testing");
1001 IHTMLXMLHttpRequest_Release(xhr
);
1005 static IHTMLDocument2
*create_doc_from_url(const WCHAR
*start_url
)
1010 IPersistMoniker
*persist_mon
;
1011 IHTMLDocument2
*doc
;
1014 hres
= CreateBindCtx(0, &bc
);
1015 ok(hres
== S_OK
, "CreateBindCtx failed: 0x%08x\n", hres
);
1017 url
= SysAllocString(start_url
);
1018 hres
= CreateURLMoniker(NULL
, url
, &url_mon
);
1019 ok(hres
== S_OK
, "CreateURLMoniker failed: 0x%08x\n", hres
);
1021 hres
= CoCreateInstance(&CLSID_HTMLDocument
, NULL
,
1022 CLSCTX_INPROC_SERVER
| CLSCTX_INPROC_HANDLER
, &IID_IHTMLDocument2
,
1024 #if !defined(__i386__) && !defined(__x86_64__)
1027 ok(hres
== S_OK
, "CoCreateInstance failed: 0x%08x\n", hres
);
1029 hres
= IHTMLDocument2_QueryInterface(doc
, &IID_IPersistMoniker
,
1030 (void**)&persist_mon
);
1031 ok(hres
== S_OK
, "IHTMLDocument2_QueryInterface failed: 0x%08x\n", hres
);
1033 hres
= IPersistMoniker_Load(persist_mon
, FALSE
, url_mon
, bc
,
1034 STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
);
1035 ok(hres
== S_OK
, "IPersistMoniker_Load failed: 0x%08x\n", hres
);
1037 IPersistMoniker_Release(persist_mon
);
1038 IMoniker_Release(url_mon
);
1039 IBindCtx_Release(bc
);
1042 doc_complete
= FALSE
;
1044 do_advise((IUnknown
*)doc
, &IID_IPropertyNotifySink
, (IUnknown
*)&PropertyNotifySink
);
1045 pump_msgs(&doc_complete
);
1050 START_TEST(xmlhttprequest
)
1052 IHTMLDocument2
*doc
;
1053 static const WCHAR start_url
[] = L
"http://test.winehq.org/tests/hello.html";
1054 static const WCHAR xml_url
[] = L
"http://test.winehq.org/tests/xmltest.xml";
1055 static const WCHAR large_page_url
[] = L
"http://test.winehq.org/tests/data.php";
1056 static const WCHAR expect_response_text
[] = L
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<a>TEST</a>";
1060 content_type
= SysAllocString(L
"Content-Type");
1061 doc
= create_doc_from_url(start_url
);
1063 test_sync_xhr(doc
, xml_url
, expect_response_text
);
1064 test_sync_xhr(doc
, large_page_url
, NULL
);
1065 test_async_xhr(doc
, xml_url
, expect_response_text
);
1066 test_async_xhr(doc
, large_page_url
, NULL
);
1067 test_async_xhr_abort(doc
, large_page_url
);
1069 IHTMLDocument2_Release(doc
);
1071 SysFreeString(content_type
);