From 27a2254546543bd7e55da85d3191b56e3e10615d Mon Sep 17 00:00:00 2001 From: Christoph von Wittich Date: Mon, 18 Jan 2010 16:59:11 +0000 Subject: [PATCH] [MSHTML_WINETEST] update mshtml winetest to wine 1.1.36 svn path=/trunk/; revision=45136 --- rostests/winetests/mshtml/dom.c | 1011 +++++++++++++++++-- rostests/winetests/mshtml/events.c | 375 ++++++- rostests/winetests/mshtml/htmldoc.c | 892 ++++++++++++++--- rostests/winetests/mshtml/htmllocation.c | 368 +++++++ rostests/winetests/mshtml/jstest.html | 20 + rostests/winetests/mshtml/mshtml.rbuild | 4 + rostests/winetests/mshtml/rsrc.rc | 20 + rostests/winetests/mshtml/script.c | 1130 ++++++++++++++++++---- rostests/winetests/mshtml/testlist.c | 2 + 9 files changed, 3427 insertions(+), 395 deletions(-) create mode 100644 rostests/winetests/mshtml/htmllocation.c create mode 100644 rostests/winetests/mshtml/jstest.html create mode 100644 rostests/winetests/mshtml/rsrc.rc diff --git a/rostests/winetests/mshtml/dom.c b/rostests/winetests/mshtml/dom.c index c13c0a8c606..5c7380ed8e4 100644 --- a/rostests/winetests/mshtml/dom.c +++ b/rostests/winetests/mshtml/dom.c @@ -49,15 +49,26 @@ static const char elem_test_str[] = "
td1 texttd2 text
" "" "" - "" + "" "" + "
" ""; +static const char elem_test2_str[] = + "test" + "
" + ""; + static const char indent_test_str[] = "testabc
123"; static const char cond_comment_str[] = "test" "" ""; +static const char frameset_str[] = + "frameset test" + "" + "" + ""; static WCHAR characterW[] = {'c','h','a','r','a','c','t','e','r',0}; static WCHAR texteditW[] = {'t','e','x','t','e','d','i','t',0}; @@ -87,7 +98,8 @@ typedef enum { ET_IMG, ET_TR, ET_TD, - ET_IFRAME + ET_IFRAME, + ET_FORM } elem_type_t; static const IID * const none_iids[] = { @@ -304,12 +316,25 @@ static const IID * const iframe_iids[] = { &IID_IHTMLElement, &IID_IHTMLElement2, &IID_IHTMLElement3, + &IID_IHTMLFrameBase, &IID_IHTMLFrameBase2, &IID_IDispatchEx, &IID_IConnectionPointContainer, NULL }; +static const IID * const form_iids[] = { + &IID_IHTMLDOMNode, + &IID_IHTMLDOMNode2, + &IID_IHTMLElement, + &IID_IHTMLElement2, + &IID_IHTMLElement3, + &IID_IHTMLFormElement, + &IID_IDispatchEx, + &IID_IConnectionPointContainer, + NULL +}; + static const IID * const generic_iids[] = { &IID_IHTMLDOMNode, &IID_IHTMLDOMNode2, @@ -341,6 +366,14 @@ static const IID * const cstyle_iids[] = { NULL }; +static const IID * const img_factory_iids[] = { + &IID_IUnknown, + &IID_IDispatch, + &IID_IDispatchEx, + &IID_IHTMLImageElementFactory, + NULL +}; + typedef struct { const char *tag; REFIID *iids; @@ -371,7 +404,8 @@ static const elem_type_info_t elem_type_infos[] = { {"IMG", img_iids, &DIID_DispHTMLImg}, {"TR", tr_iids, &DIID_DispHTMLTableRow}, {"TD", td_iids, NULL}, - {"IFRAME", iframe_iids, &DIID_DispHTMLIFrame} + {"IFRAME", iframe_iids, &DIID_DispHTMLIFrame}, + {"FORM", form_iids, &DIID_DispHTMLFormElement} }; static const char *dbgstr_guid(REFIID riid) @@ -429,6 +463,8 @@ static IHTMLDocument2 *create_document(void) hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, &IID_IHTMLDocument2, (void**)&doc); ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres); + if(FAILED(hres)) + return NULL; hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument5, (void**)&doc5); if(FAILED(hres)) { @@ -466,7 +502,7 @@ static BOOL _test_get_dispid(unsigned line, IUnknown *unk, IID *iid) HRESULT hres; hres = IUnknown_QueryInterface(unk, &IID_IDispatchEx, (void**)&dispex); - ok_(__FILE__,line) (hres == S_OK, "Could not get IDispatch: %08x\n", hres); + ok_(__FILE__,line) (hres == S_OK, "Could not get IDispatchEx: %08x\n", hres); if(FAILED(hres)) return FALSE; @@ -621,6 +657,17 @@ static IHTMLAnchorElement *_get_anchor_iface(unsigned line, IUnknown *unk) return anchor; } +#define get_text_iface(u) _get_text_iface(__LINE__,u) +static IHTMLDOMTextNode *_get_text_iface(unsigned line, IUnknown *unk) +{ + IHTMLDOMTextNode *text; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IHTMLDOMTextNode, (void**)&text); + ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLDOMTextNode: %08x\n", hres); + return text; +} + #define test_node_name(u,n) _test_node_name(__LINE__,u,n) static void _test_node_name(unsigned line, IUnknown *unk, const char *exname) { @@ -641,21 +688,36 @@ static IHTMLDocument2 *_get_owner_doc(unsigned line, IUnknown *unk) { IHTMLDOMNode2 *node = _get_node2_iface(line, unk); IDispatch *disp = (void*)0xdeadbeef; - IHTMLDocument2 *doc; + IHTMLDocument2 *doc = NULL; HRESULT hres; hres = IHTMLDOMNode2_get_ownerDocument(node, &disp); IHTMLDOMNode2_Release(node); ok_(__FILE__,line)(hres == S_OK, "get_ownerDocument failed: %08x\n", hres); - ok_(__FILE__,line)(disp != NULL, "disp = NULL\n"); - hres = IDispatch_QueryInterface(disp, &IID_IHTMLDocument2, (void**)&doc); - IDispatch_Release(disp); - ok_(__FILE__,line)(hres == S_OK, "Could not get IHTMLDocument2 iface: %08x\n", hres); + if(disp) { + hres = IDispatch_QueryInterface(disp, &IID_IHTMLDocument2, (void**)&doc); + IDispatch_Release(disp); + ok_(__FILE__,line)(hres == S_OK, "Could not get IHTMLDocument2 iface: %08x\n", hres); + } return doc; } +#define get_doc_window(d) _get_doc_window(__LINE__,d) +static IHTMLWindow2 *_get_doc_window(unsigned line, IHTMLDocument2 *doc) +{ + IHTMLWindow2 *window; + HRESULT hres; + + window = NULL; + hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok_(__FILE__,line)(hres == S_OK, "get_parentWindow failed: %08x\n", hres); + ok_(__FILE__,line)(window != NULL, "window == NULL\n"); + + return window; +} + #define clone_node(n,d) _clone_node(__LINE__,n,d) static IHTMLDOMNode *_clone_node(unsigned line, IUnknown *unk, VARIANT_BOOL deep) { @@ -809,6 +871,64 @@ static IHTMLDocument2 *_get_doc_node(unsigned line, IHTMLDocument2 *doc) return ret; } +#define test_window_name(d,e) _test_window_name(__LINE__,d,e) +static void _test_window_name(unsigned line, IHTMLWindow2 *window, const char *exname) +{ + BSTR name; + HRESULT hres; + + hres = IHTMLWindow2_get_name(window, &name); + ok_(__FILE__,line)(hres == S_OK, "get_name failed: %08x\n", hres); + if(exname) + ok_(__FILE__,line)(!strcmp_wa(name, exname), "name = %s\n", wine_dbgstr_w(name)); + else + ok_(__FILE__,line)(!name, "name = %s\n", wine_dbgstr_w(name)); +} + +#define set_window_name(w,n) _set_window_name(__LINE__,w,n) +static void _set_window_name(unsigned line, IHTMLWindow2 *window, const char *name) +{ + BSTR str; + HRESULT hres; + + str = a2bstr(name); + hres = IHTMLWindow2_put_name(window, str); + SysFreeString(str); + ok_(__FILE__,line)(hres == S_OK, "put_name failed: %08x\n", hres); + + _test_window_name(line, window, name); +} + +#define test_window_length(w,l) _test_window_length(__LINE__,w,l) +static void _test_window_length(unsigned line, IHTMLWindow2 *window, LONG exlen) +{ + LONG length = -1; + HRESULT hres; + + hres = IHTMLWindow2_get_length(window, &length); + ok_(__FILE__,line)(hres == S_OK, "get_length failed: %08x\n", hres); + ok_(__FILE__,line)(length == exlen, "length = %d, expected %d\n", length, exlen); +} + +#define get_frame_content_window(e) _get_frame_content_window(__LINE__,e) +static IHTMLWindow2 *_get_frame_content_window(unsigned line, IUnknown *elem) +{ + IHTMLFrameBase2 *base2; + IHTMLWindow2 *window; + HRESULT hres; + + hres = IUnknown_QueryInterface(elem, &IID_IHTMLFrameBase2, (void**)&base2); + ok(hres == S_OK, "Could not get IHTMFrameBase2 iface: %08x\n", hres); + + window = NULL; + hres = IHTMLFrameBase2_get_contentWindow(base2, &window); + IHTMLFrameBase2_Release(base2); + ok(hres == S_OK, "get_contentWindow failed: %08x\n", hres); + ok(window != NULL, "contentWindow = NULL\n"); + + return window; +} + static void test_get_set_attr(IHTMLDocument2 *doc) { IHTMLElement *elem; @@ -875,8 +995,8 @@ static void test_get_set_attr(IHTMLDocument2 *doc) bstr = a2bstr("newattribute"); hres = IHTMLElement_getAttribute(elem, bstr, 0, &val); ok(hres == S_OK, "getAttribute failed: %08x\n", hres); - todo_wine ok(V_VT(&val) == VT_BOOL, "variant type should have been VT_BOOL (0x%x), was: 0x%x\n", VT_BOOL, V_VT(&val)); - todo_wine ok(V_BOOL(&val) == VARIANT_TRUE, "variant value should have been VARIANT_TRUE (0x%x), was %d\n", VARIANT_TRUE, V_BOOL(&val)); + ok(V_VT(&val) == VT_BOOL, "variant type should have been VT_BOOL (0x%x), was: 0x%x\n", VT_BOOL, V_VT(&val)); + ok(V_BOOL(&val) == VARIANT_TRUE, "variant value should have been VARIANT_TRUE (0x%x), was %d\n", VARIANT_TRUE, V_BOOL(&val)); VariantClear(&val); SysFreeString(bstr); @@ -1002,6 +1122,105 @@ static IHTMLOptionElement *_create_option_elem(unsigned line, IHTMLDocument2 *do return option; } +#define test_img_width(o,w) _test_img_width(__LINE__,o,w) +static void _test_img_width(unsigned line, IHTMLImgElement *img, const long exp) +{ + LONG found = -1; + HRESULT hres; + + hres = IHTMLImgElement_get_width(img, &found); + todo_wine ok_(__FILE__,line) (hres == S_OK, "get_width failed: %08x\n", hres); + todo_wine ok_(__FILE__,line) (found == exp, "width=%d\n", found); +} + +#define test_img_put_width(o,w) _test_img_put_width(__LINE__,o,w) +static void _test_img_put_width(unsigned line, IHTMLImgElement *img, const long width) +{ + HRESULT hres; + + hres = IHTMLImgElement_put_width(img, width); + todo_wine ok(hres == S_OK, "put_width failed: %08x\n", hres); + + _test_img_width(line, img, width); +} + +#define test_img_height(o,h) _test_img_height(__LINE__,o,h) +static void _test_img_height(unsigned line, IHTMLImgElement *img, const long exp) +{ + LONG found = -1; + HRESULT hres; + + hres = IHTMLImgElement_get_height(img, &found); + todo_wine ok_(__FILE__,line) (hres == S_OK, "get_height failed: %08x\n", hres); + todo_wine ok_(__FILE__,line) (found == exp, "height=%d\n", found); +} + +#define test_img_put_height(o,w) _test_img_put_height(__LINE__,o,w) +static void _test_img_put_height(unsigned line, IHTMLImgElement *img, const long height) +{ + HRESULT hres; + + hres = IHTMLImgElement_put_height(img, height); + todo_wine ok(hres == S_OK, "put_height failed: %08x\n", hres); + + _test_img_height(line, img, height); +} + +#define create_img_elem(d,t,v) _create_img_elem(__LINE__,d,t,v) +static IHTMLImgElement *_create_img_elem(unsigned line, IHTMLDocument2 *doc, + LONG wdth, LONG hght) +{ + IHTMLImageElementFactory *factory; + IHTMLImgElement *img; + IHTMLWindow2 *window; + VARIANT width, height; + char buf[16]; + HRESULT hres; + + hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok_(__FILE__,line) (hres == S_OK, "get_parentElement failed: %08x\n", hres); + + hres = IHTMLWindow2_get_Image(window, &factory); + IHTMLWindow2_Release(window); + ok_(__FILE__,line) (hres == S_OK, "get_Image failed: %08x\n", hres); + + test_ifaces((IUnknown*)factory, img_factory_iids); + test_disp((IUnknown*)factory, &IID_IHTMLImageElementFactory, "[object]"); + + if(wdth >= 0){ + snprintf(buf, 16, "%d", wdth); + V_VT(&width) = VT_BSTR; + V_BSTR(&width) = a2bstr(buf); + }else{ + V_VT(&width) = VT_EMPTY; + wdth = 0; + } + + if(hght >= 0){ + snprintf(buf, 16, "%d", hght); + V_VT(&height) = VT_BSTR; + V_BSTR(&height) = a2bstr(buf); + }else{ + V_VT(&height) = VT_EMPTY; + hght = 0; + } + + hres = IHTMLImageElementFactory_create(factory, width, height, &img); + ok_(__FILE__,line) (hres == S_OK, "create failed: %08x\n", hres); + + IHTMLImageElementFactory_Release(factory); + VariantClear(&width); + VariantClear(&height); + + if(SUCCEEDED(hres)) { + _test_img_width(line, img, wdth); + _test_img_height(line, img, hght); + return img; + } + + return NULL; +} + #define test_select_length(s,l) _test_select_length(__LINE__,s,l) static void _test_select_length(unsigned line, IHTMLSelectElement *select, LONG length) { @@ -1404,6 +1623,21 @@ static void _test_elem_set_innerhtml(unsigned line, IUnknown *unk, const char *i SysFreeString(html); } +#define test_elem_set_outerhtml(e,t) _test_elem_set_outerhtml(__LINE__,e,t) +static void _test_elem_set_outerhtml(unsigned line, IUnknown *unk, const char *outer_html) +{ + IHTMLElement *elem = _get_elem_iface(line, unk); + BSTR html; + HRESULT hres; + + html = a2bstr(outer_html); + hres = IHTMLElement_put_outerHTML(elem, html); + ok_(__FILE__,line)(hres == S_OK, "put_outerHTML failed: %08x\n", hres); + + IHTMLElement_Release(elem); + SysFreeString(html); +} + #define get_first_child(n) _get_first_child(__LINE__,n) static IHTMLDOMNode *_get_first_child(unsigned line, IUnknown *unk) { @@ -1446,6 +1680,20 @@ static IHTMLDOMNode *_test_node_get_parent(unsigned line, IUnknown *unk) return parent; } +#define node_get_next(u) _node_get_next(__LINE__,u) +static IHTMLDOMNode *_node_get_next(unsigned line, IUnknown *unk) +{ + IHTMLDOMNode *node = _get_node_iface(line, unk); + IHTMLDOMNode *next; + HRESULT hres; + + hres = IHTMLDOMNode_get_nextSibling(node, &next); + IHTMLDOMNode_Release(node); + ok_(__FILE__,line) (hres == S_OK, "get_nextSiblibg failed: %08x\n", hres); + + return next; +} + #define test_elem_get_parent(u) _test_elem_get_parent(__LINE__,u) static IHTMLElement *_test_elem_get_parent(unsigned line, IUnknown *unk) { @@ -1501,6 +1749,19 @@ static void _test_select_get_disabled(unsigned line, IHTMLSelectElement *select, _test_elem3_get_disabled(line, (IUnknown*)select, exb); } +#define test_text_length(u,l) _test_text_length(__LINE__,u,l) +static void _test_text_length(unsigned line, IUnknown *unk, LONG l) +{ + IHTMLDOMTextNode *text = _get_text_iface(line, unk); + LONG length; + HRESULT hres; + + hres = IHTMLDOMTextNode_get_length(text, &length); + ok_(__FILE__,line)(hres == S_OK, "get_length failed: %08x\n", hres); + ok_(__FILE__,line)(length == l, "length = %d, expected %d\n", length, l); + IHTMLDOMTextNode_Release(text); +} + #define test_select_set_disabled(i,b) _test_select_set_disabled(__LINE__,i,b) static void _test_select_set_disabled(unsigned line, IHTMLSelectElement *select, VARIANT_BOOL b) { @@ -1666,6 +1927,20 @@ static void _test_img_set_alt(unsigned line, IUnknown *unk, const char *alt) _test_img_alt(line, unk, alt); } +#define test_img_name(u, c) _test_img_name(__LINE__,u, c) +static void _test_img_name(unsigned line, IUnknown *unk, const char *pValue) +{ + IHTMLImgElement *img = _get_img_iface(line, unk); + BSTR sName; + HRESULT hres; + + hres = IHTMLImgElement_get_name(img, &sName); + ok_(__FILE__,line) (hres == S_OK, "get_Name failed: %08x\n", hres); + ok_(__FILE__,line) (!strcmp_wa (sName, pValue), "expected '%s' got '%s'\n", pValue, wine_dbgstr_w(sName)); + SysFreeString(sName); +} + + #define test_input_get_disabled(i,b) _test_input_get_disabled(__LINE__,i,b) static void _test_input_get_disabled(unsigned line, IHTMLInputElement *input, VARIANT_BOOL exb) { @@ -1847,6 +2122,39 @@ static void _test_elem_set_tabindex(unsigned line, IUnknown *unk, short index) _test_elem_tabindex(line, unk, index); } +#define test_elem_filters(u) _test_elem_filters(__LINE__,u) +static void _test_elem_filters(unsigned line, IUnknown *unk) +{ + IHTMLElement *elem = _get_elem_iface(line, unk); + HRESULT hres; + IHTMLFiltersCollection *filters; + + hres = IHTMLElement_get_filters(elem, &filters); + ok_(__FILE__,line) (hres == S_OK || broken(hres == REGDB_E_CLASSNOTREG) /* NT4 */, + "get_filters failed: %08x\n", hres); + if(hres == S_OK) + { + LONG len; + IDispatchEx *dispex; + + hres = IHTMLFiltersCollection_get_length(filters, &len); + ok_(__FILE__,line) (hres == S_OK, "get_length failed: %08x\n", hres); + ok_(__FILE__,line) (len == 0, "expect 0 got %d\n", len); + + hres = IHTMLFiltersCollection_QueryInterface(filters, &IID_IDispatchEx, (void**)&dispex); + ok_(__FILE__,line) (hres == S_OK || broken(hres == E_NOINTERFACE), + "Could not get IDispatchEx interface: %08x\n", hres); + if(SUCCEEDED(hres)) { + test_disp((IUnknown*)filters, &IID_IHTMLFiltersCollection, "[object]"); + IDispatchEx_Release(dispex); + } + + IHTMLFiltersCollection_Release(filters); + } + + IHTMLElement_Release(elem); +} + #define test_elem_set_class(u,c) _test_elem_set_class(__LINE__,u,c) static void _test_elem_set_class(unsigned line, IUnknown *unk, const char *class) { @@ -2000,6 +2308,40 @@ static void _test_elem_client_rect(unsigned line, IUnknown *unk) IHTMLElement2_Release(elem); } +#define get_elem_doc(e) _get_elem_doc(__LINE__,e) +static IHTMLDocument2 *_get_elem_doc(unsigned line, IUnknown *unk) +{ + IHTMLElement *elem = _get_elem_iface(line, unk); + IHTMLDocument2 *doc; + IDispatch *disp; + HRESULT hres; + + disp = NULL; + hres = IHTMLElement_get_document(elem, &disp); + ok(hres == S_OK, "get_document failed: %08x\n", hres); + ok(disp != NULL, "disp == NULL\n"); + + hres = IDispatch_QueryInterface(disp, &IID_IHTMLDocument2, (void**)&doc); + IDispatch_Release(disp); + ok(hres == S_OK, "Could not get IHTMLDocument2 iface: %08x\n", hres); + + return doc; +} + +#define get_window_doc(e) _get_window_doc(__LINE__,e) +static IHTMLDocument2 *_get_window_doc(unsigned line, IHTMLWindow2 *window) +{ + IHTMLDocument2 *doc; + HRESULT hres; + + doc = NULL; + hres = IHTMLWindow2_get_document(window, &doc); + ok(hres == S_OK, "get_document failed: %08x\n", hres); + ok(doc != NULL, "disp == NULL\n"); + + return doc; +} + #define test_create_elem(d,t) _test_create_elem(__LINE__,d,t) static IHTMLElement *_test_create_elem(unsigned line, IHTMLDocument2 *doc, const char *tag) { @@ -2378,6 +2720,30 @@ static void test_create_option_elem(IHTMLDocument2 *doc) IHTMLOptionElement_Release(option); } +static void test_create_img_elem(IHTMLDocument2 *doc) +{ + IHTMLImgElement *img; + + img = create_img_elem(doc, 10, 15); + + if(img){ + test_img_put_width(img, 5); + test_img_put_height(img, 20); + + IHTMLImgElement_Release(img); + img = NULL; + } + + img = create_img_elem(doc, -1, -1); + + if(img){ + test_img_put_width(img, 5); + test_img_put_height(img, 20); + + IHTMLImgElement_Release(img); + } +} + static IHTMLTxtRange *test_create_body_range(IHTMLDocument2 *doc) { IHTMLBodyElement *body; @@ -2753,6 +3119,60 @@ static void test_navigator(IHTMLDocument2 *doc) ok(!ref, "navigator should be destroyed here\n"); } +static void test_screen(IHTMLWindow2 *window) +{ + IHTMLScreen *screen, *screen2; + IDispatchEx *dispex; + LONG l, exl; + HDC hdc; + HRESULT hres; + + static const WCHAR displayW[] = {'D','I','S','P','L','A','Y',0}; + + screen = NULL; + hres = IHTMLWindow2_get_screen(window, &screen); + ok(hres == S_OK, "get_screen failed: %08x\n", hres); + ok(screen != NULL, "screen == NULL\n"); + + screen2 = NULL; + hres = IHTMLWindow2_get_screen(window, &screen2); + ok(hres == S_OK, "get_screen failed: %08x\n", hres); + ok(screen2 != NULL, "screen == NULL\n"); + ok(iface_cmp((IUnknown*)screen2, (IUnknown*)screen), "screen2 != screen\n"); + IHTMLScreen_Release(screen2); + + hres = IHTMLScreen_QueryInterface(screen, &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK || broken(hres == E_NOINTERFACE), "Could not get IDispatchEx interface: %08x\n", hres); + if(SUCCEEDED(hres)) { + test_disp((IUnknown*)screen, &DIID_DispHTMLScreen, "[object]"); + IDispatchEx_Release(dispex); + } + + hdc = CreateICW(displayW, NULL, NULL, NULL); + + exl = GetDeviceCaps(hdc, HORZRES); + l = 0xdeadbeef; + hres = IHTMLScreen_get_width(screen, &l); + ok(hres == S_OK, "get_width failed: %08x\n", hres); + ok(l == exl, "width = %d, expected %d\n", l, exl); + + exl = GetDeviceCaps(hdc, VERTRES); + l = 0xdeadbeef; + hres = IHTMLScreen_get_height(screen, &l); + ok(hres == S_OK, "get_height failed: %08x\n", hres); + ok(l == exl, "height = %d, expected %d\n", l, exl); + + exl = GetDeviceCaps(hdc, BITSPIXEL); + l = 0xdeadbeef; + hres = IHTMLScreen_get_colorDepth(screen, &l); + ok(hres == S_OK, "get_height failed: %08x\n", hres); + ok(l == exl, "height = %d, expected %d\n", l, exl); + + DeleteObject(hdc); + + IHTMLScreen_Release(screen); +} + static void test_current_style(IHTMLCurrentStyle *current_style) { BSTR str; @@ -3017,6 +3437,7 @@ static void test_current_style(IHTMLCurrentStyle *current_style) static void test_style2(IHTMLStyle2 *style2) { + VARIANT v; BSTR str; HRESULT hres; @@ -3035,6 +3456,27 @@ static void test_style2(IHTMLStyle2 *style2) ok(hres == S_OK, "get_position failed: %08x\n", hres); ok(!strcmp_wa(str, "absolute"), "get_position returned %s\n", wine_dbgstr_w(str)); SysFreeString(str); + + /* Test right */ + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle2_get_right(style2, &v); + ok(hres == S_OK, "get_top failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(right)=%d\n", V_VT(&v)); + ok(!V_BSTR(&v), "V_BSTR(right) != NULL\n"); + VariantClear(&v); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("3px"); + hres = IHTMLStyle2_put_right(style2, v); + ok(hres == S_OK, "put_right failed: %08x\n", hres); + VariantClear(&v); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle2_get_right(style2, &v); + ok(hres == S_OK, "get_right failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "3px"), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); } static void test_style3(IHTMLStyle3 *style3) @@ -3429,6 +3871,24 @@ static void test_default_style(IHTMLStyle *style) hres = IHTMLStyle_put_margin(style, NULL); ok(hres == S_OK, "put_margin failed: %08x\n", hres); + str = (void*)0xdeadbeef; + hres = IHTMLStyle_get_marginTop(style, &v); + ok(hres == S_OK, "get_marginTop failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(marginTop) = %d\n", V_VT(&v)); + ok(!V_BSTR(&v), "V_BSTR(marginTop) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("6px"); + hres = IHTMLStyle_put_marginTop(style, v); + SysFreeString(V_BSTR(&v)); + ok(hres == S_OK, "put_marginTop failed: %08x\n", hres); + + str = (void*)0xdeadbeef; + hres = IHTMLStyle_get_marginTop(style, &v); + ok(hres == S_OK, "get_marginTop failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(marginTop) = %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "6px"), "V_BSTR(marginTop) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + str = NULL; hres = IHTMLStyle_get_border(style, &str); ok(hres == S_OK, "get_border failed: %08x\n", hres); @@ -3943,6 +4403,108 @@ static void test_default_style(IHTMLStyle *style) ok(hres == S_OK, "put_borderColor failed: %08x\n", hres); SysFreeString(sDefault); + /* BorderRight */ + hres = IHTMLStyle_get_borderRight(style, &sDefault); + ok(hres == S_OK, "get_borderRight failed: %08x\n", hres); + + str = a2bstr("thick dotted red"); + hres = IHTMLStyle_put_borderRight(style, str); + ok(hres == S_OK, "put_borderRight failed: %08x\n", hres); + SysFreeString(str); + + /* IHTMLStyle_get_borderRight appears to have a bug where + it returns the first letter of the color. So we check + each style individually. + */ + V_BSTR(&v) = NULL; + hres = IHTMLStyle_get_borderRightColor(style, &v); + todo_wine ok(hres == S_OK, "get_borderRightColor failed: %08x\n", hres); + todo_wine ok(!strcmp_wa(V_BSTR(&v), "red"), "str=%s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + V_BSTR(&v) = NULL; + hres = IHTMLStyle_get_borderRightWidth(style, &v); + ok(hres == S_OK, "get_borderRightWidth failed: %08x\n", hres); + ok(!strcmp_wa(V_BSTR(&v), "thick"), "str=%s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_get_borderRightStyle(style, &str); + ok(hres == S_OK, "get_borderRightStyle failed: %08x\n", hres); + ok(!strcmp_wa(str, "dotted"), "str=%s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLStyle_put_borderRight(style, sDefault); + ok(hres == S_OK, "put_borderRight failed: %08x\n", hres); + SysFreeString(sDefault); + + /* BorderTop */ + hres = IHTMLStyle_get_borderTop(style, &sDefault); + ok(hres == S_OK, "get_borderTop failed: %08x\n", hres); + + str = a2bstr("thick dotted red"); + hres = IHTMLStyle_put_borderTop(style, str); + ok(hres == S_OK, "put_borderTop failed: %08x\n", hres); + SysFreeString(str); + + /* IHTMLStyle_get_borderTop appears to have a bug where + it returns the first letter of the color. So we check + each style individually. + */ + V_BSTR(&v) = NULL; + hres = IHTMLStyle_get_borderTopColor(style, &v); + todo_wine ok(hres == S_OK, "get_borderTopColor failed: %08x\n", hres); + todo_wine ok(!strcmp_wa(V_BSTR(&v), "red"), "str=%s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + V_BSTR(&v) = NULL; + hres = IHTMLStyle_get_borderTopWidth(style, &v); + ok(hres == S_OK, "get_borderTopWidth failed: %08x\n", hres); + ok(!strcmp_wa(V_BSTR(&v), "thick"), "str=%s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_get_borderTopStyle(style, &str); + ok(hres == S_OK, "get_borderTopStyle failed: %08x\n", hres); + ok(!strcmp_wa(str, "dotted"), "str=%s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLStyle_put_borderTop(style, sDefault); + ok(hres == S_OK, "put_borderTop failed: %08x\n", hres); + SysFreeString(sDefault); + + /* BorderBottom */ + hres = IHTMLStyle_get_borderBottom(style, &sDefault); + ok(hres == S_OK, "get_borderBottom failed: %08x\n", hres); + + str = a2bstr("thick dotted red"); + hres = IHTMLStyle_put_borderBottom(style, str); + ok(hres == S_OK, "put_borderBottom failed: %08x\n", hres); + SysFreeString(str); + + /* IHTMLStyle_get_borderBottom appears to have a bug where + it returns the first letter of the color. So we check + each style individually. + */ + V_BSTR(&v) = NULL; + hres = IHTMLStyle_get_borderBottomColor(style, &v); + todo_wine ok(hres == S_OK, "get_borderBottomColor failed: %08x\n", hres); + todo_wine ok(!strcmp_wa(V_BSTR(&v), "red"), "str=%s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + V_BSTR(&v) = NULL; + hres = IHTMLStyle_get_borderBottomWidth(style, &v); + ok(hres == S_OK, "get_borderBottomWidth failed: %08x\n", hres); + ok(!strcmp_wa(V_BSTR(&v), "thick"), "str=%s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_get_borderBottomStyle(style, &str); + ok(hres == S_OK, "get_borderBottomStyle failed: %08x\n", hres); + ok(!strcmp_wa(str, "dotted"), "str=%s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLStyle_put_borderBottom(style, sDefault); + ok(hres == S_OK, "put_borderBottom failed: %08x\n", hres); + SysFreeString(sDefault); + /* BorderLeft */ hres = IHTMLStyle_get_borderLeft(style, &sDefault); ok(hres == S_OK, "get_borderLeft failed: %08x\n", hres); @@ -4215,9 +4777,12 @@ static void test_doc_elem(IHTMLDocument2 *doc) doc_node = get_doc_node(doc); owner_doc = get_owner_doc((IUnknown*)elem); ok(iface_cmp((IUnknown *)doc_node, (IUnknown *)owner_doc), "doc_node != owner_doc\n"); - IHTMLDocument2_Release(doc_node); IHTMLDocument2_Release(owner_doc); + owner_doc = get_owner_doc((IUnknown*)doc_node); + ok(!owner_doc, "owner_doc = %p\n", owner_doc); + IHTMLDocument2_Release(doc_node); + test_elem_client_rect((IUnknown*)elem); IHTMLElement_Release(elem); @@ -4229,8 +4794,6 @@ static void test_default_body(IHTMLBodyElement *body) BSTR bstr; HRESULT hres; VARIANT v; - WCHAR sBodyText[] = {'#','F','F','0','0','0','0',0}; - WCHAR sTextInvalid[] = {'I','n','v','a','l','i','d',0}; bstr = (void*)0xdeadbeef; hres = IHTMLBodyElement_get_background(body, &bstr); @@ -4251,10 +4814,9 @@ static void test_default_body(IHTMLBodyElement *body) ok(V_VT(&v) == VT_BSTR, "Expected VT_BSTR got %d\n", V_VT(&v)); ok(bstr == NULL, "bstr != NULL\n"); - /* get_text - Invalid Text */ V_VT(&v) = VT_BSTR; - V_BSTR(&v) = SysAllocString(sTextInvalid); + V_BSTR(&v) = a2bstr("Invalid"); hres = IHTMLBodyElement_put_text(body, v); ok(hres == S_OK, "expect S_OK got 0x%08d\n", hres); VariantClear(&v); @@ -4263,12 +4825,12 @@ static void test_default_body(IHTMLBodyElement *body) hres = IHTMLBodyElement_get_text(body, &v); ok(hres == S_OK, "expect S_OK got 0x%08d\n", hres); ok(V_VT(&v) == VT_BSTR, "Expected VT_BSTR got %d\n", V_VT(&v)); - ok(!strcmp_wa(V_BSTR(&v), "#00a0d0"), "v != '#00a0d0'\n"); + ok(!strcmp_wa(V_BSTR(&v), "#00a0d0"), "v = %s, expected '#00a0d0'\n", wine_dbgstr_w(V_BSTR(&v))); VariantClear(&v); /* get_text - Valid Text */ V_VT(&v) = VT_BSTR; - V_BSTR(&v) = SysAllocString(sBodyText); + V_BSTR(&v) = a2bstr("#FF0000"); hres = IHTMLBodyElement_put_text(body, v); ok(hres == S_OK, "expect S_OK got 0x%08d\n", hres); VariantClear(&v); @@ -4277,23 +4839,22 @@ static void test_default_body(IHTMLBodyElement *body) hres = IHTMLBodyElement_get_text(body, &v); ok(hres == S_OK, "expect S_OK got 0x%08d\n", hres); ok(V_VT(&v) == VT_BSTR, "Expected VT_BSTR got %d\n", V_VT(&v)); - ok(!strcmp_wa(V_BSTR(&v), "#ff0000"), "v != '#ff0000'\n"); + ok(!strcmp_wa(V_BSTR(&v), "#ff0000"), "v = %s, expected '#ff0000'\n", wine_dbgstr_w(V_BSTR(&v))); VariantClear(&v); } static void test_body_funs(IHTMLBodyElement *body) { - static WCHAR sRed[] = {'r','e','d',0}; - VARIANT vbg; - VARIANT vDefaultbg; + VARIANT vbg, vDefaultbg; HRESULT hres; hres = IHTMLBodyElement_get_bgColor(body, &vDefaultbg); ok(hres == S_OK, "get_bgColor failed: %08x\n", hres); ok(V_VT(&vDefaultbg) == VT_BSTR, "bstr != NULL\n"); + ok(!V_BSTR(&vDefaultbg), "V_BSTR(bgColor) = %s\n", wine_dbgstr_w(V_BSTR(&vDefaultbg))); V_VT(&vbg) = VT_BSTR; - V_BSTR(&vbg) = SysAllocString(sRed); + V_BSTR(&vbg) = a2bstr("red"); hres = IHTMLBodyElement_put_bgColor(body, vbg); ok(hres == S_OK, "put_bgColor failed: %08x\n", hres); VariantClear(&vbg); @@ -4369,6 +4930,11 @@ static void test_window(IHTMLDocument2 *doc) ok(!strcmp_wa(str, "[object]"), "toString returned %s\n", wine_dbgstr_w(str)); SysFreeString(str); + test_window_name(window, NULL); + set_window_name(window, "test"); + test_window_length(window, 0); + test_screen(window); + IHTMLWindow2_Release(window); } @@ -4481,6 +5047,9 @@ static void test_defaults(IHTMLDocument2 *doc) IHTMLStyleSheetsCollection_Release(stylesheetcol); + hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLFiltersCollection, (void**)&body); + ok(hres == E_NOINTERFACE, "got interface IHTMLFiltersCollection\n"); + test_default_selection(doc); test_doc_title(doc, ""); } @@ -4573,12 +5142,27 @@ static void doc_write(IHTMLDocument2 *doc, BOOL ln, const char *text) SafeArrayDestroy(sa); } +static void test_frame_doc(IUnknown *frame_elem) +{ + IHTMLDocument2 *window_doc, *elem_doc; + IHTMLWindow2 *content_window; + + content_window = get_frame_content_window(frame_elem); + window_doc = get_window_doc(content_window); + IHTMLWindow2_Release(content_window); + + elem_doc = get_elem_doc(frame_elem); + ok(iface_cmp((IUnknown*)window_doc, (IUnknown*)elem_doc), "content_doc != elem_doc\n"); + + IHTMLDocument2_Release(elem_doc); + IHTMLDocument2_Release(window_doc); +} + static void test_iframe_elem(IHTMLElement *elem) { + IHTMLDocument2 *content_doc, *owner_doc; IHTMLElementCollection *col; - IHTMLDocument2 *content_doc; IHTMLWindow2 *content_window; - IHTMLFrameBase2 *base2; IDispatch *disp; VARIANT errv; BSTR str; @@ -4592,21 +5176,13 @@ static void test_iframe_elem(IHTMLElement *elem) ET_BR }; - hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLFrameBase2, (void**)&base2); - ok(hres == S_OK, "Could not get IHTMFrameBase2 iface: %08x\n", hres); - if (!base2) return; + test_frame_doc((IUnknown*)elem); - content_window = NULL; - hres = IHTMLFrameBase2_get_contentWindow(base2, &content_window); - IHTMLFrameBase2_Release(base2); - ok(hres == S_OK, "get_contentWindow failed: %08x\n", hres); - ok(content_window != NULL, "contentWindow = NULL\n"); + content_window = get_frame_content_window((IUnknown*)elem); + test_window_length(content_window, 0); - content_doc = NULL; - hres = IHTMLWindow2_get_document(content_window, &content_doc); + content_doc = get_window_doc(content_window); IHTMLWindow2_Release(content_window); - ok(hres == S_OK, "get_document failed: %08x\n", hres); - ok(content_doc != NULL, "content_doc = NULL\n"); str = a2bstr("text/html"); V_VT(&errv) = VT_ERROR; @@ -4629,6 +5205,9 @@ static void test_iframe_elem(IHTMLElement *elem) hres = IHTMLDocument2_close(content_doc); ok(hres == S_OK, "close failed: %08x\n", hres); + owner_doc = get_owner_doc((IUnknown*)content_doc); + ok(!owner_doc, "owner_doc = %p\n", owner_doc); + IHTMLDocument2_Release(content_doc); } @@ -4738,6 +5317,7 @@ static void test_elems(IHTMLDocument2 *doc) IHTMLDOMChildrenCollection *child_col; IHTMLElement *elem, *elem2, *elem3; IHTMLDOMNode *node, *node2; + IHTMLWindow2 *window; IDispatch *disp; LONG type; HRESULT hres; @@ -4767,7 +5347,8 @@ static void test_elems(IHTMLDocument2 *doc) ET_SCRIPT, ET_TEST, ET_IMG, - ET_IFRAME + ET_IFRAME, + ET_FORM }; static const elem_type_t item_types[] = { @@ -4831,6 +5412,7 @@ static void test_elems(IHTMLDocument2 *doc) test_elem_set_class((IUnknown*)elem, NULL); test_elem_tabindex((IUnknown*)elem, 0); test_elem_set_tabindex((IUnknown*)elem, 1); + test_elem_filters((IUnknown*)elem); node = test_node_get_parent((IUnknown*)elem); ok(node != NULL, "node == NULL\n"); @@ -4875,7 +5457,7 @@ static void test_elems(IHTMLDocument2 *doc) elem = get_elem_by_id(doc, "s", TRUE); if(elem) { IHTMLSelectElement *select; - IHTMLDocument2 *doc_node; + IHTMLDocument2 *doc_node, *elem_doc; hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLSelectElement, (void**)&select); ok(hres == S_OK, "Could not get IHTMLSelectElement interface: %08x\n", hres); @@ -4899,12 +5481,12 @@ static void test_elems(IHTMLDocument2 *doc) IHTMLSelectElement_Release(select); - hres = IHTMLElement_get_document(elem, &disp); - ok(hres == S_OK, "get_document failed: %08x\n", hres); + elem_doc = get_elem_doc((IUnknown*)elem); doc_node = get_doc_node(doc); - ok(iface_cmp((IUnknown*)disp, (IUnknown*)doc_node), "disp != doc\n"); + ok(iface_cmp((IUnknown*)elem_doc, (IUnknown*)doc_node), "disp != doc\n"); IHTMLDocument2_Release(doc_node); + IHTMLDocument2_Release(elem_doc); IHTMLElement_Release(elem); } @@ -4991,6 +5573,7 @@ static void test_elems(IHTMLDocument2 *doc) test_img_set_src((IUnknown*)elem, "about:blank"); test_img_alt((IUnknown*)elem, NULL); test_img_set_alt((IUnknown*)elem, "alt test"); + test_img_name((IUnknown*)elem, "WineImg"); IHTMLElement_Release(elem); } @@ -5054,11 +5637,13 @@ static void test_elems(IHTMLDocument2 *doc) ok(hres == S_OK, "get_length failed: %08x\n", hres); ok(length, "length=0\n"); + node2 = NULL; node = get_child_item(child_col, 0); ok(node != NULL, "node == NULL\n"); if(node) { type = get_node_type((IUnknown*)node); ok(type == 3, "type=%d\n", type); + node2 = node_get_next((IUnknown*)node); IHTMLDOMNode_Release(node); } @@ -5069,6 +5654,8 @@ static void test_elems(IHTMLDocument2 *doc) ok(type == 8, "type=%d\n", type); test_elem_id((IUnknown*)node, NULL); + ok(iface_cmp((IUnknown*)node2, (IUnknown*)node), "node2 != node\n"); + IHTMLDOMNode_Release(node2); IHTMLDOMNode_Release(node); } @@ -5097,6 +5684,7 @@ static void test_elems(IHTMLDocument2 *doc) test_stylesheets(doc); test_create_option_elem(doc); + test_create_img_elem(doc); elem = get_doc_elem_by_id(doc, "tbl"); ok(elem != NULL, "elem = NULL\n"); @@ -5148,9 +5736,50 @@ static void test_elems(IHTMLDocument2 *doc) test_elem_innerhtml((IUnknown*)elem, "inner html"); test_elem_set_innerhtml((IUnknown*)elem, ""); test_elem_innerhtml((IUnknown*)elem, NULL); + node = node_get_next((IUnknown*)elem); + ok(!node, "node = %p\n", node); + + elem2 = get_doc_elem_by_id(doc, "x"); + test_elem_tag((IUnknown*)elem2, "A"); + node = node_get_next((IUnknown*)elem2); + IHTMLDOMNode_Release(node); + IHTMLElement_Release(elem2); IHTMLElement_Release(elem); IHTMLDocument3_Release(doc3); + + window = get_doc_window(doc); + test_window_name(window, NULL); + set_window_name(window, "test name"); + test_window_length(window, 1); + IHTMLWindow2_Release(window); +} + +static void test_elems2(IHTMLDocument2 *doc) +{ + IHTMLElement *elem, *elem2; + + static const elem_type_t outer_types[] = { + ET_BR, + ET_A + }; + + elem = get_doc_elem_by_id(doc, "divid"); + + test_elem_set_innerhtml((IUnknown*)elem, "
"); + elem2 = get_doc_elem_by_id(doc, "innerid"); + ok(elem2 != NULL, "elem2 == NULL\n"); + test_elem_set_outerhtml((IUnknown*)elem2, "
a"); + test_elem_all((IUnknown*)elem, outer_types, sizeof(outer_types)/sizeof(*outer_types)); + IHTMLElement_Release(elem2); + + elem2 = get_doc_elem_by_id(doc, "aid"); + ok(elem2 != NULL, "elem2 == NULL\n"); + test_elem_set_outerhtml((IUnknown*)elem2, ""); + test_elem_all((IUnknown*)elem, outer_types, 1); + IHTMLElement_Release(elem2); + + IHTMLElement_Release(elem); } static void test_create_elems(IHTMLDocument2 *doc) @@ -5201,6 +5830,7 @@ static void test_create_elems(IHTMLDocument2 *doc) node = test_create_text(doc, "test"); test_ifaces((IUnknown*)node, text_iids); test_disp((IUnknown*)node, &DIID_DispHTMLDOMTextNode, "[object]"); + test_text_length((IUnknown*)node, 4); V_VT(&var) = VT_NULL; node2 = test_node_insertbefore((IUnknown*)body, node, &var); @@ -5315,6 +5945,257 @@ static void test_cond_comment(IHTMLDocument2 *doc) IHTMLElementCollection_Release(col); } +static void test_frame(IDispatch *disp, const char *exp_id) +{ + IHTMLWindow2 *frame2, *parent, *top; + IHTMLDocument2 *parent_doc, *top_doc; + IHTMLWindow4 *frame; + IHTMLFrameBase *frame_elem; + HRESULT hres; + + hres = IDispatch_QueryInterface(disp, &IID_IHTMLWindow4, (void**)&frame); + ok(hres == S_OK, "Could not get IHTMLWindow4 interface: 0x%08x\n", hres); + if(FAILED(hres)) + return; + + hres = IHTMLWindow4_get_frameElement(frame, &frame_elem); + ok(hres == S_OK, "IHTMLWindow4_get_frameElement failed: 0x%08x\n", hres); + IHTMLWindow4_Release(frame); + if(FAILED(hres)) + return; + + test_frame_doc((IUnknown*)frame_elem); + test_elem_id((IUnknown*)frame_elem, exp_id); + IHTMLElement_Release(frame_elem); + + hres = IDispatch_QueryInterface(disp, &IID_IHTMLWindow2, (void**)&frame2); + ok(hres == S_OK, "Could not get IHTMLWindow2 interface: 0x%08x\n", hres); + if(FAILED(hres)) + return; + + hres = IHTMLWindow2_get_parent(frame2, &parent); + ok(hres == S_OK, "IHTMLWindow2_get_parent failed: 0x%08x\n", hres); + if(FAILED(hres)){ + IHTMLWindow2_Release(frame2); + return; + } + + hres = IHTMLWindow2_get_document(parent, &parent_doc); + ok(hres == S_OK, "IHTMLWindow2_get_document failed: 0x%08x\n", hres); + IHTMLWindow2_Release(parent); + if(FAILED(hres)){ + IHTMLWindow2_Release(frame2); + return; + } + + test_doc_title(parent_doc, "frameset test"); + IHTMLDocument2_Release(parent_doc); + + /* test get_top */ + hres = IHTMLWindow2_get_top(frame2, &top); + ok(hres == S_OK, "IHTMLWindow2_get_top failed: 0x%08x\n", hres); + IHTMLWindow2_Release(frame2); + if(FAILED(hres)) + return; + + hres = IHTMLWindow2_get_document(top, &top_doc); + ok(hres == S_OK, "IHTMLWindow2_get_document failed: 0x%08x\n", hres); + IHTMLWindow2_Release(top); + if(FAILED(hres)) + return; + + test_doc_title(top_doc, "frameset test"); + IHTMLDocument2_Release(top_doc); +} + +static void test_frameset(IHTMLDocument2 *doc) +{ + IHTMLWindow2 *window; + IHTMLFramesCollection2 *frames; + IHTMLElement *elem; + IHTMLFrameBase *fbase; + LONG length; + VARIANT index_var, result_var; + BSTR str; + HRESULT hres; + + window = get_doc_window(doc); + + /* test using IHTMLFramesCollection object */ + + hres = IHTMLWindow2_get_frames(window, &frames); + ok(hres == S_OK, "IHTMLWindow2_get_frames failed: 0x%08x\n", hres); + IHTMLWindow2_Release(window); + if(FAILED(hres)) + return; + + /* test result length */ + hres = IHTMLFramesCollection2_get_length(frames, &length); + ok(hres == S_OK, "IHTMLFramesCollection2_get_length failed: 0x%08x\n", hres); + ok(length == 3, "IHTMLFramesCollection2_get_length should have been 3, was: %d\n", length); + + /* test first frame */ + V_VT(&index_var) = VT_I4; + V_I4(&index_var) = 0; + hres = IHTMLFramesCollection2_item(frames, &index_var, &result_var); + ok(hres == S_OK, "IHTMLFramesCollection2_item failed: 0x%08x\n", hres); + if(SUCCEEDED(hres)) { + ok(V_VT(&result_var) == VT_DISPATCH, "result type should have been VT_DISPATCH, was: 0x%x\n", V_VT(&result_var)); + test_frame((IDispatch*)V_DISPATCH(&result_var), "fr1"); + } + VariantClear(&result_var); + + /* test second frame */ + V_I4(&index_var) = 1; + hres = IHTMLFramesCollection2_item(frames, &index_var, &result_var); + ok(hres == S_OK, "IHTMLFramesCollection2_item failed: 0x%08x\n", hres); + if(SUCCEEDED(hres)) { + ok(V_VT(&result_var) == VT_DISPATCH, "result type should have been VT_DISPATCH, was: 0x%x\n", V_VT(&result_var)); + test_frame((IDispatch*)V_DISPATCH(&result_var), "fr2"); + } + VariantClear(&result_var); + + /* fail on next frame */ + V_I4(&index_var) = 3; + hres = IHTMLFramesCollection2_item(frames, &index_var, &result_var); + ok(hres == DISP_E_MEMBERNOTFOUND, "IHTMLFramesCollection2_item should have" + "failed with DISP_E_MEMBERNOTFOUND, instead: 0x%08x\n", hres); + VariantClear(&result_var); + + /* string argument (element id lookup) */ + V_VT(&index_var) = VT_BSTR; + V_BSTR(&index_var) = a2bstr("fr1"); + hres = IHTMLFramesCollection2_item(frames, &index_var, &result_var); + ok(hres == S_OK, "IHTMLFramesCollection2_item failed: 0x%08x\n", hres); + if(SUCCEEDED(hres)) { + ok(V_VT(&result_var) == VT_DISPATCH, "result type should have been VT_DISPATCH, was: 0x%x\n", V_VT(&result_var)); + test_frame(V_DISPATCH(&result_var), "fr1"); + } + VariantClear(&result_var); + VariantClear(&index_var); + + /* invalid argument */ + V_VT(&index_var) = VT_BOOL; + V_BOOL(&index_var) = VARIANT_TRUE; + hres = IHTMLFramesCollection2_item(frames, &index_var, &result_var); + ok(hres == E_INVALIDARG, "IHTMLFramesCollection2_item should have" + "failed with E_INVALIDARG, instead: 0x%08x\n", hres); + VariantClear(&result_var); + + IHTMLFramesCollection2_Release(frames); + + /* test using IHTMLWindow2 inheritance */ + + /* test result length */ + hres = IHTMLWindow2_get_length(window, &length); + ok(hres == S_OK, "IHTMLWindow2_get_length failed: 0x%08x\n", hres); + ok(length == 3, "IHTMLWindow2_get_length should have been 3, was: %d\n", length); + + /* test first frame */ + V_VT(&index_var) = VT_I4; + V_I4(&index_var) = 0; + hres = IHTMLWindow2_item(window, &index_var, &result_var); + ok(hres == S_OK, "IHTMLWindow2_item failed: 0x%08x\n", hres); + if(SUCCEEDED(hres)) { + ok(V_VT(&result_var) == VT_DISPATCH, "result type should have been VT_DISPATCH, was: 0x%x\n", V_VT(&result_var)); + test_frame((IDispatch*)V_DISPATCH(&result_var), "fr1"); + } + VariantClear(&result_var); + + /* test second frame */ + V_I4(&index_var) = 1; + hres = IHTMLWindow2_item(window, &index_var, &result_var); + ok(hres == S_OK, "IHTMLWindow2_item failed: 0x%08x\n", hres); + if(SUCCEEDED(hres)) { + ok(V_VT(&result_var) == VT_DISPATCH, "result type should have been VT_DISPATCH, was: 0x%x\n", V_VT(&result_var)); + test_frame((IDispatch*)V_DISPATCH(&result_var), "fr2"); + } + VariantClear(&result_var); + + /* fail on next frame */ + V_I4(&index_var) = 3; + hres = IHTMLWindow2_item(window, &index_var, &result_var); + ok(hres == DISP_E_MEMBERNOTFOUND, "IHTMLWindow2_item should have" + "failed with DISP_E_MEMBERNOTFOUND, instead: 0x%08x\n", hres); + VariantClear(&result_var); + + /* string argument (element id lookup) */ + V_VT(&index_var) = VT_BSTR; + V_BSTR(&index_var) = a2bstr("fr2"); + hres = IHTMLWindow2_item(window, &index_var, &result_var); + ok(hres == S_OK, "IHTMLWindow2_item failed: 0x%08x\n", hres); + if(SUCCEEDED(hres)) { + ok(V_VT(&result_var) == VT_DISPATCH, "result type should have been VT_DISPATCH, was: 0x%x\n", V_VT(&result_var)); + test_frame((IDispatch*)V_DISPATCH(&result_var), "fr2"); + } + VariantClear(&result_var); + VariantClear(&index_var); + + /* invalid argument */ + V_VT(&index_var) = VT_BOOL; + V_BOOL(&index_var) = VARIANT_TRUE; + hres = IHTMLWindow2_item(window, &index_var, &result_var); + ok(hres == E_INVALIDARG, "IHTMLWindow2_item should have" + "failed with E_INVALIDARG, instead: 0x%08x\n", hres); + VariantClear(&result_var); + + /* getElementById with node name attributes */ + elem = get_doc_elem_by_id(doc, "nm1"); + test_elem_id((IUnknown*)elem, "fr1"); + + /* get/put scrolling */ + hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLFrameBase, (void**)&fbase); + ok(hres == S_OK, "Could not get IHTMLFrameBase interface: 0x%08x\n", hres); + + hres = IHTMLFrameBase_get_scrolling(fbase, &str); + ok(hres == S_OK, "IHTMLFrameBase_get_scrolling failed: 0x%08x\n", hres); + ok(!strcmp_wa(str, "auto"), "get_scrolling should have given 'auto', gave: %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + str = a2bstr("no"); + hres = IHTMLFrameBase_put_scrolling(fbase, str); + ok(hres == S_OK, "IHTMLFrameBase_put_scrolling failed: 0x%08x\n", hres); + SysFreeString(str); + + hres = IHTMLFrameBase_get_scrolling(fbase, &str); + ok(hres == S_OK, "IHTMLFrameBase_get_scrolling failed: 0x%08x\n", hres); + ok(!strcmp_wa(str, "no"), "get_scrolling should have given 'no', gave: %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + str = a2bstr("junk"); + hres = IHTMLFrameBase_put_scrolling(fbase, str); + ok(hres == E_INVALIDARG, "IHTMLFrameBase_put_scrolling should have failed " + "with E_INVALIDARG, instead: 0x%08x\n", hres); + SysFreeString(str); + + hres = IHTMLFrameBase_get_scrolling(fbase, &str); + ok(hres == S_OK, "IHTMLFrameBase_get_scrolling failed: 0x%08x\n", hres); + ok(!strcmp_wa(str, "no"), "get_scrolling should have given 'no', gave: %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + /* get_name */ + hres = IHTMLFrameBase_get_name(fbase, &str); + ok(hres == S_OK, "IHTMLFrameBase_get_name failed: 0x%08x\n", hres); + ok(!strcmp_wa(str, "nm1"), "get_name should have given 'nm1', gave: %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + IHTMLFrameBase_Release(fbase); + IHTMLElement_Release(elem); + + /* get_name with no name attr */ + elem = get_doc_elem_by_id(doc, "fr3"); + hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLFrameBase, (void**)&fbase); + ok(hres == S_OK, "Could not get IHTMLFrameBase interface: 0x%08x\n", hres); + + hres = IHTMLFrameBase_get_name(fbase, &str); + ok(hres == S_OK, "IHTMLFrameBase_get_name failed: 0x%08x\n", hres); + ok(str == NULL, "get_name should have given 'null', gave: %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + IHTMLFrameBase_Release(fbase); + IHTMLElement_Release(elem); +} + static IHTMLDocument2 *notif_doc; static BOOL doc_complete; @@ -5425,10 +6306,8 @@ typedef void (*domtest_t)(IHTMLDocument2*); static void run_domtest(const char *str, domtest_t test) { IHTMLDocument2 *doc; - IHTMLElement *body = NULL; ULONG ref; MSG msg; - HRESULT hres; doc = create_doc_with_string(str); if(!doc) @@ -5441,15 +6320,7 @@ static void run_domtest(const char *str, domtest_t test) DispatchMessage(&msg); } - hres = IHTMLDocument2_get_body(doc, &body); - ok(hres == S_OK, "get_body failed: %08x\n", hres); - - if(body) { - IHTMLElement_Release(body); - test(doc); - }else { - skip("Could not get document body. Assuming no Gecko installed.\n"); - } + test(doc); ref = IHTMLDocument2_Release(doc); ok(!ref || @@ -5457,39 +6328,8 @@ static void run_domtest(const char *str, domtest_t test) "ref = %d\n", ref); } -static void gecko_installer_workaround(BOOL disable) -{ - HKEY hkey; - DWORD res; - - static BOOL has_url = FALSE; - static char url[2048]; - - if(!disable && !has_url) - return; - - res = RegOpenKey(HKEY_CURRENT_USER, "Software\\Wine\\MSHTML", &hkey); - if(res != ERROR_SUCCESS) - return; - - if(disable) { - DWORD type, size = sizeof(url); - - res = RegQueryValueEx(hkey, "GeckoUrl", NULL, &type, (PVOID)url, &size); - if(res == ERROR_SUCCESS && type == REG_SZ) - has_url = TRUE; - - RegDeleteValue(hkey, "GeckoUrl"); - }else { - RegSetValueEx(hkey, "GeckoUrl", 0, REG_SZ, (PVOID)url, lstrlenA(url)+1); - } - - RegCloseKey(hkey); -} - START_TEST(dom) { - gecko_installer_workaround(TRUE); CoInitialize(NULL); run_domtest(doc_str1, test_doc_elem); @@ -5501,11 +6341,12 @@ START_TEST(dom) }else { skip("IE running in Enhanced Security Configuration\n"); } + run_domtest(elem_test2_str, test_elems2); run_domtest(doc_blank, test_create_elems); run_domtest(doc_blank, test_defaults); run_domtest(indent_test_str, test_indent); run_domtest(cond_comment_str, test_cond_comment); + run_domtest(frameset_str, test_frameset); CoUninitialize(); - gecko_installer_workaround(FALSE); } diff --git a/rostests/winetests/mshtml/events.c b/rostests/winetests/mshtml/events.c index d0ddadb44da..84bfae25347 100644 --- a/rostests/winetests/mshtml/events.c +++ b/rostests/winetests/mshtml/events.c @@ -27,6 +27,7 @@ #include "winbase.h" #include "ole2.h" #include "mshtml.h" +#include "mshtmdid.h" #include "docobj.h" #include "hlink.h" #include "dispex.h" @@ -61,10 +62,15 @@ DEFINE_EXPECT(body_onclick); DEFINE_EXPECT(div_onclick); DEFINE_EXPECT(div_onclick_attached); DEFINE_EXPECT(timeout); +DEFINE_EXPECT(doccp_onclick); +DEFINE_EXPECT(iframe_onreadystatechange_loading); +DEFINE_EXPECT(iframe_onreadystatechange_interactive); +DEFINE_EXPECT(iframe_onreadystatechange_complete); static HWND container_hwnd = NULL; static IHTMLWindow2 *window; static IOleDocumentView *view; +static BOOL xy_todo; typedef struct { LONG x; @@ -84,12 +90,8 @@ static const char click_doc_str[] = "
click here
" ""; -static const char *debugstr_w(LPCWSTR str) -{ - static char buf[1024]; - WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL); - return buf; -} +static const char readystate_doc_str[] = + "<"; static const char *debugstr_guid(REFIID riid) { @@ -209,6 +211,18 @@ static IHTMLElement2 *_get_elem2_iface(unsigned line, IUnknown *unk) return elem2; } +#define get_elem3_iface(u) _get_elem3_iface(__LINE__,u) +static IHTMLElement3 *_get_elem3_iface(unsigned line, IUnknown *unk) +{ + IHTMLElement3 *elem3; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IHTMLElement3, (void**)&elem3); + ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLElement3 iface: %08x\n", hres); + + return elem3; +} + #define doc_get_body(d) _doc_get_body(__LINE__,d) static IHTMLElement *_doc_get_body(unsigned line, IHTMLDocument2 *doc) { @@ -249,7 +263,7 @@ static void _test_elem_tag(unsigned line, IUnknown *unk, const char *extag) hres = IHTMLElement_get_tagName(elem, &tag); IHTMLElement_Release(elem); ok_(__FILE__, line) (hres == S_OK, "get_tagName failed: %08x\n", hres); - ok_(__FILE__, line) (!strcmp_wa(tag, extag), "got tag: %s, expected %s\n", debugstr_w(tag), extag); + ok_(__FILE__, line) (!strcmp_wa(tag, extag), "got tag: %s, expected %s\n", wine_dbgstr_w(tag), extag); SysFreeString(tag); } @@ -268,6 +282,22 @@ static IHTMLEventObj *_get_event_obj(unsigned line) return event; } +#define elem_fire_event(a,b,c) _elem_fire_event(__LINE__,a,b,c) +static void _elem_fire_event(unsigned line, IUnknown *unk, const char *event, VARIANT *evobj) +{ + IHTMLElement3 *elem3 = _get_elem3_iface(line, unk); + VARIANT_BOOL b; + BSTR str; + HRESULT hres; + + b = 100; + str = a2bstr(event); + hres = IHTMLElement3_fireEvent(elem3, str, evobj, &b); + SysFreeString(str); + ok_(__FILE__,line)(hres == S_OK, "fireEvent failed: %08x\n", hres); + ok_(__FILE__,line)(b == VARIANT_TRUE, "fireEvent returned %x\n", b); +} + #define test_event_args(a,b,c,d,e,f,g) _test_event_args(__LINE__,a,b,c,d,e,f,g) static void _test_event_args(unsigned line, const IID *dispiid, DISPID id, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) @@ -312,8 +342,8 @@ static void _test_attached_event_args(unsigned line, DISPID id, WORD wFlags, DIS IHTMLEventObj_Release(event); } -#define test_event_src(t) _test_event_src(__LINE__,t) -static void _test_event_src(unsigned line, const char *src_tag) +#define get_event_src() _get_event_src(__LINE__) +static IHTMLElement *_get_event_src(unsigned line) { IHTMLEventObj *event = _get_event_obj(line); IHTMLElement *src_elem = NULL; @@ -323,6 +353,14 @@ static void _test_event_src(unsigned line, const char *src_tag) IHTMLEventObj_Release(event); ok_(__FILE__,line) (hres == S_OK, "get_srcElement failed: %08x\n", hres); + return src_elem; +} + +#define test_event_src(t) _test_event_src(__LINE__,t) +static void _test_event_src(unsigned line, const char *src_tag) +{ + IHTMLElement *src_elem = _get_event_src(line); + if(src_tag) { ok_(__FILE__,line) (src_elem != NULL, "src_elem = NULL\n"); _test_elem_tag(line, (IUnknown*)src_elem, src_tag); @@ -465,10 +503,14 @@ static void _test_event_clientx(unsigned line, IHTMLEventObj *event, LONG exl) hres = IHTMLEventObj_get_clientX(event, &l); ok_(__FILE__,line)(hres == S_OK, "get_clientX failed: %08x\n", hres); - if(exl == -10) /* don't test the exact value */ - ok_(__FILE__,line)(l > 0, "clientX = %d\n", l); - else + if(exl == -10) {/* don't test the exact value */ + if(xy_todo) + todo_wine ok_(__FILE__,line)(l > 0, "clientX = %d\n", l); + else + ok_(__FILE__,line)(l > 0, "clientX = %d\n", l); + }else { ok_(__FILE__,line)(l == exl, "clientX = %d, expected %d\n", l, exl); + } } static void _test_event_clienty(unsigned line, IHTMLEventObj *event, LONG exl) @@ -478,10 +520,14 @@ static void _test_event_clienty(unsigned line, IHTMLEventObj *event, LONG exl) hres = IHTMLEventObj_get_clientY(event, &l); ok_(__FILE__,line)(hres == S_OK, "get_clientY failed: %08x\n", hres); - if(exl == -10) /* don't test the exact value */ - ok_(__FILE__,line)(l > 0, "clientY = %d\n", l); - else + if(exl == -10) {/* don't test the exact value */ + if(xy_todo) + todo_wine ok_(__FILE__,line)(l > 0, "clientY = %d\n", l); + else + ok_(__FILE__,line)(l > 0, "clientY = %d\n", l); + }else { ok_(__FILE__,line)(l == exl, "clientY = %d, expected %d\n", l, exl); + } } static void _test_event_offsetx(unsigned line, IHTMLEventObj *event, LONG exl) @@ -517,10 +563,14 @@ static void _test_event_screenx(unsigned line, IHTMLEventObj *event, LONG exl) hres = IHTMLEventObj_get_screenX(event, &l); ok_(__FILE__,line)(hres == S_OK, "get_screenX failed: %08x\n", hres); - if(exl == -10) /* don't test the exact value */ - ok_(__FILE__,line)(l > 0, "screenX = %d\n", l); - else + if(exl == -10) { /* don't test the exact value */ + if(xy_todo) + todo_wine ok_(__FILE__,line)(l > 0, "screenX = %d\n", l); + else + ok_(__FILE__,line)(l > 0, "screenX = %d\n", l); + }else { ok_(__FILE__,line)(l == exl, "screenX = %d, expected %d\n", l, exl); + } } static void _test_event_screeny(unsigned line, IHTMLEventObj *event, LONG exl) @@ -530,10 +580,14 @@ static void _test_event_screeny(unsigned line, IHTMLEventObj *event, LONG exl) hres = IHTMLEventObj_get_screenY(event, &l); ok_(__FILE__,line)(hres == S_OK, "get_screenY failed: %08x\n", hres); - if(exl == -10) /* don't test the exact value */ - ok_(__FILE__,line)(l > 0, "screenY = %d\n", l); - else + if(exl == -10) { /* don't test the exact value */ + if(xy_todo) + todo_wine ok_(__FILE__,line)(l > 0, "screenY = %d\n", l); + else + ok_(__FILE__,line)(l > 0, "screenY = %d\n", l); + }else { ok_(__FILE__,line)(l == exl, "screenY = %d, expected %d\n", l, exl); + } } static void _test_event_type(unsigned line, IHTMLEventObj *event, const char *exstr) @@ -690,7 +744,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) { - ok(0, "unexpected call %s %x\n", debugstr_w(bstrName), grfdex); + ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName), grfdex); return E_NOTIMPL; } @@ -793,6 +847,54 @@ static HRESULT WINAPI body_onclick(IDispatchEx *iface, DISPID id, LCID lcid, WOR EVENT_HANDLER_FUNC_OBJ(body_onclick); +static HRESULT WINAPI iframe_onreadystatechange(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + IHTMLFrameBase2 *iframe; + IHTMLElement2 *elem2; + IHTMLElement *elem; + VARIANT v; + BSTR str; + HRESULT hres; + + test_event_args(&DIID_DispHTMLIFrame, id, wFlags, pdp, pvarRes, pei, pspCaller); + test_event_src("IFRAME"); + + elem = get_event_src(); + elem2 = get_elem2_iface((IUnknown*)elem); + IHTMLElement_Release(elem); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLElement2_get_readyState(elem2, &v); + ok(hres == S_OK, "get_readyState failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(readyState) = %d\n", V_VT(&v)); + + hres = IHTMLElement2_QueryInterface(elem2, &IID_IHTMLFrameBase2, (void**)&iframe); + IHTMLElement2_Release(elem2); + ok(hres == S_OK, "Could not get IHTMLFrameBase2 iface: %08x\n", hres); + + str = NULL; + hres = IHTMLFrameBase2_get_readyState(iframe, &str); + IHTMLFrameBase2_Release(iframe); + ok(hres == S_OK, "get_readyState failed: %08x\n", hres); + ok(str != NULL, "readyState == NULL\n"); + ok(!lstrcmpW(str, V_BSTR(&v)), "ready states differ\n"); + VariantClear(&v); + + if(!strcmp_wa(str, "loading")) + CHECK_EXPECT(iframe_onreadystatechange_loading); + else if(!strcmp_wa(str, "interactive")) + CHECK_EXPECT(iframe_onreadystatechange_interactive); + else if(!strcmp_wa(str, "complete")) + CHECK_EXPECT(iframe_onreadystatechange_complete); + else + ok(0, "unexpected state %s\n", wine_dbgstr_w(str)); + + return S_OK; +} + +EVENT_HANDLER_FUNC_OBJ(iframe_onreadystatechange); + static HRESULT WINAPI nocall(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { @@ -802,6 +904,74 @@ static HRESULT WINAPI nocall(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFla EVENT_HANDLER_FUNC_OBJ(nocall); +#define CONNECTION_POINT_OBJ(cpname, diid) \ + static HRESULT WINAPI cpname ## _QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) \ + { \ + *ppv = NULL; \ + if(IsEqualGUID(riid, &IID_IUnknown) \ + || IsEqualGUID(riid, &IID_IDispatch) \ + || IsEqualGUID(riid, &diid)) \ + *ppv = iface; \ + else { \ + ok(0, "unexpected riid %s\n", debugstr_guid(riid)); \ + return E_NOINTERFACE; \ + } \ + return S_OK; \ + } \ + static IDispatchExVtbl cpname ## Vtbl = { \ + cpname ## _QueryInterface, \ + DispatchEx_AddRef, \ + DispatchEx_Release, \ + DispatchEx_GetTypeInfoCount, \ + DispatchEx_GetTypeInfo, \ + DispatchEx_GetIDsOfNames, \ + cpname, \ + DispatchEx_GetDispID, \ + DispatchEx_InvokeEx, \ + DispatchEx_DeleteMemberByName, \ + DispatchEx_DeleteMemberByDispID, \ + DispatchEx_GetMemberProperties, \ + DispatchEx_GetMemberName, \ + DispatchEx_GetNextDispID, \ + DispatchEx_GetNameSpaceParent \ + }; \ + static IDispatchEx cpname ## _obj = { &cpname ## Vtbl } + +#define test_cp_args(a,b,c,d,e,f) _test_cp_args(__LINE__,a,b,c,d,e,f) +static void _test_cp_args(unsigned line, REFIID riid, WORD flags, DISPPARAMS *dp, VARIANT *vres, EXCEPINFO *ei, UINT *argerr) +{ + ok_(__FILE__,line)(IsEqualGUID(&IID_NULL, riid), "riid = %s\n", debugstr_guid(riid)); + ok_(__FILE__,line)(flags == DISPATCH_METHOD, "flags = %x\n", flags); + ok_(__FILE__,line)(dp != NULL, "dp == NULL\n"); + ok_(__FILE__,line)(!dp->cArgs, "dp->cArgs = %d\n", dp->cArgs); + ok_(__FILE__,line)(!dp->rgvarg, "dp->rgvarg = %p\n", dp->rgvarg); + ok_(__FILE__,line)(!dp->cNamedArgs, "dp->cNamedArgs = %d\n", dp->cNamedArgs); + ok_(__FILE__,line)(!dp->rgdispidNamedArgs, "dp->rgdispidNamedArgs = %p\n", dp->rgdispidNamedArgs); + ok_(__FILE__,line)(vres != NULL, "vres == NULL\n"); + ok_(__FILE__,line)(V_VT(vres) == VT_EMPTY, "V_VT(vres) = %d\n", V_VT(vres)); + ok_(__FILE__,line)(ei != NULL, "ei == NULL\n"); + ok_(__FILE__,line)(argerr != NULL, "argerr == NULL\n"); +} + +static HRESULT WINAPI doccp(IDispatchEx *iface, DISPID dispIdMember, + REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pVarResult, EXCEPINFO *pei, UINT *puArgErr) +{ + switch(dispIdMember) { + case DISPID_HTMLDOCUMENTEVENTS_ONCLICK: + CHECK_EXPECT(doccp_onclick); + test_cp_args(riid, wFlags, pdp, pVarResult, pei, puArgErr); + break; + default: + ok(0, "unexpected call %d\n", dispIdMember); + return E_NOTIMPL; + } + + return S_OK; +} + +CONNECTION_POINT_OBJ(doccp, DIID_HTMLDocumentEvents); + static HRESULT WINAPI timeoutFunc_Invoke(IDispatchEx *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) @@ -854,9 +1024,51 @@ static void pump_msgs(BOOL *b) } } +static IConnectionPoint *get_cp(IUnknown *unk, REFIID riid) +{ + IConnectionPointContainer *cp_container; + IConnectionPoint *cp; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IConnectionPointContainer, (void**)&cp_container); + ok(hres == S_OK, "Could not get IConnectionPointContainer: %08x\n", hres); + + hres = IConnectionPointContainer_FindConnectionPoint(cp_container, riid, &cp); + IConnectionPointContainer_Release(cp_container); + ok(hres == S_OK, "FindConnectionPoint failed: %08x\n", hres); + + return cp; +} + +static DWORD register_cp(IUnknown *unk, REFIID riid, IUnknown *sink) +{ + IConnectionPoint *cp; + DWORD cookie; + HRESULT hres; + + cp = get_cp(unk, riid); + hres = IConnectionPoint_Advise(cp, sink, &cookie); + IConnectionPoint_Release(cp); + ok(hres == S_OK, "Advise failed: %08x\n", hres); + + return cookie; +} + +static void unregister_cp(IUnknown *unk, REFIID riid, DWORD cookie) +{ + IConnectionPoint *cp; + HRESULT hres; + + cp = get_cp(unk, riid); + hres = IConnectionPoint_Unadvise(cp, cookie); + IConnectionPoint_Release(cp); + ok(hres == S_OK, "Unadvise failed: %08x\n", hres); +} + static void test_onclick(IHTMLDocument2 *doc) { IHTMLElement *div, *body; + DWORD cp_cookie; VARIANT v; HRESULT hres; @@ -870,6 +1082,10 @@ static void test_onclick(IHTMLDocument2 *doc) ok(hres == S_OK, "get_onclick failed: %08x\n", hres); ok(V_VT(&v) == VT_NULL, "V_VT(onclick) = %d\n", V_VT(&v)); + V_VT(&v) = VT_EMPTY; + hres = IHTMLElement_put_onclick(div, v); + ok(hres == E_NOTIMPL, "put_onclick failed: %08x\n", hres); + V_VT(&v) = VT_DISPATCH; V_DISPATCH(&v) = (IDispatch*)&div_onclick_obj; hres = IHTMLElement_put_onclick(div, v); @@ -918,10 +1134,106 @@ static void test_onclick(IHTMLDocument2 *doc) CHECK_CALLED(document_onclick); } + xy_todo = TRUE; + + SET_EXPECT(div_onclick); + SET_EXPECT(div_onclick_attached); + SET_EXPECT(body_onclick); + SET_EXPECT(document_onclick); + + hres = IHTMLElement_click(div); + ok(hres == S_OK, "click failed: %08x\n", hres); + + CHECK_CALLED(div_onclick); + CHECK_CALLED(div_onclick_attached); + CHECK_CALLED(body_onclick); + CHECK_CALLED(document_onclick); + + SET_EXPECT(div_onclick); + SET_EXPECT(div_onclick_attached); + SET_EXPECT(body_onclick); + SET_EXPECT(document_onclick); + + V_VT(&v) = VT_EMPTY; + elem_fire_event((IUnknown*)div, "onclick", &v); + + CHECK_CALLED(div_onclick); + CHECK_CALLED(div_onclick_attached); + CHECK_CALLED(body_onclick); + CHECK_CALLED(document_onclick); + + cp_cookie = register_cp((IUnknown*)doc, &DIID_HTMLDocumentEvents, (IUnknown*)&doccp_obj); + + SET_EXPECT(div_onclick); + SET_EXPECT(div_onclick_attached); + SET_EXPECT(body_onclick); + SET_EXPECT(document_onclick); + SET_EXPECT(doccp_onclick); + + hres = IHTMLElement_click(div); + ok(hres == S_OK, "click failed: %08x\n", hres); + + CHECK_CALLED(div_onclick); + CHECK_CALLED(div_onclick_attached); + CHECK_CALLED(body_onclick); + CHECK_CALLED(document_onclick); + CHECK_CALLED(doccp_onclick); + + unregister_cp((IUnknown*)doc, &DIID_HTMLDocumentEvents, cp_cookie); + IHTMLElement_Release(div); IHTMLElement_Release(body); } +static void test_onreadystatechange(IHTMLDocument2 *doc) +{ + IHTMLFrameBase *iframe; + IHTMLElement2 *elem2; + IHTMLElement *elem; + VARIANT v; + BSTR str; + HRESULT hres; + + elem = get_elem_id(doc, "iframe"); + elem2 = get_elem2_iface((IUnknown*)elem); + IHTMLElement_Release(elem); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLElement2_get_onreadystatechange(elem2, &v); + ok(hres == S_OK, "get_onreadystatechange failed: %08x\n", hres); + ok(V_VT(&v) == VT_NULL, "V_VT(onreadystatechange) = %d\n", V_VT(&v)); + + V_VT(&v) = VT_DISPATCH; + V_DISPATCH(&v) = (IDispatch*)&iframe_onreadystatechange_obj; + hres = IHTMLElement2_put_onreadystatechange(elem2, v); + ok(hres == S_OK, "put_onreadystatechange failed: %08x\n", hres); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLElement2_get_onreadystatechange(elem2, &v); + ok(hres == S_OK, "get_onreadystatechange failed: %08x\n", hres); + ok(V_VT(&v) == VT_DISPATCH, "V_VT(onreadystatechange) = %d\n", V_VT(&v)); + ok(V_DISPATCH(&v) == (IDispatch*)&iframe_onreadystatechange_obj, "unexpected onreadystatechange value\n"); + + hres = IHTMLElement2_QueryInterface(elem2, &IID_IHTMLFrameBase, (void**)&iframe); + IHTMLElement2_Release(elem2); + ok(hres == S_OK, "Could not get IHTMLFrameBase iface: %08x\n", hres); + + hres = IHTMLFrameBase_put_src(iframe, (str = a2bstr("about:blank"))); + SysFreeString(str); + ok(hres == S_OK, "put_src failed: %08x\n", hres); + + SET_EXPECT(iframe_onreadystatechange_loading); + SET_EXPECT(iframe_onreadystatechange_interactive); + SET_EXPECT(iframe_onreadystatechange_complete); + pump_msgs(&called_iframe_onreadystatechange_complete); + todo_wine + CHECK_CALLED(iframe_onreadystatechange_loading); + CHECK_CALLED(iframe_onreadystatechange_interactive); + CHECK_CALLED(iframe_onreadystatechange_complete); + + IHTMLFrameBase_Release(iframe); +} + static void test_timeout(IHTMLDocument2 *doc) { IHTMLWindow3 *win3; @@ -1462,12 +1774,23 @@ static void set_client_site(IHTMLDocument2 *doc, BOOL set) static IHTMLDocument2 *create_document(void) { IHTMLDocument2 *doc; + IHTMLDocument5 *doc5; HRESULT hres; hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, &IID_IHTMLDocument2, (void**)&doc); ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres); + if (FAILED(hres)) + return NULL; + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument5, (void**)&doc5); + if(FAILED(hres)) { + win_skip("Could not get IHTMLDocument5 interface, probably too old IE\n"); + IHTMLDocument2_Release(doc); + return NULL; + } + IHTMLDocument5_Release(doc5); return doc; } @@ -1478,11 +1801,13 @@ static void run_test(const char *str, testfunc_t test) { IHTMLDocument2 *doc; IHTMLElement *body = NULL; - ULONG ref; MSG msg; HRESULT hres; + xy_todo = FALSE; doc = create_document(); + if (!doc) + return; set_client_site(doc, TRUE); doc_load_string(doc, str); do_advise((IUnknown*)doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink); @@ -1511,8 +1836,7 @@ static void run_test(const char *str, testfunc_t test) } set_client_site(doc, FALSE); - ref = IHTMLDocument2_Release(doc); - ok(!ref, "ref = %d\n", ref); + IHTMLDocument2_Release(doc); } static LRESULT WINAPI wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) @@ -1548,6 +1872,7 @@ START_TEST(events) run_test(empty_doc_str, test_timeout); run_test(click_doc_str, test_onclick); + run_test(readystate_doc_str, test_onreadystatechange); DestroyWindow(container_hwnd); CoUninitialize(); diff --git a/rostests/winetests/mshtml/htmldoc.c b/rostests/winetests/mshtml/htmldoc.c index 7a4d5eeeeaa..166602091bf 100644 --- a/rostests/winetests/mshtml/htmldoc.c +++ b/rostests/winetests/mshtml/htmldoc.c @@ -29,6 +29,7 @@ #include "ole2.h" #include "mshtml.h" #include "docobj.h" +#include "wininet.h" #include "mshtmhst.h" #include "mshtmdid.h" #include "mshtmcid.h" @@ -148,15 +149,18 @@ DEFINE_EXPECT(EnableModeless_FALSE); DEFINE_EXPECT(Frame_EnableModeless_TRUE); DEFINE_EXPECT(Frame_EnableModeless_FALSE); DEFINE_EXPECT(Frame_GetWindow); +DEFINE_EXPECT(TranslateUrl); +DEFINE_EXPECT(Advise_Close); static IUnknown *doc_unk; static IMoniker *doc_mon; static BOOL expect_LockContainer_fLock; static BOOL expect_InPlaceUIWindow_SetActiveObject_active = TRUE; -static BOOL ipsex; +static BOOL ipsex, ipsw; static BOOL set_clientsite = FALSE, container_locked = FALSE; static BOOL readystate_set_loading = FALSE, readystate_set_interactive = FALSE, load_from_stream; static BOOL editmode = FALSE, show_failed; +static BOOL inplace_deactivated; static int stream_read, protocol_read; static enum load_state_t { LD_DOLOAD, @@ -177,12 +181,14 @@ static const char html_page[] = static const char css_data[] = "body {color: red}"; +static const WCHAR http_urlW[] = + {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',0}; + static const WCHAR doc_url[] = {'w','i','n','e','t','e','s','t',':','d','o','c',0}; static const WCHAR about_blank_url[] = {'a','b','o','u','t',':','b','l','a','n','k',0}; static HRESULT QueryInterface(REFIID riid, void **ppv); static void test_MSHTML_QueryStatus(IUnknown*,DWORD); -static BOOL nogecko = FALSE; #define test_readyState(u) _test_readyState(__LINE__,u) static void _test_readyState(unsigned,IUnknown*); @@ -211,6 +217,30 @@ static int strcmp_wa(LPCWSTR strw, const char *stra) return lstrcmpA(stra, buf); } +static const WCHAR *strstrW( const WCHAR *str, const WCHAR *sub ) +{ + while (*str) + { + const WCHAR *p1 = str, *p2 = sub; + while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; } + if (!*p2) return str; + str++; + } + return NULL; +} + +static BSTR a2bstr(const char *str) +{ + BSTR ret; + int len; + + len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + ret = SysAllocStringLen(NULL, len); + MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); + + return ret; +} + static BOOL is_english(void) { return PRIMARYLANGID(GetSystemDefaultLangID()) == LANG_ENGLISH @@ -652,6 +682,7 @@ static HRESULT WINAPI HlinkFrame_Navigate(IHlinkFrame *iface, DWORD grfHLNF, LPB DWORD site_data = 0xdeadbeef; hres = IHlink_GetTargetFrameName(pihlNavigate, &frame_name); + todo_wine ok(hres == S_FALSE, "GetTargetFrameName failed: %08x\n", hres); ok(frame_name == NULL, "frame_name = %p\n", frame_name); @@ -663,6 +694,7 @@ static HRESULT WINAPI HlinkFrame_Navigate(IHlinkFrame *iface, DWORD grfHLNF, LPB hres = IHlink_GetHlinkSite(pihlNavigate, &site, &site_data); ok(hres == S_OK, "GetHlinkSite failed: %08x\n", hres); ok(site == NULL, "site = %p\n, expected NULL\n", site); + todo_wine ok(site_data == 0xdeadbeef, "site_data = %x\n", site_data); } @@ -749,6 +781,7 @@ static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, D case 1012: CHECK_EXPECT(OnChanged_1012); return S_OK; + case 1030: case 3000029: case 3000030: /* TODO */ @@ -1455,22 +1488,23 @@ static const IOleInPlaceFrameVtbl InPlaceUIWindowVtbl = { static IOleInPlaceFrame InPlaceUIWindow = { &InPlaceUIWindowVtbl }; -static HRESULT WINAPI InPlaceSite_QueryInterface(IOleInPlaceSiteEx *iface, REFIID riid, void **ppv) +static HRESULT WINAPI InPlaceSiteWindowless_QueryInterface(IOleInPlaceSiteWindowless *iface, REFIID riid, void **ppv) { return QueryInterface(riid, ppv); } -static ULONG WINAPI InPlaceSite_AddRef(IOleInPlaceSiteEx *iface) +static ULONG WINAPI InPlaceSiteWindowless_AddRef(IOleInPlaceSiteWindowless *iface) { return 2; } -static ULONG WINAPI InPlaceSite_Release(IOleInPlaceSiteEx *iface) +static ULONG WINAPI InPlaceSiteWindowless_Release(IOleInPlaceSiteWindowless *iface) { return 1; } -static HRESULT WINAPI InPlaceSite_GetWindow(IOleInPlaceSiteEx *iface, HWND *phwnd) +static HRESULT WINAPI InPlaceSiteWindowless_GetWindow( + IOleInPlaceSiteWindowless *iface, HWND *phwnd) { CHECK_EXPECT2(GetWindow); ok(phwnd != NULL, "phwnd = NULL\n"); @@ -1478,32 +1512,38 @@ static HRESULT WINAPI InPlaceSite_GetWindow(IOleInPlaceSiteEx *iface, HWND *phwn return S_OK; } -static HRESULT WINAPI InPlaceSite_ContextSensitiveHelp(IOleInPlaceSiteEx *iface, BOOL fEnterMode) +static HRESULT WINAPI InPlaceSiteWindowless_ContextSensitiveHelp( + IOleInPlaceSiteWindowless *iface, BOOL fEnterMode) { ok(0, "unexpected call\n"); return E_NOTIMPL; } -static HRESULT WINAPI InPlaceSite_CanInPlaceActivate(IOleInPlaceSiteEx *iface) +static HRESULT WINAPI InPlaceSiteWindowless_CanInPlaceActivate( + IOleInPlaceSiteWindowless *iface) { CHECK_EXPECT(CanInPlaceActivate); return S_OK; } -static HRESULT WINAPI InPlaceSite_OnInPlaceActivate(IOleInPlaceSiteEx *iface) +static HRESULT WINAPI InPlaceSiteWindowless_OnInPlaceActivate( + IOleInPlaceSiteWindowless *iface) { CHECK_EXPECT(OnInPlaceActivate); + inplace_deactivated = FALSE; return S_OK; } -static HRESULT WINAPI InPlaceSite_OnUIActivate(IOleInPlaceSiteEx *iface) +static HRESULT WINAPI InPlaceSiteWindowless_OnUIActivate( + IOleInPlaceSiteWindowless *iface) { CHECK_EXPECT(OnUIActivate); return S_OK; } -static HRESULT WINAPI InPlaceSite_GetWindowContext(IOleInPlaceSiteEx *iface, - IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect, +static HRESULT WINAPI InPlaceSiteWindowless_GetWindowContext( + IOleInPlaceSiteWindowless *iface, IOleInPlaceFrame **ppFrame, + IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo) { static const RECT rect = {0,0,500,500}; @@ -1534,44 +1574,52 @@ static HRESULT WINAPI InPlaceSite_GetWindowContext(IOleInPlaceSiteEx *iface, return S_OK; } -static HRESULT WINAPI InPlaceSite_Scroll(IOleInPlaceSiteEx *iface, SIZE scrollExtant) +static HRESULT WINAPI InPlaceSiteWindowless_Scroll( + IOleInPlaceSiteWindowless *iface, SIZE scrollExtent) { ok(0, "unexpected call\n"); return E_NOTIMPL; } -static HRESULT WINAPI InPlaceSite_OnUIDeactivate(IOleInPlaceSiteEx *iface, BOOL fUndoable) +static HRESULT WINAPI InPlaceSiteWindowless_OnUIDeactivate( + IOleInPlaceSiteWindowless *iface, BOOL fUndoable) { CHECK_EXPECT(OnUIDeactivate); ok(!fUndoable, "fUndoable = TRUE\n"); return S_OK; } -static HRESULT WINAPI InPlaceSite_OnInPlaceDeactivate(IOleInPlaceSiteEx *iface) +static HRESULT WINAPI InPlaceSiteWindowless_OnInPlaceDeactivate( + IOleInPlaceSiteWindowless *iface) { CHECK_EXPECT(OnInPlaceDeactivate); + inplace_deactivated = TRUE; return S_OK; } -static HRESULT WINAPI InPlaceSite_DiscardUndoState(IOleInPlaceSiteEx *iface) +static HRESULT WINAPI InPlaceSiteWindowless_DiscardUndoState( + IOleInPlaceSiteWindowless *iface) { ok(0, "unexpected call\n"); return E_NOTIMPL; } -static HRESULT WINAPI InPlaceSite_DeactivateAndUndo(IOleInPlaceSiteEx *iface) +static HRESULT WINAPI InPlaceSiteWindowless_DeactivateAndUndo( + IOleInPlaceSiteWindowless *iface) { ok(0, "unexpected call\n"); return E_NOTIMPL; } -static HRESULT WINAPI InPlaceSite_OnPosRectChange(IOleInPlaceSiteEx *iface, LPCRECT lprcPosRect) +static HRESULT WINAPI InPlaceSiteWindowless_OnPosRectChange( + IOleInPlaceSiteWindowless *iface, LPCRECT lprcPosRect) { ok(0, "unexpected call\n"); return E_NOTIMPL; } -static HRESULT WINAPI InPlaceSiteEx_OnInPlaceActivateEx(IOleInPlaceSiteEx *iface, BOOL *pfNoRedraw, DWORD dwFlags) +static HRESULT WINAPI InPlaceSiteWindowless_OnInPlaceActivateEx( + IOleInPlaceSiteWindowless *iface, BOOL *pfNoRedraw, DWORD dwFlags) { CHECK_EXPECT(OnInPlaceActivateEx); @@ -1582,7 +1630,8 @@ static HRESULT WINAPI InPlaceSiteEx_OnInPlaceActivateEx(IOleInPlaceSiteEx *iface return S_OK; } -static HRESULT WINAPI InPlaceSiteEx_OnInPlaceDeactivateEx(IOleInPlaceSiteEx *iface, BOOL fNoRedraw) +static HRESULT WINAPI InPlaceSiteWindowless_OnInPlaceDeactivateEx( + IOleInPlaceSiteWindowless *iface, BOOL fNoRedraw) { CHECK_EXPECT(OnInPlaceDeactivateEx); @@ -1591,34 +1640,134 @@ static HRESULT WINAPI InPlaceSiteEx_OnInPlaceDeactivateEx(IOleInPlaceSiteEx *ifa return S_OK; } -static HRESULT WINAPI InPlaceSiteEx_RequestUIActivate(IOleInPlaceSiteEx *iface) +static HRESULT WINAPI InPlaceSiteWindowless_RequestUIActivate( + IOleInPlaceSiteWindowless *iface) { - CHECK_EXPECT(RequestUIActivate); + CHECK_EXPECT2(RequestUIActivate); return S_OK; } -static const IOleInPlaceSiteExVtbl InPlaceSiteVtbl = { - InPlaceSite_QueryInterface, - InPlaceSite_AddRef, - InPlaceSite_Release, - InPlaceSite_GetWindow, - InPlaceSite_ContextSensitiveHelp, - InPlaceSite_CanInPlaceActivate, - InPlaceSite_OnInPlaceActivate, - InPlaceSite_OnUIActivate, - InPlaceSite_GetWindowContext, - InPlaceSite_Scroll, - InPlaceSite_OnUIDeactivate, - InPlaceSite_OnInPlaceDeactivate, - InPlaceSite_DiscardUndoState, - InPlaceSite_DeactivateAndUndo, - InPlaceSite_OnPosRectChange, - InPlaceSiteEx_OnInPlaceActivateEx, - InPlaceSiteEx_OnInPlaceDeactivateEx, - InPlaceSiteEx_RequestUIActivate +static HRESULT WINAPI InPlaceSiteWindowless_CanWindowlessActivate( + IOleInPlaceSiteWindowless *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceSiteWindowless_GetCapture( + IOleInPlaceSiteWindowless *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceSiteWindowless_SetCapture( + IOleInPlaceSiteWindowless *iface, BOOL fCapture) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceSiteWindowless_GetFocus( + IOleInPlaceSiteWindowless *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceSiteWindowless_SetFocus( + IOleInPlaceSiteWindowless *iface, BOOL fFocus) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceSiteWindowless_GetDC( + IOleInPlaceSiteWindowless *iface, LPCRECT pRect, + DWORD grfFlags, HDC *phDC) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceSiteWindowless_ReleaseDC( + IOleInPlaceSiteWindowless *iface, HDC hDC) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceSiteWindowless_InvalidateRect( + IOleInPlaceSiteWindowless *iface, LPCRECT pRect, BOOL fErase) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceSiteWindowless_InvalidateRgn( + IOleInPlaceSiteWindowless *iface, HRGN hRGN, BOOL fErase) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceSiteWindowless_ScrollRect( + IOleInPlaceSiteWindowless *iface, INT dx, INT dy, + LPCRECT pRectScroll, LPCRECT pRectClip) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceSiteWindowless_AdjustRect( + IOleInPlaceSiteWindowless *iface, LPRECT prc) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceSiteWindowless_OnDefWindowMessage( + IOleInPlaceSiteWindowless *iface, UINT msg, + WPARAM wParam, LPARAM lParam, LRESULT *plResult) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const IOleInPlaceSiteWindowlessVtbl InPlaceSiteWindowlessVtbl = { + InPlaceSiteWindowless_QueryInterface, + InPlaceSiteWindowless_AddRef, + InPlaceSiteWindowless_Release, + InPlaceSiteWindowless_GetWindow, + InPlaceSiteWindowless_ContextSensitiveHelp, + InPlaceSiteWindowless_CanInPlaceActivate, + InPlaceSiteWindowless_OnInPlaceActivate, + InPlaceSiteWindowless_OnUIActivate, + InPlaceSiteWindowless_GetWindowContext, + InPlaceSiteWindowless_Scroll, + InPlaceSiteWindowless_OnUIDeactivate, + InPlaceSiteWindowless_OnInPlaceDeactivate, + InPlaceSiteWindowless_DiscardUndoState, + InPlaceSiteWindowless_DeactivateAndUndo, + InPlaceSiteWindowless_OnPosRectChange, + InPlaceSiteWindowless_OnInPlaceActivateEx, + InPlaceSiteWindowless_OnInPlaceDeactivateEx, + InPlaceSiteWindowless_RequestUIActivate, + InPlaceSiteWindowless_CanWindowlessActivate, + InPlaceSiteWindowless_GetCapture, + InPlaceSiteWindowless_SetCapture, + InPlaceSiteWindowless_GetFocus, + InPlaceSiteWindowless_SetFocus, + InPlaceSiteWindowless_GetDC, + InPlaceSiteWindowless_ReleaseDC, + InPlaceSiteWindowless_InvalidateRect, + InPlaceSiteWindowless_InvalidateRgn, + InPlaceSiteWindowless_ScrollRect, + InPlaceSiteWindowless_AdjustRect, + InPlaceSiteWindowless_OnDefWindowMessage }; -static IOleInPlaceSiteEx InPlaceSiteEx = { &InPlaceSiteVtbl }; +static IOleInPlaceSiteWindowless InPlaceSiteWindowless = { &InPlaceSiteWindowlessVtbl }; static HRESULT WINAPI ClientSite_QueryInterface(IOleClientSite *iface, REFIID riid, void **ppv) { @@ -1723,7 +1872,7 @@ static HRESULT WINAPI DocumentSite_ActivateMe(IOleDocumentSite *iface, IOleDocum ok(hres == S_OK, "could not get IOleDocument: %08x\n", hres); if(SUCCEEDED(hres)) { - hres = IOleDocument_CreateView(document, (IOleInPlaceSite*)&InPlaceSiteEx, NULL, 0, &view); + hres = IOleDocument_CreateView(document, (IOleInPlaceSite*)&InPlaceSiteWindowless, NULL, 0, &view); ok(hres == S_OK, "CreateView failed: %08x\n", hres); if(SUCCEEDED(hres)) { @@ -1734,16 +1883,16 @@ static HRESULT WINAPI DocumentSite_ActivateMe(IOleDocumentSite *iface, IOleDocum hres = IOleDocumentView_GetInPlaceSite(view, &inplacesite); ok(hres == S_OK, "GetInPlaceSite failed: %08x\n", hres); - ok(inplacesite == (IOleInPlaceSite*)&InPlaceSiteEx, "inplacesite=%p, expected %p\n", - inplacesite, &InPlaceSiteEx); + ok(inplacesite == (IOleInPlaceSite*)&InPlaceSiteWindowless, "inplacesite=%p, expected %p\n", + inplacesite, &InPlaceSiteWindowless); - hres = IOleDocumentView_SetInPlaceSite(view, (IOleInPlaceSite*)&InPlaceSiteEx); + hres = IOleDocumentView_SetInPlaceSite(view, (IOleInPlaceSite*)&InPlaceSiteWindowless); ok(hres == S_OK, "SetInPlaceSite failed: %08x\n", hres); hres = IOleDocumentView_GetInPlaceSite(view, &inplacesite); ok(hres == S_OK, "GetInPlaceSite failed: %08x\n", hres); - ok(inplacesite == (IOleInPlaceSite*)&InPlaceSiteEx, "inplacesite=%p, expected %p\n", - inplacesite, &InPlaceSiteEx); + ok(inplacesite == (IOleInPlaceSite*)&InPlaceSiteWindowless, "inplacesite=%p, expected %p\n", + inplacesite, &InPlaceSiteWindowless); hres = IOleDocumentView_QueryInterface(view, &IID_IOleInPlaceActiveObject, (void**)&activeobj); ok(hres == S_OK, "Could not get IOleInPlaceActiveObject: %08x\n", hres); @@ -2092,8 +2241,13 @@ static HRESULT WINAPI DocHostUIHandler_GetExternal(IDocHostUIHandler2 *iface, ID static HRESULT WINAPI DocHostUIHandler_TranslateUrl(IDocHostUIHandler2 *iface, DWORD dwTranslate, OLECHAR *pchURLIn, OLECHAR **ppchURLOut) { - ok(0, "unexpected call\n"); - return E_NOTIMPL; + CHECK_EXPECT(TranslateUrl); + ok(!dwTranslate, "dwTranslate = %x\n", dwTranslate); + ok(!strcmp_wa(pchURLIn, "about:blank"), "pchURLIn = %s\n", wine_dbgstr_w(pchURLIn)); + ok(ppchURLOut != NULL, "ppchURLOut == NULL\n"); + ok(!*ppchURLOut, "*ppchURLOut = %p\n", *ppchURLOut); + + return S_FALSE; } static HRESULT WINAPI DocHostUIHandler_FilterDataObject(IDocHostUIHandler2 *iface, IDataObject *pDO, @@ -2216,6 +2370,8 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID ok(nCmdexecopt == 0, "nCmdexecopts=%08x\n", nCmdexecopt); ok(pvaOut == NULL, "pvaOut=%p\n", pvaOut); ok(pvaIn == NULL, "pvaIn=%p\n", pvaIn); + readystate_set_loading = FALSE; + readystate_set_interactive = FALSE; load_state = LD_COMPLETE; return S_OK; case OLECMDID_SETDOWNLOADSTATE: @@ -2508,6 +2664,62 @@ static const IServiceProviderVtbl ServiceProviderVtbl = { static IServiceProvider ServiceProvider = { &ServiceProviderVtbl }; +static HRESULT WINAPI AdviseSink_QueryInterface(IAdviseSink *iface, + REFIID riid, void **ppv) +{ + return QueryInterface(riid, ppv); +} + +static ULONG WINAPI AdviseSink_AddRef(IAdviseSink *iface) +{ + return 2; +} + +static ULONG WINAPI AdviseSink_Release(IAdviseSink *iface) +{ + return 1; +} + +static void WINAPI AdviseSink_OnDataChange(IAdviseSink *iface, + FORMATETC *pFormatetc, STGMEDIUM *pStgmed) +{ + ok(0, "unexpected call\n"); +} + +static void WINAPI AdviseSink_OnViewChange(IAdviseSink *iface, + DWORD dwAspect, LONG lindex) +{ + ok(0, "unexpected call\n"); +} + +static void WINAPI AdviseSink_OnRename(IAdviseSink *iface, IMoniker *pmk) +{ + ok(0, "unexpected call\n"); +} + +static void WINAPI AdviseSink_OnSave(IAdviseSink *iface) +{ + ok(0, "unexpected call\n"); +} + +static void WINAPI AdviseSink_OnClose(IAdviseSink *iface) +{ + CHECK_EXPECT(Advise_Close); +} + +static const IAdviseSinkVtbl AdviseSinkVtbl = { + AdviseSink_QueryInterface, + AdviseSink_AddRef, + AdviseSink_Release, + AdviseSink_OnDataChange, + AdviseSink_OnViewChange, + AdviseSink_OnRename, + AdviseSink_OnSave, + AdviseSink_OnClose +}; + +static IAdviseSink AdviseSink = { &AdviseSinkVtbl }; + DEFINE_GUID(IID_unk1, 0xD48A6EC6,0x6A4A,0x11CF,0x94,0xA7,0x44,0x45,0x53,0x54,0x00,0x00); /* HTMLWindow2 ? */ DEFINE_GUID(IID_IThumbnailView, 0x7BB0B520,0xB1A7,0x11D2,0xBB,0x23,0x00,0xC0,0x4F,0x79,0xAB,0xCD); DEFINE_GUID(IID_IRenMailEditor, 0x000670BA,0x0000,0x0000,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46); @@ -2527,7 +2739,7 @@ static HRESULT QueryInterface(REFIID riid, void **ppv) else if(IsEqualGUID(&IID_IOleContainer, riid)) *ppv = &OleContainer; else if(IsEqualGUID(&IID_IOleWindow, riid) || IsEqualGUID(&IID_IOleInPlaceSite, riid)) - *ppv = &InPlaceSiteEx; + *ppv = &InPlaceSiteWindowless; else if(IsEqualGUID(&IID_IOleCommandTarget , riid)) *ppv = &OleCommandTarget; else if(IsEqualGUID(&IID_IDispatch, riid)) @@ -2535,7 +2747,9 @@ static HRESULT QueryInterface(REFIID riid, void **ppv) else if(IsEqualGUID(&IID_IServiceProvider, riid)) *ppv = &ServiceProvider; else if(IsEqualGUID(&IID_IOleInPlaceSiteEx, riid)) - *ppv = ipsex ? &InPlaceSiteEx : NULL; + *ppv = ipsex ? &InPlaceSiteWindowless : NULL; + else if(IsEqualGUID(&IID_IOleInPlaceSiteWindowless, riid)) + *ppv = ipsw ? &InPlaceSiteWindowless : NULL; else if(IsEqualGUID(&IID_IOleControlSite, riid)) *ppv = &OleControlSite; else if(IsEqualGUID(&IID_IDocHostShowUI, riid)) @@ -2565,10 +2779,58 @@ static LRESULT WINAPI wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam return DefWindowProc(hwnd, msg, wParam, lParam); } +static void test_doscroll(IUnknown *unk) +{ + IHTMLDocument3 *doc; + IHTMLElement2 *elem2; + IHTMLElement *elem; + VARIANT v; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IHTMLDocument3, (void**)&doc); + ok(hres == S_OK, "Could not get IHTMLDocument3 iface: %08x\n", hres); + if(FAILED(hres)) + return; + + hres = IHTMLDocument3_get_documentElement(doc, &elem); + IHTMLDocument3_Release(doc); + ok(hres == S_OK, "get_documentElement failed: %08x\n", hres); + switch(load_state) { + case LD_DOLOAD: + case LD_NO: + ok(!elem, "elem != NULL\n"); + default: + break; + case LD_INTERACTIVE: + case LD_COMPLETE: + ok(elem != NULL, "elem == NULL\n"); + } + if(!elem) + return; + + hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLElement2, (void**)&elem2); + IHTMLElement_Release(elem); + ok(hres == S_OK, "Could not get IHTMLElement2 iface: %08x\n", hres); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("left"); + hres = IHTMLElement2_doScroll(elem2, v); + SysFreeString(V_BSTR(&v)); + IHTMLElement2_Release(elem2); + + if(inplace_deactivated) + ok(hres == E_PENDING, "doScroll failed: %08x\n", hres); + else if(load_state == LD_COMPLETE) + ok(hres == S_OK, "doScroll failed: %08x\n", hres); + else + ok(hres == E_PENDING || hres == S_OK, "doScroll failed: %08x\n", hres); +} + static void _test_readyState(unsigned line, IUnknown *unk) { IHTMLDocument2 *htmldoc; DISPPARAMS dispparams; + IHTMLElement *elem; BSTR state; VARIANT out; HRESULT hres; @@ -2604,6 +2866,26 @@ static void _test_readyState(unsigned line, IUnknown *unk) wine_dbgstr_w(state), load_state); SysFreeString(state); + hres = IHTMLDocument2_get_body(htmldoc, &elem); + ok_(__FILE__,line)(hres == S_OK, "get_body failed: %08x\n", hres); + if(elem) { + IHTMLElement2 *elem2; + VARIANT var; + + hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLElement2, (void**)&elem2); + IHTMLElement_Release(elem); + ok(hres == S_OK, "Could not get IHTMLElement2 iface: %08x\n", hres); + + hres = IHTMLElement2_get_readyState(elem2, &var); + IHTMLElement2_Release(elem2); + ok(hres == S_OK, "get_readyState failed: %08x\n", hres); + ok(V_VT(&var) == VT_BSTR, "V_VT(state) = %d\n", V_VT(&var)); + ok(!strcmp_wa(V_BSTR(&var), "complete"), "unexpected body state %s\n", wine_dbgstr_w(V_BSTR(&var))); + VariantClear(&var); + }else { + ok_(__FILE__,line)(load_state != LD_COMPLETE, "body is NULL in complete state\n"); + } + dispparams.cArgs = 0; dispparams.cNamedArgs = 0; dispparams.rgdispidNamedArgs = NULL; @@ -2618,6 +2900,8 @@ static void _test_readyState(unsigned line, IUnknown *unk) ok_(__FILE__,line) (V_VT(&out) == VT_I4, "V_VT(out)=%d\n", V_VT(&out)); ok_(__FILE__,line) (V_I4(&out) == load_state%5, "VT_I4(out)=%d, expected %d\n", V_I4(&out), load_state%5); + test_doscroll((IUnknown*)htmldoc); + IHTMLDocument2_Release(htmldoc); } @@ -2669,6 +2953,7 @@ static void test_ConnectionPointContainer(IUnknown *unk) if(FAILED(hres)) return; + test_ConnectionPoint(container, &IID_IDispatch); test_ConnectionPoint(container, &IID_IPropertyNotifySink); test_ConnectionPoint(container, &DIID_HTMLDocumentEvents); test_ConnectionPoint(container, &DIID_HTMLDocumentEvents2); @@ -2780,6 +3065,7 @@ static void test_Load(IPersistMoniker *persist, IMoniker *mon) #define DWL_CSS 0x0002 #define DWL_TRYCSS 0x0004 #define DWL_HTTP 0x0008 +#define DWL_EMPTY 0x0010 static void test_download(DWORD flags) { @@ -2796,7 +3082,8 @@ static void test_download(DWORD flags) if((flags & DWL_VERBDONE) && !load_from_stream) SET_EXPECT(GetHostInfo); SET_EXPECT(SetStatusText); - SET_EXPECT(Exec_SETDOWNLOADSTATE_1); + if(!(flags & DWL_EMPTY)) + SET_EXPECT(Exec_SETDOWNLOADSTATE_1); SET_EXPECT(GetDropTarget); if(flags & DWL_TRYCSS) SET_EXPECT(Exec_ShellDocView_84); @@ -2821,7 +3108,8 @@ static void test_download(DWORD flags) SET_EXPECT(OnChanged_1005); SET_EXPECT(OnChanged_READYSTATE); SET_EXPECT(Exec_SETPROGRESSPOS); - SET_EXPECT(Exec_SETDOWNLOADSTATE_0); + if(!(flags & DWL_EMPTY)) + SET_EXPECT(Exec_SETDOWNLOADSTATE_0); SET_EXPECT(Exec_ShellDocView_103); SET_EXPECT(Exec_ShellDocView_105); SET_EXPECT(Exec_ShellDocView_140); @@ -2842,31 +3130,18 @@ static void test_download(DWORD flags) if((flags & DWL_VERBDONE) && !load_from_stream) CHECK_CALLED(GetHostInfo); CHECK_CALLED(SetStatusText); - CHECK_CALLED(Exec_SETDOWNLOADSTATE_1); + if(!(flags & DWL_EMPTY)) + CHECK_CALLED(Exec_SETDOWNLOADSTATE_1); CHECK_CALLED(GetDropTarget); if(flags & DWL_TRYCSS) SET_CALLED(Exec_ShellDocView_84); if(flags & DWL_CSS) { - if(called_CreateInstance) { - CHECK_CALLED(CreateInstance); - CHECK_CALLED(Start); - CHECK_CALLED(LockRequest); - CHECK_CALLED(Terminate); - CHECK_CALLED(Protocol_Read); - CHECK_CALLED(UnlockRequest); - }else { - skip("CreateInstance not called. Assuming no Gecko installed.\n"); - - SET_CALLED(Exec_ShellDocView_84); - SET_CALLED(CreateInstance); - SET_CALLED(Start); - SET_CALLED(LockRequest); - SET_CALLED(Terminate); - SET_CALLED(Protocol_Read); - SET_CALLED(UnlockRequest); - - nogecko = TRUE; - } + CHECK_CALLED(CreateInstance); + CHECK_CALLED(Start); + CHECK_CALLED(LockRequest); + CHECK_CALLED(Terminate); + CHECK_CALLED(Protocol_Read); + CHECK_CALLED(UnlockRequest); } SET_CALLED(Exec_Explorer_69); SET_CALLED(EnableModeless_TRUE); /* IE7 */ @@ -2881,7 +3156,8 @@ static void test_download(DWORD flags) CHECK_CALLED(OnChanged_1005); CHECK_CALLED(OnChanged_READYSTATE); CHECK_CALLED(Exec_SETPROGRESSPOS); - CHECK_CALLED(Exec_SETDOWNLOADSTATE_0); + if(!(flags & DWL_EMPTY)) + CHECK_CALLED(Exec_SETDOWNLOADSTATE_0); SET_CALLED(Exec_ShellDocView_103); SET_CALLED(Exec_ShellDocView_105); SET_CALLED(Exec_ShellDocView_140); @@ -2933,6 +3209,34 @@ static void test_Persist(IUnknown *unk, IMoniker *mon) } } +static void test_put_href(IUnknown *unk) +{ + IHTMLLocation *location; + IHTMLDocument2 *doc; + BSTR str; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IHTMLDocument2, (void**)&doc); + ok(hres == S_OK, "Could not get IHTMLDocument2 iface: %08x\n", hres); + + location = NULL; + hres = IHTMLDocument2_get_location(doc, &location); + IHTMLDocument2_Release(doc); + ok(hres == S_OK, "get_location failed: %08x\n", hres); + ok(location != NULL, "location == NULL\n"); + + SET_EXPECT(TranslateUrl); + SET_EXPECT(Navigate); + str = a2bstr("about:blank"); + hres = IHTMLLocation_put_href(location, str); + SysFreeString(str); + ok(hres == S_OK, "put_href failed: %08x\n", hres); + CHECK_CALLED(TranslateUrl); + CHECK_CALLED(Navigate); + + IHTMLLocation_Release(location); +} + static const OLECMDF expect_cmds[OLECMDID_GETPRINTTEMPLATE+1] = { 0, OLECMDF_SUPPORTED, /* OLECMDID_OPEN */ @@ -3227,13 +3531,12 @@ static void test_exec_fontname(IUnknown *unk, LPCWSTR name, LPCWSTR exname) } hres = IOleCommandTarget_Exec(cmdtrg, &CGID_MSHTML, IDM_FONTNAME, 0, in, out); - if(!nogecko) - ok(hres == S_OK, "Exec(IDM_FONTNAME) failed: %08x\n", hres); + ok(hres == S_OK, "Exec(IDM_FONTNAME) failed: %08x\n", hres); if(in) VariantClear(in); - if(out && !nogecko) { + if(out) { ok(V_VT(out) == VT_BSTR, "V_VT(out) = %x\n", V_VT(out)); if(V_VT(out) == VT_BSTR) { if(exname) @@ -3503,6 +3806,54 @@ static void test_Close(IUnknown *unk, BOOL set_client) IOleObject_Release(oleobj); } +static void test_Advise(IUnknown *unk) +{ + IOleObject *oleobj = NULL; + IEnumSTATDATA *enum_advise = (void*)0xdeadbeef; + DWORD conn; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IOleObject, (void**)&oleobj); + ok(hres == S_OK, "QueryInterface(IID_IOleObject) failed: %08x\n", hres); + if(FAILED(hres)) + return; + + hres = IOleObject_Unadvise(oleobj, 0); + ok(hres == OLE_E_NOCONNECTION, "Unadvise returned: %08x\n", hres); + + hres = IOleObject_EnumAdvise(oleobj, &enum_advise); + ok(hres == S_OK, "EnumAdvise returned: %08x\n", hres); + ok(enum_advise == NULL, "enum_advise != NULL\n"); + + conn = -1; + hres = IOleObject_Advise(oleobj, NULL, &conn); + /* Old IE returns S_OK and sets conn to 1 */ + ok(hres == E_INVALIDARG || hres == S_OK, "Advise returned: %08x\n", hres); + ok(conn == 0 || conn == 1, "conn = %d\n", conn); + + hres = IOleObject_Advise(oleobj, &AdviseSink, NULL); + ok(hres == E_INVALIDARG, "Advise returned: %08x\n", hres); + + hres = IOleObject_Advise(oleobj, &AdviseSink, &conn); + ok(hres == S_OK, "Advise returned: %08x\n", hres); + ok(conn == 1, "conn = %d\n", conn); + + hres = IOleObject_Advise(oleobj, &AdviseSink, &conn); + ok(hres == S_OK, "Advise returned: %08x\n", hres); + ok(conn == 2, "conn = %d\n", conn); + + hres = IOleObject_Unadvise(oleobj, 1); + ok(hres == S_OK, "Unadvise returned: %08x\n", hres); + + hres = IOleObject_Unadvise(oleobj, 1); + ok(hres == OLE_E_NOCONNECTION, "Unadvise returned: %08x\n", hres); + + hres = IOleObject_Unadvise(oleobj, 2); + ok(hres == S_OK, "Unadvise returned: %08x\n", hres); + + IOleObject_Release(oleobj); +} + static void test_OnFrameWindowActivate(IUnknown *unk) { IOleInPlaceActiveObject *inplaceact; @@ -3818,6 +4169,36 @@ static void test_StreamLoad(IUnknown *unk) IPersistStreamInit_Release(init); } +static void test_StreamInitNew(IUnknown *unk) +{ + IPersistStreamInit *init; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IPersistStreamInit, (void**)&init); + ok(hres == S_OK, "QueryInterface(IID_IPersistStreamInit) failed: %08x\n", hres); + if(FAILED(hres)) + return; + + SET_EXPECT(Invoke_AMBIENT_SILENT); + SET_EXPECT(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); + SET_EXPECT(Exec_ShellDocView_37); + SET_EXPECT(OnChanged_READYSTATE); + readystate_set_loading = TRUE; + + hres = IPersistStreamInit_InitNew(init); + ok(hres == S_OK, "Load failed: %08x\n", hres); + + CHECK_CALLED(Invoke_AMBIENT_SILENT); + CHECK_CALLED(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); + CHECK_CALLED(Exec_ShellDocView_37); + CHECK_CALLED(OnChanged_READYSTATE); + + test_timer(EXPECT_SETTITLE); + test_GetCurMoniker(unk, NULL, about_blank_url); + + IPersistStreamInit_Release(init); +} + static void test_QueryInterface(IUnknown *unk) { IUnknown *qi; @@ -3868,6 +4249,7 @@ static void init_test(enum load_state_t ls) { stream_read = 0; protocol_read = 0; ipsex = FALSE; + inplace_deactivated = FALSE; } static void test_HTMLDocument(BOOL do_load) @@ -3886,6 +4268,7 @@ static void test_HTMLDocument(BOOL do_load) doc_unk = unk; test_QueryInterface(unk); + test_Advise(unk); test_IsDirty(unk, S_FALSE); test_MSHTML_QueryStatus(unk, OLECMDF_SUPPORTED); test_external(unk, FALSE); @@ -4013,6 +4396,63 @@ static void test_HTMLDocument_hlink(void) ok(ref == 0, "ref=%d, expected 0\n", ref); } +static void test_cookies(IUnknown *unk) +{ + WCHAR buf[1024]; + IHTMLDocument2 *doc; + DWORD size; + BSTR str, str2; + BOOL b; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IHTMLDocument2, (void**)&doc); + ok(hres == S_OK, "QueryInterface(IID_IHTMLDocument2) failed: %08x\n", hres); + + hres = IHTMLDocument2_get_cookie(doc, &str); + ok(hres == S_OK, "get_cookie failed: %08x\n", hres); + if(str) { + size = sizeof(buf)/sizeof(WCHAR); + b = InternetGetCookieW(http_urlW, NULL, buf, &size); + ok(b, "InternetGetCookieW failed: %08x\n", GetLastError()); + ok(!lstrcmpW(buf, str), "cookie = %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buf)); + SysFreeString(str); + } + + str = a2bstr("test=testval"); + hres = IHTMLDocument2_put_cookie(doc, str); + ok(hres == S_OK, "put_cookie failed: %08x\n", hres); + + str2 = NULL; + hres = IHTMLDocument2_get_cookie(doc, &str2); + ok(hres == S_OK, "get_cookie failed: %08x\n", hres); + ok(str2 != NULL, "cookie = NULL\n"); + size = sizeof(buf)/sizeof(WCHAR); + b = InternetGetCookieW(http_urlW, NULL, buf, &size); + ok(b, "InternetGetCookieW failed: %08x\n", GetLastError()); + ok(!lstrcmpW(buf, str2), "cookie = %s, expected %s\n", wine_dbgstr_w(str2), wine_dbgstr_w(buf)); + ok(strstrW(str2, str) != NULL, "could not find %s in %s\n", wine_dbgstr_w(str), wine_dbgstr_w(str2)); + SysFreeString(str); + SysFreeString(str2); + + str = a2bstr("test=testval2"); + hres = IHTMLDocument2_put_cookie(doc, str); + ok(hres == S_OK, "put_cookie failed: %08x\n", hres); + + str2 = NULL; + hres = IHTMLDocument2_get_cookie(doc, &str2); + ok(hres == S_OK, "get_cookie failed: %08x\n", hres); + ok(str2 != NULL, "cookie = NULL\n"); + size = sizeof(buf)/sizeof(WCHAR); + b = InternetGetCookieW(http_urlW, NULL, buf, &size); + ok(b, "InternetGetCookieW failed: %08x\n", GetLastError()); + ok(!lstrcmpW(buf, str2), "cookie = %s, expected %s\n", wine_dbgstr_w(str2), wine_dbgstr_w(buf)); + ok(strstrW(str2, str) != NULL, "could not find %s in %s\n", wine_dbgstr_w(str), wine_dbgstr_w(str2)); + SysFreeString(str); + SysFreeString(str2); + + IHTMLDocument2_Release(doc); +} + static void test_HTMLDocument_http(void) { IMoniker *http_mon; @@ -4020,9 +4460,6 @@ static void test_HTMLDocument_http(void) ULONG ref; HRESULT hres; - static const WCHAR http_urlW[] = - {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',0}; - trace("Testing HTMLDocument (http)...\n"); hres = CreateURLMoniker(NULL, http_urlW, &http_mon); @@ -4050,9 +4487,12 @@ static void test_HTMLDocument_http(void) else win_skip("IE running in Enhanced Security Configuration\n"); + test_cookies(unk); test_IsDirty(unk, S_FALSE); test_MSHTML_QueryStatus(unk, OLECMDF_SUPPORTED); + test_put_href(unk); + test_InPlaceDeactivate(unk, TRUE); test_Close(unk, FALSE); test_IsDirty(unk, S_FALSE); @@ -4069,10 +4509,29 @@ static void test_HTMLDocument_http(void) ok(!ref, "ref=%d, expected 0\n", ref); } +static void test_QueryService(IUnknown *unk, BOOL success) +{ + IServiceProvider *sp; + IHlinkFrame *hf; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IServiceProvider, (void**)&sp); + ok(hres == S_OK, "QueryService returned %08x\n", hres); + + hres = IServiceProvider_QueryService(sp, &IID_IHlinkFrame, &IID_IHlinkFrame, (void**)&hf); + if(SUCCEEDED(hres)) + IHlinkFrame_Release(hf); + + ok(hres == (success?S_OK:E_NOINTERFACE), "QueryService returned %08x, expected %08x\n", hres, success?S_OK:E_NOINTERFACE); + + IServiceProvider_Release(sp); +} + static void test_HTMLDocument_StreamLoad(void) { IOleObject *oleobj; IUnknown *unk; + DWORD conn; HRESULT hres; ULONG ref; @@ -4089,10 +4548,15 @@ static void test_HTMLDocument_StreamLoad(void) hres = IUnknown_QueryInterface(unk, &IID_IOleObject, (void**)&oleobj); ok(hres == S_OK, "Could not get IOleObject: %08x\n", hres); + hres = IOleObject_Advise(oleobj, &AdviseSink, &conn); + ok(hres == S_OK, "Advise failed: %08x\n", hres); + test_readyState(unk); test_IsDirty(unk, S_FALSE); test_ConnectionPointContainer(unk); + test_QueryService(unk, FALSE); test_ClientSite(oleobj, CLIENTSITE_EXPECTPATH); + test_QueryService(unk, TRUE); test_DoVerb(oleobj); test_MSHTML_QueryStatus(unk, OLECMDF_SUPPORTED); @@ -4105,7 +4569,64 @@ static void test_HTMLDocument_StreamLoad(void) test_UIDeactivate(); test_InPlaceDeactivate(unk, TRUE); + SET_EXPECT(Advise_Close); + test_Close(unk, FALSE); + CHECK_CALLED(Advise_Close); + test_IsDirty(unk, S_FALSE); + + if(view) { + IOleDocumentView_Release(view); + view = NULL; + } + + + ref = IUnknown_Release(unk); + ok(ref == 0, "ref=%d, expected 0\n", ref); +} + +static void test_HTMLDocument_StreamInitNew(void) +{ + IOleObject *oleobj; + IUnknown *unk; + DWORD conn; + HRESULT hres; + ULONG ref; + + trace("Testing HTMLDocument (IPersistStreamInit)...\n"); + + init_test(LD_DOLOAD); + load_from_stream = TRUE; + + hres = create_document(&unk); + if(FAILED(hres)) + return; + doc_unk = unk; + + hres = IUnknown_QueryInterface(unk, &IID_IOleObject, (void**)&oleobj); + ok(hres == S_OK, "Could not get IOleObject: %08x\n", hres); + + hres = IOleObject_Advise(oleobj, &AdviseSink, &conn); + ok(hres == S_OK, "Advise failed: %08x\n", hres); + + test_readyState(unk); + test_IsDirty(unk, S_FALSE); + test_ConnectionPointContainer(unk); + test_ClientSite(oleobj, CLIENTSITE_EXPECTPATH); + test_DoVerb(oleobj); + test_MSHTML_QueryStatus(unk, OLECMDF_SUPPORTED); + + IOleObject_Release(oleobj); + + test_GetCurMoniker(unk, NULL, NULL); + test_StreamInitNew(unk); + test_download(DWL_VERBDONE|DWL_TRYCSS|DWL_EMPTY); + test_MSHTML_QueryStatus(unk, OLECMDF_SUPPORTED); + + test_UIDeactivate(); + test_InPlaceDeactivate(unk, TRUE); + SET_EXPECT(Advise_Close); test_Close(unk, FALSE); + CHECK_CALLED(Advise_Close); test_IsDirty(unk, S_FALSE); if(view) { @@ -4149,6 +4670,7 @@ static void test_editing_mode(BOOL do_load) { IUnknown *unk; IOleObject *oleobj; + DWORD conn; HRESULT hres; ULONG ref; @@ -4165,6 +4687,9 @@ static void test_editing_mode(BOOL do_load) hres = IUnknown_QueryInterface(unk, &IID_IOleObject, (void**)&oleobj); ok(hres == S_OK, "Could not get IOleObject: %08x\n", hres); + hres = IOleObject_Advise(oleobj, &AdviseSink, &conn); + ok(hres == S_OK, "Advise failed: %08x\n", hres); + test_readyState(unk); test_ConnectionPointContainer(unk); test_ClientSite(oleobj, CLIENTSITE_EXPECTPATH); @@ -4197,17 +4722,15 @@ static void test_editing_mode(BOOL do_load) test_exec_noargs(unk, IDM_JUSTIFYRIGHT); test_timer(EXPECT_UPDATEUI); - if(!nogecko) - test_QueryStatus(unk, &CGID_MSHTML, IDM_JUSTIFYRIGHT, - OLECMDF_SUPPORTED|OLECMDF_ENABLED|OLECMDF_LATCHED); + test_QueryStatus(unk, &CGID_MSHTML, IDM_JUSTIFYRIGHT, + OLECMDF_SUPPORTED|OLECMDF_ENABLED|OLECMDF_LATCHED); test_exec_noargs(unk, IDM_JUSTIFYCENTER); test_timer(EXPECT_UPDATEUI); test_QueryStatus(unk, &CGID_MSHTML, IDM_JUSTIFYRIGHT, OLECMDF_SUPPORTED|OLECMDF_ENABLED); - if(!nogecko) - test_QueryStatus(unk, &CGID_MSHTML, IDM_JUSTIFYCENTER, - OLECMDF_SUPPORTED|OLECMDF_ENABLED|OLECMDF_LATCHED); + test_QueryStatus(unk, &CGID_MSHTML, IDM_JUSTIFYCENTER, + OLECMDF_SUPPORTED|OLECMDF_ENABLED|OLECMDF_LATCHED); test_exec_noargs(unk, IDM_HORIZONTALLINE); test_timer(EXPECT_UPDATEUI); @@ -4217,7 +4740,9 @@ static void test_editing_mode(BOOL do_load) test_UIDeactivate(); test_InPlaceDeactivate(unk, TRUE); + SET_EXPECT(Advise_Close); test_Close(unk, FALSE); + CHECK_CALLED(Advise_Close); if(view) { IOleDocumentView_Release(view); @@ -4228,51 +4753,171 @@ static void test_editing_mode(BOOL do_load) ok(ref == 0, "ref=%d, expected 0\n", ref); } -static void register_protocol(void) +static void test_UIActivate(BOOL do_load, BOOL use_ipsex, BOOL use_ipsw) { - IInternetSession *session; + IUnknown *unk; + IOleObject *oleobj; + IOleInPlaceSite *inplacesite; HRESULT hres; + ULONG ref; - static const WCHAR wsz_winetest[] = {'w','i','n','e','t','e','s','t',0}; + trace("Running OleDocumentView_UIActivate tests (%d %d %d)\n", do_load, use_ipsex, use_ipsw); - hres = CoInternetGetSession(0, &session, 0); - ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres); + init_test(do_load ? LD_DOLOAD : LD_NO); - hres = IInternetSession_RegisterNameSpace(session, &ClassFactory, &IID_NULL, - wsz_winetest, 0, NULL, 0); - ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres); + hres = create_document(&unk); + if(FAILED(hres)) + return; + doc_unk = unk; - IInternetSession_Release(session); -} + ipsex = use_ipsex; + ipsw = use_ipsw; -static void gecko_installer_workaround(BOOL disable) -{ - HKEY hkey; - DWORD res; + hres = IUnknown_QueryInterface(unk, &IID_IOleObject, (void**)&oleobj); + ok(hres == S_OK, "QueryInterface(IID_IOleObject) failed: %08x\n", hres); - static BOOL has_url = FALSE; - static char url[2048]; + hres = IUnknown_QueryInterface(unk, &IID_IOleDocumentView, (void**)&view); + ok(hres == S_OK, "QueryInterface(IID_IOleDocumentView) failed: %08x\n", hres); - if(!disable && !has_url) - return; + SET_EXPECT(Invoke_AMBIENT_USERMODE); + SET_EXPECT(GetHostInfo); + SET_EXPECT(Invoke_AMBIENT_DLCONTROL); + SET_EXPECT(Invoke_AMBIENT_SILENT); + SET_EXPECT(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); + SET_EXPECT(Invoke_AMBIENT_USERAGENT); + SET_EXPECT(Invoke_AMBIENT_PALETTE); + SET_EXPECT(GetOptionKeyPath); + SET_EXPECT(GetOverrideKeyPath); + SET_EXPECT(GetWindow); + SET_EXPECT(QueryStatus_SETPROGRESSTEXT); + SET_EXPECT(Exec_SETPROGRESSMAX); + SET_EXPECT(Exec_SETPROGRESSPOS); - res = RegOpenKey(HKEY_CURRENT_USER, "Software\\Wine\\MSHTML", &hkey); - if(res != ERROR_SUCCESS) - return; + hres = IOleObject_SetClientSite(oleobj, &ClientSite); + ok(hres == S_OK, "SetClientSite failed: %08x\n", hres); - if(disable) { - DWORD type, size = sizeof(url); + CHECK_CALLED(Invoke_AMBIENT_USERMODE); + CHECK_CALLED(GetHostInfo); + CHECK_CALLED(Invoke_AMBIENT_DLCONTROL); + CHECK_CALLED(Invoke_AMBIENT_SILENT); + CHECK_CALLED(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); + CHECK_CALLED(Invoke_AMBIENT_USERAGENT); + CHECK_CALLED(Invoke_AMBIENT_PALETTE); + CHECK_CALLED(GetOptionKeyPath); + CHECK_CALLED(GetOverrideKeyPath); + CHECK_CALLED(GetWindow); + CHECK_CALLED(QueryStatus_SETPROGRESSTEXT); + CHECK_CALLED(Exec_SETPROGRESSMAX); + CHECK_CALLED(Exec_SETPROGRESSPOS); - res = RegQueryValueEx(hkey, "GeckoUrl", NULL, &type, (PVOID)url, &size); - if(res == ERROR_SUCCESS && type == REG_SZ) - has_url = TRUE; + hres = IOleDocumentView_GetInPlaceSite(view, &inplacesite); + ok(hres == S_OK, "GetInPlaceSite failed: %08x\n", hres); + ok(inplacesite == NULL, "inplacesite = %p, expected NULL\n", inplacesite); - RegDeleteValue(hkey, "GeckoUrl"); - }else { - RegSetValueEx(hkey, "GeckoUrl", 0, REG_SZ, (PVOID)url, lstrlenA(url)+1); + SET_EXPECT(GetContainer); + SET_EXPECT(LockContainer); + SET_EXPECT(CanInPlaceActivate); + SET_EXPECT(GetWindowContext); + SET_EXPECT(GetWindow); + if(use_ipsex) { + SET_EXPECT(OnInPlaceActivateEx); + SET_EXPECT(RequestUIActivate); } + else + SET_EXPECT(OnInPlaceActivate); + SET_EXPECT(OnUIActivate); + SET_EXPECT(SetStatusText); + SET_EXPECT(Exec_SETPROGRESSMAX); + SET_EXPECT(Exec_SETPROGRESSPOS); + SET_EXPECT(ShowUI); + SET_EXPECT(InPlaceUIWindow_SetActiveObject); + SET_EXPECT(InPlaceFrame_SetBorderSpace); + SET_EXPECT(OnFocus_TRUE); + SET_EXPECT(SetActiveObject); + expect_LockContainer_fLock = TRUE; + + hres = IOleDocumentView_UIActivate(view, TRUE); + ok(hres == S_OK, "UIActivate failed: %08x\n", hres); + + CHECK_CALLED(GetContainer); + CHECK_CALLED(LockContainer); + CHECK_CALLED(CanInPlaceActivate); + CHECK_CALLED(GetWindowContext); + CHECK_CALLED(GetWindow); + if(use_ipsex) { + CHECK_CALLED(OnInPlaceActivateEx); + SET_EXPECT(RequestUIActivate); + } + else + CHECK_CALLED(OnInPlaceActivate); + CHECK_CALLED(OnUIActivate); + CHECK_CALLED(SetStatusText); + CHECK_CALLED(Exec_SETPROGRESSMAX); + CHECK_CALLED(Exec_SETPROGRESSPOS); + CHECK_CALLED(ShowUI); + CHECK_CALLED(InPlaceUIWindow_SetActiveObject); + CHECK_CALLED(InPlaceFrame_SetBorderSpace); + CHECK_CALLED(OnFocus_TRUE); + CHECK_CALLED(SetActiveObject); + container_locked = TRUE; + + SET_EXPECT(SetActiveObject_null); + SET_EXPECT(InPlaceUIWindow_SetActiveObject); + SET_EXPECT(HideUI); + SET_EXPECT(OnUIDeactivate); + + hres = IOleDocumentView_UIActivate(view, FALSE); + ok(hres == S_OK, "UIActivate failed: %08x\n", hres); + + CHECK_CALLED(SetActiveObject_null); + CHECK_CALLED(InPlaceUIWindow_SetActiveObject); + CHECK_CALLED(HideUI); + CHECK_CALLED(OnUIDeactivate); + + hres = IOleDocumentView_GetInPlaceSite(view, &inplacesite); + ok(hres == S_OK, "GetInPlaceSite failed: %08x\n", hres); + ok(inplacesite != NULL, "inplacesite = NULL\n"); + IOleInPlaceSite_Release(inplacesite); + + SET_EXPECT(OnFocus_FALSE); + if(use_ipsex) + SET_EXPECT(OnInPlaceDeactivateEx); + else + SET_EXPECT(OnInPlaceDeactivate); + + test_CloseView(); + + CHECK_CALLED(OnFocus_FALSE); + if(use_ipsex) + CHECK_CALLED(OnInPlaceDeactivateEx); + else + CHECK_CALLED(OnInPlaceDeactivate); - RegCloseKey(hkey); + test_Close(unk, TRUE); + + IOleObject_Release(oleobj); + IOleDocumentView_Release(view); + view = NULL; + + ref = IUnknown_Release(unk); + ok(ref == 0, "ref=%d, expected 0\n", ref); +} + +static void register_protocol(void) +{ + IInternetSession *session; + HRESULT hres; + + static const WCHAR wsz_winetest[] = {'w','i','n','e','t','e','s','t',0}; + + hres = CoInternetGetSession(0, &session, 0); + ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres); + + hres = IInternetSession_RegisterNameSpace(session, &ClassFactory, &IID_NULL, + wsz_winetest, 0, NULL, 0); + ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres); + + IInternetSession_Release(session); } static void test_HTMLDoc_ISupportErrorInfo(void) @@ -4322,8 +4967,6 @@ static void test_IPersistHistory(void) START_TEST(htmldoc) { - gecko_installer_workaround(TRUE); - CoInitialize(NULL); container_hwnd = create_container_window(); register_protocol(); @@ -4333,15 +4976,20 @@ START_TEST(htmldoc) test_HTMLDocument(FALSE); test_HTMLDocument(TRUE); test_HTMLDocument_StreamLoad(); + test_HTMLDocument_StreamInitNew(); test_editing_mode(FALSE); test_editing_mode(TRUE); test_HTMLDocument_http(); + test_UIActivate(FALSE, FALSE, FALSE); + test_UIActivate(FALSE, TRUE, FALSE); + test_UIActivate(FALSE, TRUE, TRUE); + test_UIActivate(TRUE, FALSE, FALSE); + test_UIActivate(TRUE, TRUE, FALSE); + test_UIActivate(TRUE, TRUE, TRUE); } test_HTMLDoc_ISupportErrorInfo(); test_IPersistHistory(); DestroyWindow(container_hwnd); CoUninitialize(); - - gecko_installer_workaround(FALSE); } diff --git a/rostests/winetests/mshtml/htmllocation.c b/rostests/winetests/mshtml/htmllocation.c new file mode 100644 index 00000000000..60a1f204cc4 --- /dev/null +++ b/rostests/winetests/mshtml/htmllocation.c @@ -0,0 +1,368 @@ +/* + * Copyright 2009 Andrew Eikum for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS +#define CONST_VTABLE + +#include + +#include "mshtml.h" + +struct location_test { + const char *name; + const WCHAR *url; + + const char *href; + const char *protocol; + const char *host; + const char *hostname; + const char *port; + const char *pathname; + const char *search; + const char *hash; +}; + +static const WCHAR http_url[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g','?','s','e','a','r','c','h','#','h','a','s','h',0}; +static const struct location_test http_test = { + "HTTP", + http_url, + "http://www.winehq.org/?search#hash", + "http:", + "www.winehq.org:80", + "www.winehq.org", + "80", + "", + "?search", + "#hash" + }; + +static const WCHAR http_file_url[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g','/','f','i','l','e','?','s','e','a','r','c','h','#','h','a','s','h',0}; +static const struct location_test http_file_test = { + "HTTP with file", + http_file_url, + "http://www.winehq.org/file?search#hash", + "http:", + "www.winehq.org:80", + "www.winehq.org", + "80", + "file", + "?search", + "#hash" + }; + +static const WCHAR ftp_url[] = {'f','t','p',':','/','/','f','t','p','.','w','i','n','e','h','q','.','o','r','g','/',0}; +static const struct location_test ftp_test = { + "FTP", + ftp_url, + "ftp://ftp.winehq.org/", + "ftp:", + "ftp.winehq.org:21", + "ftp.winehq.org", + "21", + "", + NULL, + NULL + }; + +static const WCHAR ftp_file_url[] = {'f','t','p',':','/','/','f','t','p','.','w','i','n','e','h','q','.','o','r','g','/','f','i','l','e',0}; +static const struct location_test ftp_file_test = { + "FTP with file", + ftp_file_url, + "ftp://ftp.winehq.org/file", + "ftp:", + "ftp.winehq.org:21", + "ftp.winehq.org", + "21", + "file", + NULL, + NULL + }; + +static const WCHAR file_url[] = {'f','i','l','e',':','/','/','C',':','\\','w','i','n','d','o','w','s','\\','w','i','n','.','i','n','i',0}; +static const struct location_test file_test = { + "FILE", + file_url, + "file:///C:/windows/win.ini", + "file:", + NULL, + NULL, + "", + "C:\\windows\\win.ini", + NULL, + NULL + }; + +static int str_eq_wa(LPCWSTR strw, const char *stra) +{ + CHAR buf[512]; + + if(strw == NULL || stra == NULL){ + if((void*)strw == (void*)stra) + return 1; + return 0; + } + + WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL); + return !lstrcmpA(stra, buf); +} + +static void test_href(IHTMLLocation *loc, const struct location_test *test) +{ + HRESULT hres; + BSTR str; + + hres = IHTMLLocation_get_href(loc, NULL); + ok(hres == E_POINTER, + "%s: get_href should have failed with E_POINTER (0x%08x), was: 0x%08x\n", + test->name, E_POINTER, hres); + + hres = IHTMLLocation_get_href(loc, &str); + ok(hres == S_OK, "%s: get_href failed: 0x%08x\n", test->name, hres); + if(hres == S_OK) + ok(str_eq_wa(str, test->href), + "%s: expected retrieved href to be L\"%s\", was: %s\n", + test->name, test->href, wine_dbgstr_w(str)); +} + +static void test_protocol(IHTMLLocation *loc, const struct location_test *test) +{ + HRESULT hres; + BSTR str; + + hres = IHTMLLocation_get_protocol(loc, NULL); + ok(hres == E_POINTER, + "%s: get_protocol should have failed with E_POINTER (0x%08x), was: 0x%08x\n", + test->name, E_POINTER, hres); + + hres = IHTMLLocation_get_protocol(loc, &str); + ok(hres == S_OK, "%s: get_protocol failed: 0x%08x\n", test->name, hres); + if(hres == S_OK) + ok(str_eq_wa(str, test->protocol), + "%s: expected retrieved protocol to be L\"%s\", was: %s\n", + test->name, test->protocol, wine_dbgstr_w(str)); +} + +static void test_host(IHTMLLocation *loc, const struct location_test *test) +{ + HRESULT hres; + BSTR str; + + hres = IHTMLLocation_get_host(loc, NULL); + ok(hres == E_POINTER, + "%s: get_host should have failed with E_POINTER (0x%08x), was: 0x%08x\n", + test->name, E_POINTER, hres); + + hres = IHTMLLocation_get_host(loc, &str); + ok(hres == S_OK, "%s: get_host failed: 0x%08x\n", test->name, hres); + if(hres == S_OK) + ok(str_eq_wa(str, test->host), + "%s: expected retrieved host to be L\"%s\", was: %s\n", + test->name, test->host, wine_dbgstr_w(str)); +} + +static void test_hostname(IHTMLLocation *loc, const struct location_test *test) +{ + HRESULT hres; + BSTR str; + + hres = IHTMLLocation_get_hostname(loc, NULL); + ok(hres == E_POINTER, + "%s: get_hostname should have failed with E_POINTER (0x%08x), was: 0x%08x\n", + test->name, E_POINTER, hres); + + hres = IHTMLLocation_get_hostname(loc, &str); + ok(hres == S_OK, "%s: get_hostname failed: 0x%08x\n", test->name, hres); + if(hres == S_OK) + ok(str_eq_wa(str, test->hostname), + "%s: expected retrieved hostname to be L\"%s\", was: %s\n", + test->name, test->hostname, wine_dbgstr_w(str)); +} + +static void test_port(IHTMLLocation *loc, const struct location_test *test) +{ + HRESULT hres; + BSTR str; + + hres = IHTMLLocation_get_port(loc, NULL); + ok(hres == E_POINTER, + "%s: get_port should have failed with E_POINTER (0x%08x), was: 0x%08x\n", + test->name, E_POINTER, hres); + + hres = IHTMLLocation_get_port(loc, &str); + ok(hres == S_OK, "%s: get_port failed: 0x%08x\n", test->name, hres); + if(hres == S_OK) + ok(str_eq_wa(str, test->port), + "%s: expected retrieved port to be L\"%s\", was: %s\n", + test->name, test->port, wine_dbgstr_w(str)); +} + +static void test_pathname(IHTMLLocation *loc, const struct location_test *test) +{ + HRESULT hres; + BSTR str; + + hres = IHTMLLocation_get_pathname(loc, NULL); + ok(hres == E_POINTER, + "%s: get_pathname should have failed with E_POINTER (0x%08x), was: 0x%08x\n", + test->name, E_POINTER, hres); + + hres = IHTMLLocation_get_pathname(loc, &str); + ok(hres == S_OK, "%s: get_pathname failed: 0x%08x\n", test->name, hres); + if(hres == S_OK) + ok(str_eq_wa(str, test->pathname), + "%s: expected retrieved pathname to be L\"%s\", was: %s\n", + test->name, test->pathname, wine_dbgstr_w(str)); +} + +static void test_search(IHTMLLocation *loc, const struct location_test *test) +{ + HRESULT hres; + BSTR str; + + hres = IHTMLLocation_get_search(loc, NULL); + ok(hres == E_POINTER, + "%s: get_search should have failed with E_POINTER (0x%08x), was: 0x%08x\n", + test->name, E_POINTER, hres); + + hres = IHTMLLocation_get_search(loc, &str); + ok(hres == S_OK, "%s: get_search failed: 0x%08x\n", test->name, hres); + if(hres == S_OK) + ok(str_eq_wa(str, test->search), + "%s: expected retrieved search to be L\"%s\", was: %s\n", + test->name, test->search, wine_dbgstr_w(str)); +} + +static void test_hash(IHTMLLocation *loc, const struct location_test *test) +{ + HRESULT hres; + BSTR str; + + hres = IHTMLLocation_get_hash(loc, NULL); + ok(hres == E_POINTER, + "%s: get_hash should have failed with E_POINTER (0x%08x), was: 0x%08x\n", + test->name, E_POINTER, hres); + + hres = IHTMLLocation_get_hash(loc, &str); + ok(hres == S_OK, "%s: get_hash failed: 0x%08x\n", test->name, hres); + if(hres == S_OK) + ok(str_eq_wa(str, test->hash), + "%s: expected retrieved hash to be L\"%s\", was: %s\n", + test->name, test->hash, wine_dbgstr_w(str)); +} + +static void perform_test(const struct location_test* test) +{ + HRESULT hres; + IBindCtx *bc; + IMoniker *url_mon; + IPersistMoniker *persist_mon; + IHTMLDocument2 *doc; + IHTMLDocument6 *doc6; + IHTMLLocation *location; + + hres = CreateBindCtx(0, &bc); + ok(hres == S_OK, "%s: CreateBindCtx failed: 0x%08x\n", test->name, hres); + if(FAILED(hres)) + return; + + hres = CreateURLMoniker(NULL, test->url, &url_mon); + ok(hres == S_OK, "%s: CreateURLMoniker failed: 0x%08x\n", test->name, hres); + if(FAILED(hres)){ + IBindCtx_Release(bc); + return; + } + + hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, + CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, &IID_IHTMLDocument2, + (void**)&doc); + ok(hres == S_OK, "%s: CoCreateInstance failed: 0x%08x\n", test->name, hres); + if(FAILED(hres)){ + IMoniker_Release(url_mon); + IBindCtx_Release(bc); + return; + } + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument6, (void**)&doc6); + if(hres == S_OK){ + IHTMLDocument6_Release(doc6); + }else{ + win_skip("%s: Could not get IHTMLDocument6, probably too old IE. Requires IE 8+\n", test->name); + IMoniker_Release(url_mon); + IBindCtx_Release(bc); + return; + } + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IPersistMoniker, + (void**)&persist_mon); + ok(hres == S_OK, "%s: IHTMlDocument2_QueryInterface failed: 0x%08x\n", test->name, hres); + if(FAILED(hres)){ + IHTMLDocument2_Release(doc); + IMoniker_Release(url_mon); + IBindCtx_Release(bc); + return; + } + + hres = IPersistMoniker_Load(persist_mon, FALSE, url_mon, bc, + STGM_SHARE_EXCLUSIVE | STGM_READWRITE); + ok(hres == S_OK, "%s: IPersistMoniker_Load failed: 0x%08x\n", test->name, hres); + if(FAILED(hres)){ + IPersistMoniker_Release(persist_mon); + IHTMLDocument2_Release(doc); + IMoniker_Release(url_mon); + IBindCtx_Release(bc); + return; + } + + hres = IHTMLDocument2_get_location(doc, &location); + ok(hres == S_OK, "%s: IHTMLDocument2_get_location failed: 0x%08x\n", test->name, hres); + if(FAILED(hres)){ + IPersistMoniker_Release(persist_mon); + IHTMLDocument2_Release(doc); + IMoniker_Release(url_mon); + IBindCtx_Release(bc); + return; + } + + test_href(location, test); + test_protocol(location, test); + test_host(location, test); + test_hostname(location, test); + test_port(location, test); + test_pathname(location, test); + test_search(location, test); + test_hash(location, test); + + IHTMLLocation_Release(location); + IPersistMoniker_Release(persist_mon); + IHTMLDocument2_Release(doc); + IMoniker_Release(url_mon); + IBindCtx_Release(bc); +} + +START_TEST(htmllocation) +{ + CoInitialize(NULL); + + perform_test(&http_test); + perform_test(&http_file_test); + perform_test(&ftp_test); + perform_test(&ftp_file_test); + perform_test(&file_test); + + CoUninitialize(); +} diff --git a/rostests/winetests/mshtml/jstest.html b/rostests/winetests/mshtml/jstest.html new file mode 100644 index 00000000000..72ef427485a --- /dev/null +++ b/rostests/winetests/mshtml/jstest.html @@ -0,0 +1,20 @@ + + + + +
+ + diff --git a/rostests/winetests/mshtml/mshtml.rbuild b/rostests/winetests/mshtml/mshtml.rbuild index 280dced8372..90696e467e8 100644 --- a/rostests/winetests/mshtml/mshtml.rbuild +++ b/rostests/winetests/mshtml/mshtml.rbuild @@ -7,16 +7,20 @@ dom.c events.c htmldoc.c + htmllocation.c misc.c protocol.c script.c testlist.c + rsrc.rc wine uuid strmiids + wininet ole32 oleaut32 user32 + gdi32 urlmon advapi32 ntdll diff --git a/rostests/winetests/mshtml/rsrc.rc b/rostests/winetests/mshtml/rsrc.rc new file mode 100644 index 00000000000..70925ca8022 --- /dev/null +++ b/rostests/winetests/mshtml/rsrc.rc @@ -0,0 +1,20 @@ +/* + * Copyright 2009 Jacek Caban + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* @makedep: jstest.html */ +jstest.html HTML "jstest.html" diff --git a/rostests/winetests/mshtml/script.c b/rostests/winetests/mshtml/script.c index 5f59ea4e1b6..fae49c8bcee 100644 --- a/rostests/winetests/mshtml/script.c +++ b/rostests/winetests/mshtml/script.c @@ -26,8 +26,12 @@ #include "windef.h" #include "winbase.h" #include "ole2.h" +#include "wininet.h" +#include "docobj.h" #include "dispex.h" +#include "hlink.h" #include "mshtml.h" +#include "mshtmhst.h" #include "initguid.h" #include "activscp.h" #include "activdbg.h" @@ -112,16 +116,25 @@ DEFINE_EXPECT(AddNamedItem); DEFINE_EXPECT(ParseScriptText); DEFINE_EXPECT(GetScriptDispatch); DEFINE_EXPECT(funcDisp); +DEFINE_EXPECT(script_divid_d); DEFINE_EXPECT(script_testprop_d); DEFINE_EXPECT(script_testprop_i); +DEFINE_EXPECT(script_testprop2_d); DEFINE_EXPECT(AXQueryInterface_IActiveScript); DEFINE_EXPECT(AXQueryInterface_IObjectSafety); DEFINE_EXPECT(AXGetInterfaceSafetyOptions); DEFINE_EXPECT(AXSetInterfaceSafetyOptions); +DEFINE_EXPECT(external_success); #define TESTSCRIPT_CLSID "{178fc163-f585-4e24-9c13-4bb7faf80746}" +#define TESTACTIVEX_CLSID "{178fc163-f585-4e24-9c13-4bb7faf80646}" #define DISPID_SCRIPT_TESTPROP 0x100000 +#define DISPID_SCRIPT_TESTPROP2 0x100001 + +#define DISPID_EXTERNAL_OK 0x300000 +#define DISPID_EXTERNAL_TRACE 0x300001 +#define DISPID_EXTERNAL_REPORTSUCCESS 0x300002 static const GUID CLSID_TestScript = {0x178fc163,0xf585,0x4e24,{0x9c,0x13,0x4b,0xb7,0xfa,0xf8,0x07,0x46}}; @@ -129,9 +142,12 @@ static const GUID CLSID_TestActiveX = {0x178fc163,0xf585,0x4e24,{0x9c,0x13,0x4b,0xb7,0xfa,0xf8,0x06,0x46}}; static IHTMLDocument2 *notif_doc; +static IOleDocumentView *view; static IDispatchEx *window_dispex; static BOOL doc_complete; static IDispatch *script_disp; +static BOOL ax_objsafe; +static HWND container_hwnd; static const char *debugstr_guid(REFIID riid) { @@ -164,6 +180,28 @@ static BSTR a2bstr(const char *str) return ret; } +static BOOL init_key(const char *key_name, const char *def_value, BOOL init) +{ + HKEY hkey; + DWORD res; + + if(!init) { + RegDeleteKey(HKEY_CLASSES_ROOT, key_name); + return TRUE; + } + + res = RegCreateKeyA(HKEY_CLASSES_ROOT, key_name, &hkey); + if(res != ERROR_SUCCESS) + return FALSE; + + if(def_value) + res = RegSetValueA(hkey, NULL, REG_SZ, def_value, strlen(def_value)); + + RegCloseKey(hkey); + + return res == ERROR_SUCCESS; +} + static HRESULT WINAPI PropertyNotifySink_QueryInterface(IPropertyNotifySink *iface, REFIID riid, void**ppv) { @@ -298,128 +336,716 @@ static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BS return E_NOTIMPL; } -static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid) +static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI funcDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + CHECK_EXPECT(funcDisp); + + ok(id == DISPID_VALUE, "id = %d\n", id); + ok(lcid == 0, "lcid = %x\n", lcid); + ok(wFlags == DISPATCH_METHOD, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->cArgs == 2, "pdp->cArgs = %d\n", pdp->cArgs); + ok(pdp->cNamedArgs == 1, "pdp->cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pdp->rgdispidNamedArgs[0] == DISPID_THIS, "pdp->rgdispidNamedArgs[0] = %d\n", pdp->rgdispidNamedArgs[0]); + ok(V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(rgvarg) = %d\n", V_VT(pdp->rgvarg)); + ok(V_VT(pdp->rgvarg+1) == VT_BOOL, "V_VT(rgvarg[1]) = %d\n", V_VT(pdp->rgvarg)); + ok(V_BOOL(pdp->rgvarg+1) == VARIANT_TRUE, "V_BOOL(rgvarg[1]) = %x\n", V_BOOL(pdp->rgvarg)); + ok(pvarRes != NULL, "pvarRes == NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + ok(!pspCaller, "pspCaller != NULL\n"); + + V_VT(pvarRes) = VT_I4; + V_I4(pvarRes) = 100; + return S_OK; +} + +static IDispatchExVtbl testObjVtbl = { + DispatchEx_QueryInterface, + DispatchEx_AddRef, + DispatchEx_Release, + DispatchEx_GetTypeInfoCount, + DispatchEx_GetTypeInfo, + DispatchEx_GetIDsOfNames, + DispatchEx_Invoke, + DispatchEx_GetDispID, + funcDisp_InvokeEx, + DispatchEx_DeleteMemberByName, + DispatchEx_DeleteMemberByDispID, + DispatchEx_GetMemberProperties, + DispatchEx_GetMemberName, + DispatchEx_GetNextDispID, + DispatchEx_GetNameSpaceParent +}; + +static IDispatchEx funcDisp = { &testObjVtbl }; + +static HRESULT WINAPI scriptDisp_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) +{ + if(!strcmp_wa(bstrName, "testProp")) { + CHECK_EXPECT(script_testprop_d); + ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex); + *pid = DISPID_SCRIPT_TESTPROP; + return S_OK; + } + + if(!strcmp_wa(bstrName, "testProp2")) { + CHECK_EXPECT(script_testprop2_d); + ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex); + *pid = DISPID_SCRIPT_TESTPROP2; + return S_OK; + } + + if(!strcmp_wa(bstrName, "divid")) { + CHECK_EXPECT(script_divid_d); + ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex); + return E_FAIL; + } + + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI scriptDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + switch(id) { + case DISPID_SCRIPT_TESTPROP: + CHECK_EXPECT(script_testprop_i); + + ok(lcid == 0, "lcid = %x\n", lcid); + ok(wFlags == DISPATCH_PROPERTYGET, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->cArgs == 0, "pdp->cArgs = %d\n", pdp->cArgs); + ok(pdp->cNamedArgs == 0, "pdp->cNamedArgs = %d\n", pdp->cNamedArgs); + ok(!pdp->rgdispidNamedArgs, "pdp->rgdispidNamedArgs != NULL\n"); + ok(!pdp->rgvarg, "rgvarg != NULL\n"); + ok(pvarRes != NULL, "pvarRes == NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + ok(!pspCaller, "pspCaller != NULL\n"); + + V_VT(pvarRes) = VT_NULL; + break; + default: + ok(0, "unexpected call\n"); + return E_NOTIMPL; + } + + return S_OK; +} + +static IDispatchExVtbl scriptDispVtbl = { + DispatchEx_QueryInterface, + DispatchEx_AddRef, + DispatchEx_Release, + DispatchEx_GetTypeInfoCount, + DispatchEx_GetTypeInfo, + DispatchEx_GetIDsOfNames, + DispatchEx_Invoke, + scriptDisp_GetDispID, + scriptDisp_InvokeEx, + DispatchEx_DeleteMemberByName, + DispatchEx_DeleteMemberByDispID, + DispatchEx_GetMemberProperties, + DispatchEx_GetMemberName, + DispatchEx_GetNextDispID, + DispatchEx_GetNameSpaceParent +}; + +static IDispatchEx scriptDisp = { &scriptDispVtbl }; + +static HRESULT WINAPI externalDisp_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) +{ + if(!strcmp_wa(bstrName, "ok")) { + *pid = DISPID_EXTERNAL_OK; + return S_OK; + } + if(!strcmp_wa(bstrName, "trace")) { + *pid = DISPID_EXTERNAL_TRACE; + return S_OK; + } + if(!strcmp_wa(bstrName, "reportSuccess")) { + *pid = DISPID_EXTERNAL_REPORTSUCCESS; + return S_OK; + } + + ok(0, "unexpected name %s\n", wine_dbgstr_w(bstrName)); + return DISP_E_UNKNOWNNAME; +} + +static HRESULT WINAPI externalDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + switch(id) { + case DISPID_EXTERNAL_OK: + ok(wFlags == INVOKE_FUNC || wFlags == (INVOKE_FUNC|INVOKE_PROPERTYGET), "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->rgvarg != NULL, "rgvarg == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(pdp->cArgs == 2, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pei != NULL, "pei == NULL\n"); + + ok(V_VT(pdp->rgvarg) == VT_BSTR, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg)); + ok(V_VT(pdp->rgvarg+1) == VT_BOOL, "V_VT(psp->rgvargs+1) = %d\n", V_VT(pdp->rgvarg)); + ok(V_BOOL(pdp->rgvarg+1), "%s\n", wine_dbgstr_w(V_BSTR(pdp->rgvarg))); + + return S_OK; + + case DISPID_EXTERNAL_TRACE: + ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->rgvarg != NULL, "rgvarg == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(!pvarRes, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + ok(V_VT(pdp->rgvarg) == VT_BSTR, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg)); + if(V_VT(pdp->rgvarg) == VT_BSTR) + trace("%s\n", wine_dbgstr_w(V_BSTR(pdp->rgvarg))); + + return S_OK; + + case DISPID_EXTERNAL_REPORTSUCCESS: + CHECK_EXPECT(external_success); + + ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(pdp->cArgs == 0, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(!pvarRes, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + return S_OK; + + default: + ok(0, "unexpected call\n"); + return E_NOTIMPL; + } + + return S_OK; +} + +static IDispatchExVtbl externalDispVtbl = { + DispatchEx_QueryInterface, + DispatchEx_AddRef, + DispatchEx_Release, + DispatchEx_GetTypeInfoCount, + DispatchEx_GetTypeInfo, + DispatchEx_GetIDsOfNames, + DispatchEx_Invoke, + externalDisp_GetDispID, + externalDisp_InvokeEx, + DispatchEx_DeleteMemberByName, + DispatchEx_DeleteMemberByDispID, + DispatchEx_GetMemberProperties, + DispatchEx_GetMemberName, + DispatchEx_GetNextDispID, + DispatchEx_GetNameSpaceParent +}; + +static IDispatchEx externalDisp = { &externalDispVtbl }; + +static HRESULT QueryInterface(REFIID,void**); + +static HRESULT WINAPI DocHostUIHandler_QueryInterface(IDocHostUIHandler2 *iface, REFIID riid, void **ppv) +{ + return QueryInterface(riid, ppv); +} + +static ULONG WINAPI DocHostUIHandler_AddRef(IDocHostUIHandler2 *iface) +{ + return 2; +} + +static ULONG WINAPI DocHostUIHandler_Release(IDocHostUIHandler2 *iface) +{ + return 1; +} + +static HRESULT WINAPI DocHostUIHandler_ShowContextMenu(IDocHostUIHandler2 *iface, DWORD dwID, POINT *ppt, + IUnknown *pcmdtReserved, IDispatch *pdicpReserved) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI DocHostUIHandler_GetHostInfo(IDocHostUIHandler2 *iface, DOCHOSTUIINFO *pInfo) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI DocHostUIHandler_ShowUI(IDocHostUIHandler2 *iface, DWORD dwID, + IOleInPlaceActiveObject *pActiveObject, IOleCommandTarget *pCommandTarget, + IOleInPlaceFrame *pFrame, IOleInPlaceUIWindow *pDoc) +{ + return S_OK; +} + +static HRESULT WINAPI DocHostUIHandler_HideUI(IDocHostUIHandler2 *iface) +{ + return S_OK; +} + +static HRESULT WINAPI DocHostUIHandler_UpdateUI(IDocHostUIHandler2 *iface) +{ + return S_OK; +} + +static HRESULT WINAPI DocHostUIHandler_EnableModeless(IDocHostUIHandler2 *iface, BOOL fEnable) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI DocHostUIHandler_OnDocWindowActivate(IDocHostUIHandler2 *iface, BOOL fActivate) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI DocHostUIHandler_OnFrameWindowActivate(IDocHostUIHandler2 *iface, BOOL fActivate) +{ + return S_OK; +} + +static HRESULT WINAPI DocHostUIHandler_ResizeBorder(IDocHostUIHandler2 *iface, LPCRECT prcBorder, + IOleInPlaceUIWindow *pUIWindow, BOOL fRameWindow) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI DocHostUIHandler_TranslateAccelerator(IDocHostUIHandler2 *iface, LPMSG lpMsg, + const GUID *pguidCmdGroup, DWORD nCmdID) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI DocHostUIHandler_GetOptionKeyPath(IDocHostUIHandler2 *iface, + LPOLESTR *pchKey, DWORD dw) +{ + return S_OK; +} + +static HRESULT WINAPI DocHostUIHandler_GetDropTarget(IDocHostUIHandler2 *iface, + IDropTarget *pDropTarget, IDropTarget **ppDropTarget) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI DocHostUIHandler_GetExternal(IDocHostUIHandler2 *iface, IDispatch **ppDispatch) +{ + *ppDispatch = (IDispatch*)&externalDisp; + return S_OK; +} + +static HRESULT WINAPI DocHostUIHandler_TranslateUrl(IDocHostUIHandler2 *iface, DWORD dwTranslate, + OLECHAR *pchURLIn, OLECHAR **ppchURLOut) +{ + return S_FALSE; +} + +static HRESULT WINAPI DocHostUIHandler_FilterDataObject(IDocHostUIHandler2 *iface, IDataObject *pDO, + IDataObject **ppPORet) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI DocHostUIHandler_GetOverrideKeyPath(IDocHostUIHandler2 *iface, + LPOLESTR *pchKey, DWORD dw) +{ + return E_NOTIMPL; +} + +static const IDocHostUIHandler2Vtbl DocHostUIHandlerVtbl = { + DocHostUIHandler_QueryInterface, + DocHostUIHandler_AddRef, + DocHostUIHandler_Release, + DocHostUIHandler_ShowContextMenu, + DocHostUIHandler_GetHostInfo, + DocHostUIHandler_ShowUI, + DocHostUIHandler_HideUI, + DocHostUIHandler_UpdateUI, + DocHostUIHandler_EnableModeless, + DocHostUIHandler_OnDocWindowActivate, + DocHostUIHandler_OnFrameWindowActivate, + DocHostUIHandler_ResizeBorder, + DocHostUIHandler_TranslateAccelerator, + DocHostUIHandler_GetOptionKeyPath, + DocHostUIHandler_GetDropTarget, + DocHostUIHandler_GetExternal, + DocHostUIHandler_TranslateUrl, + DocHostUIHandler_FilterDataObject, + DocHostUIHandler_GetOverrideKeyPath +}; + +static IDocHostUIHandler2 DocHostUIHandler = { &DocHostUIHandlerVtbl }; + +static HRESULT WINAPI InPlaceFrame_QueryInterface(IOleInPlaceFrame *iface, REFIID riid, void **ppv) +{ + return E_NOINTERFACE; +} + +static ULONG WINAPI InPlaceFrame_AddRef(IOleInPlaceFrame *iface) +{ + return 2; +} + +static ULONG WINAPI InPlaceFrame_Release(IOleInPlaceFrame *iface) +{ + return 1; +} + +static HRESULT WINAPI InPlaceFrame_GetWindow(IOleInPlaceFrame *iface, HWND *phwnd) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceFrame_ContextSensitiveHelp(IOleInPlaceFrame *iface, BOOL fEnterMode) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceFrame_GetBorder(IOleInPlaceFrame *iface, LPRECT lprectBorder) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceFrame_RequestBorderSpace(IOleInPlaceFrame *iface, + LPCBORDERWIDTHS pborderwidths) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceFrame_SetBorderSpace(IOleInPlaceFrame *iface, + LPCBORDERWIDTHS pborderwidths) +{ + return S_OK; +} + +static HRESULT WINAPI InPlaceFrame_SetActiveObject(IOleInPlaceFrame *iface, + IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName) +{ + return S_OK; +} + +static HRESULT WINAPI InPlaceFrame_InsertMenus(IOleInPlaceFrame *iface, HMENU hmenuShared, + LPOLEMENUGROUPWIDTHS lpMenuWidths) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceFrame_SetMenu(IOleInPlaceFrame *iface, HMENU hmenuShared, + HOLEMENU holemenu, HWND hwndActiveObject) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceFrame_RemoveMenus(IOleInPlaceFrame *iface, HMENU hmenuShared) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceFrame_SetStatusText(IOleInPlaceFrame *iface, LPCOLESTR pszStatusText) +{ + return S_OK; +} + +static HRESULT WINAPI InPlaceFrame_EnableModeless(IOleInPlaceFrame *iface, BOOL fEnable) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceFrame_TranslateAccelerator(IOleInPlaceFrame *iface, LPMSG lpmsg, WORD wID) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const IOleInPlaceFrameVtbl InPlaceFrameVtbl = { + InPlaceFrame_QueryInterface, + InPlaceFrame_AddRef, + InPlaceFrame_Release, + InPlaceFrame_GetWindow, + InPlaceFrame_ContextSensitiveHelp, + InPlaceFrame_GetBorder, + InPlaceFrame_RequestBorderSpace, + InPlaceFrame_SetBorderSpace, + InPlaceFrame_SetActiveObject, + InPlaceFrame_InsertMenus, + InPlaceFrame_SetMenu, + InPlaceFrame_RemoveMenus, + InPlaceFrame_SetStatusText, + InPlaceFrame_EnableModeless, + InPlaceFrame_TranslateAccelerator +}; + +static IOleInPlaceFrame InPlaceFrame = { &InPlaceFrameVtbl }; + +static HRESULT WINAPI InPlaceSite_QueryInterface(IOleInPlaceSite *iface, REFIID riid, void **ppv) +{ + return QueryInterface(riid, ppv); +} + +static ULONG WINAPI InPlaceSite_AddRef(IOleInPlaceSite *iface) +{ + return 2; +} + +static ULONG WINAPI InPlaceSite_Release(IOleInPlaceSite *iface) +{ + return 1; +} + +static HRESULT WINAPI InPlaceSite_GetWindow(IOleInPlaceSite *iface, HWND *phwnd) +{ + *phwnd = container_hwnd; + return S_OK; +} + +static HRESULT WINAPI InPlaceSite_ContextSensitiveHelp(IOleInPlaceSite *iface, BOOL fEnterMode) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceSite_CanInPlaceActivate(IOleInPlaceSite *iface) +{ + return S_OK; +} + +static HRESULT WINAPI InPlaceSite_OnInPlaceActivate(IOleInPlaceSite *iface) +{ + return S_OK; +} + +static HRESULT WINAPI InPlaceSite_OnUIActivate(IOleInPlaceSite *iface) +{ + return S_OK; +} + +static HRESULT WINAPI InPlaceSite_GetWindowContext(IOleInPlaceSite *iface, + IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect, + LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo) +{ + static const RECT rect = {0,0,300,300}; + + *ppFrame = &InPlaceFrame; + *ppDoc = (IOleInPlaceUIWindow*)&InPlaceFrame; + *lprcPosRect = rect; + *lprcClipRect = rect; + + lpFrameInfo->cb = sizeof(*lpFrameInfo); + lpFrameInfo->fMDIApp = FALSE; + lpFrameInfo->hwndFrame = container_hwnd; + lpFrameInfo->haccel = NULL; + lpFrameInfo->cAccelEntries = 0; + + return S_OK; +} + +static HRESULT WINAPI InPlaceSite_Scroll(IOleInPlaceSite *iface, SIZE scrollExtant) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceSite_OnUIDeactivate(IOleInPlaceSite *iface, BOOL fUndoable) +{ + return S_OK; +} + +static HRESULT WINAPI InPlaceSite_OnInPlaceDeactivate(IOleInPlaceSite *iface) +{ + return S_OK; +} + +static HRESULT WINAPI InPlaceSite_DiscardUndoState(IOleInPlaceSite *iface) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceSite_DeactivateAndUndo(IOleInPlaceSite *iface) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceSite_OnPosRectChange(IOleInPlaceSite *iface, LPCRECT lprcPosRect) +{ + return E_NOTIMPL; +} + +static const IOleInPlaceSiteVtbl InPlaceSiteVtbl = { + InPlaceSite_QueryInterface, + InPlaceSite_AddRef, + InPlaceSite_Release, + InPlaceSite_GetWindow, + InPlaceSite_ContextSensitiveHelp, + InPlaceSite_CanInPlaceActivate, + InPlaceSite_OnInPlaceActivate, + InPlaceSite_OnUIActivate, + InPlaceSite_GetWindowContext, + InPlaceSite_Scroll, + InPlaceSite_OnUIDeactivate, + InPlaceSite_OnInPlaceDeactivate, + InPlaceSite_DiscardUndoState, + InPlaceSite_DeactivateAndUndo, + InPlaceSite_OnPosRectChange, +}; + +static IOleInPlaceSite InPlaceSite = { &InPlaceSiteVtbl }; + +static HRESULT WINAPI ClientSite_QueryInterface(IOleClientSite *iface, REFIID riid, void **ppv) +{ + return QueryInterface(riid, ppv); +} + +static ULONG WINAPI ClientSite_AddRef(IOleClientSite *iface) +{ + return 2; +} + +static ULONG WINAPI ClientSite_Release(IOleClientSite *iface) +{ + return 1; +} + +static HRESULT WINAPI ClientSite_SaveObject(IOleClientSite *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ClientSite_GetMoniker(IOleClientSite *iface, DWORD dwAssign, DWORD dwWhichMoniker, + IMoniker **ppmon) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ClientSite_GetContainer(IOleClientSite *iface, IOleContainer **ppContainer) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ClientSite_ShowObject(IOleClientSite *iface) { ok(0, "unexpected call\n"); return E_NOTIMPL; } -static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk) +static HRESULT WINAPI ClientSite_OnShowWindow(IOleClientSite *iface, BOOL fShow) { ok(0, "unexpected call\n"); return E_NOTIMPL; } -static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) +static HRESULT WINAPI ClientSite_RequestNewObjectLayout(IOleClientSite *iface) { ok(0, "unexpected call\n"); return E_NOTIMPL; } -static HRESULT WINAPI funcDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, - VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) -{ - CHECK_EXPECT(funcDisp); +static const IOleClientSiteVtbl ClientSiteVtbl = { + ClientSite_QueryInterface, + ClientSite_AddRef, + ClientSite_Release, + ClientSite_SaveObject, + ClientSite_GetMoniker, + ClientSite_GetContainer, + ClientSite_ShowObject, + ClientSite_OnShowWindow, + ClientSite_RequestNewObjectLayout +}; - ok(id == DISPID_VALUE, "id = %d\n", id); - ok(lcid == 0, "lcid = %x\n", lcid); - ok(wFlags == DISPATCH_METHOD, "wFlags = %x\n", wFlags); - ok(pdp != NULL, "pdp == NULL\n"); - ok(pdp->cArgs == 2, "pdp->cArgs = %d\n", pdp->cArgs); - ok(pdp->cNamedArgs == 1, "pdp->cNamedArgs = %d\n", pdp->cNamedArgs); - ok(pdp->rgdispidNamedArgs[0] == DISPID_THIS, "pdp->rgdispidNamedArgs[0] = %d\n", pdp->rgdispidNamedArgs[0]); - ok(V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(rgvarg) = %d\n", V_VT(pdp->rgvarg)); - ok(V_VT(pdp->rgvarg+1) == VT_BOOL, "V_VT(rgvarg[1]) = %d\n", V_VT(pdp->rgvarg)); - ok(V_BOOL(pdp->rgvarg+1) == VARIANT_TRUE, "V_BOOL(rgvarg[1]) = %x\n", V_BOOL(pdp->rgvarg)); - ok(pvarRes != NULL, "pvarRes == NULL\n"); - ok(pei != NULL, "pei == NULL\n"); - ok(!pspCaller, "pspCaller != NULL\n"); +static IOleClientSite ClientSite = { &ClientSiteVtbl }; - V_VT(pvarRes) = VT_I4; - V_I4(pvarRes) = 100; - return S_OK; +static HRESULT WINAPI DocumentSite_QueryInterface(IOleDocumentSite *iface, REFIID riid, void **ppv) +{ + return QueryInterface(riid, ppv); } -static IDispatchExVtbl testObjVtbl = { - DispatchEx_QueryInterface, - DispatchEx_AddRef, - DispatchEx_Release, - DispatchEx_GetTypeInfoCount, - DispatchEx_GetTypeInfo, - DispatchEx_GetIDsOfNames, - DispatchEx_Invoke, - DispatchEx_GetDispID, - funcDisp_InvokeEx, - DispatchEx_DeleteMemberByName, - DispatchEx_DeleteMemberByDispID, - DispatchEx_GetMemberProperties, - DispatchEx_GetMemberName, - DispatchEx_GetNextDispID, - DispatchEx_GetNameSpaceParent -}; - -static IDispatchEx funcDisp = { &testObjVtbl }; - -static HRESULT WINAPI scriptDisp_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) +static ULONG WINAPI DocumentSite_AddRef(IOleDocumentSite *iface) { - if(!strcmp_wa(bstrName, "testProp")) { - CHECK_EXPECT(script_testprop_d); - ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex); - *pid = DISPID_SCRIPT_TESTPROP; - return S_OK; - } + return 2; +} - ok(0, "unexpected call\n"); - return E_NOTIMPL; +static ULONG WINAPI DocumentSite_Release(IOleDocumentSite *iface) +{ + return 1; } -static HRESULT WINAPI scriptDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, - VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +static HRESULT WINAPI DocumentSite_ActivateMe(IOleDocumentSite *iface, IOleDocumentView *pViewToActivate) { - switch(id) { - case DISPID_SCRIPT_TESTPROP: - CHECK_EXPECT(script_testprop_i); + RECT rect = {0,0,300,300}; + IOleDocument *document; + HRESULT hres; - ok(lcid == 0, "lcid = %x\n", lcid); - ok(wFlags == DISPATCH_PROPERTYGET, "wFlags = %x\n", wFlags); - ok(pdp != NULL, "pdp == NULL\n"); - ok(pdp->cArgs == 0, "pdp->cArgs = %d\n", pdp->cArgs); - ok(pdp->cNamedArgs == 0, "pdp->cNamedArgs = %d\n", pdp->cNamedArgs); - ok(!pdp->rgdispidNamedArgs, "pdp->rgdispidNamedArgs != NULL\n"); - ok(!pdp->rgvarg, "rgvarg != NULL\n"); - ok(pvarRes != NULL, "pvarRes == NULL\n"); - ok(pei != NULL, "pei == NULL\n"); - ok(!pspCaller, "pspCaller != NULL\n"); + hres = IOleDocumentView_QueryInterface(pViewToActivate, &IID_IOleDocument, (void**)&document); + ok(hres == S_OK, "could not get IOleDocument: %08x\n", hres); - V_VT(pvarRes) = VT_NULL; - break; - default: - ok(0, "unexpected call\n"); - return E_NOTIMPL; - } + hres = IOleDocument_CreateView(document, &InPlaceSite, NULL, 0, &view); + IOleDocument_Release(document); + ok(hres == S_OK, "CreateView failed: %08x\n", hres); + + hres = IOleDocumentView_SetInPlaceSite(view, &InPlaceSite); + ok(hres == S_OK, "SetInPlaceSite failed: %08x\n", hres); + + hres = IOleDocumentView_UIActivate(view, TRUE); + ok(hres == S_OK, "UIActivate failed: %08x\n", hres); + + hres = IOleDocumentView_SetRect(view, &rect); + ok(hres == S_OK, "SetRect failed: %08x\n", hres); + + hres = IOleDocumentView_Show(view, TRUE); + ok(hres == S_OK, "Show failed: %08x\n", hres); return S_OK; } -static IDispatchExVtbl scriptDispVtbl = { - DispatchEx_QueryInterface, - DispatchEx_AddRef, - DispatchEx_Release, - DispatchEx_GetTypeInfoCount, - DispatchEx_GetTypeInfo, - DispatchEx_GetIDsOfNames, - DispatchEx_Invoke, - scriptDisp_GetDispID, - scriptDisp_InvokeEx, - DispatchEx_DeleteMemberByName, - DispatchEx_DeleteMemberByDispID, - DispatchEx_GetMemberProperties, - DispatchEx_GetMemberName, - DispatchEx_GetNextDispID, - DispatchEx_GetNameSpaceParent +static const IOleDocumentSiteVtbl DocumentSiteVtbl = { + DocumentSite_QueryInterface, + DocumentSite_AddRef, + DocumentSite_Release, + DocumentSite_ActivateMe }; -static IDispatchEx scriptDisp = { &scriptDispVtbl }; +static IOleDocumentSite DocumentSite = { &DocumentSiteVtbl }; + +static HRESULT QueryInterface(REFIID riid, void **ppv) +{ + *ppv = NULL; + + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IOleClientSite, riid)) + *ppv = &ClientSite; + else if(IsEqualGUID(&IID_IOleDocumentSite, riid)) + *ppv = &DocumentSite; + else if(IsEqualGUID(&IID_IOleWindow, riid) || IsEqualGUID(&IID_IOleInPlaceSite, riid)) + *ppv = &InPlaceSite; + else if(IsEqualGUID(&IID_IDocHostUIHandler, riid) || IsEqualGUID(&IID_IDocHostUIHandler2, riid)) + *ppv = &DocHostUIHandler; + + return *ppv ? S_OK : E_NOINTERFACE; +} static IHTMLDocument2 *create_document(void) { @@ -433,18 +1059,13 @@ static IHTMLDocument2 *create_document(void) return doc; } -static IHTMLDocument2 *create_doc_with_string(const char *str) +static void load_string(IHTMLDocument2 *doc, const char *str) { IPersistStreamInit *init; IStream *stream; - IHTMLDocument2 *doc; HGLOBAL mem; SIZE_T len; - notif_doc = doc = create_document(); - if(!doc) - return NULL; - doc_complete = FALSE; len = strlen(str); mem = GlobalAlloc(0, len); @@ -456,45 +1077,76 @@ static IHTMLDocument2 *create_doc_with_string(const char *str) IPersistStreamInit_Load(init, stream); IPersistStreamInit_Release(init); IStream_Release(stream); - - return doc; } -static void do_advise(IUnknown *unk, REFIID riid, IUnknown *unk_advise) +static void do_advise(IHTMLDocument2 *doc, REFIID riid, IUnknown *unk_advise) { IConnectionPointContainer *container; IConnectionPoint *cp; DWORD cookie; HRESULT hres; - hres = IUnknown_QueryInterface(unk, &IID_IConnectionPointContainer, (void**)&container); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IConnectionPointContainer, (void**)&container); ok(hres == S_OK, "QueryInterface(IID_IConnectionPointContainer) failed: %08x\n", hres); hres = IConnectionPointContainer_FindConnectionPoint(container, riid, &cp); IConnectionPointContainer_Release(container); ok(hres == S_OK, "FindConnectionPoint failed: %08x\n", hres); + notif_doc = doc; + hres = IConnectionPoint_Advise(cp, unk_advise, &cookie); IConnectionPoint_Release(cp); ok(hres == S_OK, "Advise failed: %08x\n", hres); } +static void set_client_site(IHTMLDocument2 *doc, BOOL set) +{ + IOleObject *oleobj; + HRESULT hres; + + if(!set && view) { + IOleDocumentView_Show(view, FALSE); + IOleDocumentView_CloseView(view, 0); + IOleDocumentView_SetInPlaceSite(view, NULL); + IOleDocumentView_Release(view); + view = NULL; + } + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj); + ok(hres == S_OK, "Could not et IOleObject: %08x\n", hres); + + hres = IOleObject_SetClientSite(oleobj, set ? &ClientSite : NULL); + ok(hres == S_OK, "SetClientSite failed: %08x\n", hres); + + if(set) { + IHlinkTarget *hlink; + + hres = IOleObject_QueryInterface(oleobj, &IID_IHlinkTarget, (void**)&hlink); + ok(hres == S_OK, "Could not get IHlinkTarget iface: %08x\n", hres); + + hres = IHlinkTarget_Navigate(hlink, 0, NULL); + ok(hres == S_OK, "Navgate failed: %08x\n", hres); + + IHlinkTarget_Release(hlink); + } + + IOleObject_Release(oleobj); +} + typedef void (*domtest_t)(IHTMLDocument2*); -static IHTMLDocument2 *create_and_load_doc(const char *str) +static void load_doc(IHTMLDocument2 *doc, const char *str) { - IHTMLDocument2 *doc; IHTMLElement *body = NULL; - ULONG ref; MSG msg; HRESULT hres; static const WCHAR ucPtr[] = {'b','a','c','k','g','r','o','u','n','d',0}; DISPID dispID = -1; OLECHAR *name; - - doc = create_doc_with_string(str); - do_advise((IUnknown*)doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink); + load_string(doc, str); + do_advise(doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink); while(!doc_complete && GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); @@ -504,13 +1156,6 @@ static IHTMLDocument2 *create_and_load_doc(const char *str) hres = IHTMLDocument2_get_body(doc, &body); ok(hres == S_OK, "get_body failed: %08x\n", hres); - if(!body) { - skip("Could not get document body. Assuming no Gecko installed.\n"); - ref = IHTMLDocument2_Release(doc); - ok(!ref, "ref = %d\n", ref); - return NULL; - } - /* Check we can query for function on the IHTMLElementBody interface */ name = (WCHAR*)ucPtr; hres = IHTMLElement_GetIDsOfNames(body, &IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &dispID); @@ -518,7 +1163,6 @@ static IHTMLDocument2 *create_and_load_doc(const char *str) ok(dispID == DISPID_IHTMLBODYELEMENT_BACKGROUND, "Incorrect dispID got (%d)\n", dispID); IHTMLElement_Release(body); - return doc; } static IActiveScriptSite *site; @@ -592,6 +1236,8 @@ static HRESULT WINAPI AXObjectSafety_QueryInterface(IObjectSafety *iface, REFIID if(IsEqualGUID(&IID_IObjectSafety, riid)) { CHECK_EXPECT(AXQueryInterface_IObjectSafety); + if(!ax_objsafe) + return E_NOINTERFACE; *ppv = iface; return S_OK; } @@ -640,6 +1286,12 @@ static const IObjectSafetyVtbl AXObjectSafetyVtbl = { static IObjectSafety AXObjectSafety = { &AXObjectSafetyVtbl }; +static BOOL set_safe_reg(BOOL init) +{ + return init_key("CLSID\\"TESTACTIVEX_CLSID"\\Implemented Categories\\{7dd95801-9882-11cf-9fa9-00aa006c42c4}", + NULL, init); +} + static void test_security(void) { IInternetHostSecurityManager *sec_mgr; @@ -666,6 +1318,7 @@ static void test_security(void) cs.pUnk = (IUnknown*)&AXObjectSafety; cs.dwFlags = 0; + ax_objsafe = TRUE; SET_EXPECT(AXQueryInterface_IActiveScript); SET_EXPECT(AXQueryInterface_IObjectSafety); SET_EXPECT(AXGetInterfaceSafetyOptions); @@ -682,6 +1335,55 @@ static void test_security(void) ok(*(DWORD*)ppolicy == URLPOLICY_ALLOW, "policy = %x\n", *(DWORD*)ppolicy); CoTaskMemFree(ppolicy); + ax_objsafe = FALSE; + SET_EXPECT(AXQueryInterface_IActiveScript); + SET_EXPECT(AXQueryInterface_IObjectSafety); + hres = IInternetHostSecurityManager_QueryCustomPolicy(sec_mgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY, + &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0); + CHECK_CALLED(AXQueryInterface_IActiveScript); + CHECK_CALLED(AXQueryInterface_IObjectSafety); + + ok(hres == S_OK, "QueryCusromPolicy failed: %08x\n", hres); + ok(policy_size == sizeof(DWORD), "policy_size = %d\n", policy_size); + ok(*(DWORD*)ppolicy == URLPOLICY_DISALLOW, "policy = %x\n", *(DWORD*)ppolicy); + CoTaskMemFree(ppolicy); + + if(set_safe_reg(TRUE)) { + ax_objsafe = FALSE; + SET_EXPECT(AXQueryInterface_IActiveScript); + SET_EXPECT(AXQueryInterface_IObjectSafety); + hres = IInternetHostSecurityManager_QueryCustomPolicy(sec_mgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY, + &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0); + CHECK_CALLED(AXQueryInterface_IActiveScript); + CHECK_CALLED(AXQueryInterface_IObjectSafety); + + ok(hres == S_OK, "QueryCusromPolicy failed: %08x\n", hres); + ok(policy_size == sizeof(DWORD), "policy_size = %d\n", policy_size); + ok(*(DWORD*)ppolicy == URLPOLICY_ALLOW, "policy = %x\n", *(DWORD*)ppolicy); + CoTaskMemFree(ppolicy); + + ax_objsafe = TRUE; + SET_EXPECT(AXQueryInterface_IActiveScript); + SET_EXPECT(AXQueryInterface_IObjectSafety); + SET_EXPECT(AXGetInterfaceSafetyOptions); + SET_EXPECT(AXSetInterfaceSafetyOptions); + hres = IInternetHostSecurityManager_QueryCustomPolicy(sec_mgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY, + &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0); + CHECK_CALLED(AXQueryInterface_IActiveScript); + CHECK_CALLED(AXQueryInterface_IObjectSafety); + CHECK_CALLED(AXGetInterfaceSafetyOptions); + CHECK_CALLED(AXSetInterfaceSafetyOptions); + + ok(hres == S_OK, "QueryCusromPolicy failed: %08x\n", hres); + ok(policy_size == sizeof(DWORD), "policy_size = %d\n", policy_size); + ok(*(DWORD*)ppolicy == URLPOLICY_ALLOW, "policy = %x\n", *(DWORD*)ppolicy); + CoTaskMemFree(ppolicy); + + set_safe_reg(FALSE); + }else { + skip("Could not set safety registry\n"); + } + IInternetHostSecurityManager_Release(sec_mgr); } @@ -817,13 +1519,13 @@ static HRESULT WINAPI ActiveScriptParse_AddScriptlet(IActiveScriptParse *iface, return E_NOTIMPL; } -static HRESULT dispex_propput(IDispatchEx *obj, DISPID id, VARIANT *var) +static HRESULT dispex_propput(IDispatchEx *obj, DISPID id, DWORD flags, VARIANT *var) { DISPID propput_arg = DISPID_PROPERTYPUT; DISPPARAMS dp = {var, &propput_arg, 1, 1}; EXCEPINFO ei = {0}; - return IDispatchEx_InvokeEx(obj, id, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dp, NULL, &ei, NULL); + return IDispatchEx_InvokeEx(obj, id, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT|flags, &dp, NULL, &ei, NULL); } static void test_func(IDispatchEx *obj) @@ -871,7 +1573,7 @@ static void test_func(IDispatchEx *obj) V_VT(&var) = VT_I4; V_I4(&var) = 100; - hres = dispex_propput(obj, id, &var); + hres = dispex_propput(obj, id, 0, &var); ok(hres == E_NOTIMPL, "InvokeEx failed: %08x\n", hres); IDispatchEx_Release(dispex); @@ -890,7 +1592,7 @@ static void test_nextdispid(IDispatchEx *dispex) SysFreeString(name); V_VT(&var) = VT_EMPTY; - hres = dispex_propput(dispex, dyn_id, &var); + hres = dispex_propput(dispex, dyn_id, 0, &var); while(last_id != dyn_id) { hres = IDispatchEx_GetNextDispID(dispex, fdexEnumAll, last_id, &id); @@ -915,6 +1617,33 @@ static void test_nextdispid(IDispatchEx *dispex) ok(id == DISPID_STARTENUM, "id != DISPID_STARTENUM\n"); } +static void test_global_id(void) +{ + VARIANT var; + DISPPARAMS dp; + EXCEPINFO ei; + BSTR tmp; + DISPID id; + HRESULT hres; + + SET_EXPECT(GetScriptDispatch); + SET_EXPECT(script_divid_d); + tmp = a2bstr("divid"); + hres = IDispatchEx_GetDispID(window_dispex, tmp, fdexNameCaseSensitive, &id); + ok(hres == S_OK, "GetDispID failed: %08x\n", hres); + SysFreeString(tmp); + CHECK_CALLED(GetScriptDispatch); + CHECK_CALLED(script_divid_d); + + VariantInit(&var); + memset(&ei, 0, sizeof(ei)); + memset(&dp, 0, sizeof(dp)); + hres = IDispatchEx_InvokeEx(window_dispex, id, 0, DISPATCH_PROPERTYGET, &dp, &var, &ei, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&var) == VT_DISPATCH, "V_VT(var) = %d\n", V_VT(&var)); + VariantClear(&var); +} + static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *iface, LPCOLESTR pstrCode, LPCOLESTR pstrItemName, IUnknown *punkContext, LPCOLESTR pstrDelimiter, CTXARG_T dwSourceContextCookie, ULONG ulStartingLine, @@ -976,7 +1705,7 @@ static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *ifac V_VT(&var) = VT_I4; V_I4(&var) = 100; - hres = dispex_propput(document, id, &var); + hres = dispex_propput(document, id, 0, &var); ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); tmp = SysAllocString(testW); @@ -990,7 +1719,37 @@ static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *ifac hres = IDispatchEx_InvokeEx(document, id, LOCALE_NEUTRAL, INVOKE_PROPERTYGET, &dp, &var, &ei, NULL); ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); ok(V_VT(&var) == VT_I4, "V_VT(var)=%d\n", V_VT(&var)); - ok(V_I4(&var) == 100, "V_I4(&var) == NULL\n"); + ok(V_I4(&var) == 100, "V_I4(&var) = %d\n", V_I4(&var)); + + V_VT(&var) = VT_I4; + V_I4(&var) = 200; + hres = dispex_propput(document, id, DISPATCH_PROPERTYPUTREF, &var); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + + VariantInit(&var); + memset(&dp, 0, sizeof(dp)); + memset(&ei, 0, sizeof(ei)); + hres = IDispatchEx_InvokeEx(document, id, LOCALE_NEUTRAL, INVOKE_PROPERTYGET, &dp, &var, &ei, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&var) == VT_I4, "V_VT(var)=%d\n", V_VT(&var)); + ok(V_I4(&var) == 200, "V_I4(&var) = %d\n", V_I4(&var)); + + memset(&dp, 0, sizeof(dp)); + memset(&ei, 0, sizeof(ei)); + V_VT(&var) = VT_I4; + V_I4(&var) = 300; + dp.cArgs = 1; + dp.rgvarg = &var; + hres = IDispatchEx_InvokeEx(document, id, LOCALE_NEUTRAL, INVOKE_PROPERTYPUT, &dp, NULL, &ei, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + + VariantInit(&var); + memset(&dp, 0, sizeof(dp)); + memset(&ei, 0, sizeof(ei)); + hres = IDispatchEx_InvokeEx(document, id, LOCALE_NEUTRAL, INVOKE_PROPERTYGET, &dp, &var, &ei, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&var) == VT_I4, "V_VT(var)=%d\n", V_VT(&var)); + ok(V_I4(&var) == 300, "V_I4(&var) = %d\n", V_I4(&var)); unk = (void*)0xdeadbeef; hres = IDispatchEx_GetNameSpaceParent(window_dispex, &unk); @@ -1074,6 +1833,18 @@ static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *ifac CHECK_CALLED(GetScriptDispatch); CHECK_CALLED(script_testprop_i); + SET_EXPECT(GetScriptDispatch); + SET_EXPECT(script_testprop2_d); + tmp = a2bstr("testProp2"); + hres = IDispatchEx_GetDispID(window_dispex, tmp, fdexNameCaseSensitive|fdexNameEnsure, &id); + ok(hres == S_OK, "GetDispID failed: %08x\n", hres); + ok(id != DISPID_SCRIPT_TESTPROP2, "id == DISPID_SCRIPT_TESTPROP2\n"); + CHECK_CALLED(GetScriptDispatch); + CHECK_CALLED(script_testprop2_d); + SysFreeString(tmp); + + test_global_id(); + test_security(); return S_OK; @@ -1391,6 +2162,7 @@ static IClassFactory script_cf = { &ClassFactoryVtbl }; static const char simple_script_str[] = "" + "
" "" ""; @@ -1398,6 +2170,10 @@ static void test_simple_script(void) { IHTMLDocument2 *doc; + doc = create_document(); + if(!doc) + return; + SET_EXPECT(CreateInstance); SET_EXPECT(GetInterfaceSafetyOptions); SET_EXPECT(SetInterfaceSafetyOptions); @@ -1412,8 +2188,7 @@ static void test_simple_script(void) SET_EXPECT(ParseScriptText); SET_EXPECT(SetScriptState_CONNECTED); - doc = create_and_load_doc(simple_script_str); - if(!doc) return; + load_doc(doc, simple_script_str); CHECK_CALLED(CreateInstance); CHECK_CALLED(GetInterfaceSafetyOptions); @@ -1443,26 +2218,61 @@ static void test_simple_script(void) CHECK_CALLED(Close); } -static BOOL init_key(const char *key_name, const char *def_value, BOOL init) +static void run_js_script(const char *test_name) { - HKEY hkey; - DWORD res; + WCHAR url[INTERNET_MAX_URL_LENGTH]; + char urlA[INTERNET_MAX_URL_LENGTH]; + IPersistMoniker *persist; + IHTMLDocument2 *doc; + IMoniker *mon; + MSG msg; + HRESULT hres; - if(!init) { - RegDeleteKey(HKEY_CLASSES_ROOT, key_name); - return TRUE; - } + static const char res[] = "res://"; - res = RegCreateKeyA(HKEY_CLASSES_ROOT, key_name, &hkey); - if(res != ERROR_SUCCESS) - return FALSE; + trace("running %s...\n", test_name); - if(def_value) - res = RegSetValueA(hkey, NULL, REG_SZ, def_value, strlen(def_value)); + doc = create_document(); + if(!doc) + return; - RegCloseKey(hkey); + set_client_site(doc, TRUE); + do_advise(doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink); - return res == ERROR_SUCCESS; + lstrcpyA(urlA, res); + GetModuleFileNameA(NULL, urlA + lstrlenA(res), sizeof(urlA) - lstrlenA(res)); + lstrcatA(urlA, "/"); + lstrcatA(urlA, test_name); + MultiByteToWideChar(CP_ACP, 0, urlA, -1, url, sizeof(url)/sizeof(WCHAR)); + + hres = CreateURLMoniker(NULL, url, &mon); + ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres); + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IPersistMoniker, (void**)&persist); + ok(hres == S_OK, "Could not get IPersistMoniker iface: %08x\n", hres); + + hres = IPersistMoniker_Load(persist, FALSE, mon, NULL, 0); + ok(hres == S_OK, "Load failed: %08x\n", hres); + + IMoniker_Release(mon); + IPersistMoniker_Release(persist); + + SET_EXPECT(external_success); + + while(!called_external_success && GetMessage(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + CHECK_CALLED(external_success); + + set_client_site(doc, FALSE); + IHTMLDocument2_Release(doc); +} + +static void run_js_tests(void) +{ + run_js_script("jstest.html"); } static BOOL init_registry(BOOL init) @@ -1491,44 +2301,38 @@ static BOOL register_script_engine(void) return TRUE; } -static void gecko_installer_workaround(BOOL disable) +static LRESULT WINAPI wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { - HKEY hkey; - DWORD res; - - static BOOL has_url = FALSE; - static char url[2048]; - - if(!disable && !has_url) - return; - - res = RegOpenKey(HKEY_CURRENT_USER, "Software\\Wine\\MSHTML", &hkey); - if(res != ERROR_SUCCESS) - return; - - if(disable) { - DWORD type, size = sizeof(url); - - res = RegQueryValueEx(hkey, "GeckoUrl", NULL, &type, (PVOID)url, &size); - if(res == ERROR_SUCCESS && type == REG_SZ) - has_url = TRUE; + return DefWindowProc(hwnd, msg, wParam, lParam); +} - RegDeleteValue(hkey, "GeckoUrl"); - }else { - RegSetValueEx(hkey, "GeckoUrl", 0, REG_SZ, (PVOID)url, lstrlenA(url)+1); - } +static HWND create_container_window(void) +{ + static const CHAR szHTMLDocumentTest[] = "HTMLDocumentTest"; + static WNDCLASSEXA wndclass = { + sizeof(WNDCLASSEXA), + 0, + wnd_proc, + 0, 0, NULL, NULL, NULL, NULL, NULL, + szHTMLDocumentTest, + NULL + }; - RegCloseKey(hkey); + RegisterClassExA(&wndclass); + return CreateWindowA(szHTMLDocumentTest, szHTMLDocumentTest, + WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, + 300, 300, NULL, NULL, NULL, NULL); } START_TEST(script) { - gecko_installer_workaround(TRUE); CoInitialize(NULL); + container_hwnd = create_container_window(); if(winetest_interactive || ! is_ie_hardened()) { if(register_script_engine()) { test_simple_script(); + run_js_tests(); init_registry(FALSE); }else { skip("Could not register TestScript engine\n"); @@ -1537,6 +2341,6 @@ START_TEST(script) skip("IE running in Enhanced Security Configuration\n"); } + DestroyWindow(container_hwnd); CoUninitialize(); - gecko_installer_workaround(FALSE); } diff --git a/rostests/winetests/mshtml/testlist.c b/rostests/winetests/mshtml/testlist.c index f9026995b25..55823446f28 100644 --- a/rostests/winetests/mshtml/testlist.c +++ b/rostests/winetests/mshtml/testlist.c @@ -9,6 +9,7 @@ extern void func_dom(void); extern void func_events(void); extern void func_htmldoc(void); +extern void func_htmllocation(void); extern void func_misc(void); extern void func_protocol(void); extern void func_script(void); @@ -18,6 +19,7 @@ const struct test winetest_testlist[] = { "dom", func_dom }, { "events", func_events }, { "htmldoc", func_htmldoc }, + { "htmllocation", func_htmllocation }, { "misc", func_misc }, { "protocol", func_protocol }, { "script", func_script }, -- 2.17.1