diff --git a/rostests/winetests/directory.rbuild b/rostests/winetests/directory.rbuild
index a8c522d41e6..dee46358508 100644
--- a/rostests/winetests/directory.rbuild
+++ b/rostests/winetests/directory.rbuild
@@ -118,6 +118,9 @@
+
+
+
diff --git a/rostests/winetests/mshtml/dom.c b/rostests/winetests/mshtml/dom.c
index 4540ed405b8..36946808f89 100644
--- a/rostests/winetests/mshtml/dom.c
+++ b/rostests/winetests/mshtml/dom.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Jacek Caban for CodeWeavers
+ * Copyright 2007-2008 Jacek Caban for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -40,18 +40,23 @@ static const char range_test2_str[] =
"
abc 123 def";
static const char elem_test_str[] =
"test "
- "text test"
+ "text test"
"link "
" "
"opt1 opt2 "
""
- ""
- ""
+ ""
+ ""
" "
" "
+ ""
"";
static const char indent_test_str[] =
"test abc123 ";
+static const char cond_comment_str[] =
+ "test "
+ ""
+ "";
static const WCHAR noneW[] = {'N','o','n','e',0};
@@ -84,29 +89,34 @@ typedef enum {
ET_TEST,
ET_TESTG,
ET_COMMENT,
- ET_IMG
+ ET_IMG,
+ ET_TR,
+ ET_TD,
+ ET_IFRAME
} elem_type_t;
-static REFIID const none_iids[] = {
+static const IID * const none_iids[] = {
&IID_IUnknown,
NULL
};
-static REFIID const elem_iids[] = {
+static const IID * const elem_iids[] = {
&IID_IHTMLDOMNode,
&IID_IHTMLDOMNode2,
&IID_IHTMLElement,
&IID_IHTMLElement2,
+ &IID_IHTMLElement3,
&IID_IDispatchEx,
&IID_IConnectionPointContainer,
NULL
};
-static REFIID const body_iids[] = {
+static const IID * const body_iids[] = {
&IID_IHTMLDOMNode,
&IID_IHTMLDOMNode2,
&IID_IHTMLElement,
&IID_IHTMLElement2,
+ &IID_IHTMLElement3,
&IID_IHTMLTextContainer,
&IID_IHTMLBodyElement,
&IID_IDispatchEx,
@@ -114,22 +124,24 @@ static REFIID const body_iids[] = {
NULL
};
-static REFIID const anchor_iids[] = {
+static const IID * const anchor_iids[] = {
&IID_IHTMLDOMNode,
&IID_IHTMLDOMNode2,
&IID_IHTMLElement,
&IID_IHTMLElement2,
+ &IID_IHTMLElement3,
&IID_IHTMLAnchorElement,
&IID_IDispatchEx,
&IID_IConnectionPointContainer,
NULL
};
-static REFIID const input_iids[] = {
+static const IID * const input_iids[] = {
&IID_IHTMLDOMNode,
&IID_IHTMLDOMNode2,
&IID_IHTMLElement,
&IID_IHTMLElement2,
+ &IID_IHTMLElement3,
&IID_IHTMLInputElement,
&IID_IHTMLInputTextElement,
&IID_IDispatchEx,
@@ -137,75 +149,80 @@ static REFIID const input_iids[] = {
NULL
};
-static REFIID const select_iids[] = {
+static const IID * const select_iids[] = {
&IID_IHTMLDOMNode,
&IID_IHTMLDOMNode2,
&IID_IHTMLElement,
&IID_IHTMLElement2,
+ &IID_IHTMLElement3,
&IID_IHTMLSelectElement,
&IID_IDispatchEx,
&IID_IConnectionPointContainer,
NULL
};
-static REFIID const textarea_iids[] = {
+static const IID * const textarea_iids[] = {
&IID_IHTMLDOMNode,
&IID_IHTMLDOMNode2,
&IID_IHTMLElement,
&IID_IHTMLElement2,
+ &IID_IHTMLElement3,
&IID_IHTMLTextAreaElement,
&IID_IDispatchEx,
&IID_IConnectionPointContainer,
NULL
};
-static REFIID const option_iids[] = {
+static const IID * const option_iids[] = {
&IID_IHTMLDOMNode,
&IID_IHTMLDOMNode2,
&IID_IHTMLElement,
&IID_IHTMLElement2,
+ &IID_IHTMLElement3,
&IID_IHTMLOptionElement,
&IID_IDispatchEx,
&IID_IConnectionPointContainer,
NULL
};
-static REFIID const table_iids[] = {
+static const IID * const table_iids[] = {
&IID_IHTMLDOMNode,
&IID_IHTMLDOMNode2,
&IID_IHTMLElement,
&IID_IHTMLElement2,
+ &IID_IHTMLElement3,
&IID_IHTMLTable,
&IID_IDispatchEx,
&IID_IConnectionPointContainer,
NULL
};
-static REFIID const script_iids[] = {
+static const IID * const script_iids[] = {
&IID_IHTMLDOMNode,
&IID_IHTMLDOMNode2,
&IID_IHTMLElement,
&IID_IHTMLElement2,
+ &IID_IHTMLElement3,
&IID_IHTMLScriptElement,
&IID_IDispatchEx,
&IID_IConnectionPointContainer,
NULL
};
-static REFIID const text_iids[] = {
+static const IID * const text_iids[] = {
&IID_IHTMLDOMNode,
&IID_IHTMLDOMNode2,
&IID_IHTMLDOMTextNode,
NULL
};
-static REFIID const location_iids[] = {
+static const IID * const location_iids[] = {
&IID_IDispatch,
&IID_IHTMLLocation,
NULL
};
-static REFIID const window_iids[] = {
+static const IID * const window_iids[] = {
&IID_IDispatch,
&IID_IHTMLWindow2,
&IID_IHTMLWindow3,
@@ -213,39 +230,94 @@ static REFIID const window_iids[] = {
NULL
};
-static REFIID const comment_iids[] = {
+static const IID * const comment_iids[] = {
&IID_IHTMLDOMNode,
&IID_IHTMLDOMNode2,
&IID_IHTMLElement,
&IID_IHTMLElement2,
+ &IID_IHTMLElement3,
&IID_IHTMLCommentElement,
&IID_IDispatchEx,
&IID_IConnectionPointContainer,
NULL
};
-static REFIID const img_iids[] = {
+static const IID * const img_iids[] = {
&IID_IHTMLDOMNode,
&IID_IHTMLDOMNode2,
&IID_IHTMLElement,
&IID_IHTMLElement2,
+ &IID_IHTMLElement3,
&IID_IDispatchEx,
&IID_IHTMLImgElement,
&IID_IConnectionPointContainer,
NULL
};
-static REFIID const generic_iids[] = {
+static const IID * const tr_iids[] = {
&IID_IHTMLDOMNode,
&IID_IHTMLDOMNode2,
&IID_IHTMLElement,
&IID_IHTMLElement2,
+ &IID_IHTMLElement3,
+ &IID_IDispatchEx,
+ &IID_IHTMLTableRow,
+ &IID_IConnectionPointContainer,
+ NULL
+};
+
+static const IID * const td_iids[] = {
+ &IID_IHTMLDOMNode,
+ &IID_IHTMLDOMNode2,
+ &IID_IHTMLElement,
+ &IID_IHTMLElement2,
+ &IID_IHTMLElement3,
+ &IID_IDispatchEx,
+ &IID_IConnectionPointContainer,
+ NULL
+};
+
+static const IID * const iframe_iids[] = {
+ &IID_IHTMLDOMNode,
+ &IID_IHTMLDOMNode2,
+ &IID_IHTMLElement,
+ &IID_IHTMLElement2,
+ &IID_IHTMLElement3,
+ &IID_IHTMLFrameBase2,
+ &IID_IDispatchEx,
+ &IID_IConnectionPointContainer,
+ NULL
+};
+
+static const IID * const generic_iids[] = {
+ &IID_IHTMLDOMNode,
+ &IID_IHTMLDOMNode2,
+ &IID_IHTMLElement,
+ &IID_IHTMLElement2,
+ &IID_IHTMLElement3,
&IID_IHTMLGenericElement,
&IID_IDispatchEx,
&IID_IConnectionPointContainer,
NULL
};
+static const IID * const style_iids[] = {
+ &IID_IUnknown,
+ &IID_IDispatch,
+ &IID_IDispatchEx,
+ &IID_IHTMLStyle,
+ &IID_IHTMLStyle2,
+ NULL
+};
+
+static const IID * const cstyle_iids[] = {
+ &IID_IUnknown,
+ &IID_IDispatch,
+ &IID_IDispatchEx,
+ &IID_IHTMLCurrentStyle,
+ NULL
+};
+
typedef struct {
const char *tag;
REFIID *iids;
@@ -257,7 +329,7 @@ static const elem_type_info_t elem_type_infos[] = {
{"HTML", elem_iids, NULL},
{"HEAD", elem_iids, NULL},
{"TITLE", elem_iids, NULL},
- {"BODY", body_iids, NULL},
+ {"BODY", body_iids, &DIID_DispHTMLBody},
{"A", anchor_iids, NULL},
{"INPUT", input_iids, &DIID_DispHTMLInputElement},
{"SELECT", select_iids, &DIID_DispHTMLSelectElement},
@@ -267,13 +339,16 @@ static const elem_type_info_t elem_type_infos[] = {
{"BLOCKQUOTE",elem_iids, NULL},
{"P", elem_iids, NULL},
{"BR", elem_iids, NULL},
- {"TABLE", table_iids, NULL},
+ {"TABLE", table_iids, &DIID_DispHTMLTable},
{"TBODY", elem_iids, NULL},
{"SCRIPT", script_iids, NULL},
{"TEST", elem_iids, &DIID_DispHTMLUnknownElement},
{"TEST", generic_iids, &DIID_DispHTMLGenericElement},
{"!", comment_iids, &DIID_DispHTMLCommentElement},
- {"IMG", img_iids, &DIID_DispHTMLImg}
+ {"IMG", img_iids, &DIID_DispHTMLImg},
+ {"TR", tr_iids, &DIID_DispHTMLTableRow},
+ {"TD", td_iids, NULL},
+ {"IFRAME", iframe_iids, &DIID_DispHTMLIFrame}
};
static const char *dbgstr_w(LPCWSTR str)
@@ -316,15 +391,39 @@ static BSTR a2bstr(const char *str)
return ret;
}
+static BOOL iface_cmp(IUnknown *iface1, IUnknown *iface2)
+{
+ IUnknown *unk1, *unk2;
+
+ if(iface1 == iface2)
+ return TRUE;
+
+ IUnknown_QueryInterface(iface1, &IID_IUnknown, (void**)&unk1);
+ IUnknown_Release(unk1);
+ IUnknown_QueryInterface(iface1, &IID_IUnknown, (void**)&unk2);
+ IUnknown_Release(unk2);
+
+ return unk1 == unk2;
+}
+
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);
+ hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument5, (void**)&doc5);
+ if(FAILED(hres)) {
+ win_skip("Could not get IHTMLDocument5, probably too old IE\n");
+ IHTMLDocument2_Release(doc);
+ return NULL;
+ }
+
+ IHTMLDocument5_Release(doc5);
return doc;
}
@@ -400,6 +499,17 @@ static IHTMLElement2 *_get_elem2_iface(unsigned line, IUnknown *unk)
return elem;
}
+#define get_elem3_iface(u) _get_elem3_iface(__LINE__,u)
+static IHTMLElement3 *_get_elem3_iface(unsigned line, IUnknown *unk)
+{
+ IHTMLElement3 *elem;
+ HRESULT hres;
+
+ hres = IUnknown_QueryInterface(unk, &IID_IHTMLElement3, (void**)&elem);
+ ok_(__FILE__,line) (hres == S_OK, "Coule not get IHTMLElement3: %08x\n", hres);
+ return elem;
+}
+
#define get_node_iface(u) _get_node_iface(__LINE__,u)
static IHTMLDOMNode *_get_node_iface(unsigned line, IUnknown *unk)
{
@@ -462,6 +572,58 @@ static void _test_elem_type(unsigned line, IUnknown *unk, elem_type_t type)
_test_disp(line, unk, elem_type_infos[type].dispiid);
}
+#define get_node_type(n) _get_node_type(__LINE__,n)
+static long _get_node_type(unsigned line, IUnknown *unk)
+{
+ IHTMLDOMNode *node = _get_node_iface(line, unk);
+ long type = -1;
+ HRESULT hres;
+
+ hres = IHTMLDOMNode_get_nodeType(node, &type);
+ ok(hres == S_OK, "get_nodeType failed: %08x\n", hres);
+
+ IHTMLDOMNode_Release(node);
+
+ return type;
+}
+
+#define get_child_nodes(u) _get_child_nodes(__LINE__,u)
+static IHTMLDOMChildrenCollection *_get_child_nodes(unsigned line, IUnknown *unk)
+{
+ IHTMLDOMNode *node = _get_node_iface(line, unk);
+ IHTMLDOMChildrenCollection *col = NULL;
+ IDispatch *disp;
+ HRESULT hres;
+
+ hres = IHTMLDOMNode_get_childNodes(node, &disp);
+ IHTMLDOMNode_Release(node);
+ ok_(__FILE__,line) (hres == S_OK, "get_childNodes failed: %08x\n", hres);
+ if(FAILED(hres))
+ return NULL;
+
+ hres = IDispatch_QueryInterface(disp, &IID_IHTMLDOMChildrenCollection, (void**)&col);
+ IDispatch_Release(disp);
+ ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLDOMChildrenCollection: %08x\n", hres);
+
+ return col;
+}
+
+#define get_child_item(c,i) _get_child_item(__LINE__,c,i)
+static IHTMLDOMNode *_get_child_item(unsigned line, IHTMLDOMChildrenCollection *col, long idx)
+{
+ IHTMLDOMNode *node = NULL;
+ IDispatch *disp;
+ HRESULT hres;
+
+ hres = IHTMLDOMChildrenCollection_item(col, idx, &disp);
+ ok(hres == S_OK, "item failed: %08x\n", hres);
+
+ node = _get_node_iface(line, (IUnknown*)disp);
+ IDispatch_Release(disp);
+
+ return node;
+}
+
#define test_elem_attr(e,n,v) _test_elem_attr(__LINE__,e,n,v)
static void _test_elem_attr(unsigned line, IHTMLElement *elem, LPCWSTR name, LPCWSTR exval)
{
@@ -496,6 +658,12 @@ static void _test_elem_offset(unsigned line, IUnknown *unk)
hres = IHTMLElement_get_offsetTop(elem, &l);
ok_(__FILE__,line) (hres == S_OK, "get_offsetTop failed: %08x\n", hres);
+ hres = IHTMLElement_get_offsetHeight(elem, &l);
+ ok_(__FILE__,line) (hres == S_OK, "get_offsetHeight failed: %08x\n", hres);
+
+ hres = IHTMLElement_get_offsetWidth(elem, &l);
+ ok_(__FILE__,line) (hres == S_OK, "get_offsetWidth failed: %08x\n", hres);
+
IHTMLElement_Release(elem);
}
@@ -841,7 +1009,7 @@ static void _test_elem_collection(unsigned line, IUnknown *unk,
HRESULT hres;
hres = IUnknown_QueryInterface(unk, &IID_IHTMLElementCollection, (void**)&col);
- ok(hres == S_OK, "Could not get IHTMLElementCollection: %08x\n", hres);
+ ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLElementCollection: %08x\n", hres);
test_disp((IUnknown*)col, &DIID_DispHTMLElementCollection);
@@ -883,6 +1051,85 @@ static void _test_elem_collection(unsigned line, IUnknown *unk,
IHTMLElementCollection_Release(col);
}
+#define test_elem_getelembytag(u,t,l) _test_elem_getelembytag(__LINE__,u,t,l)
+static void _test_elem_getelembytag(unsigned line, IUnknown *unk, elem_type_t type, long exlen)
+{
+ IHTMLElement2 *elem = _get_elem2_iface(line, unk);
+ IHTMLElementCollection *col = NULL;
+ elem_type_t *types = NULL;
+ BSTR tmp;
+ int i;
+ HRESULT hres;
+
+ tmp = a2bstr(elem_type_infos[type].tag);
+ hres = IHTMLElement2_getElementsByTagName(elem, tmp, &col);
+ SysFreeString(tmp);
+ IHTMLElement2_Release(elem);
+ ok_(__FILE__,line) (hres == S_OK, "getElementByTagName failed: %08x\n", hres);
+ ok_(__FILE__,line) (col != NULL, "col == NULL\n");
+
+ if(exlen) {
+ types = HeapAlloc(GetProcessHeap(), 0, exlen*sizeof(elem_type_t));
+ for(i=0; itest ");
+
+ hres = IHTMLDocument2_get_all(content_doc, &col);
+ ok(hres == S_OK, "get_all failed: %08x\n", hres);
+ test_elem_collection((IUnknown*)col, all_types, sizeof(all_types)/sizeof(all_types[0]));
+ IHTMLElementCollection_Release(col);
+
+ hres = IHTMLDocument2_close(content_doc);
+ ok(hres == S_OK, "close failed: %08x\n", hres);
+
+ IHTMLDocument2_Release(content_doc);
}
static void test_stylesheet(IDispatch *disp)
@@ -2056,11 +3412,14 @@ static void test_elems(IHTMLDocument2 *doc)
{
IHTMLElementCollection *col;
IHTMLDOMChildrenCollection *child_col;
- IHTMLElement *elem;
+ IHTMLElement *elem, *elem2, *elem3;
IHTMLDOMNode *node, *node2;
IDispatch *disp;
long type;
HRESULT hres;
+ IHTMLElementCollection *collection;
+ IHTMLDocument3 *doc3;
+ BSTR str;
static const WCHAR imgidW[] = {'i','m','g','i','d',0};
static const WCHAR inW[] = {'i','n',0};
@@ -2068,6 +3427,9 @@ static void test_elems(IHTMLDocument2 *doc)
static const WCHAR sW[] = {'s',0};
static const WCHAR scW[] = {'s','c',0};
static const WCHAR xxxW[] = {'x','x','x',0};
+ static const WCHAR tblW[] = {'t','b','l',0};
+ static const WCHAR row2W[] = {'r','o','w','2',0};
+ static const WCHAR ifrW[] = {'i','f','r',0};
static const elem_type_t all_types[] = {
ET_HTML,
@@ -2084,9 +3446,14 @@ static void test_elems(IHTMLDocument2 *doc)
ET_TEXTAREA,
ET_TABLE,
ET_TBODY,
+ ET_TR,
+ ET_TR,
+ ET_TD,
+ ET_TD,
ET_SCRIPT,
ET_TEST,
- ET_IMG
+ ET_IMG,
+ ET_IFRAME
};
static const elem_type_t item_types[] = {
@@ -2101,6 +3468,36 @@ static void test_elems(IHTMLDocument2 *doc)
test_elem_col_item(col, xW, item_types, sizeof(item_types)/sizeof(item_types[0]));
IHTMLElementCollection_Release(col);
+ hres = IHTMLDocument2_get_images(doc, &collection);
+ ok(hres == S_OK, "get_images failed: %08x\n", hres);
+ if(hres == S_OK)
+ {
+ static const elem_type_t images_types[] = {ET_IMG};
+ test_elem_collection((IUnknown*)collection, images_types, 1);
+
+ IHTMLElementCollection_Release(collection);
+ }
+
+ hres = IHTMLDocument2_get_links(doc, &collection);
+ ok(hres == S_OK, "get_links failed: %08x\n", hres);
+ if(hres == S_OK)
+ {
+ static const elem_type_t images_types[] = {ET_A};
+ test_elem_collection((IUnknown*)collection, images_types, 1);
+
+ IHTMLElementCollection_Release(collection);
+ }
+
+ hres = IHTMLDocument2_get_anchors(doc, &collection);
+ ok(hres == S_OK, "get_anchors failed: %08x\n", hres);
+ if(hres == S_OK)
+ {
+ static const elem_type_t anchor_types[] = {ET_A};
+ test_elem_collection((IUnknown*)collection, anchor_types, 1);
+
+ IHTMLElementCollection_Release(collection);
+ }
+
elem = get_doc_elem(doc);
ok(hres == S_OK, "get_documentElement failed: %08x\n", hres);
hres = IHTMLElement_get_all(elem, &disp);
@@ -2139,12 +3536,32 @@ static void test_elems(IHTMLDocument2 *doc)
node = test_node_get_parent((IUnknown*)node2);
IHTMLDOMNode_Release(node2);
ok(node != NULL, "node == NULL\n");
- test_node_name((IUnknown*)node, "#document");
- type = get_node_type((IUnknown*)node);
- ok(type == 9, "type=%ld, expected 9\n", type);
- node2 = test_node_get_parent((IUnknown*)node);
- IHTMLDOMNode_Release(node);
- ok(node2 == NULL, "node != NULL\n");
+ if (node)
+ {
+ test_node_name((IUnknown*)node, "#document");
+ type = get_node_type((IUnknown*)node);
+ ok(type == 9, "type=%ld, expected 9\n", type);
+ node2 = test_node_get_parent((IUnknown*)node);
+ IHTMLDOMNode_Release(node);
+ ok(node2 == NULL, "node != NULL\n");
+ }
+
+ elem2 = test_elem_get_parent((IUnknown*)elem);
+ ok(elem2 != NULL, "elem2 == NULL\n");
+ test_node_name((IUnknown*)elem2, "BODY");
+ elem3 = test_elem_get_parent((IUnknown*)elem2);
+ IHTMLElement_Release(elem2);
+ ok(elem3 != NULL, "elem3 == NULL\n");
+ test_node_name((IUnknown*)elem3, "HTML");
+ elem2 = test_elem_get_parent((IUnknown*)elem3);
+ IHTMLElement_Release(elem3);
+ ok(elem2 == NULL, "elem2 != NULL\n");
+
+ test_elem_getelembytag((IUnknown*)elem, ET_OPTION, 2);
+ test_elem_getelembytag((IUnknown*)elem, ET_SELECT, 0);
+ test_elem_getelembytag((IUnknown*)elem, ET_HTML, 0);
+
+ test_elem_innertext(elem, "opt1opt2");
IHTMLElement_Release(elem);
}
@@ -2174,6 +3591,11 @@ static void test_elems(IHTMLDocument2 *doc)
ok(type == 1, "type=%ld\n", type);
IHTMLSelectElement_Release(select);
+
+ hres = IHTMLElement_get_document(elem, &disp);
+ ok(hres == S_OK, "get_document failed: %08x\n", hres);
+ ok(iface_cmp((IUnknown*)disp, (IUnknown*)doc), "disp != doc\n");
+
IHTMLElement_Release(elem);
}
@@ -2185,10 +3607,26 @@ static void test_elems(IHTMLDocument2 *doc)
hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLScriptElement, (void**)&script);
ok(hres == S_OK, "Could not get IHTMLScriptElement interface: %08x\n", hres);
- hres = IHTMLScriptElement_get_type(script, &type);
- ok(hres == S_OK, "get_type failed: %08x\n", hres);
- ok(!lstrcmpW(type, text_javascriptW), "Unexpected type %s\n", dbgstr_w(type));
- SysFreeString(type);
+ if(hres == S_OK)
+ {
+ VARIANT_BOOL vb;
+
+ hres = IHTMLScriptElement_get_type(script, &type);
+ ok(hres == S_OK, "get_type failed: %08x\n", hres);
+ ok(!lstrcmpW(type, text_javascriptW), "Unexpected type %s\n", dbgstr_w(type));
+ SysFreeString(type);
+
+ /* test defer */
+ hres = IHTMLScriptElement_put_defer(script, VARIANT_TRUE);
+ ok(hres == S_OK, "get_type failed: %08x\n", hres);
+
+ hres = IHTMLScriptElement_get_defer(script, &vb);
+ ok(hres == S_OK, "get_type failed: %08x\n", hres);
+ ok(vb == VARIANT_TRUE, "get_type failed: %08x\n", hres);
+
+ hres = IHTMLScriptElement_put_defer(script, VARIANT_FALSE);
+ ok(hres == S_OK, "get_type failed: %08x\n", hres);
+ }
IHTMLScriptElement_Release(script);
}
@@ -2205,6 +3643,10 @@ static void test_elems(IHTMLDocument2 *doc)
test_input_get_disabled(input, VARIANT_FALSE);
test_input_set_disabled(input, VARIANT_TRUE);
test_input_set_disabled(input, VARIANT_FALSE);
+ test_elem3_set_disabled((IUnknown*)input, VARIANT_TRUE);
+ test_input_get_disabled(input, VARIANT_TRUE);
+ test_elem3_set_disabled((IUnknown*)input, VARIANT_FALSE);
+ test_input_get_disabled(input, VARIANT_FALSE);
test_elem_client_size((IUnknown*)elem);
test_node_get_value_str((IUnknown*)elem, NULL);
@@ -2218,18 +3660,48 @@ static void test_elems(IHTMLDocument2 *doc)
test_elem_set_tabindex((IUnknown*)elem, 3);
test_elem_title((IUnknown*)elem, "test title");
+ test_input_get_defaultchecked(input, VARIANT_FALSE);
+ test_input_set_defaultchecked(input, VARIANT_TRUE);
+ test_input_set_defaultchecked(input, VARIANT_FALSE);
+
+ test_input_get_checked(input, VARIANT_FALSE);
+ test_input_set_checked(input, VARIANT_TRUE);
+ test_input_set_checked(input, VARIANT_FALSE);
+
IHTMLInputElement_Release(input);
IHTMLElement_Release(elem);
}
elem = get_elem_by_id(doc, imgidW, TRUE);
if(elem) {
+ test_img_src((IUnknown*)elem, "");
test_img_set_src((IUnknown*)elem, "about:blank");
test_img_alt((IUnknown*)elem, NULL);
test_img_set_alt((IUnknown*)elem, "alt test");
IHTMLElement_Release(elem);
}
+ elem = get_doc_elem_by_id(doc, tblW);
+ ok(elem != NULL, "elem == NULL\n");
+ if(elem) {
+ test_table_elem(elem);
+ IHTMLElement_Release(elem);
+ }
+
+ elem = get_doc_elem_by_id(doc, row2W);
+ ok(elem != NULL, "elem == NULL\n");
+ if(elem) {
+ test_tr_elem(elem);
+ IHTMLElement_Release(elem);
+ }
+
+ elem = get_doc_elem_by_id(doc, ifrW);
+ ok(elem != NULL, "elem == NULL\n");
+ if(elem) {
+ test_iframe_elem(elem);
+ IHTMLElement_Release(elem);
+ }
+
hres = IHTMLDocument2_get_body(doc, &elem);
ok(hres == S_OK, "get_body failed: %08x\n", hres);
@@ -2296,19 +3768,73 @@ static void test_elems(IHTMLDocument2 *doc)
IHTMLDOMChildrenCollection_Release(child_col);
}
+ test_elem3_get_disabled((IUnknown*)elem, VARIANT_FALSE);
+ test_elem3_set_disabled((IUnknown*)elem, VARIANT_TRUE);
+ test_elem3_set_disabled((IUnknown*)elem, VARIANT_FALSE);
+
IHTMLElement_Release(elem);
test_stylesheets(doc);
test_create_option_elem(doc);
+
+ elem = get_doc_elem_by_id(doc, tblW);
+ ok(elem != NULL, "elem = NULL\n");
+ test_elem_set_innertext(elem, "inner text");
+ IHTMLElement_Release(elem);
+
+ test_doc_title(doc, "test");
+ test_doc_set_title(doc, "test title");
+ test_doc_title(doc, "test title");
+
+ disp = NULL;
+ hres = IHTMLDocument2_get_Script(doc, &disp);
+ ok(hres == S_OK, "get_Script failed: %08x\n", hres);
+ if(hres == S_OK)
+ {
+ IDispatchEx *dispex;
+ hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
+ ok(hres == S_OK, "IDispatch_QueryInterface failed: %08x\n", hres);
+ if(hres == S_OK)
+ {
+ DISPID pid = -1;
+ BSTR str = a2bstr("Testing");
+ hres = IDispatchEx_GetDispID(dispex, str, 1, &pid);
+ todo_wine ok(hres == S_OK, "GetDispID failed: %08x\n", hres);
+ todo_wine ok(pid != -1, "pid == -1\n");
+ SysFreeString(str);
+ IDispatchEx_Release(dispex);
+ }
+ }
+ IDispatch_Release(disp);
+
+ hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3);
+ ok(hres == S_OK, "Could not get IHTMLDocument3 iface: %08x\n", hres);
+
+ str = a2bstr("img");
+ hres = IHTMLDocument3_getElementsByTagName(doc3, str, &col);
+ SysFreeString(str);
+ ok(hres == S_OK, "getElementByTag(%s) failed: %08x\n", dbgstr_w(ifrW), hres);
+ if(hres == S_OK)
+ {
+ static const elem_type_t img_types[] = { ET_IMG };
+
+ test_elem_collection((IUnknown*)col, img_types, sizeof(img_types)/sizeof(img_types[0]));
+ IHTMLElementCollection_Release(col);
+ }
+
+ IHTMLDocument3_Release(doc3);
}
static void test_create_elems(IHTMLDocument2 *doc)
{
IHTMLElement *elem, *body, *elem2;
- IHTMLDOMNode *node;
+ IHTMLDOMNode *node, *node2, *node3, *comment;
+ IHTMLDocument5 *doc5;
IDispatch *disp;
+ VARIANT var;
long type;
HRESULT hres;
+ BSTR str;
static const elem_type_t types1[] = { ET_TESTG };
@@ -2341,14 +3867,49 @@ static void test_create_elems(IHTMLDocument2 *doc)
IDispatch_Release(disp);
test_node_has_child((IUnknown*)body, VARIANT_FALSE);
- IHTMLElement_Release(body);
IHTMLElement_Release(elem);
IHTMLDOMNode_Release(node);
node = test_create_text(doc, "test");
test_ifaces((IUnknown*)node, text_iids);
test_disp((IUnknown*)node, &DIID_DispHTMLDOMTextNode);
+
+ V_VT(&var) = VT_NULL;
+ node2 = test_node_insertbefore((IUnknown*)body, node, &var);
IHTMLDOMNode_Release(node);
+
+ node = test_create_text(doc, "insert ");
+
+ V_VT(&var) = VT_DISPATCH;
+ V_DISPATCH(&var) = (IDispatch*)node2;
+ node3 = test_node_insertbefore((IUnknown*)body, node, &var);
+ IHTMLDOMNode_Release(node);
+ IHTMLDOMNode_Release(node2);
+ IHTMLDOMNode_Release(node3);
+
+ test_elem_innertext(body, "insert test");
+
+ hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument5, (void**)&doc5);
+ if(hres == S_OK)
+ {
+ str = a2bstr("testing");
+ hres = IHTMLDocument5_createComment(doc5, str, &comment);
+ SysFreeString(str);
+ ok(hres == S_OK, "createComment failed: %08x\n", hres);
+ if(hres == S_OK)
+ {
+ type = get_node_type((IUnknown*)comment);
+ ok(type == 8, "type=%ld, expected 8\n", type);
+
+ test_node_get_value_str((IUnknown*)comment, "testing");
+
+ IHTMLDOMNode_Release(comment);
+ }
+
+ IHTMLDocument5_Release(doc5);
+ }
+
+ IHTMLElement_Release(body);
}
static void test_exec(IUnknown *unk, const GUID *grpid, DWORD cmdid, VARIANT *in, VARIANT *out)
@@ -2406,6 +3967,25 @@ static void test_indent(IHTMLDocument2 *doc)
IHTMLElementCollection_Release(col);
}
+static void test_cond_comment(IHTMLDocument2 *doc)
+{
+ IHTMLElementCollection *col;
+ HRESULT hres;
+
+ static const elem_type_t all_types[] = {
+ ET_HTML,
+ ET_HEAD,
+ ET_TITLE,
+ ET_BODY,
+ ET_BR
+ };
+
+ hres = IHTMLDocument2_get_all(doc, &col);
+ ok(hres == S_OK, "get_all failed: %08x\n", hres);
+ test_elem_collection((IUnknown*)col, all_types, sizeof(all_types)/sizeof(all_types[0]));
+ IHTMLElementCollection_Release(col);
+}
+
static IHTMLDocument2 *notif_doc;
static BOOL doc_complete;
@@ -2524,6 +4104,9 @@ static void run_domtest(const char *str, domtest_t test)
HRESULT hres;
doc = create_doc_with_string(str);
+ if(!doc)
+ return;
+
do_advise((IUnknown*)doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink);
while(!doc_complete && GetMessage(&msg, NULL, 0, 0)) {
@@ -2542,7 +4125,9 @@ static void run_domtest(const char *str, domtest_t test)
}
ref = IHTMLDocument2_Release(doc);
- ok(!ref, "ref = %d\n", ref);
+ ok(!ref ||
+ ref == 1, /* Vista */
+ "ref = %d\n", ref);
}
static void gecko_installer_workaround(BOOL disable)
@@ -2575,6 +4160,27 @@ static void gecko_installer_workaround(BOOL disable)
RegCloseKey(hkey);
}
+/* Check if Internet Explorer is configured to run in "Enhanced Security Configuration" (aka hardened mode) */
+/* Note: this code is duplicated in dlls/mshtml/tests/dom.c, dlls/mshtml/tests/script.c and dlls/urlmon/tests/misc.c */
+static BOOL is_ie_hardened(void)
+{
+ HKEY zone_map;
+ DWORD ie_harden, type, size;
+
+ ie_harden = 0;
+ if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ZoneMap",
+ 0, KEY_QUERY_VALUE, &zone_map) == ERROR_SUCCESS) {
+ size = sizeof(DWORD);
+ if (RegQueryValueEx(zone_map, "IEHarden", NULL, &type, (LPBYTE) &ie_harden, &size) != ERROR_SUCCESS ||
+ type != REG_DWORD) {
+ ie_harden = 0;
+ }
+ RegCloseKey(zone_map);
+ }
+
+ return ie_harden != 0;
+}
+
START_TEST(dom)
{
gecko_installer_workaround(TRUE);
@@ -2583,10 +4189,15 @@ START_TEST(dom)
run_domtest(doc_str1, test_doc_elem);
run_domtest(range_test_str, test_txtrange);
run_domtest(range_test2_str, test_txtrange2);
- run_domtest(elem_test_str, test_elems);
+ if (winetest_interactive || ! is_ie_hardened()) {
+ run_domtest(elem_test_str, test_elems);
+ }else {
+ skip("IE running in Enhanced Security Configuration\n");
+ }
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);
CoUninitialize();
gecko_installer_workaround(FALSE);
diff --git a/rostests/winetests/mshtml/htmldoc.c b/rostests/winetests/mshtml/htmldoc.c
index 4de528676cd..e4ae1449875 100644
--- a/rostests/winetests/mshtml/htmldoc.c
+++ b/rostests/winetests/mshtml/htmldoc.c
@@ -25,6 +25,7 @@
#include "windef.h"
#include "winbase.h"
+#include "initguid.h"
#include "ole2.h"
#include "mshtml.h"
#include "docobj.h"
@@ -36,7 +37,8 @@
#include "idispids.h"
#include "shlguid.h"
-#include "initguid.h"
+DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
+DEFINE_GUID(IID_IProxyManager,0x00000008,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
DEFINE_OLEGUID(CGID_DocHostCmdPriv, 0x000214D4L, 0, 0);
#define DEFINE_EXPECT(func) \
@@ -136,6 +138,10 @@ DEFINE_EXPECT(RequestUIActivate);
DEFINE_EXPECT(InPlaceFrame_SetBorderSpace);
DEFINE_EXPECT(InPlaceUIWindow_SetActiveObject);
DEFINE_EXPECT(GetExternal);
+DEFINE_EXPECT(EnableModeless_TRUE);
+DEFINE_EXPECT(EnableModeless_FALSE);
+DEFINE_EXPECT(Frame_EnableModeless_TRUE);
+DEFINE_EXPECT(Frame_EnableModeless_FALSE);
static IUnknown *doc_unk;
static BOOL expect_LockContainer_fLock;
@@ -143,7 +149,7 @@ static BOOL expect_InPlaceUIWindow_SetActiveObject_active = TRUE;
static BOOL ipsex;
static BOOL set_clientsite = FALSE, container_locked = FALSE;
static BOOL readystate_set_loading = FALSE, load_from_stream;
-static BOOL editmode = FALSE;
+static BOOL editmode = FALSE, show_failed;
static int stream_read, protocol_read;
static enum load_state_t {
LD_DOLOAD,
@@ -649,11 +655,13 @@ static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, D
readystate_set_loading = FALSE;
load_state = LD_LOADING;
}
- test_readyState(NULL);
+ if(!editmode || load_state != LD_LOADING || !called_Exec_Explorer_69)
+ test_readyState(NULL);
return S_OK;
case 1005:
CHECK_EXPECT(OnChanged_1005);
- test_readyState(NULL);
+ if(!editmode)
+ test_readyState(NULL);
load_state = LD_INTERACTIVE;
return S_OK;
}
@@ -1007,8 +1015,10 @@ static HRESULT WINAPI Moniker_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMon
BINDSTATUS_ENDDOWNLOADDATA, NULL);
ok(hres == S_OK, "OnProgress(BINDSTATUS_ENDDOWNLOADDATA) failed: %08x\n", hres);
+ SET_EXPECT(GetBindResult);
hres = IBindStatusCallback_OnStopBinding(callback, S_OK, NULL);
ok(hres == S_OK, "OnStopBinding failed: %08x\n", hres);
+ SET_CALLED(GetBindResult); /* IE7 */
IBindStatusCallback_Release(callback);
@@ -1304,7 +1314,10 @@ static HRESULT WINAPI InPlaceFrame_SetStatusText(IOleInPlaceFrame *iface, LPCOLE
static HRESULT WINAPI InPlaceFrame_EnableModeless(IOleInPlaceFrame *iface, BOOL fEnable)
{
- ok(0, "unexpected call\n");
+ if(fEnable)
+ CHECK_EXPECT(Frame_EnableModeless_TRUE);
+ else
+ CHECK_EXPECT(Frame_EnableModeless_FALSE);
return E_NOTIMPL;
}
@@ -1664,11 +1677,6 @@ static HRESULT WINAPI DocumentSite_ActivateMe(IOleDocumentSite *iface, IOleDocum
expect_status_text = NULL;
hres = IOleDocumentView_UIActivate(view, TRUE);
-
- if(FAILED(hres)) {
- skip("UIActivate failed: %08x\n", hres);
- return hres;
- }
ok(hres == S_OK, "UIActivate failed: %08x\n", hres);
CHECK_CALLED(CanInPlaceActivate);
@@ -1724,6 +1732,14 @@ static HRESULT WINAPI DocumentSite_ActivateMe(IOleDocumentSite *iface, IOleDocum
expect_status_text = (load_state == LD_COMPLETE ? (LPCOLESTR)0xdeadbeef : NULL);
hres = IOleDocumentView_Show(view, TRUE);
+ if(FAILED(hres)) {
+ win_skip("Show failed\n");
+ if(activeobj)
+ IOleInPlaceActiveObject_Release(activeobj);
+ IOleDocument_Release(document);
+ show_failed = TRUE;
+ return S_OK;
+ }
ok(hres == S_OK, "Show failed: %08x\n", hres);
CHECK_CALLED(CanInPlaceActivate);
@@ -1918,7 +1934,10 @@ static HRESULT WINAPI DocHostUIHandler_UpdateUI(IDocHostUIHandler2 *iface)
static HRESULT WINAPI DocHostUIHandler_EnableModeless(IDocHostUIHandler2 *iface, BOOL fEnable)
{
- ok(0, "unexpected call\n");
+ if(fEnable)
+ CHECK_EXPECT(EnableModeless_TRUE);
+ else
+ CHECK_EXPECT(EnableModeless_FALSE);
return E_NOTIMPL;
}
@@ -2635,6 +2654,7 @@ static void test_Load(IPersistMoniker *persist)
}
SET_EXPECT(OnChanged_READYSTATE);
SET_EXPECT(Exec_ShellDocView_84);
+ SET_EXPECT(IsSystemMoniker);
SET_EXPECT(BindToStorage);
SET_EXPECT(SetActiveObject);
if(set_clientsite) {
@@ -2672,6 +2692,7 @@ static void test_Load(IPersistMoniker *persist)
container_locked = TRUE;
}
CHECK_CALLED(OnChanged_READYSTATE);
+ SET_CALLED(IsSystemMoniker); /* IE7 */
SET_CALLED(Exec_ShellDocView_84);
CHECK_CALLED(BindToStorage);
SET_CALLED(SetActiveObject); /* FIXME */
@@ -2719,6 +2740,10 @@ static void test_download(BOOL verb_done, BOOL css_dwl, BOOL css_try_dwl)
SET_EXPECT(UnlockRequest);
}
SET_EXPECT(Exec_Explorer_69);
+ SET_EXPECT(EnableModeless_TRUE); /* IE7 */
+ SET_EXPECT(Frame_EnableModeless_TRUE); /* IE7 */
+ SET_EXPECT(EnableModeless_FALSE); /* IE7 */
+ SET_EXPECT(Frame_EnableModeless_FALSE); /* IE7 */
SET_EXPECT(OnChanged_1005);
SET_EXPECT(OnChanged_READYSTATE);
SET_EXPECT(Exec_SETPROGRESSPOS);
@@ -2726,6 +2751,7 @@ static void test_download(BOOL verb_done, BOOL css_dwl, BOOL css_try_dwl)
SET_EXPECT(Exec_ShellDocView_103);
SET_EXPECT(Exec_MSHTML_PARSECOMPLETE);
SET_EXPECT(Exec_HTTPEQUIV_DONE);
+ SET_EXPECT(SetStatusText);
expect_status_text = (LPWSTR)0xdeadbeef; /* TODO */
while(!called_Exec_HTTPEQUIV_DONE && GetMessage(&msg, NULL, 0, 0)) {
@@ -2766,6 +2792,10 @@ static void test_download(BOOL verb_done, BOOL css_dwl, BOOL css_try_dwl)
}
}
SET_CALLED(Exec_Explorer_69);
+ SET_CALLED(EnableModeless_TRUE); /* IE7 */
+ SET_CALLED(Frame_EnableModeless_TRUE); /* IE7 */
+ SET_CALLED(EnableModeless_FALSE); /* IE7 */
+ SET_CALLED(Frame_EnableModeless_FALSE); /* IE7 */
CHECK_CALLED(OnChanged_1005);
CHECK_CALLED(OnChanged_READYSTATE);
CHECK_CALLED(Exec_SETPROGRESSPOS);
@@ -2773,6 +2803,7 @@ static void test_download(BOOL verb_done, BOOL css_dwl, BOOL css_try_dwl)
SET_CALLED(Exec_ShellDocView_103);
CHECK_CALLED(Exec_MSHTML_PARSECOMPLETE);
CHECK_CALLED(Exec_HTTPEQUIV_DONE);
+ SET_CALLED(SetStatusText);
load_state = LD_COMPLETE;
@@ -3044,6 +3075,7 @@ static void test_exec_editmode(IUnknown *unk, BOOL loaded)
SET_EXPECT(Invoke_AMBIENT_SILENT);
SET_EXPECT(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED);
SET_EXPECT(OnChanged_READYSTATE);
+ SET_EXPECT(IsSystemMoniker);
SET_EXPECT(Exec_ShellDocView_84);
if(loaded)
SET_EXPECT(BindToStorage);
@@ -3069,6 +3101,7 @@ static void test_exec_editmode(IUnknown *unk, BOOL loaded)
CHECK_CALLED(Invoke_AMBIENT_SILENT);
CHECK_CALLED(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED);
CHECK_CALLED(OnChanged_READYSTATE);
+ SET_CALLED(IsSystemMoniker); /* IE7 */
SET_CALLED(Exec_ShellDocView_84);
if(loaded)
CHECK_CALLED(BindToStorage);
@@ -3199,7 +3232,7 @@ static HWND create_container_window(void)
515, 530, NULL, NULL, NULL, NULL);
}
-static HRESULT test_DoVerb(IOleObject *oleobj)
+static void test_DoVerb(IOleObject *oleobj)
{
RECT rect = {0,0,500,500};
HRESULT hres;
@@ -3212,8 +3245,6 @@ static HRESULT test_DoVerb(IOleObject *oleobj)
expect_LockContainer_fLock = TRUE;
hres = IOleObject_DoVerb(oleobj, OLEIVERB_SHOW, NULL, &ClientSite, -1, container_hwnd, &rect);
- if(FAILED(hres))
- return hres;
ok(hres == S_OK, "DoVerb failed: %08x\n", hres);
if(!container_locked) {
@@ -3222,8 +3253,6 @@ static HRESULT test_DoVerb(IOleObject *oleobj)
container_locked = TRUE;
}
CHECK_CALLED(ActivateMe);
-
- return hres;
}
#define CLIENTSITE_EXPECTPATH 0x00000001
@@ -3465,7 +3494,7 @@ static void test_InPlaceDeactivate(IUnknown *unk, BOOL expect_call)
IOleInPlaceObjectWindowless_Release(windowlessobj);
}
-static HRESULT test_Activate(IUnknown *unk, DWORD flags)
+static void test_Activate(IUnknown *unk, DWORD flags)
{
IOleObject *oleobj = NULL;
IOleDocumentView *docview;
@@ -3480,8 +3509,6 @@ static HRESULT test_Activate(IUnknown *unk, DWORD flags)
hres = IUnknown_QueryInterface(unk, &IID_IOleObject, (void**)&oleobj);
ok(hres == S_OK, "QueryInterface(IID_IOleObject) failed: %08x\n", hres);
- if(FAILED(hres))
- return hres;
hres = IOleObject_GetUserClassID(oleobj, NULL);
ok(hres == E_INVALIDARG, "GetUserClassID returned: %08x, expected E_INVALIDARG\n", hres);
@@ -3494,8 +3521,7 @@ static HRESULT test_Activate(IUnknown *unk, DWORD flags)
test_ClientSite(oleobj, flags);
test_InPlaceDeactivate(unk, FALSE);
-
- hres = test_DoVerb(oleobj);
+ test_DoVerb(oleobj);
if(call_UIActivate == CallUIActivate_AfterShow) {
hres = IOleObject_QueryInterface(oleobj, &IID_IOleDocumentView, (void **)&docview);
@@ -3523,8 +3549,6 @@ static HRESULT test_Activate(IUnknown *unk, DWORD flags)
IOleObject_Release(oleobj);
test_OnFrameWindowActivate(unk);
-
- return hres;
}
static void test_Window(IUnknown *unk, BOOL expect_success)
@@ -3612,9 +3636,23 @@ static void test_Hide(void)
static HRESULT create_document(IUnknown **unk)
{
- HRESULT hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
+ IHTMLDocument5 *doc5;
+ HRESULT hres;
+
+ hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
&IID_IUnknown, (void**)unk);
ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
+ if(FAILED(hres))
+ return hres;
+
+ hres = IUnknown_QueryInterface(*unk, &IID_IHTMLDocument5, (void**)&doc5);
+ if(SUCCEEDED(hres)) {
+ IHTMLDocument5_Release(doc5);
+ }else {
+ win_skip("Could not get IHTMLDocument5, probably too old IE\n");
+ IUnknown_Release(*unk);
+ }
+
return hres;
}
@@ -3707,27 +3745,32 @@ static void test_QueryInterface(IUnknown *unk)
qi = (void*)0xdeadbeef;
hres = IUnknown_QueryInterface(unk, &IID_IRunnableObject, (void**)&qi);
ok(hres == E_NOINTERFACE, "QueryInterface returned %08x, expected E_NOINTERFACE\n", hres);
- ok(qi == NULL, "qirunnable=%p, ezpected NULL\n", qi);
+ ok(qi == NULL, "qirunnable=%p, expected NULL\n", qi);
qi = (void*)0xdeadbeef;
hres = IUnknown_QueryInterface(unk, &IID_IHTMLDOMNode, (void**)&qi);
ok(hres == E_NOINTERFACE, "QueryInterface returned %08x, expected E_NOINTERFACE\n", hres);
- ok(qi == NULL, "qi=%p, ezpected NULL\n", qi);
+ ok(qi == NULL, "qi=%p, expected NULL\n", qi);
qi = (void*)0xdeadbeef;
hres = IUnknown_QueryInterface(unk, &IID_IHTMLDOMNode2, (void**)&qi);
ok(hres == E_NOINTERFACE, "QueryInterface returned %08x, expected E_NOINTERFACE\n", hres);
- ok(qi == NULL, "qi=%p, ezpected NULL\n", qi);
+ ok(qi == NULL, "qi=%p, expected NULL\n", qi);
qi = (void*)0xdeadbeef;
hres = IUnknown_QueryInterface(unk, &IID_IPersistPropertyBag, (void**)&qi);
ok(hres == E_NOINTERFACE, "QueryInterface returned %08x, expected E_NOINTERFACE\n", hres);
- ok(qi == NULL, "qi=%p, ezpected NULL\n", qi);
+ ok(qi == NULL, "qi=%p, expected NULL\n", qi);
qi = (void*)0xdeadbeef;
hres = IUnknown_QueryInterface(unk, &IID_UndocumentedScriptIface, (void**)&qi);
ok(hres == E_NOINTERFACE, "QueryInterface returned %08x, expected E_NOINTERFACE\n", hres);
- ok(qi == NULL, "qi=%p, ezpected NULL\n", qi);
+ ok(qi == NULL, "qi=%p, expected NULL\n", qi);
+
+ qi = (void*)0xdeadbeef;
+ hres = IUnknown_QueryInterface(unk, &IID_IMarshal, (void**)&qi);
+ ok(hres == E_NOINTERFACE, "QueryInterface returned %08x, expected E_NOINTERFACE\n", hres);
+ ok(qi == NULL, "qi=%p, expected NULL\n", qi);
}
static void init_test(enum load_state_t ls) {
@@ -3768,11 +3811,7 @@ static void test_HTMLDocument(BOOL do_load)
if(!do_load)
test_OnAmbientPropertyChange2(unk);
- hres = test_Activate(unk, CLIENTSITE_EXPECTPATH);
- if(FAILED(hres)) {
- IUnknown_Release(unk);
- return;
- }
+ test_Activate(unk, CLIENTSITE_EXPECTPATH);
if(do_load) {
test_download(FALSE, TRUE, TRUE);
@@ -3865,6 +3904,10 @@ static void test_HTMLDocument_hlink(void)
test_GetCurMoniker(unk, NULL, NULL);
test_Persist(unk);
test_Navigate(unk);
+ if(show_failed) {
+ IUnknown_Release(unk);
+ return;
+ }
test_download(FALSE, TRUE, TRUE);
@@ -3999,7 +4042,11 @@ static void test_editing_mode(BOOL do_load)
test_MSHTML_QueryStatus(unk, OLECMDF_SUPPORTED);
test_download(TRUE, do_load, do_load);
+
+ SET_EXPECT(SetStatusText); /* ignore race in native mshtml */
test_timer(EXPECT_UPDATEUI);
+ SET_CALLED(SetStatusText);
+
test_MSHTML_QueryStatus(unk, OLECMDF_SUPPORTED|OLECMDF_ENABLED);
if(!do_load) {
@@ -4088,6 +4135,31 @@ static void gecko_installer_workaround(BOOL disable)
RegCloseKey(hkey);
}
+static void test_HTMLDoc_ISupportErrorInfo(void)
+{
+ HRESULT hres;
+ IUnknown *unk;
+ ISupportErrorInfo *sinfo;
+ LONG ref;
+
+ hres = create_document(&unk);
+ if(FAILED(hres))
+ return;
+
+ hres = IUnknown_QueryInterface(unk, &IID_ISupportErrorInfo, (void**)&sinfo);
+ ok(hres == S_OK, "got %x\n", hres);
+ ok(sinfo != NULL, "got %p\n", sinfo);
+ if(sinfo)
+ {
+ hres = ISupportErrorInfo_InterfaceSupportsErrorInfo(sinfo, &IID_IErrorInfo);
+ ok(hres == S_FALSE, "Expected S_OK, got %x\n", hres);
+ IUnknown_Release(sinfo);
+ }
+
+ ref = IUnknown_Release(unk);
+ ok(ref == 0, "ref=%d, expected 0\n", ref);
+}
+
START_TEST(htmldoc)
{
gecko_installer_workaround(TRUE);
@@ -4096,12 +4168,15 @@ START_TEST(htmldoc)
container_hwnd = create_container_window();
register_protocol();
- test_HTMLDocument(FALSE);
- test_HTMLDocument(TRUE);
test_HTMLDocument_hlink();
- test_HTMLDocument_StreamLoad();
- test_editing_mode(FALSE);
- test_editing_mode(TRUE);
+ if(!show_failed) {
+ test_HTMLDocument(FALSE);
+ test_HTMLDocument(TRUE);
+ test_HTMLDocument_StreamLoad();
+ test_editing_mode(FALSE);
+ test_editing_mode(TRUE);
+ }
+ test_HTMLDoc_ISupportErrorInfo();
DestroyWindow(container_hwnd);
CoUninitialize();
diff --git a/rostests/winetests/mshtml/misc.c b/rostests/winetests/mshtml/misc.c
index 62c7e37901d..ed8de36b9a3 100644
--- a/rostests/winetests/mshtml/misc.c
+++ b/rostests/winetests/mshtml/misc.c
@@ -24,9 +24,8 @@
#include "windef.h"
#include "winbase.h"
#include "ole2.h"
-#include "optary.h"
-
#include "initguid.h"
+#include "optary.h"
static void test_HTMLLoadOptions(void)
{
diff --git a/rostests/winetests/mshtml/protocol.c b/rostests/winetests/mshtml/protocol.c
index 4e8b3d0c79a..36355bf36b0 100644
--- a/rostests/winetests/mshtml/protocol.c
+++ b/rostests/winetests/mshtml/protocol.c
@@ -266,9 +266,13 @@ static void res_sec_url_cmp(LPCWSTR url, DWORD size, LPCWSTR file)
return;
}
+ SetLastError(0xdeadbeef);
len = SearchPathW(NULL, file, NULL, sizeof(buf)/sizeof(WCHAR), buf, NULL);
if(!len) {
- ok(0, "SearchPath failed: %u\n", GetLastError());
+ if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ win_skip("SearchPathW is not implemented\n");
+ else
+ ok(0, "SearchPath failed: %u\n", GetLastError());
return;
}
@@ -301,7 +305,7 @@ static void test_res_protocol(void)
hres = CoGetClassObject(&CLSID_ResProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
- if(!SUCCEEDED(hres))
+ if(FAILED(hres))
return;
hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
@@ -364,7 +368,7 @@ static void test_res_protocol(void)
sizeof(buf)/sizeof(buf[0]), &size, 0);
ok(hres == E_FAIL, "ParseUrl failed: %08x\n", hres);
ok(buf[0] == '?', "buf changed\n");
- ok(size == 1, "size=%u, ezpected 1\n", size);
+ ok(size == 1, "size=%u, expected 1\n", size);
buf[0] = '?';
hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_DOMAIN, 0, buf,
@@ -610,7 +614,7 @@ static void test_about_protocol(void)
hres = CoGetClassObject(&CLSID_AboutProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
- if(!SUCCEEDED(hres))
+ if(FAILED(hres))
return;
hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
@@ -660,7 +664,7 @@ static void test_about_protocol(void)
sizeof(buf)/sizeof(buf[0]), &size, 0);
ok(hres == E_FAIL, "ParseUrl failed: %08x\n", hres);
ok(buf[0] == '?', "buf changed\n");
- ok(size == 1, "size=%u, ezpected 1\n", size);
+ ok(size == 1, "size=%u, expected 1\n", size);
buf[0] = '?';
hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, PARSE_DOMAIN, 0, buf,
diff --git a/rostests/winetests/mshtml/script.c b/rostests/winetests/mshtml/script.c
index bbd9c3cca5f..6178cdf3fc9 100644
--- a/rostests/winetests/mshtml/script.c
+++ b/rostests/winetests/mshtml/script.c
@@ -28,11 +28,14 @@
#include "ole2.h"
#include "dispex.h"
#include "mshtml.h"
+#include "initguid.h"
#include "activscp.h"
#include "activdbg.h"
#include "objsafe.h"
#include "mshtmdid.h"
+DEFINE_GUID(CLSID_IdentityUnmarshal,0x0000001b,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
+
#define DEFINE_EXPECT(func) \
static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
@@ -81,6 +84,7 @@ DEFINE_EXPECT(SetScriptState_DISCONNECTED);
DEFINE_EXPECT(AddNamedItem);
DEFINE_EXPECT(ParseScriptText);
DEFINE_EXPECT(GetScriptDispatch);
+DEFINE_EXPECT(funcDisp);
#define TESTSCRIPT_CLSID "{178fc163-f585-4e24-9c13-4bb7faf80746}"
@@ -167,6 +171,145 @@ static IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = {
static IPropertyNotifySink PropertyNotifySink = { &PropertyNotifySinkVtbl };
+static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
+{
+ *ppv = NULL;
+
+ if(IsEqualGUID(riid, &IID_IUnknown)
+ || IsEqualGUID(riid, &IID_IDispatch)
+ || IsEqualGUID(riid, &IID_IDispatchEx))
+ *ppv = iface;
+ else
+ return E_NOINTERFACE;
+
+ return S_OK;
+}
+
+static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo,
+ LCID lcid, ITypeInfo **ppTInfo)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid,
+ LPOLESTR *rgszNames, UINT cNames,
+ LCID lcid, DISPID *rgDispId)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember,
+ REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
+ VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
+{
+ ok(0, "unexpected call %s %x\n", debugstr_w(bstrName), grfdex);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+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 IHTMLDocument2 *create_document(void)
{
IHTMLDocument2 *doc;
@@ -234,6 +377,10 @@ static IHTMLDocument2 *create_and_load_doc(const char *str)
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);
@@ -253,6 +400,12 @@ static IHTMLDocument2 *create_and_load_doc(const char *str)
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);
+ ok(hres == S_OK, "GetIDsOfNames(background) failed %08x\n", hres);
+ ok(dispID == DISPID_IHTMLBODYELEMENT_BACKGROUND, "Incorrect dispID got (%d)\n", dispID);
+
IHTMLElement_Release(body);
return doc;
}
@@ -440,7 +593,7 @@ static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *ifac
{
IDispatchEx *document;
IUnknown *unk;
- VARIANT var;
+ VARIANT var, arg;
DISPPARAMS dp;
EXCEPINFO ei;
DISPID id, named_arg = DISPID_PROPERTYPUT;
@@ -449,6 +602,7 @@ static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *ifac
static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
static const WCHAR testW[] = {'t','e','s','t',0};
+ static const WCHAR funcW[] = {'f','u','n','c',0};
CHECK_EXPECT(ParseScriptText);
@@ -512,13 +666,46 @@ static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *ifac
ok(V_VT(&var) == VT_I4, "V_VT(var)=%d\n", V_VT(&var));
ok(V_I4(&var) == 100, "V_I4(&var) == NULL\n");
- IDispatchEx_Release(document);
-
unk = (void*)0xdeadbeef;
hres = IDispatchEx_GetNameSpaceParent(window_dispex, &unk);
ok(hres == S_OK, "GetNameSpaceParent failed: %08x\n", hres);
ok(!unk, "unk=%p, expected NULL\n", unk);
+ id = 0;
+ tmp = SysAllocString(funcW);
+ hres = IDispatchEx_GetDispID(document, tmp, fdexNameCaseSensitive|fdexNameEnsure, &id);
+ SysFreeString(tmp);
+ ok(hres == S_OK, "GetDispID(func) failed: %08x\n", hres);
+ ok(id, "id == 0\n");
+
+ dp.cArgs = 1;
+ dp.rgvarg = &var;
+ dp.cNamedArgs = 0;
+ dp.rgdispidNamedArgs = NULL;
+ V_VT(&var) = VT_DISPATCH;
+ V_DISPATCH(&var) = (IDispatch*)&funcDisp;
+
+ 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));
+ V_VT(&arg) = VT_BOOL;
+ V_BOOL(&arg) = VARIANT_TRUE;
+ dp.cArgs = 1;
+ dp.rgvarg = &arg;
+
+ SET_EXPECT(funcDisp);
+ hres = IDispatchEx_InvokeEx(document, id, LOCALE_NEUTRAL, INVOKE_FUNC, &dp, &var, &ei, NULL);
+ CHECK_CALLED(funcDisp);
+
+ ok(hres == S_OK, "InvokeEx(INVOKE_FUNC) 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");
+
+ IDispatchEx_Release(document);
+
return S_OK;
}
@@ -580,6 +767,8 @@ static HRESULT WINAPI ActiveScript_SetScriptSite(IActiveScript *iface, IActiveSc
{
IActiveScriptSiteInterruptPoll *poll;
IActiveScriptSiteDebug *debug;
+ IServiceProvider *service;
+ ICanHandleException *canexpection;
LCID lcid;
HRESULT hres;
@@ -603,6 +792,14 @@ static HRESULT WINAPI ActiveScript_SetScriptSite(IActiveScript *iface, IActiveSc
if(SUCCEEDED(hres))
IActiveScriptSiteDebug32_Release(debug);
+ hres = IActiveScriptSite_QueryInterface(pass, &IID_ICanHandleException, (void**)&canexpection);
+ ok(hres == E_NOINTERFACE, "Could not get IID_ICanHandleException interface: %08x\n", hres);
+
+ hres = IActiveScriptSite_QueryInterface(pass, &IID_IServiceProvider, (void**)&service);
+ todo_wine ok(hres == S_OK, "Could not get IServiceProvider interface: %08x\n", hres);
+ if(SUCCEEDED(hres))
+ IServiceProvider_Release(service);
+
site = pass;
IActiveScriptSite_AddRef(site);
return S_OK;
@@ -940,16 +1137,41 @@ static void gecko_installer_workaround(BOOL disable)
RegCloseKey(hkey);
}
+/* Check if Internet Explorer is configured to run in "Enhanced Security Configuration" (aka hardened mode) */
+/* Note: this code is duplicated in dlls/mshtml/tests/dom.c, dlls/mshtml/tests/script.c and dlls/urlmon/tests/misc.c */
+static BOOL is_ie_hardened(void)
+{
+ HKEY zone_map;
+ DWORD ie_harden, type, size;
+
+ ie_harden = 0;
+ if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ZoneMap",
+ 0, KEY_QUERY_VALUE, &zone_map) == ERROR_SUCCESS) {
+ size = sizeof(DWORD);
+ if (RegQueryValueEx(zone_map, "IEHarden", NULL, &type, (LPBYTE) &ie_harden, &size) != ERROR_SUCCESS ||
+ type != REG_DWORD) {
+ ie_harden = 0;
+ }
+ RegCloseKey(zone_map);
+ }
+
+ return ie_harden != 0;
+}
+
START_TEST(script)
{
gecko_installer_workaround(TRUE);
CoInitialize(NULL);
- if(register_script_engine()) {
- test_simple_script();
- init_registry(FALSE);
+ if(winetest_interactive || ! is_ie_hardened()) {
+ if(register_script_engine()) {
+ test_simple_script();
+ init_registry(FALSE);
+ }else {
+ skip("Could not register TestScript engine\n");
+ }
}else {
- skip("Could not register TestScript engine\n");
+ skip("IE running in Enhanced Security Configuration\n");
}
CoUninitialize();
diff --git a/rostests/winetests/shdocvw/intshcut.c b/rostests/winetests/shdocvw/intshcut.c
new file mode 100644
index 00000000000..cf0b2251b93
--- /dev/null
+++ b/rostests/winetests/shdocvw/intshcut.c
@@ -0,0 +1,224 @@
+/*
+ * Unit tests to document InternetShortcut's behaviour
+ *
+ * Copyright 2008 Damjan Jovanovic
+ *
+ * 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
+ */
+
+#include
+#include
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "winerror.h"
+
+#include "shlobj.h"
+#include "shobjidl.h"
+#include "shlguid.h"
+#include "ole2.h"
+#include "initguid.h"
+#include "isguids.h"
+#include "intshcut.h"
+
+#include "wine/test.h"
+
+static HRESULT WINAPI Unknown_QueryInterface(IUnknown *pUnknown, REFIID riid, void **ppvObject)
+{
+ if (IsEqualGUID(&IID_IUnknown, riid))
+ {
+ *ppvObject = pUnknown;
+ return S_OK;
+ }
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI Unknown_AddRef(IUnknown *pUnknown)
+{
+ return 2;
+}
+
+static ULONG WINAPI Unknown_Release(IUnknown *pUnknown)
+{
+ return 1;
+}
+
+static IUnknownVtbl unknownVtbl = {
+ Unknown_QueryInterface,
+ Unknown_AddRef,
+ Unknown_Release
+};
+
+static IUnknown unknown = {
+ &unknownVtbl
+};
+
+static const char *printGUID(const GUID *guid)
+{
+ static char guidSTR[39];
+
+ if (!guid) return NULL;
+
+ sprintf(guidSTR, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
+ guid->Data1, guid->Data2, guid->Data3,
+ guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
+ guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
+ return guidSTR;
+}
+
+static void test_Aggregability(void)
+{
+ HRESULT hr;
+ IUnknown *pUnknown = NULL;
+
+ hr = CoCreateInstance(&CLSID_InternetShortcut, NULL, CLSCTX_ALL, &IID_IUnknown, (void**)&pUnknown);
+ ok(SUCCEEDED(hr), "could not create instance of CLSID_InternetShortcut with IID_IUnknown, hr = 0x%x\n", hr);
+ if (pUnknown)
+ IUnknown_Release(pUnknown);
+
+ hr = CoCreateInstance(&CLSID_InternetShortcut, NULL, CLSCTX_ALL, &IID_IUniformResourceLocatorA, (void**)&pUnknown);
+ ok(SUCCEEDED(hr), "could not create instance of CLSID_InternetShortcut with IID_IUniformResourceLocatorA, hr = 0x%x\n", hr);
+ if (pUnknown)
+ IUnknown_Release(pUnknown);
+
+ hr = CoCreateInstance(&CLSID_InternetShortcut, &unknown, CLSCTX_ALL, &IID_IUnknown, (void**)&pUnknown);
+ ok(FAILED(hr), "aggregation didn't fail like it should, hr = 0x%x\n", hr);
+ if (pUnknown)
+ IUnknown_Release(pUnknown);
+}
+
+static void can_query_interface(IUnknown *pUnknown, REFIID riid)
+{
+ HRESULT hr;
+ IUnknown *newInterface;
+ hr = IUnknown_QueryInterface(pUnknown, riid, (void**)&newInterface);
+ ok(SUCCEEDED(hr), "interface %s could not be queried\n", printGUID(riid));
+ if (SUCCEEDED(hr))
+ IUnknown_Release(newInterface);
+}
+
+static void test_QueryInterface(void)
+{
+ HRESULT hr;
+ IUnknown *pUnknown;
+
+ hr = CoCreateInstance(&CLSID_InternetShortcut, NULL, CLSCTX_ALL, &IID_IUnknown, (void**)&pUnknown);
+ if (SUCCEEDED(hr))
+ {
+ can_query_interface(pUnknown, &IID_IUniformResourceLocatorA);
+ can_query_interface(pUnknown, &IID_IUniformResourceLocatorW);
+ can_query_interface(pUnknown, &IID_IPersistFile);
+ IUnknown_Release(pUnknown);
+ }
+ else
+ skip("could not create a CLSID_InternetShortcut for QueryInterface tests, hr=0x%x\n", hr);
+}
+
+static CHAR *set_and_get_url(IUniformResourceLocatorA *urlA, LPCSTR input, DWORD flags)
+{
+ HRESULT hr;
+ hr = urlA->lpVtbl->SetURL(urlA, input, flags);
+ if (SUCCEEDED(hr))
+ {
+ CHAR *output;
+ hr = urlA->lpVtbl->GetURL(urlA, &output);
+ if (SUCCEEDED(hr))
+ return output;
+ else
+ skip("GetUrl failed, hr=0x%x\n", hr);
+ }
+ else
+ skip("SetUrl (%s, 0x%x) failed, hr=0x%x\n", input, flags, hr);
+ return NULL;
+}
+
+static void check_string_transform(IUniformResourceLocatorA *urlA, LPCSTR input, DWORD flags, LPCSTR expectedOutput)
+{
+ CHAR *output = set_and_get_url(urlA, input, flags);
+ if (output != NULL)
+ {
+ ok(lstrcmpA(output, expectedOutput) == 0, "unexpected URL change %s -> %s (expected %s)\n",
+ input, output, expectedOutput);
+ CoTaskMemFree(output);
+ }
+}
+
+static void test_NullURLs(void)
+{
+ HRESULT hr;
+ IUniformResourceLocatorA *urlA;
+
+ hr = CoCreateInstance(&CLSID_InternetShortcut, NULL, CLSCTX_ALL, &IID_IUniformResourceLocatorA, (void**)&urlA);
+ if (SUCCEEDED(hr))
+ {
+ LPSTR url = NULL;
+
+ hr = urlA->lpVtbl->GetURL(urlA, &url);
+ ok(SUCCEEDED(hr), "getting uninitialized URL unexpectedly failed, hr=0x%x\n", hr);
+ ok(url == NULL, "uninitialized URL is not NULL but %s\n", url);
+
+ hr = urlA->lpVtbl->SetURL(urlA, NULL, 0);
+ ok(SUCCEEDED(hr), "setting NULL URL unexpectedly failed, hr=0x%x\n", hr);
+
+ hr = urlA->lpVtbl->GetURL(urlA, &url);
+ ok(SUCCEEDED(hr), "getting NULL URL unexpectedly failed, hr=0x%x\n", hr);
+ ok(url == NULL, "URL unexpectedly not NULL but %s\n", url);
+
+ urlA->lpVtbl->Release(urlA);
+ }
+ else
+ skip("could not create a CLSID_InternetShortcut for NullURL tests, hr=0x%x\n", hr);
+}
+
+static void test_SetURLFlags(void)
+{
+ HRESULT hr;
+ IUniformResourceLocatorA *urlA;
+
+ hr = CoCreateInstance(&CLSID_InternetShortcut, NULL, CLSCTX_ALL, &IID_IUniformResourceLocatorA, (void**)&urlA);
+ if (SUCCEEDED(hr))
+ {
+ check_string_transform(urlA, "somerandomstring", 0, "somerandomstring");
+ check_string_transform(urlA, "www.winehq.org", 0, "www.winehq.org");
+
+ todo_wine
+ {
+ check_string_transform(urlA, "www.winehq.org", IURL_SETURL_FL_GUESS_PROTOCOL, "http://www.winehq.org/");
+ check_string_transform(urlA, "ftp.winehq.org", IURL_SETURL_FL_GUESS_PROTOCOL, "ftp://ftp.winehq.org/");
+ }
+
+ urlA->lpVtbl->Release(urlA);
+ }
+ else
+ skip("could not create a CLSID_InternetShortcut for SetUrl tests, hr=0x%x\n", hr);
+}
+
+static void test_InternetShortcut(void)
+{
+ test_Aggregability();
+ test_QueryInterface();
+ test_NullURLs();
+ test_SetURLFlags();
+}
+
+START_TEST(intshcut)
+{
+ OleInitialize(NULL);
+ test_InternetShortcut();
+ OleUninitialize();
+}
diff --git a/rostests/winetests/shdocvw/shdocvw.c b/rostests/winetests/shdocvw/shdocvw.c
new file mode 100644
index 00000000000..8e7b1f3d213
--- /dev/null
+++ b/rostests/winetests/shdocvw/shdocvw.c
@@ -0,0 +1,360 @@
+/*
+ * Unit tests for misc shdocvw functions
+ *
+ * Copyright 2008 Detlef Riekenberg
+ *
+ * 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
+ */
+
+
+#include
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "wininet.h"
+#include "winnls.h"
+
+#include "wine/test.h"
+
+/* ################ */
+
+static HMODULE hshdocvw;
+static HRESULT (WINAPI *pURLSubRegQueryA)(LPCSTR, LPCSTR, DWORD, LPVOID, DWORD, DWORD);
+static DWORD (WINAPI *pParseURLFromOutsideSourceA)(LPCSTR, LPSTR, LPDWORD, LPDWORD);
+static DWORD (WINAPI *pParseURLFromOutsideSourceW)(LPCWSTR, LPWSTR, LPDWORD, LPDWORD);
+
+static CHAR appdata[] = "AppData";
+static CHAR common_appdata[] = "Common AppData";
+static CHAR default_page_url[] = "Default_Page_URL";
+static CHAR does_not_exist[] = "does_not_exist";
+static CHAR regpath_iemain[] = "Software\\Microsoft\\Internet Explorer\\Main";
+static CHAR regpath_shellfolders[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
+static CHAR start_page[] = "Start Page";
+
+/* ################ */
+
+static const struct {
+ const char *url;
+ const char *newurl;
+ DWORD len;
+} ParseURL_table[] = {
+ {"http://www.winehq.org", "http://www.winehq.org/", 22},
+ {"www.winehq.org", "http://www.winehq.org/", 22},
+ {"winehq.org", "http://winehq.org/", 18},
+ {"ftp.winehq.org", "ftp://ftp.winehq.org/", 21},
+ {"http://winehq.org", "http://winehq.org/", 18},
+ {"https://winehq.org", "https://winehq.org/", 19},
+ {"https://www.winehq.org", "https://www.winehq.org/", 23},
+ {"ftp://winehq.org", "ftp://winehq.org/", 17},
+ {"ftp://ftp.winehq.org", "ftp://ftp.winehq.org/", 21},
+ {"about:blank", "about:blank", 11},
+ {"about:home", "about:home", 10},
+ {"about:mozilla", "about:mozilla", 13},
+ /* a space at the start is not allowed */
+ {" http://www.winehq.org", "http://%20http://www.winehq.org", 31}
+
+};
+
+/* ################ */
+
+static void init_functions(void)
+{
+ hshdocvw = LoadLibraryA("shdocvw.dll");
+ pURLSubRegQueryA = (void *) GetProcAddress(hshdocvw, (LPSTR) 151);
+ pParseURLFromOutsideSourceA = (void *) GetProcAddress(hshdocvw, (LPSTR) 169);
+ pParseURLFromOutsideSourceW = (void *) GetProcAddress(hshdocvw, (LPSTR) 170);
+}
+
+/* ################ */
+
+static void test_URLSubRegQueryA(void)
+{
+ CHAR buffer[INTERNET_MAX_URL_LENGTH];
+ HRESULT hr;
+ DWORD used;
+ DWORD len;
+
+ if (!pURLSubRegQueryA) {
+ skip("URLSubRegQueryA not found\n");
+ return;
+ }
+
+ memset(buffer, '#', sizeof(buffer)-1);
+ buffer[sizeof(buffer)-1] = '\0';
+ /* called by inetcpl.cpl */
+ hr = pURLSubRegQueryA(regpath_iemain, default_page_url, REG_SZ, buffer, INTERNET_MAX_URL_LENGTH, -1);
+ ok(hr == E_FAIL || hr == S_OK, "got 0x%x (expected E_FAIL or S_OK)\n", hr);
+
+ memset(buffer, '#', sizeof(buffer)-1);
+ buffer[sizeof(buffer)-1] = '\0';
+ /* called by inetcpl.cpl */
+ hr = pURLSubRegQueryA(regpath_iemain, start_page, REG_SZ, buffer, INTERNET_MAX_URL_LENGTH, -1);
+ len = lstrlenA(buffer);
+ /* respect privacy: do not dump the url */
+ ok(hr == S_OK, "got 0x%x and %d (expected S_OK)\n", hr, len);
+
+ /* test buffer length: just large enough */
+ memset(buffer, '#', sizeof(buffer)-1);
+ buffer[sizeof(buffer)-1] = '\0';
+ hr = pURLSubRegQueryA(regpath_iemain, start_page, REG_SZ, buffer, len+1, -1);
+ used = lstrlenA(buffer);
+ /* respect privacy: do not dump the url */
+ ok((hr == S_OK) && (used == len),
+ "got 0x%x and %d (expected S_OK and %d)\n", hr, used, len);
+
+ /* no space for terminating 0: result is truncated */
+ memset(buffer, '#', sizeof(buffer)-1);
+ buffer[sizeof(buffer)-1] = '\0';
+ hr = pURLSubRegQueryA(regpath_iemain, start_page, REG_SZ, buffer, len, -1);
+ used = lstrlenA(buffer);
+ ok((hr == S_OK) && (used == len - 1),
+ "got 0x%x and %d (expected S_OK and %d)\n", hr, used, len - 1);
+
+ /* no space for the complete result: truncate another char */
+ if (len > 1) {
+ memset(buffer, '#', sizeof(buffer)-1);
+ buffer[sizeof(buffer)-1] = '\0';
+ hr = pURLSubRegQueryA(regpath_iemain, start_page, REG_SZ, buffer, len-1, -1);
+ used = lstrlenA(buffer);
+ ok((hr == S_OK) && (used == (len - 2)),
+ "got 0x%x and %d (expected S_OK and %d)\n", hr, used, len - 2);
+ }
+
+ /* only space for the terminating 0: function still succeded */
+ memset(buffer, '#', sizeof(buffer)-1);
+ buffer[sizeof(buffer)-1] = '\0';
+ hr = pURLSubRegQueryA(regpath_iemain, start_page, REG_SZ, buffer, 1, -1);
+ used = lstrlenA(buffer);
+ ok((hr == S_OK) && !used,
+ "got 0x%x and %d (expected S_OK and 0)\n", hr, used);
+
+ /* size of buffer is 0, but the function still succeed.
+ buffer[0] is cleared in IE 5.01 and IE 5.5 (Buffer Overflow) */
+ memset(buffer, '#', sizeof(buffer)-1);
+ buffer[sizeof(buffer)-1] = '\0';
+ hr = pURLSubRegQueryA(regpath_iemain, start_page, REG_SZ, buffer, 0, -1);
+ used = lstrlenA(buffer);
+ ok( (hr == S_OK) &&
+ ((used == INTERNET_MAX_URL_LENGTH - 1) || broken(used == 0)) ,
+ "got 0x%x and %d (expected S_OK and INTERNET_MAX_URL_LENGTH - 1)\n",
+ hr, used);
+
+ /* still succeed without a buffer for the result */
+ hr = pURLSubRegQueryA(regpath_iemain, start_page, REG_SZ, NULL, 0, -1);
+ ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
+
+ /* still succeed, when a length is given without a buffer */
+ hr = pURLSubRegQueryA(regpath_iemain, start_page, REG_SZ, NULL, INTERNET_MAX_URL_LENGTH, -1);
+ ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
+
+ /* this value does not exist */
+ memset(buffer, '#', sizeof(buffer)-1);
+ buffer[sizeof(buffer)-1] = '\0';
+ hr = pURLSubRegQueryA(regpath_iemain, does_not_exist, REG_SZ, buffer, INTERNET_MAX_URL_LENGTH, -1);
+ /* random bytes are copied to the buffer */
+ ok((hr == E_FAIL), "got 0x%x (expected E_FAIL)\n", hr);
+
+ /* the third parameter is ignored. Is it really a type? (data is REG_SZ) */
+ memset(buffer, '#', sizeof(buffer)-1);
+ buffer[sizeof(buffer)-1] = '\0';
+ hr = pURLSubRegQueryA(regpath_iemain, start_page, REG_DWORD, buffer, INTERNET_MAX_URL_LENGTH, -1);
+ used = lstrlenA(buffer);
+ ok((hr == S_OK) && (used == len),
+ "got 0x%x and %d (expected S_OK and %d)\n", hr, used, len);
+
+ /* the function works for HKCU and HKLM */
+ memset(buffer, '#', sizeof(buffer)-1);
+ buffer[sizeof(buffer)-1] = '\0';
+ hr = pURLSubRegQueryA(regpath_shellfolders, appdata, REG_SZ, buffer, INTERNET_MAX_URL_LENGTH, -1);
+ used = lstrlenA(buffer);
+ ok(hr == S_OK, "got 0x%x and %d (expected S_OK)\n", hr, used);
+
+ memset(buffer, '#', sizeof(buffer)-1);
+ buffer[sizeof(buffer)-1] = '\0';
+ hr = pURLSubRegQueryA(regpath_shellfolders, common_appdata, REG_SZ, buffer, INTERNET_MAX_URL_LENGTH, -1);
+ used = lstrlenA(buffer);
+ ok(hr == S_OK, "got 0x%x and %d (expected S_OK)\n", hr, used);
+
+ /* todo: what does the last parameter mean? */
+}
+
+/* ################ */
+
+static void test_ParseURLFromOutsideSourceA(void)
+{
+ CHAR buffer[INTERNET_MAX_URL_LENGTH];
+ DWORD dummy;
+ DWORD maxlen;
+ DWORD len;
+ DWORD res;
+ int i;
+
+ if (!pParseURLFromOutsideSourceA) {
+ skip("ParseURLFromOutsideSourceA not found\n");
+ return;
+ }
+
+ for(i = 0; i < sizeof(ParseURL_table)/sizeof(ParseURL_table[0]); i++) {
+ memset(buffer, '#', sizeof(buffer)-1);
+ buffer[sizeof(buffer)-1] = '\0';
+ len = sizeof(buffer);
+ dummy = 0;
+ /* on success, len+1 is returned. No idea, if someone depend on this */
+ res = pParseURLFromOutsideSourceA(ParseURL_table[i].url, buffer, &len, &dummy);
+ /* len does not include the terminating 0, when buffer is large enough */
+ ok( res != 0 && len == ParseURL_table[i].len &&
+ !lstrcmpA(buffer, ParseURL_table[i].newurl),
+ "#%d: got %d and %d with '%s' (expected '!=0' and %d with '%s')\n",
+ i, res, len, buffer, ParseURL_table[i].len, ParseURL_table[i].newurl);
+
+
+ /* use the size test only for the first examples */
+ if (i > 4) continue;
+
+ maxlen = len;
+
+ memset(buffer, '#', sizeof(buffer)-1);
+ buffer[sizeof(buffer)-1] = '\0';
+ len = maxlen + 1;
+ dummy = 0;
+ res = pParseURLFromOutsideSourceA(ParseURL_table[i].url, buffer, &len, &dummy);
+ ok( res != 0 && len == ParseURL_table[i].len &&
+ !lstrcmpA(buffer, ParseURL_table[i].newurl),
+ "#%d (+1): got %d and %d with '%s' (expected '!=0' and %d with '%s')\n",
+ i, res, len, buffer, ParseURL_table[i].len, ParseURL_table[i].newurl);
+
+ memset(buffer, '#', sizeof(buffer)-1);
+ buffer[sizeof(buffer)-1] = '\0';
+ len = maxlen;
+ dummy = 0;
+ res = pParseURLFromOutsideSourceA(ParseURL_table[i].url, buffer, &len, &dummy);
+ /* len includes the terminating 0, when the buffer is too small */
+ ok( res == 0 && len == ParseURL_table[i].len + 1,
+ "#%d (==): got %d and %d (expected '0' and %d)\n",
+ i, res, len, ParseURL_table[i].len + 1);
+
+ memset(buffer, '#', sizeof(buffer)-1);
+ buffer[sizeof(buffer)-1] = '\0';
+ len = maxlen-1;
+ dummy = 0;
+ res = pParseURLFromOutsideSourceA(ParseURL_table[i].url, buffer, &len, &dummy);
+ /* len includes the terminating 0 on XP SP1 and before, when the buffer is too small */
+ ok( res == 0 && (len == ParseURL_table[i].len || len == ParseURL_table[i].len + 1),
+ "#%d (-1): got %d and %d (expected '0' and %d or %d)\n",
+ i, res, len, ParseURL_table[i].len, ParseURL_table[i].len + 1);
+
+ memset(buffer, '#', sizeof(buffer)-1);
+ buffer[sizeof(buffer)-1] = '\0';
+ len = maxlen+1;
+ dummy = 0;
+ res = pParseURLFromOutsideSourceA(ParseURL_table[i].url, NULL, &len, &dummy);
+ /* len does not include the terminating 0, when buffer is NULL */
+ ok( res == 0 && len == ParseURL_table[i].len,
+ "#%d (buffer): got %d and %d (expected '0' and %d)\n",
+ i, res, len, ParseURL_table[i].len);
+
+ if (0) {
+ /* that test crash on native shdocvw */
+ res = pParseURLFromOutsideSourceA(ParseURL_table[i].url, buffer, NULL, &dummy);
+ }
+
+ memset(buffer, '#', sizeof(buffer)-1);
+ buffer[sizeof(buffer)-1] = '\0';
+ len = maxlen+1;
+ dummy = 0;
+ res = pParseURLFromOutsideSourceA(ParseURL_table[i].url, buffer, &len, NULL);
+ ok( res != 0 && len == ParseURL_table[i].len &&
+ !lstrcmpA(buffer, ParseURL_table[i].newurl),
+ "#%d (unknown): got %d and %d with '%s' (expected '!=0' and %d with '%s')\n",
+ i, res, len, buffer, ParseURL_table[i].len, ParseURL_table[i].newurl);
+ }
+}
+
+/* ################ */
+
+static void test_ParseURLFromOutsideSourceW(void)
+{
+ WCHAR urlW[INTERNET_MAX_URL_LENGTH];
+ WCHAR bufferW[INTERNET_MAX_URL_LENGTH];
+ CHAR bufferA[INTERNET_MAX_URL_LENGTH];
+ DWORD maxlen;
+ DWORD dummy;
+ DWORD len;
+ DWORD res;
+
+ if (!pParseURLFromOutsideSourceW) {
+ skip("ParseURLFromOutsideSourceW not found\n");
+ return;
+ }
+ MultiByteToWideChar(CP_ACP, 0, ParseURL_table[0].url, -1, urlW, INTERNET_MAX_URL_LENGTH);
+
+ memset(bufferA, '#', sizeof(bufferA)-1);
+ bufferA[sizeof(bufferA) - 1] = '\0';
+ MultiByteToWideChar(CP_ACP, 0, bufferA, -1, bufferW, INTERNET_MAX_URL_LENGTH);
+
+ /* len is in characters */
+ len = sizeof(bufferW)/sizeof(bufferW[0]);
+ dummy = 0;
+ res = pParseURLFromOutsideSourceW(urlW, bufferW, &len, &dummy);
+ WideCharToMultiByte(CP_ACP, 0, bufferW, -1, bufferA, sizeof(bufferA), NULL, NULL);
+ ok( res != 0 && len == ParseURL_table[0].len &&
+ !lstrcmpA(bufferA, ParseURL_table[0].newurl),
+ "got %d and %d with '%s' (expected '!=0' and %d with '%s')\n",
+ res, len, bufferA, ParseURL_table[0].len, ParseURL_table[0].newurl);
+
+
+ maxlen = len;
+
+ memset(bufferA, '#', sizeof(bufferA)-1);
+ bufferA[sizeof(bufferA) - 1] = '\0';
+ MultiByteToWideChar(CP_ACP, 0, bufferA, -1, bufferW, INTERNET_MAX_URL_LENGTH);
+ len = maxlen+1;
+ dummy = 0;
+ res = pParseURLFromOutsideSourceW(urlW, bufferW, &len, &dummy);
+ WideCharToMultiByte(CP_ACP, 0, bufferW, -1, bufferA, sizeof(bufferA), NULL, NULL);
+ /* len does not include the terminating 0, when buffer is large enough */
+ ok( res != 0 && len == ParseURL_table[0].len &&
+ !lstrcmpA(bufferA, ParseURL_table[0].newurl),
+ "+1: got %d and %d with '%s' (expected '!=0' and %d with '%s')\n",
+ res, len, bufferA, ParseURL_table[0].len, ParseURL_table[0].newurl);
+
+ len = maxlen;
+ dummy = 0;
+ res = pParseURLFromOutsideSourceW(urlW, bufferW, &len, &dummy);
+ /* len includes the terminating 0, when the buffer is too small */
+ ok( res == 0 && len == ParseURL_table[0].len + 1,
+ "==: got %d and %d (expected '0' and %d)\n",
+ res, len, ParseURL_table[0].len + 1);
+
+ len = maxlen - 1;
+ dummy = 0;
+ res = pParseURLFromOutsideSourceW(urlW, bufferW, &len, &dummy);
+ /* len includes the terminating 0 on XP SP1 and before, when the buffer is too small */
+ ok( res == 0 && (len == ParseURL_table[0].len || len == ParseURL_table[0].len + 1),
+ "-1: got %d and %d (expected '0' and %d or %d)\n",
+ res, len, ParseURL_table[0].len, ParseURL_table[0].len + 1);
+
+}
+
+/* ################ */
+
+START_TEST(shdocvw)
+{
+ init_functions();
+ test_URLSubRegQueryA();
+ test_ParseURLFromOutsideSourceA();
+ test_ParseURLFromOutsideSourceW();
+}
diff --git a/rostests/winetests/shdocvw/shdocvw.rbuild b/rostests/winetests/shdocvw/shdocvw.rbuild
new file mode 100644
index 00000000000..ef90f60e4aa
--- /dev/null
+++ b/rostests/winetests/shdocvw/shdocvw.rbuild
@@ -0,0 +1,23 @@
+
+
+
+
+ -Wno-format
+ .
+
+ intshcut.c
+ shdocvw.c
+ shortcut.c
+ webbrowser.c
+ testlist.c
+ wine
+ gdi32
+ shell32
+ ole32
+ oleaut32
+ user32
+ advapi32
+ kernel32
+ ntdll
+
+
diff --git a/rostests/winetests/shdocvw/shortcut.c b/rostests/winetests/shdocvw/shortcut.c
new file mode 100644
index 00000000000..5a740dc7dfd
--- /dev/null
+++ b/rostests/winetests/shdocvw/shortcut.c
@@ -0,0 +1,231 @@
+/*
+ * Unit tests to document shdocvw's 'Shell Instance Objects' features
+ *
+ * Copyright 2005 Michael Jung
+ *
+ * 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
+ */
+
+/* At least since Windows 2000 it's possible to add FolderShortcut objects
+ * by creating some registry entries. Those objects, which refer to some
+ * point in the filesystem, can be registered in the shell namespace like other
+ * shell namespace extensions. Icons, names and filesystem location can be
+ * configured. This is documented at http://www.virtualplastic.net/html/ui_shell.html
+ * You can also google for a tool called "ShellObjectEditor" by "Tropical
+ * Technologies". This mechanism would be cool for wine, since we could
+ * map Gnome's virtual devices to FolderShortcuts and have them appear in the
+ * file dialogs. These unit tests are meant to document how this mechanism
+ * works on windows.
+ *
+ * Search MSDN for "Creating Shell Extensions with Shell Instance Objects" for
+ * more documentation.*/
+
+#include
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+
+#include "shlobj.h"
+#include "shobjidl.h"
+#include "shlguid.h"
+#include "ole2.h"
+
+#include "wine/test.h"
+
+/* The following definitions and helper functions are meant to make the de-/registration
+ * of the various necessary registry keys easier. */
+
+struct registry_value {
+ const char *szName;
+ const DWORD dwType;
+ const char *szValue;
+ const DWORD dwValue;
+};
+
+#define REG_VALUE_ADDR(x) ((x->dwType==REG_SZ)?(const BYTE *)x->szValue:(const BYTE *)&x->dwValue)
+#define REG_VALUE_SIZE(x) ((x->dwType==REG_SZ)?strlen(x->szValue)+1:sizeof(DWORD))
+
+struct registry_key {
+ const char *szName;
+ const struct registry_value *pValues;
+ const unsigned int cValues;
+ const struct registry_key *pSubKeys;
+ const unsigned int cSubKeys;
+};
+
+static const struct registry_value ShellFolder_values[] = {
+ { "WantsFORPARSING", REG_SZ, "", 0 },
+ { "Attributes", REG_DWORD, NULL, 0xF8000100 }
+};
+
+static const struct registry_value Instance_values[] = {
+ { "CLSID", REG_SZ, "{0AFACED1-E828-11D1-9187-B532F1E9575D}", 0 }
+};
+
+static const struct registry_value InitPropertyBag_values[] = {
+ { "Attributes", REG_DWORD, NULL, 0x00000015 },
+ { "Target", REG_SZ, "C:\\", 0 }
+};
+
+static const struct registry_key Instance_keys[] = {
+ { "InitPropertyBag", InitPropertyBag_values, 2, NULL, 0 }
+};
+
+static const struct registry_value InProcServer32_values[] = {
+ { NULL, REG_SZ, "shdocvw.dll", 0 },
+ { "ThreadingModel", REG_SZ, "Apartment", 0 }
+};
+
+static const struct registry_value DefaultIcon_values[] = {
+ { NULL, REG_SZ,"shell32.dll,8", 0 }
+};
+
+static const struct registry_key ShortcutCLSID_keys[] = {
+ { "DefaultIcon", DefaultIcon_values, 1, NULL, 0 },
+ { "InProcServer32", InProcServer32_values, 2, NULL, 0 },
+ { "Instance", Instance_values, 1, Instance_keys, 1 },
+ { "ShellFolder", ShellFolder_values, 2, NULL, 0 }
+};
+
+static const struct registry_value ShortcutCLSID_values[] = {
+ { NULL, REG_SZ, "WineTest", 0 }
+};
+
+static const struct registry_key HKEY_CLASSES_ROOT_keys[] = {
+ { "CLSID\\{9B352EBF-2765-45C1-B4C6-85CC7F7ABC64}", ShortcutCLSID_values, 1, ShortcutCLSID_keys, 4}
+};
+
+/* register_keys - helper function, which recursively creates the registry keys and values in
+ * parameter 'keys' in the registry under hRootKey. */
+static BOOL register_keys(HKEY hRootKey, const struct registry_key *keys, unsigned int numKeys) {
+ HKEY hKey;
+ unsigned int iKey, iValue;
+
+ for (iKey = 0; iKey < numKeys; iKey++) {
+ if (ERROR_SUCCESS == RegCreateKeyExA(hRootKey, keys[iKey].szName, 0, NULL, 0,
+ KEY_WRITE, NULL, &hKey, NULL))
+ {
+ for (iValue = 0; iValue < keys[iKey].cValues; iValue++) {
+ const struct registry_value * value = &keys[iKey].pValues[iValue];
+ if (ERROR_SUCCESS != RegSetValueExA(hKey, value->szName, 0, value->dwType,
+ REG_VALUE_ADDR(value), REG_VALUE_SIZE(value)))
+ {
+ RegCloseKey(hKey);
+ return FALSE;
+ }
+ }
+
+ if (!register_keys(hKey, keys[iKey].pSubKeys, keys[iKey].cSubKeys)) {
+ RegCloseKey(hKey);
+ return FALSE;
+ }
+
+ RegCloseKey(hKey);
+ }
+ }
+
+ return TRUE;
+}
+
+/* unregister_keys - clean up after register_keys */
+static void unregister_keys(HKEY hRootKey, const struct registry_key *keys, unsigned int numKeys) {
+ HKEY hKey;
+ unsigned int iKey;
+
+ for (iKey = 0; iKey < numKeys; iKey++) {
+ if (ERROR_SUCCESS == RegOpenKeyExA(hRootKey, keys[iKey].szName, 0, DELETE, &hKey)) {
+ unregister_keys(hKey, keys[iKey].pSubKeys, keys[iKey].cSubKeys);
+ RegCloseKey(hKey);
+ }
+ RegDeleteKeyA(hRootKey, keys[iKey].szName);
+ }
+}
+
+static void test_ShortcutFolder(void) {
+ LPSHELLFOLDER pDesktopFolder, pWineTestFolder;
+ IPersistFolder3 *pWineTestPersistFolder;
+ LPITEMIDLIST pidlWineTestFolder, pidlCurFolder;
+ HRESULT hr;
+ CLSID clsid;
+ const CLSID CLSID_WineTest =
+ { 0x9b352ebf, 0x2765, 0x45c1, { 0xb4, 0xc6, 0x85, 0xcc, 0x7f, 0x7a, 0xbc, 0x64 } };
+ WCHAR wszWineTestFolder[] = {
+ ':',':','{','9','B','3','5','2','E','B','F','-','2','7','6','5','-','4','5','C','1','-',
+ 'B','4','C','6','-','8','5','C','C','7','F','7','A','B','C','6','4','}',0 };
+
+ /* First, we register all the necessary registry keys/values for our 'WineTest'
+ * shell object. */
+ register_keys(HKEY_CLASSES_ROOT, HKEY_CLASSES_ROOT_keys, 1);
+
+ hr = SHGetDesktopFolder(&pDesktopFolder);
+ ok (SUCCEEDED(hr), "SHGetDesktopFolder failed! hr = %08x\n", hr);
+ if (FAILED(hr)) goto cleanup;
+
+ /* Convert the wszWineTestFolder string to an ITEMIDLIST. */
+ hr = IShellFolder_ParseDisplayName(pDesktopFolder, NULL, NULL, wszWineTestFolder, NULL,
+ &pidlWineTestFolder, NULL);
+ todo_wine
+ {
+ ok (hr == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
+ "Expected %08x, got %08x\n", HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), hr);
+ }
+ if (FAILED(hr)) {
+ IShellFolder_Release(pDesktopFolder);
+ goto cleanup;
+ }
+
+ /* FIXME: these tests are never run */
+
+ /* Bind to a WineTest folder object. There has to be some support for this in shdocvw.dll.
+ * This isn't implemented in wine yet.*/
+ hr = IShellFolder_BindToObject(pDesktopFolder, pidlWineTestFolder, NULL, &IID_IShellFolder,
+ (LPVOID*)&pWineTestFolder);
+ IShellFolder_Release(pDesktopFolder);
+ ILFree(pidlWineTestFolder);
+ ok (SUCCEEDED(hr), "IShellFolder::BindToObject(WineTestFolder) failed! hr = %08x\n", hr);
+ if (FAILED(hr)) goto cleanup;
+
+ hr = IShellFolder_QueryInterface(pWineTestFolder, &IID_IPersistFolder3, (LPVOID*)&pWineTestPersistFolder);
+ ok (SUCCEEDED(hr), "IShellFolder::QueryInterface(IPersistFolder3) failed! hr = %08x\n", hr);
+ IShellFolder_Release(pWineTestFolder);
+ if (FAILED(hr)) goto cleanup;
+
+ /* The resulting folder object has the FolderShortcut CLSID, instead of it's own. */
+ hr = IPersistFolder3_GetClassID(pWineTestPersistFolder, &clsid);
+ ok (SUCCEEDED(hr), "IPersist::GetClassID failed! hr = %08x\n", hr);
+ ok (IsEqualCLSID(&CLSID_FolderShortcut, &clsid), "GetClassId returned wrong CLSID!\n");
+
+ pidlCurFolder = (LPITEMIDLIST)0xdeadbeef;
+ hr = IPersistFolder3_GetCurFolder(pWineTestPersistFolder, &pidlCurFolder);
+ ok (SUCCEEDED(hr), "IPersistFolder3::GetCurFolder failed! hr = %08x\n", hr);
+ ok (pidlCurFolder->mkid.cb == 20 && ((LPSHITEMID)((BYTE*)pidlCurFolder+20))->cb == 0 &&
+ IsEqualCLSID(&CLSID_WineTest, (REFCLSID)((LPBYTE)pidlCurFolder+4)),
+ "GetCurFolder returned unexpected pidl!\n");
+
+ IPersistFolder3_Release(pWineTestPersistFolder);
+
+cleanup:
+ unregister_keys(HKEY_CLASSES_ROOT, HKEY_CLASSES_ROOT_keys, 1);
+}
+
+START_TEST(shortcut)
+{
+ OleInitialize(NULL);
+ test_ShortcutFolder();
+ OleUninitialize();
+}
diff --git a/rostests/winetests/shdocvw/testlist.c b/rostests/winetests/shdocvw/testlist.c
new file mode 100644
index 00000000000..18ce563f47a
--- /dev/null
+++ b/rostests/winetests/shdocvw/testlist.c
@@ -0,0 +1,22 @@
+/* Automatically generated file; DO NOT EDIT!! */
+
+#define WIN32_LEAN_AND_MEAN
+#include
+
+#define STANDALONE
+#include "wine/test.h"
+
+extern void func_intshcut(void);
+extern void func_shdocvw(void);
+extern void func_shortcut(void);
+extern void func_protocol(void);
+extern void func_webbrowser(void);
+
+const struct test winetest_testlist[] =
+{
+ { "intshcut", func_intshcut },
+ { "shdocvw", func_shdocvw },
+ { "shortcut", func_shortcut },
+ { "webbrowser", func_webbrowser },
+ { 0, 0 }
+};
diff --git a/rostests/winetests/shdocvw/webbrowser.c b/rostests/winetests/shdocvw/webbrowser.c
new file mode 100644
index 00000000000..5b041195823
--- /dev/null
+++ b/rostests/winetests/shdocvw/webbrowser.c
@@ -0,0 +1,2137 @@
+/*
+ * Copyright 2006 Jacek Caban 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
+#include
+
+#include "windef.h"
+#include "winbase.h"
+#include "initguid.h"
+#include "ole2.h"
+#include "exdisp.h"
+#include "htiframe.h"
+#include "mshtmhst.h"
+#include "idispids.h"
+#include "olectl.h"
+#include "mshtmdid.h"
+#include "shobjidl.h"
+#include "shlguid.h"
+#include "exdispid.h"
+
+DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
+
+#define DEFINE_EXPECT(func) \
+ static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
+
+#define SET_EXPECT(func) \
+ expect_ ## func = TRUE
+
+#define CHECK_EXPECT2(func) \
+ do { \
+ ok(expect_ ##func, "unexpected call " #func "\n"); \
+ called_ ## func = TRUE; \
+ }while(0)
+
+#define CHECK_EXPECT(func) \
+ do { \
+ CHECK_EXPECT2(func); \
+ expect_ ## func = FALSE; \
+ }while(0)
+
+#define CHECK_CALLED(func) \
+ do { \
+ ok(called_ ## func, "expected " #func "\n"); \
+ expect_ ## func = called_ ## func = FALSE; \
+ }while(0)
+
+#define CHECK_CALLED_BROKEN(func) \
+ do { \
+ ok(called_ ## func || broken(!called_ ## func), "expected " #func "\n"); \
+ expect_ ## func = called_ ## func = FALSE; \
+ }while(0)
+
+DEFINE_EXPECT(GetContainer);
+DEFINE_EXPECT(Site_GetWindow);
+DEFINE_EXPECT(ShowObject);
+DEFINE_EXPECT(CanInPlaceActivate);
+DEFINE_EXPECT(OnInPlaceActivate);
+DEFINE_EXPECT(OnUIActivate);
+DEFINE_EXPECT(GetWindowContext);
+DEFINE_EXPECT(Frame_GetWindow);
+DEFINE_EXPECT(Frame_SetActiveObject);
+DEFINE_EXPECT(UIWindow_SetActiveObject);
+DEFINE_EXPECT(SetMenu);
+DEFINE_EXPECT(Invoke_AMBIENT_USERMODE);
+DEFINE_EXPECT(Invoke_AMBIENT_DLCONTROL);
+DEFINE_EXPECT(Invoke_AMBIENT_USERAGENT);
+DEFINE_EXPECT(Invoke_AMBIENT_PALETTE);
+DEFINE_EXPECT(Invoke_AMBIENT_SILENT);
+DEFINE_EXPECT(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED);
+DEFINE_EXPECT(Invoke_STATUSTEXTCHANGE);
+DEFINE_EXPECT(Invoke_PROPERTYCHANGE);
+DEFINE_EXPECT(Invoke_DOWNLOADBEGIN);
+DEFINE_EXPECT(Invoke_BEFORENAVIGATE2);
+DEFINE_EXPECT(Invoke_SETSECURELOCKICON);
+DEFINE_EXPECT(Invoke_FILEDOWNLOAD);
+DEFINE_EXPECT(Invoke_COMMANDSTATECHANGE);
+DEFINE_EXPECT(Invoke_DOWNLOADCOMPLETE);
+DEFINE_EXPECT(Invoke_ONMENUBAR);
+DEFINE_EXPECT(Invoke_ONADDRESSBAR);
+DEFINE_EXPECT(Invoke_ONSTATUSBAR);
+DEFINE_EXPECT(Invoke_ONTOOLBAR);
+DEFINE_EXPECT(Invoke_ONFULLSCREEN);
+DEFINE_EXPECT(Invoke_ONTHEATERMODE);
+DEFINE_EXPECT(Invoke_WINDOWSETRESIZABLE);
+DEFINE_EXPECT(EnableModeless_TRUE);
+DEFINE_EXPECT(EnableModeless_FALSE);
+DEFINE_EXPECT(GetHostInfo);
+DEFINE_EXPECT(GetOptionKeyPath);
+DEFINE_EXPECT(GetOverridesKeyPath);
+DEFINE_EXPECT(SetStatusText);
+DEFINE_EXPECT(UpdateUI);
+DEFINE_EXPECT(Exec_SETDOWNLOADSTATE_0);
+DEFINE_EXPECT(Exec_SETDOWNLOADSTATE_1);
+DEFINE_EXPECT(Exec_SETPROGRESSMAX);
+DEFINE_EXPECT(Exec_SETPROGRESSPOS);
+DEFINE_EXPECT(QueryStatus_SETPROGRESSTEXT);
+
+static const WCHAR wszItem[] = {'i','t','e','m',0};
+static const WCHAR about_blankW[] = {'a','b','o','u','t',':','b','l','a','n','k',0};
+static const WCHAR emptyW[] = {0};
+
+static VARIANT_BOOL exvb;
+static IWebBrowser2 *wb;
+
+static HWND container_hwnd, shell_embedding_hwnd;
+
+static const char *debugstr_w(LPCWSTR str)
+{
+ static char buf[1024];
+ if(!str)
+ return "(null)";
+ WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL);
+ return buf;
+}
+
+static const char *debugstr_guid(REFIID riid)
+{
+ static char buf[50];
+
+ sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+ riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
+ riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
+ riid->Data4[5], riid->Data4[6], riid->Data4[7]);
+
+ return buf;
+}
+
+#define test_LocationURL(a,b) _test_LocationURL(__LINE__,a,b)
+static void _test_LocationURL(unsigned line, IUnknown *unk, LPCWSTR exurl)
+{
+ IWebBrowser2 *wb;
+ BSTR url = (void*)0xdeadbeef;
+ HRESULT hres;
+
+ hres = IUnknown_QueryInterface(unk, &IID_IWebBrowser2, (void**)&wb);
+ ok(hres == S_OK, "Could not get IWebBrowser2 interface: %08x\n", hres);
+ if(FAILED(hres))
+ return;
+
+ hres = IWebBrowser2_get_LocationURL(wb, &url);
+ ok_(__FILE__,line) (hres == (*exurl ? S_OK : S_FALSE), "get_LocationURL failed: %08x\n", hres);
+ ok_(__FILE__,line) (!lstrcmpW(url, exurl), "unexpected URL: %s\n", debugstr_w(url));
+
+ SysFreeString(url);
+ IWebBrowser2_Release(wb);
+}
+
+static HRESULT QueryInterface(REFIID,void**);
+
+static HRESULT WINAPI OleCommandTarget_QueryInterface(IOleCommandTarget *iface,
+ REFIID riid, void **ppv)
+{
+ ok(0, "unexpected call\n");
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI OleCommandTarget_AddRef(IOleCommandTarget *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI OleCommandTarget_Release(IOleCommandTarget *iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI OleCommandTarget_QueryStatus(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
+ ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
+{
+ ok(!pguidCmdGroup, "pguidCmdGroup != MULL\n");
+ ok(cCmds == 1, "cCmds=%d, expected 1\n", cCmds);
+ ok(!pCmdText, "pCmdText != NULL\n");
+
+ switch(prgCmds[0].cmdID) {
+ case OLECMDID_SETPROGRESSTEXT:
+ CHECK_EXPECT(QueryStatus_SETPROGRESSTEXT);
+ prgCmds[0].cmdf = OLECMDF_ENABLED;
+ return S_OK;
+ default:
+ ok(0, "unexpected command %d\n", prgCmds[0].cmdID);
+ }
+
+ return E_FAIL;
+}
+
+static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
+ DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
+{
+ if(!pguidCmdGroup) {
+ switch(nCmdID) {
+ case OLECMDID_SETPROGRESSMAX:
+ CHECK_EXPECT(Exec_SETPROGRESSMAX);
+ ok(nCmdexecopt == OLECMDEXECOPT_DONTPROMPTUSER, "nCmdexecopts=%08x\n", nCmdexecopt);
+ ok(pvaIn != NULL, "pvaIn == NULL\n");
+ if(pvaIn)
+ ok(V_VT(pvaIn) == VT_I4, "V_VT(pvaIn)=%d, expected VT_I4\n", V_VT(pvaIn));
+ ok(pvaOut == NULL, "pvaOut=%p, expected NULL\n", pvaOut);
+ return S_OK;
+ case OLECMDID_SETPROGRESSPOS:
+ CHECK_EXPECT(Exec_SETPROGRESSPOS);
+ ok(nCmdexecopt == OLECMDEXECOPT_DONTPROMPTUSER, "nCmdexecopts=%08x\n", nCmdexecopt);
+ ok(pvaIn != NULL, "pvaIn == NULL\n");
+ if(pvaIn)
+ ok(V_VT(pvaIn) == VT_I4, "V_VT(pvaIn)=%d, expected VT_I4\n", V_VT(pvaIn));
+ ok(pvaOut == NULL, "pvaOut=%p, expected NULL\n", pvaOut);
+ return S_OK;
+ case OLECMDID_SETDOWNLOADSTATE:
+ ok(!nCmdexecopt, "nCmdexecopts=%08x\n", nCmdexecopt);
+ ok(pvaOut == NULL, "pvaOut=%p\n", pvaOut);
+ ok(pvaIn != NULL, "pvaIn == NULL\n");
+ ok(V_VT(pvaIn) == VT_I4, "V_VT(pvaIn)=%d\n", V_VT(pvaIn));
+ switch(V_I4(pvaIn)) {
+ case 0:
+ CHECK_EXPECT(Exec_SETDOWNLOADSTATE_0);
+ break;
+ case 1:
+ CHECK_EXPECT2(Exec_SETDOWNLOADSTATE_1);
+ break;
+ default:
+ ok(0, "unexpevted V_I4(pvaIn)=%d\n", V_I4(pvaIn));
+ }
+ return S_OK;
+ default:
+ ok(0, "unexpected nsCmdID %d\n", nCmdID);
+ }
+ }else if(IsEqualGUID(&CGID_Explorer, pguidCmdGroup)) {
+ switch(nCmdID) {
+ case 24:
+ return E_FAIL; /* TODO */
+ case 25:
+ return E_FAIL; /* IE5 */
+ case 66:
+ return E_FAIL; /* TODO */
+ default:
+ ok(0, "unexpected nCmdID %d\n", nCmdID);
+ }
+ }else {
+ ok(0, "unepected pguidCmdGroup %s\n", debugstr_guid(pguidCmdGroup));
+ }
+
+ return E_FAIL;
+}
+
+static IOleCommandTargetVtbl OleCommandTargetVtbl = {
+ OleCommandTarget_QueryInterface,
+ OleCommandTarget_AddRef,
+ OleCommandTarget_Release,
+ OleCommandTarget_QueryStatus,
+ OleCommandTarget_Exec
+};
+
+static IOleCommandTarget OleCommandTarget = { &OleCommandTargetVtbl };
+
+static HRESULT WINAPI OleContainer_QueryInterface(IOleContainer *iface, REFIID riid, void **ppv)
+{
+ if(IsEqualGUID(&IID_ITargetContainer, riid))
+ return E_NOINTERFACE; /* TODO */
+
+ if(IsEqualGUID(&IID_IOleCommandTarget, riid)) {
+ *ppv = &OleCommandTarget;
+ return S_OK;
+ }
+
+ ok(0, "unexpected call\n");
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI OleContainer_AddRef(IOleContainer *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI OleContainer_Release(IOleContainer *iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI OleContainer_ParseDisplayName(IOleContainer *iface, IBindCtx *pbc,
+ LPOLESTR pszDiaplayName, ULONG *pchEaten, IMoniker **ppmkOut)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI OleContainer_EnumObjects(IOleContainer *iface, DWORD grfFlags,
+ IEnumUnknown **ppenum)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI OleContainer_LockContainer(IOleContainer *iface, BOOL fLock)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static const IOleContainerVtbl OleContainerVtbl = {
+ OleContainer_QueryInterface,
+ OleContainer_AddRef,
+ OleContainer_Release,
+ OleContainer_ParseDisplayName,
+ OleContainer_EnumObjects,
+ OleContainer_LockContainer
+};
+
+static IOleContainer OleContainer = { &OleContainerVtbl };
+
+static HRESULT WINAPI Dispatch_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
+{
+ return QueryInterface(riid, ppv);
+}
+
+static ULONG WINAPI Dispatch_AddRef(IDispatch *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI Dispatch_Release(IDispatch *iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI Dispatch_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Dispatch_GetTypeInfo(IDispatch *iface, UINT iTInfo, LCID lcid,
+ ITypeInfo **ppTInfo)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Dispatch_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *rgszNames,
+ UINT cNames, LCID lcid, DISPID *rgDispId)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Dispatch_Invoke(IDispatch *iface, DISPID dispIdMember, REFIID riid,
+ LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
+ EXCEPINFO *pExcepInfo, UINT *puArgErr)
+{
+ ok(IsEqualGUID(&IID_NULL, riid), "riid != IID_NULL\n");
+ ok(pDispParams != NULL, "pDispParams == NULL\n");
+ ok(pExcepInfo == NULL, "pExcepInfo=%p, expected NULL\n", pExcepInfo);
+ ok(V_VT(pVarResult) == VT_EMPTY, "V_VT(pVarResult)=%d\n", V_VT(pVarResult));
+ ok(wFlags == DISPATCH_PROPERTYGET, "wFlags=%08x, expected DISPATCH_PROPERTYGET\n", wFlags);
+ ok(pDispParams->rgvarg == NULL, "pDispParams->rgvarg = %p\n", pDispParams->rgvarg);
+ ok(pDispParams->rgdispidNamedArgs == NULL,
+ "pDispParams->rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
+ ok(pDispParams->cArgs == 0, "pDispParams->cArgs = %d\n", pDispParams->cArgs);
+ ok(pDispParams->cNamedArgs == 0, "pDispParams->cNamedArgs = %d\n", pDispParams->cNamedArgs);
+
+ switch(dispIdMember) {
+ case DISPID_AMBIENT_USERMODE:
+ CHECK_EXPECT2(Invoke_AMBIENT_USERMODE);
+ return E_FAIL;
+ case DISPID_AMBIENT_DLCONTROL:
+ CHECK_EXPECT(Invoke_AMBIENT_DLCONTROL);
+ ok(puArgErr != NULL, "puArgErr=%p\n", puArgErr);
+ return E_FAIL;
+ case DISPID_AMBIENT_USERAGENT:
+ CHECK_EXPECT(Invoke_AMBIENT_USERAGENT);
+ ok(puArgErr != NULL, "puArgErr=%p\n", puArgErr);
+ return E_FAIL;
+ case DISPID_AMBIENT_PALETTE:
+ CHECK_EXPECT(Invoke_AMBIENT_PALETTE);
+ ok(puArgErr != NULL, "puArgErr=%p\n", puArgErr);
+ return E_FAIL;
+ case DISPID_AMBIENT_OFFLINEIFNOTCONNECTED:
+ CHECK_EXPECT(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED);
+ ok(puArgErr == NULL, "puArgErr=%p\n", puArgErr);
+ V_VT(pVarResult) = VT_BOOL;
+ V_BOOL(pVarResult) = VARIANT_FALSE;
+ return S_OK;
+ case DISPID_AMBIENT_SILENT:
+ CHECK_EXPECT(Invoke_AMBIENT_SILENT);
+ ok(puArgErr == NULL, "puArgErr=%p\n", puArgErr);
+ V_VT(pVarResult) = VT_BOOL;
+ V_BOOL(pVarResult) = VARIANT_FALSE;
+ return S_OK;
+ }
+
+ ok(0, "unexpected dispIdMember %d\n", dispIdMember);
+ return E_NOTIMPL;
+}
+
+static IDispatchVtbl DispatchVtbl = {
+ Dispatch_QueryInterface,
+ Dispatch_AddRef,
+ Dispatch_Release,
+ Dispatch_GetTypeInfoCount,
+ Dispatch_GetTypeInfo,
+ Dispatch_GetIDsOfNames,
+ Dispatch_Invoke
+};
+
+static IDispatch Dispatch = { &DispatchVtbl };
+
+static HRESULT WINAPI WebBrowserEvents2_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
+{
+ *ppv = NULL;
+
+ if(IsEqualGUID(&DIID_DWebBrowserEvents2, riid)) {
+ *ppv = iface;
+ return S_OK;
+ }
+
+ ok(0, "unexpected riid %s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+}
+
+#define test_invoke_bool(p,s) _test_invoke_bool(__LINE__,p,s)
+static void _test_invoke_bool(unsigned line, const DISPPARAMS *params, BOOL strict)
+{
+ ok_(__FILE__,line) (params->rgvarg != NULL, "rgvarg == NULL\n");
+ ok_(__FILE__,line) (params->cArgs == 1, "cArgs=%d, expected 1\n", params->cArgs);
+ ok_(__FILE__,line) (V_VT(params->rgvarg) == VT_BOOL, "V_VT(arg)=%d\n", V_VT(params->rgvarg));
+ if(strict)
+ ok_(__FILE__,line) (V_BOOL(params->rgvarg) == exvb, "V_VT(arg)=%x, expected %x\n",
+ V_BOOL(params->rgvarg), exvb);
+ else
+ ok_(__FILE__,line) (!V_BOOL(params->rgvarg) == !exvb, "V_VT(arg)=%x, expected %x\n",
+ V_BOOL(params->rgvarg), exvb);
+}
+
+static void test_OnBeforeNavigate(const VARIANT *disp, const VARIANT *url, const VARIANT *flags,
+ const VARIANT *frame, const VARIANT *post_data, const VARIANT *headers, const VARIANT *cancel)
+{
+ ok(V_VT(disp) == VT_DISPATCH, "V_VT(disp)=%d, expected VT_DISPATCH\n", V_VT(disp));
+ ok(V_DISPATCH(disp) != NULL, "V_DISPATCH(disp) == NULL\n");
+ ok(V_DISPATCH(disp) == (IDispatch*)wb, "V_DISPATCH(disp)=%p, wb=%p\n", V_DISPATCH(disp), wb);
+
+ ok(V_VT(url) == (VT_BYREF|VT_VARIANT), "V_VT(url)=%x, expected VT_BYREF|VT_VARIANT\n", V_VT(url));
+ ok(V_VARIANTREF(url) != NULL, "V_VARIANTREF(url) == NULL)\n");
+ if(V_VARIANTREF(url)) {
+ ok(V_VT(V_VARIANTREF(url)) == VT_BSTR, "V_VT(V_VARIANTREF(url))=%d, expected VT_BSTR\n",
+ V_VT(V_VARIANTREF(url)));
+ ok(V_BSTR(V_VARIANTREF(url)) != NULL, "V_BSTR(V_VARIANTREF(url)) == NULL\n");
+ ok(!lstrcmpW(V_BSTR(V_VARIANTREF(url)), about_blankW), "unexpected url %s\n",
+ debugstr_w(V_BSTR(V_VARIANTREF(url))));
+ }
+
+ ok(V_VT(flags) == (VT_BYREF|VT_VARIANT), "V_VT(flags)=%x, expected VT_BYREF|VT_VARIANT\n",
+ V_VT(flags));
+ ok(V_VT(flags) == (VT_BYREF|VT_VARIANT), "V_VT(flags)=%x, expected VT_BYREF|VT_VARIANT\n",
+ V_VT(flags));
+ ok(V_VARIANTREF(flags) != NULL, "V_VARIANTREF(flags) == NULL)\n");
+ if(V_VARIANTREF(flags)) {
+ ok(V_VT(V_VARIANTREF(flags)) == VT_I4, "V_VT(V_VARIANTREF(flags))=%d, expected VT_I4\n",
+ V_VT(V_VARIANTREF(flags)));
+ ok(V_I4(V_VARIANTREF(flags)) == 0, "V_I4(V_VARIANTREF(flags)) = %d, expected 0\n",
+ V_I4(V_VARIANTREF(flags)));
+ }
+
+ ok(V_VT(frame) == (VT_BYREF|VT_VARIANT), "V_VT(frame)=%x, expected VT_BYREF|VT_VARIANT\n",
+ V_VT(frame));
+ ok(V_VT(frame) == (VT_BYREF|VT_VARIANT), "V_VT(frame)=%x, expected VT_BYREF|VT_VARIANT\n",
+ V_VT(frame));
+ ok(V_VARIANTREF(frame) != NULL, "V_VARIANTREF(frame) == NULL)\n");
+ if(V_VARIANTREF(frame)) {
+ ok(V_VT(V_VARIANTREF(frame)) == VT_BSTR, "V_VT(V_VARIANTREF(frame))=%d, expected VT_BSTR\n",
+ V_VT(V_VARIANTREF(frame)));
+ ok(V_BSTR(V_VARIANTREF(frame)) == NULL, "V_BSTR(V_VARIANTREF(frame)) = %p, expected NULL\n",
+ V_BSTR(V_VARIANTREF(frame)));
+ }
+
+ ok(V_VT(post_data) == (VT_BYREF|VT_VARIANT), "V_VT(post_data)=%x, expected VT_BYREF|VT_VARIANT\n",
+ V_VT(post_data));
+ ok(V_VT(post_data) == (VT_BYREF|VT_VARIANT), "V_VT(post_data)=%x, expected VT_BYREF|VT_VARIANT\n",
+ V_VT(post_data));
+ ok(V_VARIANTREF(post_data) != NULL, "V_VARIANTREF(post_data) == NULL)\n");
+ if(V_VARIANTREF(post_data)) {
+ ok(V_VT(V_VARIANTREF(post_data)) == (VT_VARIANT|VT_BYREF),
+ "V_VT(V_VARIANTREF(post_data))=%d, expected VT_VARIANT|VT_BYREF\n",
+ V_VT(V_VARIANTREF(post_data)));
+ ok(V_VARIANTREF(V_VARIANTREF(post_data)) != NULL,
+ "V_VARIANTREF(V_VARIANTREF(post_data)) == NULL\n");
+ if(V_VARIANTREF(V_VARIANTREF(post_data))) {
+ ok(V_VT(V_VARIANTREF(V_VARIANTREF(post_data))) == VT_EMPTY,
+ "V_VT(V_VARIANTREF(V_VARIANTREF(post_data))) = %d, expected VT_EMPTY\n",
+ V_VT(V_VARIANTREF(V_VARIANTREF(post_data))));
+
+ if(V_VT(V_VARIANTREF(V_VARIANTREF(post_data))) == (VT_UI1|VT_ARRAY)) {
+ const SAFEARRAY *sa = V_ARRAY(V_VARIANTREF(V_VARIANTREF(post_data)));
+
+ ok(sa->cDims == 1, "sa->cDims = %d, expected 1\n", sa->cDims);
+ ok(sa->fFeatures == 0, "sa->fFeatures = %d, expected 0\n", sa->fFeatures);
+ }
+ }
+ }
+
+ ok(V_VT(headers) == (VT_BYREF|VT_VARIANT), "V_VT(headers)=%x, expected VT_BYREF|VT_VARIANT\n",
+ V_VT(headers));
+ ok(V_VARIANTREF(headers) != NULL, "V_VARIANTREF(headers) == NULL)\n");
+ if(V_VARIANTREF(headers)) {
+ ok(V_VT(V_VARIANTREF(headers)) == VT_BSTR, "V_VT(V_VARIANTREF(headers))=%d, expected VT_BSTR\n",
+ V_VT(V_VARIANTREF(headers)));
+ ok(V_BSTR(V_VARIANTREF(headers)) == NULL, "V_BSTR(V_VARIANTREF(heders)) = %p, expected NULL\n",
+ V_BSTR(V_VARIANTREF(headers)));
+ }
+
+ ok(V_VT(cancel) == (VT_BYREF|VT_BOOL), "V_VT(cancel)=%x, expected VT_BYREF|VT_BOOL\n",
+ V_VT(cancel));
+ ok(V_BOOLREF(cancel) != NULL, "V_BOOLREF(pDispParams->rgvarg[0] == NULL)\n");
+ if(V_BOOLREF(cancel))
+ ok(*V_BOOLREF(cancel) == VARIANT_FALSE, "*V_BOOLREF(calcel) = %x, expected VARIANT_FALSE\n",
+ *V_BOOLREF(cancel));
+}
+
+static HRESULT WINAPI WebBrowserEvents2_Invoke(IDispatch *iface, DISPID dispIdMember, REFIID riid,
+ LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
+ EXCEPINFO *pExcepInfo, UINT *puArgErr)
+{
+ ok(IsEqualGUID(&IID_NULL, riid), "riid != IID_NULL\n");
+ ok(pDispParams != NULL, "pDispParams == NULL\n");
+ ok(pExcepInfo == NULL, "pExcepInfo=%p, expected NULL\n", pExcepInfo);
+ ok(pVarResult == NULL, "pVarResult=%p\n", pVarResult);
+ ok(wFlags == DISPATCH_METHOD, "wFlags=%08x, expected DISPATCH_METHOD\n", wFlags);
+ ok(pDispParams->rgdispidNamedArgs == NULL,
+ "pDispParams->rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
+ ok(pDispParams->cNamedArgs == 0, "pDispParams->cNamedArgs = %d\n", pDispParams->cNamedArgs);
+
+ switch(dispIdMember) {
+ case DISPID_STATUSTEXTCHANGE:
+ CHECK_EXPECT2(Invoke_STATUSTEXTCHANGE);
+
+ ok(pDispParams->rgvarg != NULL, "rgvarg == NULL\n");
+ ok(pDispParams->cArgs == 1, "cArgs=%d, expected 1\n", pDispParams->cArgs);
+ ok(V_VT(pDispParams->rgvarg) == VT_BSTR, "V_VT(pDispParams->rgvarg)=%d, expected VT_BSTR\n",
+ V_VT(pDispParams->rgvarg));
+ /* TODO: Check text */
+ break;
+
+ case DISPID_PROPERTYCHANGE:
+ CHECK_EXPECT2(Invoke_PROPERTYCHANGE);
+
+ ok(pDispParams->rgvarg != NULL, "rgvarg == NULL\n");
+ ok(pDispParams->cArgs == 1, "cArgs=%d, expected 1\n", pDispParams->cArgs);
+ /* TODO: Check args */
+ break;
+
+ case DISPID_DOWNLOADBEGIN:
+ CHECK_EXPECT(Invoke_DOWNLOADBEGIN);
+
+ ok(pDispParams->rgvarg == NULL, "rgvarg=%p, expected NULL\n", pDispParams->rgvarg);
+ ok(pDispParams->cArgs == 0, "cArgs=%d, expected 0\n", pDispParams->cArgs);
+ break;
+
+ case DISPID_BEFORENAVIGATE2:
+ CHECK_EXPECT(Invoke_BEFORENAVIGATE2);
+
+ ok(pDispParams->rgvarg != NULL, "rgvarg == NULL\n");
+ ok(pDispParams->cArgs == 7, "cArgs=%d, expected 7\n", pDispParams->cArgs);
+ test_OnBeforeNavigate(pDispParams->rgvarg+6, pDispParams->rgvarg+5, pDispParams->rgvarg+4,
+ pDispParams->rgvarg+3, pDispParams->rgvarg+2, pDispParams->rgvarg+1,
+ pDispParams->rgvarg);
+ break;
+
+ case DISPID_SETSECURELOCKICON:
+ CHECK_EXPECT2(Invoke_SETSECURELOCKICON);
+
+ ok(pDispParams->rgvarg != NULL, "rgvarg == NULL\n");
+ ok(pDispParams->cArgs == 1, "cArgs=%d, expected 1\n", pDispParams->cArgs);
+ /* TODO: Check args */
+ break;
+
+ case DISPID_FILEDOWNLOAD:
+ CHECK_EXPECT(Invoke_FILEDOWNLOAD);
+
+ ok(pDispParams->rgvarg != NULL, "rgvarg == NULL\n");
+ ok(pDispParams->cArgs == 2, "cArgs=%d, expected 2\n", pDispParams->cArgs);
+ /* TODO: Check args */
+ break;
+
+ case DISPID_COMMANDSTATECHANGE:
+ CHECK_EXPECT2(Invoke_COMMANDSTATECHANGE);
+
+ ok(pDispParams->rgvarg != NULL, "rgvarg == NULL\n");
+ ok(pDispParams->cArgs == 2, "cArgs=%d, expected 2\n", pDispParams->cArgs);
+ /* TODO: Check args */
+ break;
+
+ case DISPID_DOWNLOADCOMPLETE:
+ CHECK_EXPECT(Invoke_DOWNLOADCOMPLETE);
+
+ ok(pDispParams->rgvarg == NULL, "rgvarg=%p, expected NULL\n", pDispParams->rgvarg);
+ ok(pDispParams->cArgs == 0, "cArgs=%d, expected 0\n", pDispParams->cArgs);
+ break;
+
+ case DISPID_ONMENUBAR:
+ CHECK_EXPECT(Invoke_ONMENUBAR);
+ test_invoke_bool(pDispParams, TRUE);
+ break;
+
+ case DISPID_ONADDRESSBAR:
+ CHECK_EXPECT(Invoke_ONADDRESSBAR);
+ test_invoke_bool(pDispParams, TRUE);
+ break;
+
+ case DISPID_ONSTATUSBAR:
+ CHECK_EXPECT(Invoke_ONSTATUSBAR);
+ test_invoke_bool(pDispParams, TRUE);
+ break;
+
+ case DISPID_ONTOOLBAR:
+ CHECK_EXPECT(Invoke_ONTOOLBAR);
+ test_invoke_bool(pDispParams, FALSE);
+ break;
+
+ case DISPID_ONFULLSCREEN:
+ CHECK_EXPECT(Invoke_ONFULLSCREEN);
+ test_invoke_bool(pDispParams, TRUE);
+ break;
+
+ case DISPID_ONTHEATERMODE:
+ CHECK_EXPECT(Invoke_ONTHEATERMODE);
+ test_invoke_bool(pDispParams, TRUE);
+ break;
+
+ case DISPID_WINDOWSETRESIZABLE:
+ CHECK_EXPECT(Invoke_WINDOWSETRESIZABLE);
+ test_invoke_bool(pDispParams, TRUE);
+ break;
+
+ default:
+ ok(0, "unexpected dispIdMember %d\n", dispIdMember);
+ }
+
+ return S_OK;
+}
+
+static IDispatchVtbl WebBrowserEvents2Vtbl = {
+ WebBrowserEvents2_QueryInterface,
+ Dispatch_AddRef,
+ Dispatch_Release,
+ Dispatch_GetTypeInfoCount,
+ Dispatch_GetTypeInfo,
+ Dispatch_GetIDsOfNames,
+ WebBrowserEvents2_Invoke
+};
+
+static IDispatch WebBrowserEvents2 = { &WebBrowserEvents2Vtbl };
+
+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)
+{
+ CHECK_EXPECT(GetContainer);
+
+ ok(ppContainer != NULL, "ppContainer == NULL\n");
+ if(ppContainer)
+ *ppContainer = &OleContainer;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI ClientSite_ShowObject(IOleClientSite *iface)
+{
+ CHECK_EXPECT(ShowObject);
+ return S_OK;
+}
+
+static HRESULT WINAPI ClientSite_OnShowWindow(IOleClientSite *iface, BOOL fShow)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ClientSite_RequestNewObjectLayout(IOleClientSite *iface)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static const IOleClientSiteVtbl ClientSiteVtbl = {
+ ClientSite_QueryInterface,
+ ClientSite_AddRef,
+ ClientSite_Release,
+ ClientSite_SaveObject,
+ ClientSite_GetMoniker,
+ ClientSite_GetContainer,
+ ClientSite_ShowObject,
+ ClientSite_OnShowWindow,
+ ClientSite_RequestNewObjectLayout
+};
+
+static IOleClientSite ClientSite = { &ClientSiteVtbl };
+
+static HRESULT WINAPI InPlaceUIWindow_QueryInterface(IOleInPlaceFrame *iface,
+ REFIID riid, void **ppv)
+{
+ ok(0, "unexpected call\n");
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI InPlaceUIWindow_AddRef(IOleInPlaceFrame *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI InPlaceUIWindow_Release(IOleInPlaceFrame *iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI InPlaceUIWindow_GetWindow(IOleInPlaceFrame *iface, HWND *phwnd)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceFrame_GetWindow(IOleInPlaceFrame *iface, HWND *phwnd)
+{
+ CHECK_EXPECT(Frame_GetWindow);
+ ok(phwnd != NULL, "phwnd == NULL\n");
+ if(phwnd)
+ *phwnd = container_hwnd;
+ return S_OK;
+}
+
+static HRESULT WINAPI InPlaceUIWindow_ContextSensitiveHelp(IOleInPlaceFrame *iface, BOOL fEnterMode)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceUIWindow_GetBorder(IOleInPlaceFrame *iface, LPRECT lprectBorder)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceUIWindow_RequestBorderSpace(IOleInPlaceFrame *iface,
+ LPCBORDERWIDTHS pborderwidths)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceUIWindow_SetBorderSpace(IOleInPlaceFrame *iface,
+ LPCBORDERWIDTHS pborderwidths)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceUIWindow_SetActiveObject(IOleInPlaceFrame *iface,
+ IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
+{
+ CHECK_EXPECT(UIWindow_SetActiveObject);
+ ok(pActiveObject != NULL, "pActiveObject = NULL\n");
+ ok(!lstrcmpW(pszObjName, wszItem), "unexpected pszObjName\n");
+ return S_OK;
+}
+
+static HRESULT WINAPI InPlaceFrame_SetActiveObject(IOleInPlaceFrame *iface,
+ IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
+{
+ CHECK_EXPECT(Frame_SetActiveObject);
+ ok(pActiveObject != NULL, "pActiveObject = NULL\n");
+ ok(!lstrcmpW(pszObjName, wszItem), "unexpected pszObjName\n");
+ return S_OK;
+}
+
+static HRESULT WINAPI InPlaceFrame_InsertMenus(IOleInPlaceFrame *iface, HMENU hmenuShared,
+ LPOLEMENUGROUPWIDTHS lpMenuWidths)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceFrame_SetMenu(IOleInPlaceFrame *iface, HMENU hmenuShared,
+ HOLEMENU holemenu, HWND hwndActiveObject)
+{
+ CHECK_EXPECT(SetMenu);
+ ok(hmenuShared == NULL, "hmenuShared=%p\n", hmenuShared);
+ ok(holemenu == NULL, "holemenu=%p\n", holemenu);
+ ok(hwndActiveObject == shell_embedding_hwnd, "hwndActiveObject=%p, expected %p\n",
+ hwndActiveObject, shell_embedding_hwnd);
+ return S_OK;
+}
+
+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)
+{
+ CHECK_EXPECT2(SetStatusText);
+ /* FIXME: Check pszStatusText */
+ return S_OK;
+}
+
+static HRESULT WINAPI InPlaceFrame_EnableModeless(IOleInPlaceFrame *iface, BOOL fEnable)
+{
+ if(fEnable)
+ CHECK_EXPECT(EnableModeless_TRUE);
+ else
+ CHECK_EXPECT(EnableModeless_FALSE);
+ return S_OK;
+}
+
+static HRESULT WINAPI InPlaceFrame_TranslateAccelerator(IOleInPlaceFrame *iface, LPMSG lpmsg, WORD wID)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static const IOleInPlaceFrameVtbl InPlaceUIWindowVtbl = {
+ InPlaceUIWindow_QueryInterface,
+ InPlaceUIWindow_AddRef,
+ InPlaceUIWindow_Release,
+ InPlaceUIWindow_GetWindow,
+ InPlaceUIWindow_ContextSensitiveHelp,
+ InPlaceUIWindow_GetBorder,
+ InPlaceUIWindow_RequestBorderSpace,
+ InPlaceUIWindow_SetBorderSpace,
+ InPlaceUIWindow_SetActiveObject,
+};
+
+static IOleInPlaceUIWindow InPlaceUIWindow = { (IOleInPlaceUIWindowVtbl*)&InPlaceUIWindowVtbl };
+
+static const IOleInPlaceFrameVtbl InPlaceFrameVtbl = {
+ InPlaceUIWindow_QueryInterface,
+ InPlaceUIWindow_AddRef,
+ InPlaceUIWindow_Release,
+ InPlaceFrame_GetWindow,
+ InPlaceUIWindow_ContextSensitiveHelp,
+ InPlaceUIWindow_GetBorder,
+ InPlaceUIWindow_RequestBorderSpace,
+ InPlaceUIWindow_SetBorderSpace,
+ InPlaceFrame_SetActiveObject,
+ InPlaceFrame_InsertMenus,
+ InPlaceFrame_SetMenu,
+ InPlaceFrame_RemoveMenus,
+ InPlaceFrame_SetStatusText,
+ InPlaceFrame_EnableModeless,
+ InPlaceFrame_TranslateAccelerator
+};
+
+static IOleInPlaceFrame InPlaceFrame = { &InPlaceFrameVtbl };
+
+static HRESULT WINAPI InPlaceSite_QueryInterface(IOleInPlaceSiteEx *iface, REFIID riid, void **ppv)
+{
+ return QueryInterface(riid, ppv);
+}
+
+static ULONG WINAPI InPlaceSite_AddRef(IOleInPlaceSiteEx *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI InPlaceSite_Release(IOleInPlaceSiteEx *iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI InPlaceSite_GetWindow(IOleInPlaceSiteEx *iface, HWND *phwnd)
+{
+ CHECK_EXPECT(Site_GetWindow);
+ ok(phwnd != NULL, "phwnd == NULL\n");
+ if(phwnd)
+ *phwnd = container_hwnd;
+ return S_OK;
+}
+
+static HRESULT WINAPI InPlaceSite_ContextSensitiveHelp(IOleInPlaceSiteEx *iface, BOOL fEnterMode)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceSite_CanInPlaceActivate(IOleInPlaceSiteEx *iface)
+{
+ CHECK_EXPECT(CanInPlaceActivate);
+ return S_OK;
+}
+
+static HRESULT WINAPI InPlaceSite_OnInPlaceActivate(IOleInPlaceSiteEx *iface)
+{
+ CHECK_EXPECT(OnInPlaceActivate);
+ return S_OK;
+}
+
+static HRESULT WINAPI InPlaceSite_OnUIActivate(IOleInPlaceSiteEx *iface)
+{
+ CHECK_EXPECT(OnUIActivate);
+ return S_OK;
+}
+
+static HRESULT WINAPI InPlaceSite_GetWindowContext(IOleInPlaceSiteEx *iface,
+ IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect,
+ LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
+{
+ static const RECT pos_rect = {2,1,1002,901};
+ static const RECT clip_rect = {10,10,990,890};
+
+ CHECK_EXPECT(GetWindowContext);
+
+ ok(ppFrame != NULL, "ppFrame = NULL\n");
+ if(ppFrame)
+ *ppFrame = &InPlaceFrame;
+
+ ok(ppDoc != NULL, "ppDoc = NULL\n");
+ if(ppDoc)
+ *ppDoc = &InPlaceUIWindow;
+
+ ok(lprcPosRect != NULL, "lprcPosRect = NULL\n");
+ if(lprcPosRect)
+ memcpy(lprcPosRect, &pos_rect, sizeof(RECT));
+
+ ok(lprcClipRect != NULL, "lprcClipRect = NULL\n");
+ if(lprcClipRect)
+ memcpy(lprcClipRect, &clip_rect, sizeof(RECT));
+
+ ok(lpFrameInfo != NULL, "lpFrameInfo = NULL\n");
+ if(lpFrameInfo) {
+ 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(IOleInPlaceSiteEx *iface, SIZE scrollExtant)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceSite_OnUIDeactivate(IOleInPlaceSiteEx *iface, BOOL fUndoable)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceSite_OnInPlaceDeactivate(IOleInPlaceSiteEx *iface)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceSite_DiscardUndoState(IOleInPlaceSiteEx *iface)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceSite_DeactivateAndUndo(IOleInPlaceSiteEx *iface)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceSite_OnPosRectChange(IOleInPlaceSiteEx *iface, LPCRECT lprcPosRect)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceSite_OnInPlaceActivateEx(IOleInPlaceSiteEx *iface,
+ BOOL *pNoRedraw, DWORD dwFlags)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceSite_OnInPlaceDeactivateEx(IOleInPlaceSiteEx *iface,
+ BOOL fNoRedraw)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceSite_RequestUIActivate(IOleInPlaceSiteEx *iface)
+{
+ ok(0, "unexpected call\n");
+ return S_OK;
+}
+
+static const IOleInPlaceSiteExVtbl InPlaceSiteExVtbl = {
+ 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,
+ InPlaceSite_OnInPlaceActivateEx,
+ InPlaceSite_OnInPlaceDeactivateEx,
+ InPlaceSite_RequestUIActivate
+};
+
+static IOleInPlaceSiteEx InPlaceSite = { &InPlaceSiteExVtbl };
+
+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)
+{
+ ok(0, "unexpected call %d %p %p %p\n", dwID, ppt, pcmdtReserved, pdicpReserved);
+ return S_FALSE;
+}
+
+static HRESULT WINAPI DocHostUIHandler_GetHostInfo(IDocHostUIHandler2 *iface, DOCHOSTUIINFO *pInfo)
+{
+ CHECK_EXPECT2(GetHostInfo);
+ ok(pInfo != NULL, "pInfo=NULL\n");
+ if(pInfo) {
+ ok(pInfo->cbSize == sizeof(DOCHOSTUIINFO) || broken(!pInfo->cbSize), "pInfo->cbSize=%u\n", pInfo->cbSize);
+ ok(!pInfo->dwFlags, "pInfo->dwFlags=%08x, expected 0\n", pInfo->dwFlags);
+ ok(!pInfo->dwDoubleClick, "pInfo->dwDoubleClick=%08x, expected 0\n", pInfo->dwDoubleClick);
+ ok(!pInfo->pchHostCss, "pInfo->pchHostCss=%p, expected NULL\n", pInfo->pchHostCss);
+ ok(!pInfo->pchHostNS, "pInfo->pchhostNS=%p, expected NULL\n", pInfo->pchHostNS);
+ }
+ return E_FAIL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_ShowUI(IDocHostUIHandler2 *iface, DWORD dwID,
+ IOleInPlaceActiveObject *pActiveObject, IOleCommandTarget *pCommandTarget,
+ IOleInPlaceFrame *pFrame, IOleInPlaceUIWindow *pDoc)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_HideUI(IDocHostUIHandler2 *iface)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_UpdateUI(IDocHostUIHandler2 *iface)
+{
+ CHECK_EXPECT(UpdateUI);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_EnableModeless(IDocHostUIHandler2 *iface, BOOL fEnable)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_OnDocWindowActivate(IDocHostUIHandler2 *iface, BOOL fActivate)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_OnFrameWindowActivate(IDocHostUIHandler2 *iface, BOOL fActivate)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_ResizeBorder(IDocHostUIHandler2 *iface, LPCRECT prcBorder,
+ IOleInPlaceUIWindow *pUIWindow, BOOL fRameWindow)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_TranslateAccelerator(IDocHostUIHandler2 *iface, LPMSG lpMsg,
+ const GUID *pguidCmdGroup, DWORD nCmdID)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_GetOptionKeyPath(IDocHostUIHandler2 *iface,
+ LPOLESTR *pchKey, DWORD dw)
+{
+ CHECK_EXPECT(GetOptionKeyPath);
+ ok(pchKey != NULL, "pchKey==NULL\n");
+ if(pchKey)
+ ok(*pchKey == NULL, "*pchKey=%p\n", *pchKey);
+ ok(!dw, "dw=%x\n", dw);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_GetDropTarget(IDocHostUIHandler2 *iface,
+ IDropTarget *pDropTarget, IDropTarget **ppDropTarget)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_GetExternal(IDocHostUIHandler2 *iface, IDispatch **ppDispatch)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_TranslateUrl(IDocHostUIHandler2 *iface, DWORD dwTranslate,
+ OLECHAR *pchURLIn, OLECHAR **ppchURLOut)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_FilterDataObject(IDocHostUIHandler2 *iface, IDataObject *pDO,
+ IDataObject **ppPORet)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_GetOverrideKeyPath(IDocHostUIHandler2 *iface,
+ LPOLESTR *pchKey, DWORD dw)
+{
+ CHECK_EXPECT(GetOverridesKeyPath);
+ ok(pchKey != NULL, "pchKey==NULL\n");
+ if(pchKey)
+ ok(*pchKey == NULL, "*pchKey=%p\n", *pchKey);
+ ok(!dw, "dw=%x\n", 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 QueryInterface(REFIID riid, void **ppv)
+{
+ *ppv = NULL;
+
+ if(IsEqualGUID(&IID_IUnknown, riid)
+ || IsEqualGUID(&IID_IOleClientSite, riid))
+ *ppv = &ClientSite;
+ else if(IsEqualGUID(&IID_IOleWindow, riid)
+ || IsEqualGUID(&IID_IOleInPlaceSite, riid)
+ || IsEqualGUID(&IID_IOleInPlaceSiteEx, riid))
+ *ppv = &InPlaceSite;
+ else if(IsEqualGUID(&IID_IDocHostUIHandler, riid)
+ || IsEqualGUID(&IID_IDocHostUIHandler2, riid))
+ *ppv = &DocHostUIHandler;
+ else if(IsEqualGUID(&IID_IDispatch, riid))
+ *ppv = &Dispatch;
+
+ if(*ppv)
+ return S_OK;
+
+ return E_NOINTERFACE;
+}
+
+static LRESULT WINAPI wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ return DefWindowProcW(hwnd, msg, wParam, lParam);
+}
+
+static HWND create_container_window(void)
+{
+ static const WCHAR wszWebBrowserContainer[] =
+ {'W','e','b','B','r','o','w','s','e','r','C','o','n','t','a','i','n','e','r',0};
+ static WNDCLASSEXW wndclass = {
+ sizeof(WNDCLASSEXW),
+ 0,
+ wnd_proc,
+ 0, 0, NULL, NULL, NULL, NULL, NULL,
+ wszWebBrowserContainer,
+ NULL
+ };
+
+ RegisterClassExW(&wndclass);
+ return CreateWindowW(wszWebBrowserContainer, wszWebBrowserContainer,
+ WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, NULL, NULL, NULL, NULL);
+}
+
+static void test_DoVerb(IUnknown *unk)
+{
+ IOleObject *oleobj;
+ RECT rect = {0,0,1000,1000};
+ HRESULT hres;
+
+ hres = IUnknown_QueryInterface(unk, &IID_IOleObject, (void**)&oleobj);
+ ok(hres == S_OK, "QueryInterface(IID_OleObject) failed: %08x\n", hres);
+ if(FAILED(hres))
+ return;
+
+ SET_EXPECT(CanInPlaceActivate);
+ SET_EXPECT(Site_GetWindow);
+ SET_EXPECT(OnInPlaceActivate);
+ SET_EXPECT(GetWindowContext);
+ SET_EXPECT(ShowObject);
+ SET_EXPECT(GetContainer);
+ SET_EXPECT(Frame_GetWindow);
+ SET_EXPECT(OnUIActivate);
+ SET_EXPECT(Frame_SetActiveObject);
+ SET_EXPECT(UIWindow_SetActiveObject);
+ SET_EXPECT(SetMenu);
+
+ hres = IOleObject_DoVerb(oleobj, OLEIVERB_SHOW, NULL, &ClientSite,
+ 0, (HWND)0xdeadbeef, &rect);
+ ok(hres == S_OK, "DoVerb failed: %08x\n", hres);
+
+ CHECK_CALLED(CanInPlaceActivate);
+ CHECK_CALLED(Site_GetWindow);
+ CHECK_CALLED(OnInPlaceActivate);
+ CHECK_CALLED(GetWindowContext);
+ CHECK_CALLED(ShowObject);
+ CHECK_CALLED(GetContainer);
+ CHECK_CALLED(Frame_GetWindow);
+ CHECK_CALLED(OnUIActivate);
+ CHECK_CALLED(Frame_SetActiveObject);
+ CHECK_CALLED(UIWindow_SetActiveObject);
+ CHECK_CALLED(SetMenu);
+
+ hres = IOleObject_DoVerb(oleobj, OLEIVERB_SHOW, NULL, &ClientSite,
+ 0, (HWND)0xdeadbeef, &rect);
+ ok(hres == S_OK, "DoVerb failed: %08x\n", hres);
+
+ IOleObject_Release(oleobj);
+}
+
+static void test_GetMiscStatus(IOleObject *oleobj)
+{
+ DWORD st, i;
+ HRESULT hres;
+
+ for(i=0; i<10; i++) {
+ st = 0xdeadbeef;
+ hres = IOleObject_GetMiscStatus(oleobj, i, &st);
+ ok(hres == S_OK, "GetMiscStatus failed: %08x\n", hres);
+ ok(st == (OLEMISC_SETCLIENTSITEFIRST|OLEMISC_ACTIVATEWHENVISIBLE|OLEMISC_INSIDEOUT
+ |OLEMISC_CANTLINKINSIDE|OLEMISC_RECOMPOSEONRESIZE),
+ "st=%08x, expected OLEMISC_SETCLIENTSITEFIRST|OLEMISC_ACTIVATEWHENVISIBLE|"
+ "OLEMISC_INSIDEOUT|OLEMISC_CANTLINKINSIDE|OLEMISC_RECOMPOSEONRESIZE)\n", st);
+ }
+}
+
+static void test_SetHostNames(IOleObject *oleobj)
+{
+ HRESULT hres;
+
+ static const WCHAR test_appW[] = {'t','e','s','t',' ','a','p','p',0};
+
+ hres = IOleObject_SetHostNames(oleobj, test_appW, (void*)0xdeadbeef);
+ ok(hres == S_OK, "SetHostNames failed: %08x\n", hres);
+}
+
+static void test_ClientSite(IUnknown *unk, IOleClientSite *client)
+{
+ IOleObject *oleobj;
+ IOleInPlaceObject *inplace;
+ HWND hwnd;
+ HRESULT hres;
+
+ hres = IUnknown_QueryInterface(unk, &IID_IOleObject, (void**)&oleobj);
+ ok(hres == S_OK, "QueryInterface(IID_OleObject) failed: %08x\n", hres);
+ if(FAILED(hres))
+ return;
+
+ test_GetMiscStatus(oleobj);
+ test_SetHostNames(oleobj);
+
+ hres = IUnknown_QueryInterface(unk, &IID_IOleInPlaceObject, (void**)&inplace);
+ ok(hres == S_OK, "QueryInterface(IID_OleInPlaceObject) failed: %08x\n", hres);
+ if(FAILED(hres)) {
+ IOleObject_Release(oleobj);
+ return;
+ }
+
+ hres = IOleInPlaceObject_GetWindow(inplace, &hwnd);
+ ok(hres == S_OK, "GetWindow failed: %08x\n", hres);
+ ok((hwnd == NULL) ^ (client == NULL), "unexpected hwnd %p\n", hwnd);
+
+ if(client) {
+ SET_EXPECT(GetContainer);
+ SET_EXPECT(Site_GetWindow);
+ SET_EXPECT(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED);
+ SET_EXPECT(Invoke_AMBIENT_SILENT);
+ }else {
+ SET_EXPECT(Invoke_DOWNLOADCOMPLETE);
+ SET_EXPECT(Exec_SETDOWNLOADSTATE_0);
+ SET_EXPECT(Invoke_COMMANDSTATECHANGE);
+ }
+
+ hres = IOleObject_SetClientSite(oleobj, client);
+ ok(hres == S_OK, "SetClientSite failed: %08x\n", hres);
+
+ if(client) {
+ CHECK_CALLED(GetContainer);
+ CHECK_CALLED(Site_GetWindow);
+ CHECK_CALLED(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED);
+ CHECK_CALLED(Invoke_AMBIENT_SILENT);
+ }else {
+ todo_wine CHECK_CALLED(Invoke_DOWNLOADCOMPLETE);
+ todo_wine CHECK_CALLED(Exec_SETDOWNLOADSTATE_0);
+ todo_wine CHECK_CALLED(Invoke_COMMANDSTATECHANGE);
+ }
+
+ hres = IOleInPlaceObject_GetWindow(inplace, &hwnd);
+ ok(hres == S_OK, "GetWindow failed: %08x\n", hres);
+ ok((hwnd == NULL) == (client == NULL), "unexpected hwnd %p\n", hwnd);
+
+ shell_embedding_hwnd = hwnd;
+
+ test_SetHostNames(oleobj);
+
+ IOleInPlaceObject_Release(inplace);
+ IOleObject_Release(oleobj);
+}
+
+static void test_ClassInfo(IUnknown *unk)
+{
+ IProvideClassInfo2 *class_info;
+ GUID guid;
+ HRESULT hres;
+
+ hres = IUnknown_QueryInterface(unk, &IID_IProvideClassInfo2, (void**)&class_info);
+ ok(hres == S_OK, "QueryInterface(IID_IProvideClassInfo) failed: %08x\n", hres);
+ if(FAILED(hres))
+ return;
+
+ hres = IProvideClassInfo2_GetGUID(class_info, GUIDKIND_DEFAULT_SOURCE_DISP_IID, &guid);
+ ok(hres == S_OK, "GetGUID failed: %08x\n", hres);
+ ok(IsEqualGUID(&DIID_DWebBrowserEvents2, &guid), "wrong guid\n");
+
+ hres = IProvideClassInfo2_GetGUID(class_info, 0, &guid);
+ ok(hres == E_FAIL, "GetGUID failed: %08x, expected E_FAIL\n", hres);
+ ok(IsEqualGUID(&IID_NULL, &guid), "wrong guid\n");
+
+ hres = IProvideClassInfo2_GetGUID(class_info, 2, &guid);
+ ok(hres == E_FAIL, "GetGUID failed: %08x, expected E_FAIL\n", hres);
+ ok(IsEqualGUID(&IID_NULL, &guid), "wrong guid\n");
+
+ hres = IProvideClassInfo2_GetGUID(class_info, GUIDKIND_DEFAULT_SOURCE_DISP_IID, NULL);
+ ok(hres == E_POINTER, "GetGUID failed: %08x, expected E_POINTER\n", hres);
+
+ hres = IProvideClassInfo2_GetGUID(class_info, 0, NULL);
+ ok(hres == E_POINTER, "GetGUID failed: %08x, expected E_POINTER\n", hres);
+
+ IProvideClassInfo2_Release(class_info);
+}
+
+static void test_ie_funcs(IUnknown *unk)
+{
+ IWebBrowser2 *wb;
+ IDispatch *disp;
+ VARIANT_BOOL b;
+ int i;
+ long hwnd;
+ HRESULT hres;
+
+ hres = IUnknown_QueryInterface(unk, &IID_IWebBrowser2, (void**)&wb);
+ ok(hres == S_OK, "Could not get IWebBrowser2 interface: %08x\n", hres);
+ if(FAILED(hres))
+ return;
+
+ /* HWND */
+
+ hwnd = 0xdeadbeef;
+ hres = IWebBrowser2_get_HWND(wb, &hwnd);
+ ok(hres == E_FAIL, "get_HWND failed: %08x, expected E_FAIL\n", hres);
+ ok(hwnd == 0, "unexpected hwnd %lx\n", hwnd);
+
+ /* MenuBar */
+
+ hres = IWebBrowser2_get_MenuBar(wb, &b);
+ ok(hres == S_OK, "get_MenuBar failed: %08x\n", hres);
+ ok(b == VARIANT_TRUE, "b=%x\n", b);
+
+ SET_EXPECT(Invoke_ONMENUBAR);
+ hres = IWebBrowser2_put_MenuBar(wb, (exvb = VARIANT_FALSE));
+ ok(hres == S_OK, "put_MenuBar failed: %08x\n", hres);
+ CHECK_CALLED(Invoke_ONMENUBAR);
+
+ hres = IWebBrowser2_get_MenuBar(wb, &b);
+ ok(hres == S_OK, "get_MenuBar failed: %08x\n", hres);
+ ok(b == VARIANT_FALSE, "b=%x\n", b);
+
+ SET_EXPECT(Invoke_ONMENUBAR);
+ hres = IWebBrowser2_put_MenuBar(wb, (exvb = 100));
+ ok(hres == S_OK, "put_MenuBar failed: %08x\n", hres);
+ CHECK_CALLED(Invoke_ONMENUBAR);
+
+ hres = IWebBrowser2_get_MenuBar(wb, &b);
+ ok(hres == S_OK, "get_MenuBar failed: %08x\n", hres);
+ ok(b == VARIANT_TRUE, "b=%x\n", b);
+
+ /* AddressBar */
+
+ hres = IWebBrowser2_get_AddressBar(wb, &b);
+ ok(hres == S_OK, "get_AddressBar failed: %08x\n", hres);
+ ok(b == VARIANT_TRUE, "b=%x\n", b);
+
+ SET_EXPECT(Invoke_ONADDRESSBAR);
+ hres = IWebBrowser2_put_AddressBar(wb, (exvb = VARIANT_FALSE));
+ ok(hres == S_OK, "put_AddressBar failed: %08x\n", hres);
+ CHECK_CALLED(Invoke_ONADDRESSBAR);
+
+ hres = IWebBrowser2_get_AddressBar(wb, &b);
+ ok(hres == S_OK, "get_MenuBar failed: %08x\n", hres);
+ ok(b == VARIANT_FALSE, "b=%x\n", b);
+
+ SET_EXPECT(Invoke_ONADDRESSBAR);
+ hres = IWebBrowser2_put_AddressBar(wb, (exvb = 100));
+ ok(hres == S_OK, "put_AddressBar failed: %08x\n", hres);
+ CHECK_CALLED(Invoke_ONADDRESSBAR);
+
+ hres = IWebBrowser2_get_AddressBar(wb, &b);
+ ok(hres == S_OK, "get_AddressBar failed: %08x\n", hres);
+ ok(b == VARIANT_TRUE, "b=%x\n", b);
+
+ SET_EXPECT(Invoke_ONADDRESSBAR);
+ hres = IWebBrowser2_put_AddressBar(wb, (exvb = VARIANT_TRUE));
+ ok(hres == S_OK, "put_MenuBar failed: %08x\n", hres);
+ CHECK_CALLED(Invoke_ONADDRESSBAR);
+
+ /* StatusBar */
+
+ hres = IWebBrowser2_get_StatusBar(wb, &b);
+ ok(hres == S_OK, "get_StatusBar failed: %08x\n", hres);
+ ok(b == VARIANT_TRUE, "b=%x\n", b);
+
+ SET_EXPECT(Invoke_ONSTATUSBAR);
+ hres = IWebBrowser2_put_StatusBar(wb, (exvb = VARIANT_TRUE));
+ ok(hres == S_OK, "put_StatusBar failed: %08x\n", hres);
+ CHECK_CALLED(Invoke_ONSTATUSBAR);
+
+ hres = IWebBrowser2_get_StatusBar(wb, &b);
+ ok(hres == S_OK, "get_StatusBar failed: %08x\n", hres);
+ ok(b == VARIANT_TRUE, "b=%x\n", b);
+
+ SET_EXPECT(Invoke_ONSTATUSBAR);
+ hres = IWebBrowser2_put_StatusBar(wb, (exvb = VARIANT_FALSE));
+ ok(hres == S_OK, "put_StatusBar failed: %08x\n", hres);
+ CHECK_CALLED(Invoke_ONSTATUSBAR);
+
+ hres = IWebBrowser2_get_StatusBar(wb, &b);
+ ok(hres == S_OK, "get_StatusBar failed: %08x\n", hres);
+ ok(b == VARIANT_FALSE, "b=%x\n", b);
+
+ SET_EXPECT(Invoke_ONSTATUSBAR);
+ hres = IWebBrowser2_put_StatusBar(wb, (exvb = 100));
+ ok(hres == S_OK, "put_StatusBar failed: %08x\n", hres);
+ CHECK_CALLED(Invoke_ONSTATUSBAR);
+
+ hres = IWebBrowser2_get_StatusBar(wb, &b);
+ ok(hres == S_OK, "get_StatusBar failed: %08x\n", hres);
+ ok(b == VARIANT_TRUE, "b=%x\n", b);
+
+ /* ToolBar */
+
+ hres = IWebBrowser2_get_ToolBar(wb, &i);
+ ok(hres == S_OK, "get_ToolBar failed: %08x\n", hres);
+ ok(i, "i=%x\n", i);
+
+ SET_EXPECT(Invoke_ONTOOLBAR);
+ hres = IWebBrowser2_put_ToolBar(wb, (exvb = VARIANT_FALSE));
+ ok(hres == S_OK, "put_ToolBar failed: %08x\n", hres);
+ CHECK_CALLED(Invoke_ONTOOLBAR);
+
+ hres = IWebBrowser2_get_ToolBar(wb, &i);
+ ok(hres == S_OK, "get_ToolBar failed: %08x\n", hres);
+ ok(i == VARIANT_FALSE, "b=%x\n", i);
+
+ SET_EXPECT(Invoke_ONTOOLBAR);
+ hres = IWebBrowser2_put_ToolBar(wb, (exvb = 100));
+ ok(hres == S_OK, "put_ToolBar failed: %08x\n", hres);
+ CHECK_CALLED(Invoke_ONTOOLBAR);
+
+ hres = IWebBrowser2_get_ToolBar(wb, &i);
+ ok(hres == S_OK, "get_ToolBar failed: %08x\n", hres);
+ ok(i, "i=%x\n", i);
+
+ SET_EXPECT(Invoke_ONTOOLBAR);
+ hres = IWebBrowser2_put_ToolBar(wb, (exvb = VARIANT_TRUE));
+ ok(hres == S_OK, "put_ToolBar failed: %08x\n", hres);
+ CHECK_CALLED(Invoke_ONTOOLBAR);
+
+ /* FullScreen */
+
+ hres = IWebBrowser2_get_FullScreen(wb, &b);
+ ok(hres == S_OK, "get_FullScreen failed: %08x\n", hres);
+ ok(b == VARIANT_FALSE, "b=%x\n", b);
+
+ SET_EXPECT(Invoke_ONFULLSCREEN);
+ hres = IWebBrowser2_put_FullScreen(wb, (exvb = VARIANT_TRUE));
+ ok(hres == S_OK, "put_FullScreen failed: %08x\n", hres);
+ CHECK_CALLED(Invoke_ONFULLSCREEN);
+
+ hres = IWebBrowser2_get_FullScreen(wb, &b);
+ ok(hres == S_OK, "get_FullScreen failed: %08x\n", hres);
+ ok(b == VARIANT_TRUE, "b=%x\n", b);
+
+ SET_EXPECT(Invoke_ONFULLSCREEN);
+ hres = IWebBrowser2_put_FullScreen(wb, (exvb = 100));
+ ok(hres == S_OK, "put_FullScreen failed: %08x\n", hres);
+ CHECK_CALLED(Invoke_ONFULLSCREEN);
+
+ hres = IWebBrowser2_get_FullScreen(wb, &b);
+ ok(hres == S_OK, "get_FullScreen failed: %08x\n", hres);
+ ok(b == VARIANT_TRUE, "b=%x\n", b);
+
+ SET_EXPECT(Invoke_ONFULLSCREEN);
+ hres = IWebBrowser2_put_FullScreen(wb, (exvb = VARIANT_FALSE));
+ ok(hres == S_OK, "put_FullScreen failed: %08x\n", hres);
+ CHECK_CALLED(Invoke_ONFULLSCREEN);
+
+ /* TheaterMode */
+
+ hres = IWebBrowser2_get_TheaterMode(wb, &b);
+ ok(hres == S_OK, "get_TheaterMode failed: %08x\n", hres);
+ ok(b == VARIANT_FALSE, "b=%x\n", b);
+
+ SET_EXPECT(Invoke_ONTHEATERMODE);
+ hres = IWebBrowser2_put_TheaterMode(wb, (exvb = VARIANT_TRUE));
+ ok(hres == S_OK, "put_TheaterMode failed: %08x\n", hres);
+ CHECK_CALLED(Invoke_ONTHEATERMODE);
+
+ hres = IWebBrowser2_get_TheaterMode(wb, &b);
+ ok(hres == S_OK, "get_TheaterMode failed: %08x\n", hres);
+ ok(b == VARIANT_TRUE, "b=%x\n", b);
+
+ SET_EXPECT(Invoke_ONTHEATERMODE);
+ hres = IWebBrowser2_put_TheaterMode(wb, (exvb = 100));
+ ok(hres == S_OK, "put_TheaterMode failed: %08x\n", hres);
+ CHECK_CALLED(Invoke_ONTHEATERMODE);
+
+ hres = IWebBrowser2_get_TheaterMode(wb, &b);
+ ok(hres == S_OK, "get_TheaterMode failed: %08x\n", hres);
+ ok(b == VARIANT_TRUE, "b=%x\n", b);
+
+ SET_EXPECT(Invoke_ONTHEATERMODE);
+ hres = IWebBrowser2_put_TheaterMode(wb, (exvb = VARIANT_FALSE));
+ ok(hres == S_OK, "put_TheaterMode failed: %08x\n", hres);
+ CHECK_CALLED(Invoke_ONTHEATERMODE);
+
+ /* Resizable */
+
+ b = 0x100;
+ hres = IWebBrowser2_get_Resizable(wb, &b);
+ ok(hres == E_NOTIMPL, "get_Resizable failed: %08x\n", hres);
+ ok(b == 0x100, "b=%x\n", b);
+
+ SET_EXPECT(Invoke_WINDOWSETRESIZABLE);
+ hres = IWebBrowser2_put_Resizable(wb, (exvb = VARIANT_TRUE));
+ ok(hres == S_OK || broken(hres == E_NOTIMPL), "put_Resizable failed: %08x\n", hres);
+ CHECK_CALLED_BROKEN(Invoke_WINDOWSETRESIZABLE);
+
+ SET_EXPECT(Invoke_WINDOWSETRESIZABLE);
+ hres = IWebBrowser2_put_Resizable(wb, (exvb = VARIANT_FALSE));
+ ok(hres == S_OK || broken(hres == E_NOTIMPL), "put_Resizable failed: %08x\n", hres);
+ CHECK_CALLED_BROKEN(Invoke_WINDOWSETRESIZABLE);
+
+ hres = IWebBrowser2_get_Resizable(wb, &b);
+ ok(hres == E_NOTIMPL, "get_Resizable failed: %08x\n", hres);
+ ok(b == 0x100, "b=%x\n", b);
+
+ /* Application */
+
+ disp = NULL;
+ hres = IWebBrowser2_get_Application(wb, &disp);
+ ok(hres == S_OK, "get_Application failed: %08x\n", hres);
+ ok(disp == (void*)wb, "disp=%p, expected %p\n", disp, wb);
+ if(disp)
+ IDispatch_Release(disp);
+
+ hres = IWebBrowser2_get_Application(wb, NULL);
+ ok(hres == E_POINTER, "get_Application failed: %08x, expected E_POINTER\n", hres);
+
+ /* Quit */
+
+ hres = IWebBrowser2_Quit(wb);
+ ok(hres == E_FAIL, "Quit failed: %08x, expected E_FAIL\n", hres);
+
+ IWebBrowser2_Release(wb);
+}
+
+static void test_Silent(IWebBrowser2 *wb, IOleControl *control, BOOL is_clientsite)
+{
+ VARIANT_BOOL b;
+ HRESULT hres;
+
+ b = 100;
+ hres = IWebBrowser2_get_Silent(wb, &b);
+ ok(hres == S_OK, "get_Silent failed: %08x\n", hres);
+ ok(b == VARIANT_FALSE, "b=%x\n", b);
+
+ hres = IWebBrowser2_put_Silent(wb, VARIANT_TRUE);
+ ok(hres == S_OK, "set_Silent failed: %08x\n", hres);
+
+ b = 100;
+ hres = IWebBrowser2_get_Silent(wb, &b);
+ ok(hres == S_OK, "get_Silent failed: %08x\n", hres);
+ ok(b == VARIANT_TRUE, "b=%x\n", b);
+
+ hres = IWebBrowser2_put_Silent(wb, 100);
+ ok(hres == S_OK, "set_Silent failed: %08x\n", hres);
+
+ b = 100;
+ hres = IWebBrowser2_get_Silent(wb, &b);
+ ok(hres == S_OK, "get_Silent failed: %08x\n", hres);
+ ok(b == VARIANT_TRUE, "b=%x\n", b);
+
+ hres = IWebBrowser2_put_Silent(wb, VARIANT_FALSE);
+ ok(hres == S_OK, "set_Silent failed: %08x\n", hres);
+
+ b = 100;
+ hres = IWebBrowser2_get_Silent(wb, &b);
+ ok(hres == S_OK, "get_Silent failed: %08x\n", hres);
+ ok(b == VARIANT_FALSE, "b=%x\n", b);
+
+ if(is_clientsite) {
+ hres = IWebBrowser2_put_Silent(wb, VARIANT_TRUE);
+ ok(hres == S_OK, "set_Silent failed: %08x\n", hres);
+
+ SET_EXPECT(Invoke_AMBIENT_SILENT);
+ }
+
+ hres = IOleControl_OnAmbientPropertyChange(control, DISPID_AMBIENT_SILENT);
+ ok(hres == S_OK, "OnAmbientPropertyChange failed %08x\n", hres);
+
+ if(is_clientsite)
+ CHECK_CALLED(Invoke_AMBIENT_SILENT);
+
+ b = 100;
+ hres = IWebBrowser2_get_Silent(wb, &b);
+ ok(hres == S_OK, "get_Silent failed: %08x\n", hres);
+ ok(b == VARIANT_FALSE, "b=%x\n", b);
+}
+
+static void test_Offline(IWebBrowser2 *wb, IOleControl *control, BOOL is_clientsite)
+{
+ VARIANT_BOOL b;
+ HRESULT hres;
+
+ b = 100;
+ hres = IWebBrowser2_get_Offline(wb, &b);
+ ok(hres == S_OK, "get_Offline failed: %08x\n", hres);
+ ok(b == VARIANT_FALSE, "b=%x\n", b);
+
+ hres = IWebBrowser2_put_Offline(wb, VARIANT_TRUE);
+ ok(hres == S_OK, "set_Offline failed: %08x\n", hres);
+
+ b = 100;
+ hres = IWebBrowser2_get_Offline(wb, &b);
+ ok(hres == S_OK, "get_Offline failed: %08x\n", hres);
+ ok(b == VARIANT_TRUE, "b=%x\n", b);
+
+ hres = IWebBrowser2_put_Offline(wb, 100);
+ ok(hres == S_OK, "set_Offline failed: %08x\n", hres);
+
+ b = 100;
+ hres = IWebBrowser2_get_Offline(wb, &b);
+ ok(hres == S_OK, "get_Offline failed: %08x\n", hres);
+ ok(b == VARIANT_TRUE, "b=%x\n", b);
+
+ hres = IWebBrowser2_put_Offline(wb, VARIANT_FALSE);
+ ok(hres == S_OK, "set_Offline failed: %08x\n", hres);
+
+ b = 100;
+ hres = IWebBrowser2_get_Offline(wb, &b);
+ ok(hres == S_OK, "get_Offline failed: %08x\n", hres);
+ ok(b == VARIANT_FALSE, "b=%x\n", b);
+
+ if(is_clientsite) {
+ hres = IWebBrowser2_put_Offline(wb, VARIANT_TRUE);
+ ok(hres == S_OK, "set_Offline failed: %08x\n", hres);
+
+ SET_EXPECT(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED);
+ }
+
+ hres = IOleControl_OnAmbientPropertyChange(control, DISPID_AMBIENT_OFFLINEIFNOTCONNECTED);
+ ok(hres == S_OK, "OnAmbientPropertyChange failed %08x\n", hres);
+
+ if(is_clientsite)
+ CHECK_CALLED(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED);
+
+ b = 100;
+ hres = IWebBrowser2_get_Offline(wb, &b);
+ ok(hres == S_OK, "get_Offline failed: %08x\n", hres);
+ ok(b == VARIANT_FALSE, "b=%x\n", b);
+}
+
+static void test_wb_funcs(IUnknown *unk, BOOL is_clientsite)
+{
+ IWebBrowser2 *wb;
+ IOleControl *control;
+ HRESULT hres;
+
+ hres = IUnknown_QueryInterface(unk, &IID_IWebBrowser2, (void**)&wb);
+ ok(hres == S_OK, "Could not get IWebBrowser2 interface: %08x\n", hres);
+
+ hres = IUnknown_QueryInterface(unk, &IID_IOleControl, (void**)&control);
+ ok(hres == S_OK, "Could not get IOleControl interface: %08x\n", hres);
+
+ test_Silent(wb, control, is_clientsite);
+ test_Offline(wb, control, is_clientsite);
+
+ IWebBrowser_Release(wb);
+ IOleControl_Release(control);
+}
+
+static void test_GetControlInfo(IUnknown *unk)
+{
+ IOleControl *control;
+ CONTROLINFO info;
+ HRESULT hres;
+
+ hres = IUnknown_QueryInterface(unk, &IID_IOleControl, (void**)&control);
+ ok(hres == S_OK, "Could not get IOleControl: %08x\n", hres);
+ if(FAILED(hres))
+ return;
+
+ hres = IOleControl_GetControlInfo(control, &info);
+ ok(hres == E_NOTIMPL, "GetControlInfo failed: %08x, exxpected E_NOTIMPL\n", hres);
+ hres = IOleControl_GetControlInfo(control, NULL);
+ ok(hres == E_NOTIMPL, "GetControlInfo failed: %08x, exxpected E_NOTIMPL\n", hres);
+
+ IOleControl_Release(control);
+}
+
+static void test_Extent(IUnknown *unk)
+{
+ IOleObject *oleobj;
+ SIZE size, expected;
+ HRESULT hres;
+ DWORD dpi_x;
+ DWORD dpi_y;
+ HDC hdc;
+
+ /* default aspect ratio is 96dpi / 96dpi */
+ hdc = GetDC(0);
+ dpi_x = GetDeviceCaps(hdc, LOGPIXELSX);
+ dpi_y = GetDeviceCaps(hdc, LOGPIXELSY);
+ ReleaseDC(0, hdc);
+ if (dpi_x != 96 || dpi_y != 96)
+ trace("dpi: %d / %d\n", dpi_y, dpi_y);
+
+ hres = IUnknown_QueryInterface(unk, &IID_IOleObject, (void**)&oleobj);
+ ok(hres == S_OK, "Could not get IOleObkect: %08x\n", hres);
+ if(FAILED(hres))
+ return;
+
+ size.cx = size.cy = 0xdeadbeef;
+ hres = IOleObject_GetExtent(oleobj, DVASPECT_CONTENT, &size);
+ ok(hres == S_OK, "GetExtent failed: %08x\n", hres);
+ /* Default size is 50x20 pixels, in himetric units */
+ expected.cx = MulDiv( 50, 2540, dpi_x );
+ expected.cy = MulDiv( 20, 2540, dpi_y );
+ ok(size.cx == expected.cx && size.cy == expected.cy, "size = {%d %d} (expected %d %d)\n",
+ size.cx, size.cy, expected.cx, expected.cy );
+
+ size.cx = 800;
+ size.cy = 700;
+ hres = IOleObject_SetExtent(oleobj, DVASPECT_CONTENT, &size);
+ ok(hres == S_OK, "SetExtent failed: %08x\n", hres);
+
+ size.cx = size.cy = 0xdeadbeef;
+ hres = IOleObject_GetExtent(oleobj, DVASPECT_CONTENT, &size);
+ ok(hres == S_OK, "GetExtent failed: %08x\n", hres);
+ ok(size.cx == 800 && size.cy == 700, "size = {%d %d}\n", size.cx, size.cy);
+
+ size.cx = size.cy = 0xdeadbeef;
+ hres = IOleObject_GetExtent(oleobj, 0, &size);
+ ok(hres == S_OK, "GetExtent failed: %08x\n", hres);
+ ok(size.cx == 800 && size.cy == 700, "size = {%d %d}\n", size.cx, size.cy);
+
+ size.cx = 900;
+ size.cy = 800;
+ hres = IOleObject_SetExtent(oleobj, 0, &size);
+ ok(hres == S_OK, "SetExtent failed: %08x\n", hres);
+
+ size.cx = size.cy = 0xdeadbeef;
+ hres = IOleObject_GetExtent(oleobj, 0, &size);
+ ok(hres == S_OK, "GetExtent failed: %08x\n", hres);
+ ok(size.cx == 900 && size.cy == 800, "size = {%d %d}\n", size.cx, size.cy);
+
+ size.cx = size.cy = 0xdeadbeef;
+ hres = IOleObject_GetExtent(oleobj, 0xdeadbeef, &size);
+ ok(hres == S_OK, "GetExtent failed: %08x\n", hres);
+ ok(size.cx == 900 && size.cy == 800, "size = {%d %d}\n", size.cx, size.cy);
+
+ size.cx = 1000;
+ size.cy = 900;
+ hres = IOleObject_SetExtent(oleobj, 0xdeadbeef, &size);
+ ok(hres == S_OK, "SetExtent failed: %08x\n", hres);
+
+ size.cx = size.cy = 0xdeadbeef;
+ hres = IOleObject_GetExtent(oleobj, 0xdeadbeef, &size);
+ ok(hres == S_OK, "GetExtent failed: %08x\n", hres);
+ ok(size.cx == 1000 && size.cy == 900, "size = {%d %d}\n", size.cx, size.cy);
+
+ size.cx = size.cy = 0xdeadbeef;
+ hres = IOleObject_GetExtent(oleobj, DVASPECT_CONTENT, &size);
+ ok(hres == S_OK, "GetExtent failed: %08x\n", hres);
+ ok(size.cx == 1000 && size.cy == 900, "size = {%d %d}\n", size.cx, size.cy);
+
+ IOleObject_Release(oleobj);
+}
+
+static void test_ConnectionPoint(IUnknown *unk, BOOL init)
+{
+ IConnectionPointContainer *container;
+ IConnectionPoint *point;
+ HRESULT hres;
+
+ static DWORD dw = 100;
+
+ hres = IUnknown_QueryInterface(unk, &IID_IConnectionPointContainer, (void**)&container);
+ ok(hres == S_OK, "QueryInterface(IID_IConnectionPointContainer) failed: %08x\n", hres);
+ if(FAILED(hres))
+ return;
+
+ hres = IConnectionPointContainer_FindConnectionPoint(container, &DIID_DWebBrowserEvents2, &point);
+ IConnectionPointContainer_Release(container);
+ ok(hres == S_OK, "FindConnectionPoint failed: %08x\n", hres);
+ if(FAILED(hres))
+ return;
+
+ if(init) {
+ hres = IConnectionPoint_Advise(point, (IUnknown*)&WebBrowserEvents2, &dw);
+ ok(hres == S_OK, "Advise failed: %08x\n", hres);
+ ok(dw == 1, "dw=%d, expected 1\n", dw);
+ }else {
+ hres = IConnectionPoint_Unadvise(point, dw);
+ ok(hres == S_OK, "Unadvise failed: %08x\n", hres);
+ }
+
+ IConnectionPoint_Release(point);
+}
+
+static void test_Navigate2(IUnknown *unk)
+{
+ IWebBrowser2 *webbrowser;
+ VARIANT url;
+ HRESULT hres;
+
+ hres = IUnknown_QueryInterface(unk, &IID_IWebBrowser2, (void**)&webbrowser);
+ ok(hres == S_OK, "QueryInterface(IID_IWebBrowser) failed: %08x\n", hres);
+ if(FAILED(hres))
+ return;
+
+ test_LocationURL(unk, emptyW);
+
+ V_VT(&url) = VT_BSTR;
+ V_BSTR(&url) = SysAllocString(about_blankW);
+
+ SET_EXPECT(Invoke_AMBIENT_USERMODE);
+ SET_EXPECT(Invoke_PROPERTYCHANGE);
+ SET_EXPECT(Invoke_BEFORENAVIGATE2);
+ SET_EXPECT(Invoke_DOWNLOADBEGIN);
+ SET_EXPECT(Exec_SETDOWNLOADSTATE_1);
+ SET_EXPECT(EnableModeless_FALSE);
+ SET_EXPECT(Invoke_STATUSTEXTCHANGE);
+ SET_EXPECT(SetStatusText);
+ SET_EXPECT(GetHostInfo);
+ SET_EXPECT(Invoke_AMBIENT_DLCONTROL);
+ SET_EXPECT(Invoke_AMBIENT_USERAGENT);
+ SET_EXPECT(Invoke_AMBIENT_PALETTE);
+ SET_EXPECT(GetOptionKeyPath);
+ SET_EXPECT(GetOverridesKeyPath);
+ SET_EXPECT(QueryStatus_SETPROGRESSTEXT);
+ SET_EXPECT(Exec_SETPROGRESSMAX);
+ SET_EXPECT(Exec_SETPROGRESSPOS);
+ SET_EXPECT(Invoke_SETSECURELOCKICON);
+ SET_EXPECT(Invoke_FILEDOWNLOAD);
+ SET_EXPECT(Exec_SETDOWNLOADSTATE_0);
+ SET_EXPECT(Invoke_COMMANDSTATECHANGE);
+ SET_EXPECT(EnableModeless_TRUE);
+
+ hres = IWebBrowser2_Navigate2(webbrowser, &url, NULL, NULL, NULL, NULL);
+ ok(hres == S_OK, "Navigate2 failed: %08x\n", hres);
+
+ CHECK_CALLED(Invoke_AMBIENT_USERMODE);
+ todo_wine CHECK_CALLED(Invoke_PROPERTYCHANGE);
+ CHECK_CALLED(Invoke_BEFORENAVIGATE2);
+ todo_wine CHECK_CALLED(Invoke_DOWNLOADBEGIN);
+ todo_wine CHECK_CALLED(Exec_SETDOWNLOADSTATE_1);
+ CHECK_CALLED(EnableModeless_FALSE);
+ CHECK_CALLED(Invoke_STATUSTEXTCHANGE);
+ CHECK_CALLED(SetStatusText);
+ CHECK_CALLED(GetHostInfo);
+ CHECK_CALLED(Invoke_AMBIENT_DLCONTROL);
+ CHECK_CALLED(Invoke_AMBIENT_USERAGENT);
+ CHECK_CALLED(Invoke_AMBIENT_PALETTE);
+ CHECK_CALLED(GetOptionKeyPath);
+ CHECK_CALLED_BROKEN(GetOverridesKeyPath);
+ todo_wine CHECK_CALLED(QueryStatus_SETPROGRESSTEXT);
+ todo_wine CHECK_CALLED(Exec_SETPROGRESSMAX);
+ todo_wine CHECK_CALLED(Exec_SETPROGRESSPOS);
+ todo_wine CHECK_CALLED_BROKEN(Invoke_SETSECURELOCKICON);
+ todo_wine CHECK_CALLED_BROKEN(Invoke_FILEDOWNLOAD);
+ todo_wine CHECK_CALLED(Invoke_COMMANDSTATECHANGE);
+ todo_wine CHECK_CALLED(Exec_SETDOWNLOADSTATE_0);
+ CHECK_CALLED(EnableModeless_TRUE);
+
+ VariantClear(&url);
+ IWebBrowser2_Release(webbrowser);
+}
+
+static void test_IServiceProvider(IUnknown *unk)
+{
+ IServiceProvider *servprov = (void*)0xdeadbeef;
+ HRESULT hres;
+ IUnknown *ret = NULL;
+ static const IID IID_IBrowserService2 =
+ {0x68BD21CC,0x438B,0x11d2,{0xA5,0x60,0x00,0xA0,0xC,0x2D,0xBF,0xE8}};
+
+ hres = IUnknown_QueryInterface(unk, &IID_IServiceProvider, (void**)&servprov);
+ ok(hres == S_OK, "QueryInterface returned %08x, expected S_OK\n", hres);
+ if(FAILED(hres))
+ return;
+
+ hres = IServiceProvider_QueryService(servprov, &SID_STopLevelBrowser, &IID_IBrowserService2, (LPVOID*)&ret);
+ ok(hres == E_FAIL, "QueryService returned %08x, expected E_FAIL\n", hres);
+ ok(ret == NULL, "ret returned %p, expected NULL\n", ret);
+ if(hres == S_OK)
+ {
+ IUnknown_Release(ret);
+ }
+
+ IServiceProvider_Release(servprov);
+}
+
+static void test_QueryInterface(IUnknown *unk)
+{
+ IQuickActivate *qa = (IQuickActivate*)0xdeadbeef;
+ IRunnableObject *runnable = (IRunnableObject*)0xdeadbeef;
+ IPerPropertyBrowsing *propbrowse = (void*)0xdeadbeef;
+ IOleInPlaceSite *inplace = (void*)0xdeadbeef;
+ IOleCache *cache = (void*)0xdeadbeef;
+ IObjectWithSite *site = (void*)0xdeadbeef;
+ IViewObjectEx *viewex = (void*)0xdeadbeef;
+ HRESULT hres;
+
+ hres = IUnknown_QueryInterface(unk, &IID_IQuickActivate, (void**)&qa);
+ ok(hres == E_NOINTERFACE, "QueryInterface returned %08x, expected E_NOINTERFACE\n", hres);
+ ok(qa == NULL, "qa=%p, expected NULL\n", qa);
+
+ hres = IUnknown_QueryInterface(unk, &IID_IRunnableObject, (void**)&runnable);
+ ok(hres == E_NOINTERFACE, "QueryInterface returned %08x, expected E_NOINTERFACE\n", hres);
+ ok(runnable == NULL, "runnable=%p, expected NULL\n", runnable);
+
+ hres = IUnknown_QueryInterface(unk, &IID_IPerPropertyBrowsing, (void**)&propbrowse);
+ ok(hres == E_NOINTERFACE, "QueryInterface returned %08x, expected E_NOINTERFACE\n", hres);
+ ok(propbrowse == NULL, "propbrowse=%p, expected NULL\n", propbrowse);
+
+ hres = IUnknown_QueryInterface(unk, &IID_IOleCache, (void**)&cache);
+ ok(hres == E_NOINTERFACE, "QueryInterface returned %08x, expected E_NOINTERFACE\n", hres);
+ ok(cache == NULL, "cache=%p, expected NULL\n", cache);
+
+ hres = IUnknown_QueryInterface(unk, &IID_IOleInPlaceSite, (void**)&inplace);
+ ok(hres == E_NOINTERFACE, "QueryInterface returned %08x, expected E_NOINTERFACE\n", hres);
+ ok(inplace == NULL, "inplace=%p, expected NULL\n", inplace);
+
+ hres = IUnknown_QueryInterface(unk, &IID_IObjectWithSite, (void**)&site);
+ ok(hres == E_NOINTERFACE, "QueryInterface returned %08x, expected E_NOINTERFACE\n", hres);
+ ok(site == NULL, "site=%p, expected NULL\n", site);
+
+ hres = IUnknown_QueryInterface(unk, &IID_IViewObjectEx, (void**)&viewex);
+ ok(hres == E_NOINTERFACE, "QueryInterface returned %08x, expected E_NOINTERFACE\n", hres);
+ ok(viewex == NULL, "viewex=%p, expected NULL\n", viewex);
+
+}
+
+static void test_WebBrowser(void)
+{
+ IUnknown *unk = NULL;
+ ULONG ref;
+ HRESULT hres;
+
+ hres = CoCreateInstance(&CLSID_WebBrowser, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
+ &IID_IUnknown, (void**)&unk);
+ ok(hres == S_OK, "CoCreateInterface failed: %08x\n", hres);
+ if(FAILED(hres))
+ return;
+
+ hres = IUnknown_QueryInterface(unk, &IID_IWebBrowser2, (void**)&wb);
+ ok(hres == S_OK, "Could not get IWebBrowser2 iface: %08x\n", hres);
+
+ test_QueryInterface(unk);
+ test_ClassInfo(unk);
+ test_LocationURL(unk, emptyW);
+ test_ConnectionPoint(unk, TRUE);
+ test_ClientSite(unk, &ClientSite);
+ test_Extent(unk);
+ test_wb_funcs(unk, TRUE);
+ test_DoVerb(unk);
+ test_Navigate2(unk);
+ test_ClientSite(unk, NULL);
+ test_ie_funcs(unk);
+ test_GetControlInfo(unk);
+ test_wb_funcs(unk, FALSE);
+ test_ConnectionPoint(unk, FALSE);
+ test_IServiceProvider(unk);
+
+ IWebBrowser2_Release(wb);
+ ref = IUnknown_Release(unk);
+ ok(ref == 0, "ref=%d, expected 0\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(webbrowser)
+{
+ gecko_installer_workaround(TRUE);
+
+ container_hwnd = create_container_window();
+
+ OleInitialize(NULL);
+
+ test_WebBrowser();
+
+ OleUninitialize();
+
+ gecko_installer_workaround(FALSE);
+}