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 static BSTR
a2bstr(const char *str
)
26 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
27 ret
= SysAllocStringLen(NULL
, len
);
28 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
33 static int strcmp_wa(LPCWSTR strw
, const char *stra
)
36 WideCharToMultiByte(CP_ACP
, 0, strw
, -1, buf
, sizeof(buf
), NULL
, NULL
);
37 return lstrcmpA(stra
, buf
);
40 #define DEFINE_EXPECT(func) \
41 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
43 #define SET_EXPECT(func) \
44 do { called_ ## func = FALSE; expect_ ## func = TRUE; } while(0)
46 #define CHECK_EXPECT2(func) \
49 ok(expect_ ##func, "unexpected call " #func "\n"); \
50 called_ ## func = TRUE; \
53 #define CHECK_EXPECT(func) \
55 CHECK_EXPECT2(func); \
56 expect_ ## func = FALSE; \
59 #define CHECK_CALLED(func) \
61 ok(called_ ## func, "expected " #func "\n"); \
62 expect_ ## func = called_ ## func = FALSE; \
65 static IHTMLXMLHttpRequest
*xhr
= NULL
;
66 static BSTR content_type
= NULL
;
67 static int loading_cnt
= 0;
68 static int readystatechange_cnt
= 0;
70 DEFINE_EXPECT(xmlhttprequest_onreadystatechange_opened
);
71 DEFINE_EXPECT(xmlhttprequest_onreadystatechange_headers_received
);
72 DEFINE_EXPECT(xmlhttprequest_onreadystatechange_loading
);
73 DEFINE_EXPECT(xmlhttprequest_onreadystatechange_done
);
75 #define test_disp(u,id) _test_disp(__LINE__,u,id)
76 static void _test_disp(unsigned line
, IUnknown
*unk
, const IID
*diid
)
83 hres
= IUnknown_QueryInterface(unk
, &IID_IDispatchEx
, (void**)&dispex
);
84 ok_(__FILE__
,line
) (hres
== S_OK
, "Could not get IDispatch: %08x\n", hres
);
89 hres
= IDispatchEx_GetTypeInfoCount(dispex
, &ticnt
);
90 ok_(__FILE__
,line
) (hres
== S_OK
, "GetTypeInfoCount failed: %08x\n", hres
);
91 ok_(__FILE__
,line
) (ticnt
== 1, "ticnt=%u\n", ticnt
);
93 hres
= IDispatchEx_GetTypeInfo(dispex
, 0, 0, &typeinfo
);
94 ok_(__FILE__
,line
) (hres
== S_OK
, "GetTypeInfo failed: %08x\n", hres
);
99 hres
= ITypeInfo_GetTypeAttr(typeinfo
, &type_attr
);
100 ok_(__FILE__
,line
) (hres
== S_OK
, "GetTypeAttr failed: %08x\n", hres
);
101 ok_(__FILE__
,line
) (IsEqualGUID(&type_attr
->guid
, diid
), "unexpected guid %s\n",
102 wine_dbgstr_guid(&type_attr
->guid
));
104 ITypeInfo_ReleaseTypeAttr(typeinfo
, type_attr
);
105 ITypeInfo_Release(typeinfo
);
108 IDispatchEx_Release(dispex
);
111 #define test_event_args(a,b,c,d,e,f,g) _test_event_args(__LINE__,a,b,c,d,e,f,g)
112 static void _test_event_args(unsigned line
, const IID
*dispiid
, DISPID id
, WORD wFlags
, DISPPARAMS
*pdp
,
113 VARIANT
*pvarRes
, EXCEPINFO
*pei
, IServiceProvider
*pspCaller
)
115 ok_(__FILE__
,line
) (id
== DISPID_VALUE
, "id = %d\n", id
);
116 ok_(__FILE__
,line
) (wFlags
== DISPATCH_METHOD
, "wFlags = %x\n", wFlags
);
117 ok_(__FILE__
,line
) (pdp
!= NULL
, "pdp == NULL\n");
118 ok_(__FILE__
,line
) (pdp
->cArgs
== 1, "pdp->cArgs = %d\n", pdp
->cArgs
);
119 ok_(__FILE__
,line
) (pdp
->cNamedArgs
== 1, "pdp->cNamedArgs = %d\n", pdp
->cNamedArgs
);
120 ok_(__FILE__
,line
) (pdp
->rgdispidNamedArgs
[0] == DISPID_THIS
, "pdp->rgdispidNamedArgs[0] = %d\n",
121 pdp
->rgdispidNamedArgs
[0]);
122 ok_(__FILE__
,line
) (V_VT(pdp
->rgvarg
) == VT_DISPATCH
, "V_VT(rgvarg) = %d\n", V_VT(pdp
->rgvarg
));
123 ok_(__FILE__
,line
) (pvarRes
!= NULL
, "pvarRes == NULL\n");
124 ok_(__FILE__
,line
) (pei
!= NULL
, "pei == NULL");
125 ok_(__FILE__
,line
) (!pspCaller
, "pspCaller != NULL\n");
128 _test_disp(line
, (IUnknown
*)V_DISPATCH(pdp
->rgvarg
), dispiid
);
131 static HRESULT WINAPI
DispatchEx_QueryInterface(IDispatchEx
*iface
, REFIID riid
, void **ppv
)
135 if(IsEqualGUID(riid
, &IID_IUnknown
)
136 || IsEqualGUID(riid
, &IID_IDispatch
)
137 || IsEqualGUID(riid
, &IID_IDispatchEx
))
140 ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid
));
141 return E_NOINTERFACE
;
147 static ULONG WINAPI
DispatchEx_AddRef(IDispatchEx
*iface
)
152 static ULONG WINAPI
DispatchEx_Release(IDispatchEx
*iface
)
157 static HRESULT WINAPI
DispatchEx_GetTypeInfoCount(IDispatchEx
*iface
, UINT
*pctinfo
)
159 ok(0, "unexpected call\n");
163 static HRESULT WINAPI
DispatchEx_GetTypeInfo(IDispatchEx
*iface
, UINT iTInfo
,
164 LCID lcid
, ITypeInfo
**ppTInfo
)
166 ok(0, "unexpected call\n");
170 static HRESULT WINAPI
DispatchEx_GetIDsOfNames(IDispatchEx
*iface
, REFIID riid
,
171 LPOLESTR
*rgszNames
, UINT cNames
,
172 LCID lcid
, DISPID
*rgDispId
)
174 ok(0, "unexpected call\n");
178 static HRESULT WINAPI
DispatchEx_Invoke(IDispatchEx
*iface
, DISPID dispIdMember
,
179 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
180 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
182 ok(0, "unexpected call\n");
186 static HRESULT WINAPI
DispatchEx_GetDispID(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
, DISPID
*pid
)
188 ok(0, "unexpected call\n");
192 static HRESULT WINAPI
DispatchEx_DeleteMemberByName(IDispatchEx
*iface
, BSTR bstrName
, DWORD grfdex
)
194 ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName
), grfdex
);
198 static HRESULT WINAPI
DispatchEx_DeleteMemberByDispID(IDispatchEx
*iface
, DISPID id
)
200 ok(0, "unexpected call\n");
204 static HRESULT WINAPI
DispatchEx_GetMemberProperties(IDispatchEx
*iface
, DISPID id
, DWORD grfdexFetch
, DWORD
*pgrfdex
)
206 ok(0, "unexpected call\n");
210 static HRESULT WINAPI
DispatchEx_GetMemberName(IDispatchEx
*iface
, DISPID id
, BSTR
*pbstrName
)
212 ok(0, "unexpected call\n");
216 static HRESULT WINAPI
DispatchEx_GetNextDispID(IDispatchEx
*iface
, DWORD grfdex
, DISPID id
, DISPID
*pid
)
218 ok(0, "unexpected call\n");
222 static HRESULT WINAPI
DispatchEx_GetNameSpaceParent(IDispatchEx
*iface
, IUnknown
**ppunk
)
224 ok(0, "unexpected call\n");
228 static HRESULT WINAPI
xmlhttprequest_onreadystatechange(IDispatchEx
*iface
, DISPID id
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pdp
,
229 VARIANT
*pvarRes
, EXCEPINFO
*pei
, IServiceProvider
*pspCaller
)
234 test_event_args(&DIID_DispHTMLXMLHttpRequest
, id
, wFlags
, pdp
, pvarRes
, pei
, pspCaller
);
236 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
237 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
238 readystatechange_cnt
++;
242 CHECK_EXPECT(xmlhttprequest_onreadystatechange_opened
);
245 CHECK_EXPECT(xmlhttprequest_onreadystatechange_headers_received
);
249 CHECK_EXPECT2(xmlhttprequest_onreadystatechange_loading
);
252 CHECK_EXPECT(xmlhttprequest_onreadystatechange_done
);
255 ok(0, "unexpected readyState: %d\n", val
);
260 static IDispatchExVtbl xmlhttprequest_onreadystatechangeFuncVtbl
= {
261 DispatchEx_QueryInterface
,
264 DispatchEx_GetTypeInfoCount
,
265 DispatchEx_GetTypeInfo
,
266 DispatchEx_GetIDsOfNames
,
268 DispatchEx_GetDispID
,
269 xmlhttprequest_onreadystatechange
,
270 DispatchEx_DeleteMemberByName
,
271 DispatchEx_DeleteMemberByDispID
,
272 DispatchEx_GetMemberProperties
,
273 DispatchEx_GetMemberName
,
274 DispatchEx_GetNextDispID
,
275 DispatchEx_GetNameSpaceParent
277 static IDispatchEx xmlhttprequest_onreadystatechange_obj
= { &xmlhttprequest_onreadystatechangeFuncVtbl
};
279 static BOOL doc_complete
;
280 static IHTMLDocument2
*notif_doc
;
282 static HRESULT WINAPI
PropertyNotifySink_QueryInterface(IPropertyNotifySink
*iface
,
283 REFIID riid
, void**ppv
)
285 if(IsEqualGUID(&IID_IPropertyNotifySink
, riid
)) {
290 ok(0, "unexpected call\n");
291 return E_NOINTERFACE
;
294 static ULONG WINAPI
PropertyNotifySink_AddRef(IPropertyNotifySink
*iface
)
299 static ULONG WINAPI
PropertyNotifySink_Release(IPropertyNotifySink
*iface
)
304 static HRESULT WINAPI
PropertyNotifySink_OnChanged(IPropertyNotifySink
*iface
, DISPID dispID
)
306 if(dispID
== DISPID_READYSTATE
){
310 hres
= IHTMLDocument2_get_readyState(notif_doc
, &state
);
311 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
313 if(!strcmp_wa(state
, "complete"))
316 SysFreeString(state
);
322 static HRESULT WINAPI
PropertyNotifySink_OnRequestEdit(IPropertyNotifySink
*iface
, DISPID dispID
)
324 ok(0, "unexpected call\n");
328 static IPropertyNotifySinkVtbl PropertyNotifySinkVtbl
= {
329 PropertyNotifySink_QueryInterface
,
330 PropertyNotifySink_AddRef
,
331 PropertyNotifySink_Release
,
332 PropertyNotifySink_OnChanged
,
333 PropertyNotifySink_OnRequestEdit
336 static IPropertyNotifySink PropertyNotifySink
= { &PropertyNotifySinkVtbl
};
338 static void do_advise(IUnknown
*unk
, REFIID riid
, IUnknown
*unk_advise
)
340 IConnectionPointContainer
*container
;
341 IConnectionPoint
*cp
;
345 hres
= IUnknown_QueryInterface(unk
, &IID_IConnectionPointContainer
, (void**)&container
);
346 ok(hres
== S_OK
, "QueryInterface(IID_IConnectionPointContainer) failed: %08x\n", hres
);
348 hres
= IConnectionPointContainer_FindConnectionPoint(container
, riid
, &cp
);
349 IConnectionPointContainer_Release(container
);
350 ok(hres
== S_OK
, "FindConnectionPoint failed: %08x\n", hres
);
352 hres
= IConnectionPoint_Advise(cp
, unk_advise
, &cookie
);
353 IConnectionPoint_Release(cp
);
354 ok(hres
== S_OK
, "Advise failed: %08x\n", hres
);
357 static void pump_msgs(BOOL
*b
)
362 while(!*b
&& GetMessageW(&msg
, NULL
, 0, 0)) {
363 TranslateMessage(&msg
);
364 DispatchMessageW(&msg
);
367 while(PeekMessageW(&msg
, NULL
, 0, 0, PM_REMOVE
)) {
368 TranslateMessage(&msg
);
369 DispatchMessageW(&msg
);
380 static void create_xmlhttprequest(IHTMLDocument2
*doc
)
382 IHTMLWindow2
*window
;
383 IHTMLWindow5
*window5
;
385 IHTMLXMLHttpRequestFactory
*factory
;
388 hres
= IHTMLDocument2_get_parentWindow(doc
, &window
);
389 ok(hres
== S_OK
, "get_parentWindow failed: %08x\n", hres
);
390 ok(window
!= NULL
, "window == NULL\n");
392 hres
= IHTMLWindow2_QueryInterface(window
, &IID_IHTMLWindow5
, (void**)&window5
);
393 IHTMLWindow2_Release(window
);
395 win_skip("IHTMLWindow5 not supported\n");
400 hres
= IHTMLWindow5_get_XMLHttpRequest(window5
, &var
);
401 IHTMLWindow5_Release(window5
);
402 ok(hres
== S_OK
, "get_XMLHttpRequest failed: %08x\n", hres
);
403 ok(V_VT(&var
) == VT_DISPATCH
, "V_VT(&var) is %08x, expected VT_DISPATCH\n", V_VT(&var
));
405 hres
= IDispatch_QueryInterface(V_DISPATCH(&var
), &IID_IHTMLXMLHttpRequestFactory
, (void**)&factory
);
407 ok(hres
== S_OK
, "QueryInterface(IID_IHTMLXMLHttpRequestFactory) failed: %08x\n", hres
);
408 ok(factory
!= NULL
, "factory == NULL\n");
410 hres
= IHTMLXMLHttpRequestFactory_create(factory
, &xhr
);
411 IHTMLXMLHttpRequestFactory_Release(factory
);
412 ok(hres
== S_OK
, "create failed: %08x\n", hres
);
413 ok(xhr
!= NULL
, "xhr == NULL\n");
416 static void test_header(const struct HEADER_TYPE expect
[], int num
)
419 BSTR key
, text
, all_header
;
421 char all
[4096], buf
[512];
424 hres
= IHTMLXMLHttpRequest_getAllResponseHeaders(xhr
, &all_header
);
425 ok(hres
== S_OK
, "getAllResponseHeader failed: %08x\n", hres
);
426 ok(all_header
!= NULL
, "all_header == NULL\n");
428 WideCharToMultiByte(CP_UTF8
, 0, all_header
, -1, all
, sizeof(all
), NULL
, NULL
);
429 SysFreeString(all_header
);
431 for(i
= 0; i
< num
; ++i
) {
433 key
= a2bstr(expect
[i
].key
);
434 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, key
, &text
);
435 ok(hres
== S_OK
, "getResponseHeader failed, got %08x\n", hres
);
436 ok(text
!= NULL
, "text == NULL\n");
437 ok(!strcmp_wa(text
, expect
[i
].value
),
438 "Expect %s: %s, got %s\n", expect
[i
].key
, expect
[i
].value
, wine_dbgstr_w(text
));
442 strcpy(buf
, expect
[i
].key
);
444 strcat(buf
, expect
[i
].value
);
445 ok(strstr(all
, buf
) != NULL
, "AllResponseHeaders(%s) don't have expected substr(%s)\n", all
, buf
);
449 static void test_sync_xhr(IHTMLDocument2
*doc
, const char *xml_url
, const char *expect_text
)
451 VARIANT vbool
, vempty
, var
;
456 static const struct HEADER_TYPE expect_headers
[] = {
457 {"Server", "Apache"},
458 {"Accept-Ranges", "bytes"},
459 {"Content-Length", "51"},
460 {"Content-Type", "application/xml"}
463 create_xmlhttprequest(doc
);
467 V_VT(&var
) = VT_EMPTY
;
468 hres
= IHTMLXMLHttpRequest_get_onreadystatechange(xhr
, &var
);
469 ok(hres
== S_OK
, "get_onreadystatechange failed: %08x\n", hres
);
470 ok(V_VT(&var
) == VT_NULL
, "V_VT(onreadystatechange) = %d\n", V_VT(&var
));
472 V_VT(&var
) = VT_DISPATCH
;
473 V_DISPATCH(&var
) = (IDispatch
*)&xmlhttprequest_onreadystatechange_obj
;
474 hres
= IHTMLXMLHttpRequest_put_onreadystatechange(xhr
, var
);
475 ok(hres
== S_OK
, "put_onreadystatechange failed: %08x\n", hres
);
477 V_VT(&var
) = VT_EMPTY
;
478 hres
= IHTMLXMLHttpRequest_get_onreadystatechange(xhr
, &var
);
479 ok(hres
== S_OK
, "get_onreadystatechange failed: %08x\n", hres
);
480 ok(V_VT(&var
) == VT_DISPATCH
, "V_VT(onreadystatechange) = %d\n", V_VT(&var
));
481 ok(V_DISPATCH(&var
) == (IDispatch
*)&xmlhttprequest_onreadystatechange_obj
, "unexpected onreadystatechange value\n");
483 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, NULL
);
484 ok(hres
== E_POINTER
, "Expect E_POINTER, got %08x\n", hres
);
487 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
488 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
489 ok(val
== 0, "Expect UNSENT, got %d\n", val
);
491 hres
= IHTMLXMLHttpRequest_get_status(xhr
, NULL
);
492 ok(hres
== E_POINTER
, "Expect E_POINTER, got %08x\n", hres
);
495 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
496 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
497 ok(val
== 0, "Expect 0, got %d\n", val
);
499 hres
= IHTMLXMLHttpRequest_get_statusText(xhr
, NULL
);
500 ok(hres
== E_POINTER
, "Expect E_POINTER, got %08x\n", hres
);
502 hres
= IHTMLXMLHttpRequest_get_statusText(xhr
, &text
);
503 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
504 ok(text
== NULL
, "Expect NULL, got %p\n", text
);
506 text
= (BSTR
)0xdeadbeef;
507 hres
= IHTMLXMLHttpRequest_getAllResponseHeaders(xhr
, &text
);
508 ok(hres
== E_FAIL
, "got %08x\n", hres
);
509 ok(text
== NULL
, "text = %p\n", text
);
511 text
= (BSTR
)0xdeadbeef;
512 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, content_type
, &text
);
513 ok(hres
== E_FAIL
, "got %08x\n", hres
);
514 ok(text
== NULL
, "text = %p\n", text
);
516 method
= a2bstr("GET");
517 url
= a2bstr(xml_url
);
518 V_VT(&vbool
) = VT_BOOL
;
519 V_BOOL(&vbool
) = VARIANT_FALSE
;
520 V_VT(&vempty
) = VT_EMPTY
;
522 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
523 hres
= IHTMLXMLHttpRequest_open(xhr
, method
, url
, vbool
, vempty
, vempty
);
524 todo_wine
ok(hres
== S_OK
, "open failed: %08x\n", hres
); /* Gecko 30+ only supports async */
525 todo_wine
CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
527 SysFreeString(method
);
531 IHTMLXMLHttpRequest_Release(xhr
);
536 text
= (BSTR
)0xdeadbeef;
537 hres
= IHTMLXMLHttpRequest_getAllResponseHeaders(xhr
, &text
);
538 ok(hres
== E_FAIL
, "got %08x\n", hres
);
539 ok(text
== NULL
, "text = %p\n", text
);
541 text
= (BSTR
)0xdeadbeef;
542 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, content_type
, &text
);
543 ok(hres
== E_FAIL
, "got %08x\n", hres
);
544 ok(text
== NULL
, "text = %p\n", text
);
547 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
548 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
549 ok(val
== 0, "Expect 0, got %d\n", val
);
551 hres
= IHTMLXMLHttpRequest_get_statusText(xhr
, &text
);
552 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
553 ok(text
== NULL
, "Expect NULL, got %p\n", text
);
556 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
557 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
558 ok(val
== 1, "Expect OPENED, got %d\n", val
);
560 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
561 SET_EXPECT(xmlhttprequest_onreadystatechange_headers_received
);
562 SET_EXPECT(xmlhttprequest_onreadystatechange_loading
);
563 SET_EXPECT(xmlhttprequest_onreadystatechange_done
);
565 hres
= IHTMLXMLHttpRequest_send(xhr
, vempty
);
566 ok(hres
== S_OK
, "send failed: %08x\n", hres
);
567 CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
568 CHECK_CALLED(xmlhttprequest_onreadystatechange_headers_received
);
569 CHECK_CALLED(xmlhttprequest_onreadystatechange_loading
);
570 CHECK_CALLED(xmlhttprequest_onreadystatechange_done
);
571 ok(loading_cnt
== 1, "loading_cnt = %d\n", loading_cnt
);
574 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, content_type
, &text
);
575 ok(hres
== S_OK
, "getResponseHeader failed, got %08x\n", hres
);
576 ok(text
!= NULL
, "text == NULL\n");
580 test_header(expect_headers
, sizeof(expect_headers
)/sizeof(expect_headers
[0]));
583 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
584 ok(hres
== S_OK
, "get_status failed: %08x\n", hres
);
585 ok(val
== 200, "Expect 200, got %d\n", val
);
587 hres
= IHTMLXMLHttpRequest_get_statusText(xhr
, &text
);
588 ok(hres
== S_OK
, "get_statusText failed: %08x\n", hres
);
589 ok(text
!= NULL
, "text == NULL\n");
590 ok(!strcmp_wa(text
, "OK"),
591 "Expected \"OK\", got %s\n", wine_dbgstr_w(text
));
595 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
596 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
597 ok(val
== 4, "Expect DONE, got %d\n", val
);
599 hres
= IHTMLXMLHttpRequest_get_responseText(xhr
, &text
);
600 ok(hres
== S_OK
, "get_responseText failed: %08x\n", hres
);
601 ok(text
!= NULL
, "test == NULL\n");
603 ok(!strcmp_wa(text
, expect_text
), "expect %s, got %s\n",
604 expect_text
, wine_dbgstr_w(text
));
607 IHTMLXMLHttpRequest_Release(xhr
);
611 static void test_async_xhr(IHTMLDocument2
*doc
, const char *xml_url
, const char *expect_text
)
613 VARIANT vbool
, vempty
, var
;
618 static const struct HEADER_TYPE expect_headers
[] = {
619 {"Content-Length", "51"},
620 {"Content-Type", "application/xml"}
623 create_xmlhttprequest(doc
);
627 V_VT(&var
) = VT_DISPATCH
;
628 V_DISPATCH(&var
) = (IDispatch
*)&xmlhttprequest_onreadystatechange_obj
;
629 hres
= IHTMLXMLHttpRequest_put_onreadystatechange(xhr
, var
);
630 ok(hres
== S_OK
, "put_onreadystatechange failed: %08x\n", hres
);
632 V_VT(&var
) = VT_EMPTY
;
633 hres
= IHTMLXMLHttpRequest_get_onreadystatechange(xhr
, &var
);
634 ok(hres
== S_OK
, "get_onreadystatechange failed: %08x\n", hres
);
635 ok(V_VT(&var
) == VT_DISPATCH
, "V_VT(onreadystatechange) = %d\n", V_VT(&var
));
636 ok(V_DISPATCH(&var
) == (IDispatch
*)&xmlhttprequest_onreadystatechange_obj
, "unexpected onreadystatechange value\n");
638 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, NULL
, &text
);
639 ok(hres
== E_INVALIDARG
, "Expect E_INVALIDARG, got %08x\n", hres
);
641 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, content_type
, NULL
);
642 ok(hres
== E_POINTER
, "Expect E_POINTER, got %08x\n", hres
);
644 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, NULL
, NULL
);
645 ok(hres
== E_POINTER
|| broken(hres
== E_INVALIDARG
), /* Vista and before */
646 "Expect E_POINTER, got %08x\n", hres
);
648 text
= (BSTR
)0xdeadbeef;
649 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, content_type
, &text
);
650 ok(hres
== E_FAIL
, "got %08x\n", hres
);
651 ok(text
== NULL
, "text = %p\n", text
);
653 hres
= IHTMLXMLHttpRequest_getAllResponseHeaders(xhr
, NULL
);
654 ok(hres
== E_POINTER
, "Expect E_POINTER, got %08x\n", hres
);
656 text
= (BSTR
)0xdeadbeef;
657 hres
= IHTMLXMLHttpRequest_getAllResponseHeaders(xhr
, &text
);
658 ok(hres
== E_FAIL
, "got %08x\n", hres
);
659 ok(text
== NULL
, "text = %p\n", text
);
662 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
663 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
664 ok(val
== 0, "Expect 0, got %d\n", val
);
666 text
= (BSTR
)0xdeadbeef;
667 hres
= IHTMLXMLHttpRequest_get_statusText(xhr
, &text
);
668 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
669 ok(text
== NULL
, "Expect NULL, got %p\n", text
);
672 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
673 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
674 ok(val
== 0, "Expect UNSENT, got %d\n", val
);
676 method
= a2bstr("GET");
677 url
= a2bstr(xml_url
);
678 V_VT(&vbool
) = VT_BOOL
;
679 V_BOOL(&vbool
) = VARIANT_TRUE
;
680 V_VT(&vempty
) = VT_EMPTY
;
682 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
683 hres
= IHTMLXMLHttpRequest_open(xhr
, method
, url
, vbool
, vempty
, vempty
);
684 ok(hres
== S_OK
, "open failed: %08x\n", hres
);
685 CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
687 SysFreeString(method
);
691 IHTMLXMLHttpRequest_Release(xhr
);
696 text
= (BSTR
)0xdeadbeef;
697 hres
= IHTMLXMLHttpRequest_getAllResponseHeaders(xhr
, &text
);
698 ok(hres
== E_FAIL
, "got %08x\n", hres
);
699 ok(text
== NULL
, "text = %p\n", text
);
701 text
= (BSTR
)0xdeadbeef;
702 hres
= IHTMLXMLHttpRequest_getResponseHeader(xhr
, content_type
, &text
);
703 ok(hres
== E_FAIL
, "got %08x\n", hres
);
704 ok(text
== NULL
, "text = %p\n", text
);
707 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
708 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
709 ok(val
== 0, "Expect 0, got %d\n", val
);
711 hres
= IHTMLXMLHttpRequest_get_statusText(xhr
, &text
);
712 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
713 ok(text
== NULL
, "Expect NULL, got %p\n", text
);
716 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
717 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
718 ok(val
== 1, "Expect OPENED, got %d\n", val
);
720 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
721 SET_EXPECT(xmlhttprequest_onreadystatechange_headers_received
);
722 SET_EXPECT(xmlhttprequest_onreadystatechange_loading
);
723 SET_EXPECT(xmlhttprequest_onreadystatechange_done
);
725 hres
= IHTMLXMLHttpRequest_send(xhr
, vempty
);
727 ok(hres
== S_OK
, "send failed: %08x\n", hres
);
729 pump_msgs(&called_xmlhttprequest_onreadystatechange_done
);
730 todo_wine
CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
731 CHECK_CALLED(xmlhttprequest_onreadystatechange_headers_received
);
732 CHECK_CALLED(xmlhttprequest_onreadystatechange_loading
);
733 CHECK_CALLED(xmlhttprequest_onreadystatechange_done
);
734 /* Workaround for loading large files */
736 ok(loading_cnt
== 1, "loading_cnt = %d\n", loading_cnt
);
738 todo_wine
ok(loading_cnt
== 1, "loading_cnt = %d\n", loading_cnt
);
741 IHTMLXMLHttpRequest_Release(xhr
);
747 hres
= IHTMLXMLHttpRequest_getAllResponseHeaders(xhr
, &text
);
748 ok(hres
== S_OK
, "getAllResponseHeader failed, got %08x\n", hres
);
749 ok(text
!= NULL
, "text == NULL\n");
753 test_header(expect_headers
, sizeof(expect_headers
)/sizeof(expect_headers
[0]));
756 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
757 ok(hres
== S_OK
, "get_status failed: %08x\n", hres
);
758 ok(val
== 200, "Expect 200, got %d\n", val
);
761 hres
= IHTMLXMLHttpRequest_get_statusText(xhr
, &text
);
762 ok(hres
== S_OK
, "get_statusText failed: %08x\n", hres
);
763 ok(text
!= NULL
, "text == NULL\n");
764 ok(!strcmp_wa(text
, "OK"), "Expected \"OK\", got %s\n", wine_dbgstr_w(text
));
768 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
769 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
770 ok(val
== 4, "Expect DONE, got %d\n", val
);
773 hres
= IHTMLXMLHttpRequest_get_responseText(xhr
, &text
);
774 ok(hres
== S_OK
, "get_responseText failed: %08x\n", hres
);
775 ok(text
!= NULL
, "test == NULL\n");
777 ok(!strcmp_wa(text
, expect_text
), "expect %s, got %s\n",
778 expect_text
, wine_dbgstr_w(text
));
781 IHTMLXMLHttpRequest_Release(xhr
);
785 static void test_async_xhr_abort(IHTMLDocument2
*doc
, const char *xml_url
)
787 VARIANT vbool
, vempty
, var
;
792 method
= a2bstr("GET");
793 url
= a2bstr(xml_url
);
794 V_VT(&vbool
) = VT_BOOL
;
795 V_BOOL(&vbool
) = VARIANT_TRUE
;
796 V_VT(&vempty
) = VT_EMPTY
;
798 trace("abort before send() is fired\n");
799 create_xmlhttprequest(doc
);
803 V_VT(&var
) = VT_DISPATCH
;
804 V_DISPATCH(&var
) = (IDispatch
*)&xmlhttprequest_onreadystatechange_obj
;
805 hres
= IHTMLXMLHttpRequest_put_onreadystatechange(xhr
, var
);
807 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
808 hres
= IHTMLXMLHttpRequest_open(xhr
, method
, url
, vbool
, vempty
, vempty
);
809 ok(hres
== S_OK
, "open failed: %08x\n", hres
);
810 CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
812 hres
= IHTMLXMLHttpRequest_abort(xhr
);
813 ok(hres
== S_OK
, "abort failed: %08x\n", hres
);
815 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
816 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
817 ok(val
== 0, "Expect 0, got %d\n", val
);
819 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
820 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
821 ok(val
== 0, "Expect UNSENT, got %d\n", val
);
823 IHTMLXMLHttpRequest_Release(xhr
);
826 trace("abort after send() is fired\n");
827 create_xmlhttprequest(doc
);
828 V_VT(&var
) = VT_DISPATCH
;
829 V_DISPATCH(&var
) = (IDispatch
*)&xmlhttprequest_onreadystatechange_obj
;
830 hres
= IHTMLXMLHttpRequest_put_onreadystatechange(xhr
, var
);
832 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
833 hres
= IHTMLXMLHttpRequest_open(xhr
, method
, url
, vbool
, vempty
, vempty
);
834 ok(hres
== S_OK
, "open failed: %08x\n", hres
);
835 CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
838 readystatechange_cnt
= 0;
839 SET_EXPECT(xmlhttprequest_onreadystatechange_opened
);
840 SET_EXPECT(xmlhttprequest_onreadystatechange_done
);
841 hres
= IHTMLXMLHttpRequest_send(xhr
, vempty
);
842 ok(hres
== S_OK
, "send failed: %08x\n", hres
);
843 todo_wine
CHECK_CALLED(xmlhttprequest_onreadystatechange_opened
);
845 hres
= IHTMLXMLHttpRequest_abort(xhr
);
846 ok(hres
== S_OK
, "abort failed: %08x\n", hres
);
847 CHECK_CALLED(xmlhttprequest_onreadystatechange_done
);
849 hres
= IHTMLXMLHttpRequest_get_readyState(xhr
, &val
);
850 ok(hres
== S_OK
, "get_readyState failed: %08x\n", hres
);
851 ok(val
== 0, "Expect UNSENT, got %d\n", val
);
853 hres
= IHTMLXMLHttpRequest_get_status(xhr
, &val
);
854 ok(hres
== E_FAIL
, "Expect E_FAIL, got: %08x\n", hres
);
855 ok(val
== 0, "Expect 0, got %d\n", val
);
857 ok(loading_cnt
== 0, "loading_cnt = %d, expect 0, loading_cnt\n", loading_cnt
);
858 todo_wine
ok(readystatechange_cnt
== 2, "readystatechange_cnt = %d, expect 2\n", readystatechange_cnt
);
860 IHTMLXMLHttpRequest_Release(xhr
);
863 SysFreeString(method
);
867 static IHTMLDocument2
*create_doc_from_url(const char *start_url
)
872 IPersistMoniker
*persist_mon
;
876 hres
= CreateBindCtx(0, &bc
);
877 ok(hres
== S_OK
, "CreateBindCtx failed: 0x%08x\n", hres
);
879 url
= a2bstr(start_url
);
880 hres
= CreateURLMoniker(NULL
, url
, &url_mon
);
881 ok(hres
== S_OK
, "CreateURLMoniker failed: 0x%08x\n", hres
);
883 hres
= CoCreateInstance(&CLSID_HTMLDocument
, NULL
,
884 CLSCTX_INPROC_SERVER
| CLSCTX_INPROC_HANDLER
, &IID_IHTMLDocument2
,
886 ok(hres
== S_OK
, "CoCreateInstance failed: 0x%08x\n", hres
);
888 hres
= IHTMLDocument2_QueryInterface(doc
, &IID_IPersistMoniker
,
889 (void**)&persist_mon
);
890 ok(hres
== S_OK
, "IHTMLDocument2_QueryInterface failed: 0x%08x\n", hres
);
892 hres
= IPersistMoniker_Load(persist_mon
, FALSE
, url_mon
, bc
,
893 STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
);
894 ok(hres
== S_OK
, "IPersistMoniker_Load failed: 0x%08x\n", hres
);
896 IPersistMoniker_Release(persist_mon
);
897 IMoniker_Release(url_mon
);
898 IBindCtx_Release(bc
);
901 doc_complete
= FALSE
;
903 do_advise((IUnknown
*)doc
, &IID_IPropertyNotifySink
, (IUnknown
*)&PropertyNotifySink
);
904 pump_msgs(&doc_complete
);
909 START_TEST(xmlhttprequest
)
912 static const char start_url
[] = "http://test.winehq.org/tests/hello.html";
913 static const char xml_url
[] = "http://test.winehq.org/tests/xmltest.xml";
914 static const char large_page_url
[] = "http://test.winehq.org/tests/data.php";
915 static const char expect_response_text
[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<a>TEST</a>\n";
919 content_type
= a2bstr("Content-Type");
920 doc
= create_doc_from_url(start_url
);
922 test_sync_xhr(doc
, xml_url
, expect_response_text
);
923 test_sync_xhr(doc
, large_page_url
, NULL
);
924 test_async_xhr(doc
, xml_url
, expect_response_text
);
925 test_async_xhr(doc
, large_page_url
, NULL
);
926 test_async_xhr_abort(doc
, large_page_url
);
927 IHTMLDocument2_Release(doc
);
929 SysFreeString(content_type
);