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
21 #include <wine/test.h>
31 static BSTR
a2bstr(const char *str
)
36 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
37 ret
= SysAllocStringLen(NULL
, len
);
38 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
43 static int strcmp_wa(LPCWSTR strw
, const char *stra
)
46 WideCharToMultiByte(CP_ACP
, 0, strw
, -1, buf
, sizeof(buf
), NULL
, NULL
);
47 return lstrcmpA(stra
, buf
);
50 #define DEFINE_EXPECT(func) \
51 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
53 #define SET_EXPECT(func) \
54 do { called_ ## func = FALSE; expect_ ## func = TRUE; } while(0)
56 #define CHECK_EXPECT2(func) \
59 ok(expect_ ##func, "unexpected call " #func "\n"); \
60 called_ ## func = TRUE; \
63 #define CHECK_EXPECT(func) \
65 CHECK_EXPECT2(func); \
66 expect_ ## func = FALSE; \
69 #define CHECK_CALLED(func) \
71 ok(called_ ## func, "expected " #func "\n"); \
72 expect_ ## func = called_ ## func = FALSE; \
75 static IHTMLXMLHttpRequest
*xhr
= NULL
;
76 static BSTR content_type
= NULL
;
77 static int loading_cnt
= 0;
78 static int readystatechange_cnt
= 0;
80 DEFINE_EXPECT(xmlhttprequest_onreadystatechange_opened
);
81 DEFINE_EXPECT(xmlhttprequest_onreadystatechange_headers_received
);
82 DEFINE_EXPECT(xmlhttprequest_onreadystatechange_loading
);
83 DEFINE_EXPECT(xmlhttprequest_onreadystatechange_done
);
85 #define test_disp(u,id) _test_disp(__LINE__,u,id)
86 static void _test_disp(unsigned line
, IUnknown
*unk
, const IID
*diid
, const IID
*broken_diid
)
93 hres
= IUnknown_QueryInterface(unk
, &IID_IDispatchEx
, (void**)&dispex
);
94 ok_(__FILE__
,line
) (hres
== S_OK
, "Could not get IDispatch: %08x\n", hres
);
99 hres
= IDispatchEx_GetTypeInfoCount(dispex
, &ticnt
);
100 ok_(__FILE__
,line
) (hres
== S_OK
, "GetTypeInfoCount failed: %08x\n", hres
);
101 ok_(__FILE__
,line
) (ticnt
== 1, "ticnt=%u\n", ticnt
);
103 hres
= IDispatchEx_GetTypeInfo(dispex
, 0, 0, &typeinfo
);
104 ok_(__FILE__
,line
) (hres
== S_OK
, "GetTypeInfo failed: %08x\n", hres
);
106 if(SUCCEEDED(hres
)) {
109 hres
= ITypeInfo_GetTypeAttr(typeinfo
, &type_attr
);
110 ok_(__FILE__
,line
) (hres
== S_OK
, "GetTypeAttr failed: %08x\n", hres
);
111 ok_(__FILE__
,line
) (IsEqualGUID(&type_attr
->guid
, diid
)
112 || broken(broken_diid
&& IsEqualGUID(&type_attr
->guid
, broken_diid
)),
113 "unexpected guid %s\n", wine_dbgstr_guid(&type_attr
->guid
));
115 ITypeInfo_ReleaseTypeAttr(typeinfo
, type_attr
);
116 ITypeInfo_Release(typeinfo
);
119 IDispatchEx_Release(dispex
);
122 #define test_event_args(a,b,c,d,e,f,g,h) _test_event_args(__LINE__,a,b,c,d,e,f,g,h)
123 static void _test_event_args(unsigned line
, const IID
*dispiid
, const IID
*broken_dispiid
, DISPID id
, WORD wFlags
,
124 DISPPARAMS
*pdp
, VARIANT
*pvarRes
, EXCEPINFO
*pei
, IServiceProvider
*pspCaller
)
126 ok_(__FILE__
,line
) (id
== DISPID_VALUE
, "id = %d\n", id
);
127 ok_(__FILE__
,line
) (wFlags
== DISPATCH_METHOD
, "wFlags = %x\n", wFlags
);
128 ok_(__FILE__
,line
) (pdp
!= NULL
, "pdp == NULL\n");
129 ok_(__FILE__
,line
) (pdp
->cArgs
== 1, "pdp->cArgs = %d\n", pdp
->cArgs
);
130 ok_(__FILE__
,line
) (pdp
->cNamedArgs
== 1, "pdp->cNamedArgs = %d\n", pdp
->cNamedArgs
);
131 ok_(__FILE__
,line
) (pdp
->rgdispidNamedArgs
[0] == DISPID_THIS
, "pdp->rgdispidNamedArgs[0] = %d\n",
132 pdp
->rgdispidNamedArgs
[0]);
133 ok_(__FILE__
,line
) (V_VT(pdp
->rgvarg
) == VT_DISPATCH
, "V_VT(rgvarg) = %d\n", V_VT(pdp
->rgvarg
));
134 ok_(__FILE__
,line
) (pvarRes
!= NULL
, "pvarRes == NULL\n");
135 ok_(__FILE__
,line
) (pei
!= NULL
, "pei == NULL");
136 ok_(__FILE__
,line
) (!pspCaller
, "pspCaller != NULL\n");
139 _test_disp(line
, (IUnknown
*)V_DISPATCH(pdp
->rgvarg
), dispiid
, broken_dispiid
);
142 static HRESULT WINAPI
DispatchEx_QueryInterface(IDispatchEx
*iface
, REFIID riid
, void **ppv
)
146 if(IsEqualGUID(riid
, &IID_IUnknown
)
147 || IsEqualGUID(riid
, &IID_IDispatch
)
148 || IsEqualGUID(riid
, &IID_IDispatchEx
))
151 ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid
));
152 return E_NOINTERFACE
;
158 static ULONG WINAPI
DispatchEx_AddRef(IDispatchEx
*iface
)
163 static ULONG WINAPI
DispatchEx_Release(IDispatchEx
*iface
)
168 static HRESULT WINAPI
DispatchEx_GetTypeInfoCount(IDispatchEx
*iface
, UINT
*pctinfo
)
170 ok(0, "unexpected call\n");
174 static HRESULT WINAPI
DispatchEx_GetTypeInfo(IDispatchEx
*iface
, UINT iTInfo
,
175 LCID lcid
, ITypeInfo
**ppTInfo
)
177 ok(0, "unexpected call\n");
181 static HRESULT WINAPI
DispatchEx_GetIDsOfNames(IDispatchEx
*iface
, REFIID riid
,
182 LPOLESTR
*rgszNames
, UINT cNames
,
183 LCID lcid
, DISPID
*rgDispId
)
185 ok(0, "unexpected call\n");
189 static HRESULT WINAPI
DispatchEx_Invoke(IDispatchEx
*iface
, DISPID dispIdMember
,
190 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
191 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
193 ok(0, "unexpected call\n");
197 static HRESULT WINAPI
DispatchEx_GetDispID(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
, DISPID
*pid
)
199 ok(0, "unexpected call\n");
203 static HRESULT WINAPI
DispatchEx_DeleteMemberByName(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
)
205 ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName
), grfdex
);
209 static HRESULT WINAPI
DispatchEx_DeleteMemberByDispID(IDispatchEx
*iface
, DISPID id
)
211 ok(0, "unexpected call\n");
215 static HRESULT WINAPI
DispatchEx_GetMemberProperties(IDispatchEx
*iface
, DISPID id
, DWORD grfdexFetch
, DWORD
*pgrfdex
)
217 ok(0, "unexpected call\n");
221 static HRESULT WINAPI
DispatchEx_GetMemberName(IDispatchEx
*iface
, DISPID id
, BSTR
*pbstrName
)
223 ok(0, "unexpected call\n");
227 static HRESULT WINAPI
DispatchEx_GetNextDispID(IDispatchEx
*iface
, DWORD grfdex
, DISPID id
, DISPID
*pid
)
229 ok(0, "unexpected call\n");
233 static HRESULT WINAPI
DispatchEx_GetNameSpaceParent(IDispatchEx
*iface
, IUnknown
**ppunk
)
235 ok(0, "unexpected call\n");
239 static HRESULT WINAPI
xmlhttprequest_onreadystatechange(IDispatchEx
*iface
, DISPID id
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pdp
,
240 VARIANT
*pvarRes
, EXCEPINFO
*pei
, IServiceProvider
*pspCaller
)
245 test_event_args(&DIID_DispHTMLXMLHttpRequest
, &IID_IHTMLXMLHttpRequest
, id
, wFlags
, pdp
, pvarRes
, pei
, pspCaller
);
247 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
248 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
249 readystatechange_cnt
++;
253 CHECK_EXPECT(xmlhttprequest_onreadystatechange_opened
);
256 CHECK_EXPECT(xmlhttprequest_onreadystatechange_headers_received
);
260 CHECK_EXPECT2(xmlhttprequest_onreadystatechange_loading
);
263 CHECK_EXPECT(xmlhttprequest_onreadystatechange_done
);
266 ok(0, "unexpected readyState: %d\n", val
);
271 static IDispatchExVtbl xmlhttprequest_onreadystatechangeFuncVtbl
= {
272 DispatchEx_QueryInterface
,
275 DispatchEx_GetTypeInfoCount
,
276 DispatchEx_GetTypeInfo
,
277 DispatchEx_GetIDsOfNames
,
279 DispatchEx_GetDispID
,
280 xmlhttprequest_onreadystatechange
,
281 DispatchEx_DeleteMemberByName
,
282 DispatchEx_DeleteMemberByDispID
,
283 DispatchEx_GetMemberProperties
,
284 DispatchEx_GetMemberName
,
285 DispatchEx_GetNextDispID
,
286 DispatchEx_GetNameSpaceParent
288 static IDispatchEx xmlhttprequest_onreadystatechange_obj
= { &xmlhttprequest_onreadystatechangeFuncVtbl
};
290 static BOOL doc_complete
;
291 static IHTMLDocument2
*notif_doc
;
293 static HRESULT WINAPI
PropertyNotifySink_QueryInterface(IPropertyNotifySink
*iface
,
294 REFIID riid
, void**ppv
)
296 if(IsEqualGUID(&IID_IPropertyNotifySink
, riid
)) {
301 ok(0, "unexpected call\n");
302 return E_NOINTERFACE
;
305 static ULONG WINAPI
PropertyNotifySink_AddRef(IPropertyNotifySink
*iface
)
310 static ULONG WINAPI
PropertyNotifySink_Release(IPropertyNotifySink
*iface
)
315 static HRESULT WINAPI
PropertyNotifySink_OnChanged(IPropertyNotifySink
*iface
, DISPID dispID
)
317 if(dispID
== DISPID_READYSTATE
){
321 hres
= IHTMLDocument2_get_readyState(notif_doc
, &state
);
322 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
324 if(!strcmp_wa(state
, "complete"))
327 SysFreeString(state
);
333 static HRESULT WINAPI
PropertyNotifySink_OnRequestEdit(IPropertyNotifySink
*iface
, DISPID dispID
)
335 ok(0, "unexpected call\n");
339 static IPropertyNotifySinkVtbl PropertyNotifySinkVtbl
= {
340 PropertyNotifySink_QueryInterface
,
341 PropertyNotifySink_AddRef
,
342 PropertyNotifySink_Release
,
343 PropertyNotifySink_OnChanged
,
344 PropertyNotifySink_OnRequestEdit
347 static IPropertyNotifySink PropertyNotifySink
= { &PropertyNotifySinkVtbl
};
349 static void do_advise(IUnknown
*unk
, REFIID riid
, IUnknown
*unk_advise
)
351 IConnectionPointContainer
*container
;
352 IConnectionPoint
*cp
;
356 hres
= IUnknown_QueryInterface(unk
, &IID_IConnectionPointContainer
, (void**)&container
);
357 ok(hres
== S_OK
, "QueryInterface(IID_IConnectionPointContainer) failed: %08x\n", hres
);
359 hres
= IConnectionPointContainer_FindConnectionPoint(container
, riid
, &cp
);
360 IConnectionPointContainer_Release(container
);
361 ok(hres
== S_OK
, "FindConnectionPoint failed: %08x\n", hres
);
363 hres
= IConnectionPoint_Advise(cp
, unk_advise
, &cookie
);
364 IConnectionPoint_Release(cp
);
365 ok(hres
== S_OK
, "Advise failed: %08x\n", hres
);
368 static void pump_msgs(BOOL
*b
)
373 while(!*b
&& GetMessageW(&msg
, NULL
, 0, 0)) {
374 TranslateMessage(&msg
);
375 DispatchMessageW(&msg
);
378 while(PeekMessageW(&msg
, NULL
, 0, 0, PM_REMOVE
)) {
379 TranslateMessage(&msg
);
380 DispatchMessageW(&msg
);
391 static void create_xmlhttprequest(IHTMLDocument2
*doc
)
393 IHTMLWindow2
*window
;
394 IHTMLWindow5
*window5
;
396 IHTMLXMLHttpRequestFactory
*factory
;
399 hres
= IHTMLDocument2_get_parentWindow(doc
, &window
);
400 ok(hres
== S_OK
, "get_parentWindow failed: %08x\n", hres
);
401 ok(window
!= NULL
, "window == NULL\n");
403 hres
= IHTMLWindow2_QueryInterface(window
, &IID_IHTMLWindow5
, (void**)&window5
);
404 IHTMLWindow2_Release(window
);
406 win_skip("IHTMLWindow5 not supported\n");
411 hres
= IHTMLWindow5_get_XMLHttpRequest(window5
, &var
);
412 IHTMLWindow5_Release(window5
);
413 ok(hres
== S_OK
, "get_XMLHttpRequest failed: %08x\n", hres
);
414 ok(V_VT(&var
) == VT_DISPATCH
, "V_VT(&var) is %08x, expected VT_DISPATCH\n", V_VT(&var
));
416 hres
= IDispatch_QueryInterface(V_DISPATCH(&var
), &IID_IHTMLXMLHttpRequestFactory
, (void**)&factory
);
418 ok(hres
== S_OK
, "QueryInterface(IID_IHTMLXMLHttpRequestFactory) failed: %08x\n", hres
);
419 ok(factory
!= NULL
, "factory == NULL\n");
421 hres
= IHTMLXMLHttpRequestFactory_create(factory
, &xhr
);
422 IHTMLXMLHttpRequestFactory_Release(factory
);
423 ok(hres
== S_OK
, "create failed: %08x\n", hres
);
424 ok(xhr
!= NULL
, "xhr == NULL\n");
427 static void test_header(const struct HEADER_TYPE expect
[], int num
)
430 BSTR key
, text
, all_header
;
432 char all
[4096], buf
[512];
435 hres
= IHTMLXMLHttpRequest_getAllResponseHeaders(xhr
, &all_header
);
436 ok(hres
== S_OK
, "getAllResponseHeader failed: %08x\n", hres
);
437 ok(all_header
!= NULL
, "all_header == NULL\n");
439 WideCharToMultiByte(CP_UTF8
, 0, all_header
, -1, all
, sizeof(all
), NULL
, NULL
);
440 SysFreeString(all_header
);
442 for(i
= 0; i
< num
; ++i
) {
444 key
= a2bstr(expect
[i
].key
);
445 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, key
, &text
);
446 ok(hres
== S_OK
, "getResponseHeader failed, got %08x\n", hres
);
447 ok(text
!= NULL
, "text == NULL\n");
448 ok(!strcmp_wa(text
, expect
[i
].value
),
449 "Expect %s: %s, got %s\n", expect
[i
].key
, expect
[i
].value
, wine_dbgstr_w(text
));
453 strcpy(buf
, expect
[i
].key
);
455 strcat(buf
, expect
[i
].value
);
456 ok(strstr(all
, buf
) != NULL
, "AllResponseHeaders(%s) don't have expected substr(%s)\n", all
, buf
);
460 static const char *debugstr_variant(const VARIANT
*var
)
462 static char buf
[400];
472 sprintf(buf
, "{VT_BSTR: %s}", wine_dbgstr_w(V_BSTR(var
)));
475 sprintf(buf
, "{VT_BOOL: %x}", V_BOOL(var
));
478 sprintf(buf
, "{VT_UI4: %u}", V_UI4(var
));
481 sprintf(buf
, "{vt %d}", V_VT(var
));
488 static void test_illegal_xml(IXMLDOMDocument
*xmldom
)
490 IXMLDOMNode
*first
, *last
;
495 hres
= IXMLDOMDocument_get_baseName(xmldom
, NULL
);
496 ok(hres
== E_INVALIDARG
, "Expect E_INVALIDARG, got %08x\n", hres
);
497 hres
= IXMLDOMDocument_get_baseName(xmldom
, &bstr
);
498 ok(hres
== S_FALSE
, "get_baseName failed: %08x\n", hres
);
499 ok(bstr
== NULL
, "bstr(%p): %s\n", bstr
, wine_dbgstr_w(bstr
));
502 hres
= IXMLDOMDocument_get_dataType(xmldom
, NULL
);
503 ok(hres
== E_INVALIDARG
, "Expect E_INVALIDARG, got %08x\n", hres
);
504 hres
= IXMLDOMDocument_get_dataType(xmldom
, &variant
);
505 ok(hres
== S_FALSE
, "get_dataType failed: %08x\n", hres
);
506 ok(V_VT(&variant
) == VT_NULL
, "got %s\n", debugstr_variant(&variant
));
507 VariantClear(&variant
);
509 hres
= IXMLDOMDocument_get_text(xmldom
, &bstr
);
510 ok(!strcmp_wa(bstr
, ""), "text = %s\n", wine_dbgstr_w(bstr
));
513 hres
= IXMLDOMDocument_get_firstChild(xmldom
, NULL
);
514 ok(hres
== E_INVALIDARG
, "Expect E_INVALIDARG, got %08x\n", hres
);
516 first
= (void*)0xdeadbeef;
517 hres
= IXMLDOMDocument_get_firstChild(xmldom
, &first
);
518 ok(hres
== S_FALSE
, "get_firstChild failed: %08x\n", hres
);
519 ok(first
== NULL
, "first != NULL\n");
521 last
= (void*)0xdeadbeef;
522 hres
= IXMLDOMDocument_get_lastChild(xmldom
, &last
);
523 ok(hres
== S_FALSE
, "get_lastChild failed: %08x\n", hres
);
524 ok(last
== NULL
, "last != NULL\n");
527 #define set_request_header(a,b,c) _set_request_header(__LINE__,a,b,c)
528 static void _set_request_header(unsigned line
, IHTMLXMLHttpRequest
*xhr
, const char *header_a
, const char *value_a
)
530 BSTR header
= a2bstr(header_a
), value
= a2bstr(value_a
);
533 hres
= IHTMLXMLHttpRequest_setRequestHeader(xhr
, header
, value
);
534 ok_(__FILE__
,line
)(hres
== S_OK
, "setRequestHeader failed: %08x\n", hres
);
536 SysFreeString(header
);
537 SysFreeString(value
);
540 static void test_responseXML(const char *expect_text
)
543 IXMLDOMDocument
*xmldom
;
544 IObjectSafety
*safety
;
545 DWORD enabled
= 0, supported
= 0;
549 hres
= IHTMLXMLHttpRequest_get_responseXML(xhr
, &disp
);
550 ok(hres
== S_OK
, "get_responseXML failed: %08x\n", hres
);
551 ok(disp
!= NULL
, "disp == NULL\n");
554 hres
= IDispatch_QueryInterface(disp
, &IID_IXMLDOMDocument
, (void**)&xmldom
);
555 ok(hres
== S_OK
, "QueryInterface(IXMLDOMDocument) failed: %08x\n", hres
);
556 ok(xmldom
!= NULL
, "xmldom == NULL\n");
558 hres
= IXMLDOMDocument_QueryInterface(xmldom
, &IID_IObjectSafety
, (void**)&safety
);
559 ok(hres
== S_OK
, "QueryInterface IObjectSafety failed: %08x\n", hres
);
560 hres
= IObjectSafety_GetInterfaceSafetyOptions(safety
, NULL
, &supported
, &enabled
);
561 ok(hres
== S_OK
, "GetInterfaceSafetyOptions failed: %08x\n", hres
);
562 ok(broken(supported
== (INTERFACESAFE_FOR_UNTRUSTED_CALLER
| INTERFACESAFE_FOR_UNTRUSTED_DATA
)) ||
563 supported
== (INTERFACESAFE_FOR_UNTRUSTED_CALLER
| INTERFACESAFE_FOR_UNTRUSTED_DATA
| INTERFACE_USES_SECURITY_MANAGER
) /* msxml3 SP8+ */,
564 "Expected supported: (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER), got %08x\n", supported
);
565 ok(enabled
== ((INTERFACESAFE_FOR_UNTRUSTED_CALLER
| INTERFACESAFE_FOR_UNTRUSTED_DATA
| INTERFACE_USES_SECURITY_MANAGER
) & supported
),
566 "Expected enabled: (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER), got 0x%08x\n", enabled
);
567 IObjectSafety_Release(safety
);
570 test_illegal_xml(xmldom
);
572 IXMLDOMDocument_Release(xmldom
);
573 IDispatch_Release(disp
);
576 static void test_sync_xhr(IHTMLDocument2
*doc
, const char *xml_url
, const char *expect_text
)
578 VARIANT vbool
, vempty
, var
;
583 static const struct HEADER_TYPE expect_headers
[] = {
584 {"Content-Length", "51"},
585 {"Content-Type", "application/xml"}
588 trace("test_sync_xhr\n");
590 create_xmlhttprequest(doc
);
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_NULL
, "V_VT(onreadystatechange) = %d\n", V_VT(&var
));
599 V_VT(&var
) = VT_DISPATCH
;
600 V_DISPATCH(&var
) = (IDispatch
*)&xmlhttprequest_onreadystatechange_obj
;
601 hres
= IHTMLXMLHttpRequest_put_onreadystatechange(xhr
, var
);
602 ok(hres
== S_OK
, "put_onreadystatechange failed: %08x\n", hres
);
604 V_VT(&var
) = VT_EMPTY
;
605 hres
= IHTMLXMLHttpRequest_get_onreadystatechange(xhr
, &var
);
606 ok(hres
== S_OK
, "get_onreadystatechange failed: %08x\n", hres
);
607 ok(V_VT(&var
) == VT_DISPATCH
, "V_VT(onreadystatechange) = %d\n", V_VT(&var
));
608 ok(V_DISPATCH(&var
) == (IDispatch
*)&xmlhttprequest_onreadystatechange_obj
, "unexpected onreadystatechange value\n");
610 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, NULL
);
611 ok(hres
== E_POINTER
, "Expect E_POINTER, got %08x\n", hres
);
614 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
615 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
616 ok(val
== 0, "Expect UNSENT, got %d\n", val
);
618 hres
= IHTMLXMLHttpRequest_get_status(xhr
, NULL
);
619 ok(hres
== E_POINTER
, "Expect E_POINTER, got %08x\n", hres
);
622 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
623 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
624 ok(val
== 0, "Expect 0, got %d\n", val
);
626 hres
= IHTMLXMLHttpRequest_get_statusText(xhr
, NULL
);
627 ok(hres
== E_POINTER
, "Expect E_POINTER, got %08x\n", hres
);
629 hres
= IHTMLXMLHttpRequest_get_statusText(xhr
, &text
);
630 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
631 ok(text
== NULL
, "Expect NULL, got %p\n", text
);
633 text
= (BSTR
)0xdeadbeef;
634 hres
= IHTMLXMLHttpRequest_getAllResponseHeaders(xhr
, &text
);
635 ok(hres
== E_FAIL
, "got %08x\n", hres
);
636 ok(text
== NULL
, "text = %p\n", text
);
638 text
= (BSTR
)0xdeadbeef;
639 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, content_type
, &text
);
640 ok(hres
== E_FAIL
, "got %08x\n", hres
);
641 ok(text
== NULL
, "text = %p\n", text
);
643 method
= a2bstr("GET");
644 url
= a2bstr(xml_url
);
645 V_VT(&vbool
) = VT_BOOL
;
646 V_BOOL(&vbool
) = VARIANT_FALSE
;
647 V_VT(&vempty
) = VT_EMPTY
;
649 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
650 hres
= IHTMLXMLHttpRequest_open(xhr
, method
, url
, vbool
, vempty
, vempty
);
651 todo_wine
ok(hres
== S_OK
, "open failed: %08x\n", hres
); /* Gecko 30+ only supports async */
652 todo_wine
CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
654 SysFreeString(method
);
658 IHTMLXMLHttpRequest_Release(xhr
);
663 text
= (BSTR
)0xdeadbeef;
664 hres
= IHTMLXMLHttpRequest_getAllResponseHeaders(xhr
, &text
);
665 ok(hres
== E_FAIL
, "got %08x\n", hres
);
666 ok(text
== NULL
, "text = %p\n", text
);
668 text
= (BSTR
)0xdeadbeef;
669 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, content_type
, &text
);
670 ok(hres
== E_FAIL
, "got %08x\n", hres
);
671 ok(text
== NULL
, "text = %p\n", text
);
674 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
675 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
676 ok(val
== 0, "Expect 0, got %d\n", val
);
678 hres
= IHTMLXMLHttpRequest_get_statusText(xhr
, &text
);
679 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
680 ok(text
== NULL
, "Expect NULL, got %p\n", text
);
683 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
684 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
685 ok(val
== 1, "Expect OPENED, got %d\n", val
);
687 set_request_header(xhr
, "x-wine-test", "sync-test");
689 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
690 SET_EXPECT(xmlhttprequest_onreadystatechange_headers_received
);
691 SET_EXPECT(xmlhttprequest_onreadystatechange_loading
);
692 SET_EXPECT(xmlhttprequest_onreadystatechange_done
);
694 hres
= IHTMLXMLHttpRequest_send(xhr
, vempty
);
695 ok(hres
== S_OK
, "send failed: %08x\n", hres
);
696 CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
697 CHECK_CALLED(xmlhttprequest_onreadystatechange_headers_received
);
698 CHECK_CALLED(xmlhttprequest_onreadystatechange_loading
);
699 CHECK_CALLED(xmlhttprequest_onreadystatechange_done
);
700 ok(loading_cnt
== 1, "loading_cnt = %d\n", loading_cnt
);
703 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, content_type
, &text
);
704 ok(hres
== S_OK
, "getResponseHeader failed, got %08x\n", hres
);
705 ok(text
!= NULL
, "text == NULL\n");
709 test_header(expect_headers
, sizeof(expect_headers
)/sizeof(expect_headers
[0]));
712 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
713 ok(hres
== S_OK
, "get_status failed: %08x\n", hres
);
714 ok(val
== 200, "Expect 200, got %d\n", val
);
716 hres
= IHTMLXMLHttpRequest_get_statusText(xhr
, &text
);
717 ok(hres
== S_OK
, "get_statusText failed: %08x\n", hres
);
718 ok(text
!= NULL
, "text == NULL\n");
719 ok(!strcmp_wa(text
, "OK"),
720 "Expected \"OK\", got %s\n", wine_dbgstr_w(text
));
724 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
725 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
726 ok(val
== 4, "Expect DONE, got %d\n", val
);
728 hres
= IHTMLXMLHttpRequest_get_responseText(xhr
, &text
);
729 ok(hres
== S_OK
, "get_responseText failed: %08x\n", hres
);
730 ok(text
!= NULL
, "test == NULL\n");
732 ok(!strcmp_wa(text
, expect_text
), "expect %s, got %s\n",
733 expect_text
, wine_dbgstr_w(text
));
736 test_responseXML(expect_text
);
738 IHTMLXMLHttpRequest_Release(xhr
);
742 static void test_async_xhr(IHTMLDocument2
*doc
, const char *xml_url
, const char *expect_text
)
744 VARIANT vbool
, vempty
, var
;
749 static const struct HEADER_TYPE expect_headers
[] = {
750 {"Content-Length", "51"},
751 {"Content-Type", "application/xml"}
754 create_xmlhttprequest(doc
);
758 V_VT(&var
) = VT_DISPATCH
;
759 V_DISPATCH(&var
) = (IDispatch
*)&xmlhttprequest_onreadystatechange_obj
;
760 hres
= IHTMLXMLHttpRequest_put_onreadystatechange(xhr
, var
);
761 ok(hres
== S_OK
, "put_onreadystatechange failed: %08x\n", hres
);
763 V_VT(&var
) = VT_EMPTY
;
764 hres
= IHTMLXMLHttpRequest_get_onreadystatechange(xhr
, &var
);
765 ok(hres
== S_OK
, "get_onreadystatechange failed: %08x\n", hres
);
766 ok(V_VT(&var
) == VT_DISPATCH
, "V_VT(onreadystatechange) = %d\n", V_VT(&var
));
767 ok(V_DISPATCH(&var
) == (IDispatch
*)&xmlhttprequest_onreadystatechange_obj
, "unexpected onreadystatechange value\n");
769 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, NULL
, &text
);
770 ok(hres
== E_INVALIDARG
, "Expect E_INVALIDARG, got %08x\n", hres
);
772 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, content_type
, NULL
);
773 ok(hres
== E_POINTER
, "Expect E_POINTER, got %08x\n", hres
);
775 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, NULL
, NULL
);
776 ok(hres
== E_POINTER
|| broken(hres
== E_INVALIDARG
), /* Vista and before */
777 "Expect E_POINTER, got %08x\n", hres
);
779 text
= (BSTR
)0xdeadbeef;
780 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, content_type
, &text
);
781 ok(hres
== E_FAIL
, "got %08x\n", hres
);
782 ok(text
== NULL
, "text = %p\n", text
);
784 hres
= IHTMLXMLHttpRequest_getAllResponseHeaders(xhr
, NULL
);
785 ok(hres
== E_POINTER
, "Expect E_POINTER, got %08x\n", hres
);
787 text
= (BSTR
)0xdeadbeef;
788 hres
= IHTMLXMLHttpRequest_getAllResponseHeaders(xhr
, &text
);
789 ok(hres
== E_FAIL
, "got %08x\n", hres
);
790 ok(text
== NULL
, "text = %p\n", text
);
793 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
794 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
795 ok(val
== 0, "Expect 0, got %d\n", val
);
797 text
= (BSTR
)0xdeadbeef;
798 hres
= IHTMLXMLHttpRequest_get_statusText(xhr
, &text
);
799 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
800 ok(text
== NULL
, "Expect NULL, got %p\n", text
);
803 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
804 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
805 ok(val
== 0, "Expect UNSENT, got %d\n", val
);
807 method
= a2bstr("GET");
808 url
= a2bstr(xml_url
);
809 V_VT(&vbool
) = VT_BOOL
;
810 V_BOOL(&vbool
) = VARIANT_TRUE
;
811 V_VT(&vempty
) = VT_EMPTY
;
813 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
814 hres
= IHTMLXMLHttpRequest_open(xhr
, method
, url
, vbool
, vempty
, vempty
);
815 ok(hres
== S_OK
, "open failed: %08x\n", hres
);
816 CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
818 SysFreeString(method
);
822 IHTMLXMLHttpRequest_Release(xhr
);
827 text
= (BSTR
)0xdeadbeef;
828 hres
= IHTMLXMLHttpRequest_getAllResponseHeaders(xhr
, &text
);
829 ok(hres
== E_FAIL
, "got %08x\n", hres
);
830 ok(text
== NULL
, "text = %p\n", text
);
832 text
= (BSTR
)0xdeadbeef;
833 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, content_type
, &text
);
834 ok(hres
== E_FAIL
, "got %08x\n", hres
);
835 ok(text
== NULL
, "text = %p\n", text
);
838 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
839 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
840 ok(val
== 0, "Expect 0, got %d\n", val
);
842 hres
= IHTMLXMLHttpRequest_get_statusText(xhr
, &text
);
843 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
844 ok(text
== NULL
, "Expect NULL, got %p\n", text
);
847 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
848 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
849 ok(val
== 1, "Expect OPENED, got %d\n", val
);
851 set_request_header(xhr
, "x-wine-test", "async-test");
853 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
854 SET_EXPECT(xmlhttprequest_onreadystatechange_headers_received
);
855 SET_EXPECT(xmlhttprequest_onreadystatechange_loading
);
856 SET_EXPECT(xmlhttprequest_onreadystatechange_done
);
858 hres
= IHTMLXMLHttpRequest_send(xhr
, vempty
);
860 ok(hres
== S_OK
, "send failed: %08x\n", hres
);
862 pump_msgs(&called_xmlhttprequest_onreadystatechange_done
);
863 todo_wine
CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
864 CHECK_CALLED(xmlhttprequest_onreadystatechange_headers_received
);
865 CHECK_CALLED(xmlhttprequest_onreadystatechange_loading
);
866 CHECK_CALLED(xmlhttprequest_onreadystatechange_done
);
867 /* Workaround for loading large files */
868 todo_wine_if(!expect_text
)
869 ok(loading_cnt
== 1, "loading_cnt = %d\n", loading_cnt
);
872 IHTMLXMLHttpRequest_Release(xhr
);
878 hres
= IHTMLXMLHttpRequest_getAllResponseHeaders(xhr
, &text
);
879 ok(hres
== S_OK
, "getAllResponseHeader failed, got %08x\n", hres
);
880 ok(text
!= NULL
, "text == NULL\n");
884 test_header(expect_headers
, sizeof(expect_headers
)/sizeof(expect_headers
[0]));
887 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
888 ok(hres
== S_OK
, "get_status failed: %08x\n", hres
);
889 ok(val
== 200, "Expect 200, got %d\n", val
);
892 hres
= IHTMLXMLHttpRequest_get_statusText(xhr
, &text
);
893 ok(hres
== S_OK
, "get_statusText failed: %08x\n", hres
);
894 ok(text
!= NULL
, "text == NULL\n");
895 ok(!strcmp_wa(text
, "OK"), "Expected \"OK\", got %s\n", wine_dbgstr_w(text
));
899 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
900 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
901 ok(val
== 4, "Expect DONE, got %d\n", val
);
904 hres
= IHTMLXMLHttpRequest_get_responseText(xhr
, &text
);
905 ok(hres
== S_OK
, "get_responseText failed: %08x\n", hres
);
906 ok(text
!= NULL
, "test == NULL\n");
908 ok(!strcmp_wa(text
, expect_text
), "expect %s, got %s\n",
909 expect_text
, wine_dbgstr_w(text
));
912 test_responseXML(expect_text
);
914 IHTMLXMLHttpRequest_Release(xhr
);
918 static void test_async_xhr_abort(IHTMLDocument2
*doc
, const char *xml_url
)
920 VARIANT vbool
, vempty
, var
;
925 method
= a2bstr("GET");
926 url
= a2bstr(xml_url
);
927 V_VT(&vbool
) = VT_BOOL
;
928 V_BOOL(&vbool
) = VARIANT_TRUE
;
929 V_VT(&vempty
) = VT_EMPTY
;
931 trace("abort before send() is fired\n");
932 create_xmlhttprequest(doc
);
936 V_VT(&var
) = VT_DISPATCH
;
937 V_DISPATCH(&var
) = (IDispatch
*)&xmlhttprequest_onreadystatechange_obj
;
938 hres
= IHTMLXMLHttpRequest_put_onreadystatechange(xhr
, var
);
940 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
941 hres
= IHTMLXMLHttpRequest_open(xhr
, method
, url
, vbool
, vempty
, vempty
);
942 ok(hres
== S_OK
, "open failed: %08x\n", hres
);
943 CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
945 hres
= IHTMLXMLHttpRequest_abort(xhr
);
946 ok(hres
== S_OK
, "abort failed: %08x\n", hres
);
948 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
949 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
950 ok(val
== 0, "Expect 0, got %d\n", val
);
952 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
953 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
954 ok(val
== 0, "Expect UNSENT, got %d\n", val
);
956 IHTMLXMLHttpRequest_Release(xhr
);
959 trace("abort after send() is fired\n");
960 create_xmlhttprequest(doc
);
961 V_VT(&var
) = VT_DISPATCH
;
962 V_DISPATCH(&var
) = (IDispatch
*)&xmlhttprequest_onreadystatechange_obj
;
963 hres
= IHTMLXMLHttpRequest_put_onreadystatechange(xhr
, var
);
965 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
966 hres
= IHTMLXMLHttpRequest_open(xhr
, method
, url
, vbool
, vempty
, vempty
);
967 ok(hres
== S_OK
, "open failed: %08x\n", hres
);
968 CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
971 readystatechange_cnt
= 0;
972 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
973 SET_EXPECT(xmlhttprequest_onreadystatechange_done
);
974 hres
= IHTMLXMLHttpRequest_send(xhr
, vempty
);
975 ok(hres
== S_OK
, "send failed: %08x\n", hres
);
976 todo_wine
CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
978 hres
= IHTMLXMLHttpRequest_abort(xhr
);
979 ok(hres
== S_OK
, "abort failed: %08x\n", hres
);
980 CHECK_CALLED(xmlhttprequest_onreadystatechange_done
);
982 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
983 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
984 ok(val
== 0, "Expect UNSENT, got %d\n", val
);
986 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
987 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
988 ok(val
== 0, "Expect 0, got %d\n", val
);
990 ok(loading_cnt
== 0, "loading_cnt = %d, expect 0, loading_cnt\n", loading_cnt
);
991 todo_wine
ok(readystatechange_cnt
== 2, "readystatechange_cnt = %d, expect 2\n", readystatechange_cnt
);
993 IHTMLXMLHttpRequest_Release(xhr
);
996 SysFreeString(method
);
1000 static IHTMLDocument2
*create_doc_from_url(const char *start_url
)
1005 IPersistMoniker
*persist_mon
;
1006 IHTMLDocument2
*doc
;
1009 hres
= CreateBindCtx(0, &bc
);
1010 ok(hres
== S_OK
, "CreateBindCtx failed: 0x%08x\n", hres
);
1012 url
= a2bstr(start_url
);
1013 hres
= CreateURLMoniker(NULL
, url
, &url_mon
);
1014 ok(hres
== S_OK
, "CreateURLMoniker failed: 0x%08x\n", hres
);
1016 hres
= CoCreateInstance(&CLSID_HTMLDocument
, NULL
,
1017 CLSCTX_INPROC_SERVER
| CLSCTX_INPROC_HANDLER
, &IID_IHTMLDocument2
,
1019 ok(hres
== S_OK
, "CoCreateInstance failed: 0x%08x\n", hres
);
1021 hres
= IHTMLDocument2_QueryInterface(doc
, &IID_IPersistMoniker
,
1022 (void**)&persist_mon
);
1023 ok(hres
== S_OK
, "IHTMLDocument2_QueryInterface failed: 0x%08x\n", hres
);
1025 hres
= IPersistMoniker_Load(persist_mon
, FALSE
, url_mon
, bc
,
1026 STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
);
1027 ok(hres
== S_OK
, "IPersistMoniker_Load failed: 0x%08x\n", hres
);
1029 IPersistMoniker_Release(persist_mon
);
1030 IMoniker_Release(url_mon
);
1031 IBindCtx_Release(bc
);
1034 doc_complete
= FALSE
;
1036 do_advise((IUnknown
*)doc
, &IID_IPropertyNotifySink
, (IUnknown
*)&PropertyNotifySink
);
1037 pump_msgs(&doc_complete
);
1042 START_TEST(xmlhttprequest
)
1044 IHTMLDocument2
*doc
;
1045 static const char start_url
[] = "http://test.winehq.org/tests/hello.html";
1046 static const char xml_url
[] = "http://test.winehq.org/tests/xmltest.xml";
1047 static const char large_page_url
[] = "http://test.winehq.org/tests/data.php";
1048 static const char expect_response_text
[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<a>TEST</a>\n";
1052 content_type
= a2bstr("Content-Type");
1053 doc
= create_doc_from_url(start_url
);
1055 test_sync_xhr(doc
, xml_url
, expect_response_text
);
1056 test_sync_xhr(doc
, large_page_url
, NULL
);
1057 test_async_xhr(doc
, xml_url
, expect_response_text
);
1058 test_async_xhr(doc
, large_page_url
, NULL
);
1059 test_async_xhr_abort(doc
, large_page_url
);
1060 IHTMLDocument2_Release(doc
);
1062 SysFreeString(content_type
);