From d0b02e62c0be04b74cb3e4b76555ec04eed2dcf9 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Sun, 19 May 2013 21:22:21 +0000 Subject: [PATCH] [MSHTML_WINETEST] * Sync with Wine 1.5.26. svn path=/trunk/; revision=59048 --- rostests/winetests/mshtml/CMakeLists.txt | 28 +- rostests/winetests/mshtml/activex.c | 2745 +++++++++++++ rostests/winetests/mshtml/dom.c | 4446 ++++++++++++---------- rostests/winetests/mshtml/events.c | 831 +++- rostests/winetests/mshtml/events.html | 150 + rostests/winetests/mshtml/exectest.html | 139 + rostests/winetests/mshtml/externscr.js | 1 + rostests/winetests/mshtml/htmldoc.c | 3060 +++++++++++++-- rostests/winetests/mshtml/htmllocation.c | 33 +- rostests/winetests/mshtml/jstest.html | 172 +- rostests/winetests/mshtml/misc.c | 12 +- rostests/winetests/mshtml/protocol.c | 41 +- rostests/winetests/mshtml/rsrc.rc | 15 + rostests/winetests/mshtml/script.c | 713 +++- rostests/winetests/mshtml/style.c | 2635 +++++++++++++ rostests/winetests/mshtml/test_tlb.idl | 55 + rostests/winetests/mshtml/testlist.c | 11 +- rostests/winetests/mshtml/vbtest.html | 48 + 18 files changed, 12563 insertions(+), 2572 deletions(-) create mode 100644 rostests/winetests/mshtml/activex.c create mode 100644 rostests/winetests/mshtml/events.html create mode 100644 rostests/winetests/mshtml/exectest.html create mode 100644 rostests/winetests/mshtml/externscr.js create mode 100644 rostests/winetests/mshtml/style.c create mode 100644 rostests/winetests/mshtml/test_tlb.idl create mode 100644 rostests/winetests/mshtml/vbtest.html diff --git a/rostests/winetests/mshtml/CMakeLists.txt b/rostests/winetests/mshtml/CMakeLists.txt index 6f0cdafabf5..141d00463b1 100644 --- a/rostests/winetests/mshtml/CMakeLists.txt +++ b/rostests/winetests/mshtml/CMakeLists.txt @@ -1,7 +1,11 @@ add_definitions(-D__ROS_LONG64__) +add_idl_Headers(test_tlb_header test_tlb.idl) +add_typelib(test_tlb.idl) + list(APPEND SOURCE + activex.c dom.c events.c htmldoc.c @@ -9,11 +13,29 @@ list(APPEND SOURCE misc.c protocol.c script.c - testlist.c - rsrc.rc) + style.c + testlist.c) + +add_executable(mshtml_winetest ${SOURCE} rsrc.rc) + +list(APPEND mshtml_winetest_rc_deps + ${CMAKE_CURRENT_BINARY_DIR}/test_tlb.tlb + ${CMAKE_CURRENT_SOURCE_DIR}/exectest.html + ${CMAKE_CURRENT_SOURCE_DIR}/jstest.html + ${CMAKE_CURRENT_SOURCE_DIR}/vbtest.html + ${CMAKE_CURRENT_SOURCE_DIR}/events.html + ${CMAKE_CURRENT_SOURCE_DIR}/externscr.js) + +set_source_files_properties(rsrc.rc PROPERTIES OBJECT_DEPENDS "${mshtml_winetest_rc_deps}") + +if(NOT MSVC) + # FIXME: http://www.cmake.org/Bug/view.php?id=12998 + #allow_warnings(mshtml_winetest) + set_source_files_properties(${SOURCE} PROPERTIES COMPILE_FLAGS "-Wno-error") +endif() -add_executable(mshtml_winetest ${SOURCE}) target_link_libraries(mshtml_winetest wine uuid strmiids) set_module_type(mshtml_winetest win32cui) add_importlibs(mshtml_winetest wininet ole32 oleaut32 user32 gdi32 urlmon advapi32 msvcrt kernel32 ntdll) +add_dependencies(mshtml_winetest test_tlb_header stdole2) add_cd_file(TARGET mshtml_winetest DESTINATION reactos/bin FOR all) diff --git a/rostests/winetests/mshtml/activex.c b/rostests/winetests/mshtml/activex.c new file mode 100644 index 00000000000..7f20c50edaf --- /dev/null +++ b/rostests/winetests/mshtml/activex.c @@ -0,0 +1,2745 @@ +/* + * Copyright 2010 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 "ole2.h" +#include +//#include "docobj.h" +#include +//#include "dispex.h" +#include +//#include "activscp.h" +//#include "objsafe.h" +#include +#include "mshtml_test.h" + +#include +#include + +#define DEFINE_EXPECT(func) \ + static BOOL expect_ ## func = FALSE, called_ ## func = FALSE + +#define SET_EXPECT(func) \ + do { called_ ## func = FALSE; expect_ ## func = TRUE; } while(0) + +#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 CLEAR_CALLED(func) \ + expect_ ## func = called_ ## func = FALSE + +#undef GetClassInfo + +DEFINE_EXPECT(CreateInstance); +DEFINE_EXPECT(FreezeEvents_TRUE); +DEFINE_EXPECT(FreezeEvents_FALSE); +DEFINE_EXPECT(QuickActivate); +DEFINE_EXPECT(IPersistPropertyBag_InitNew); +DEFINE_EXPECT(IPersistPropertyBag_Load); +DEFINE_EXPECT(Invoke_READYSTATE); +DEFINE_EXPECT(Invoke_ENABLED); +DEFINE_EXPECT(Invoke_VALID); +DEFINE_EXPECT(Invoke_SECURITYCTX); +DEFINE_EXPECT(Invoke_SCRIPTPROP); +DEFINE_EXPECT(Invoke_SCRIPTCALL); +DEFINE_EXPECT(GetIDsOfNames_scriptprop); +DEFINE_EXPECT(DoVerb); +DEFINE_EXPECT(SetExtent); +DEFINE_EXPECT(GetExtent); +DEFINE_EXPECT(SetClientSite); +DEFINE_EXPECT(SetClientSite_NULL); +DEFINE_EXPECT(Close); +DEFINE_EXPECT(InPlaceObject_GetWindow); +DEFINE_EXPECT(SetObjectRects); +DEFINE_EXPECT(InPlaceDeactivate); +DEFINE_EXPECT(UIDeactivate); +DEFINE_EXPECT(QueryService_TestActiveX); +DEFINE_EXPECT(GetMiscStatus); +DEFINE_EXPECT(SetAdvise); +DEFINE_EXPECT(GetViewStatus); +DEFINE_EXPECT(QI_ITestActiveX); +DEFINE_EXPECT(wrapped_AddRef); +DEFINE_EXPECT(wrapped_Release); +DEFINE_EXPECT(wrapped_func); +DEFINE_EXPECT(OnAmbientPropertyChange_UNKNOWN); +DEFINE_EXPECT(GetTypeInfo); +DEFINE_EXPECT(GetClassInfo); +DEFINE_EXPECT(FindConnectionPoint); +DEFINE_EXPECT(Advise); +DEFINE_EXPECT(Unadvise); + +#define DISPID_SCRIPTPROP 1000 +#define DISPID_SCRIPTCALL 1001 + +enum { + TEST_FLASH, + TEST_NOQUICKACT, + TEST_DISPONLY +}; + +static ITypeInfo *actxtest_typeinfo, *class_typeinfo; +static HWND container_hwnd, plugin_hwnd; +static int plugin_behavior; +static BOOL no_quickact; + +#define TESTACTIVEX_CLSID "{178fc163-f585-4e24-9c13-4bb7f6680746}" + +static const GUID CLSID_TestActiveX = + {0x178fc163,0xf585,0x4e24,{0x9c,0x13,0x4b,0xb7,0xf6,0x68,0x07,0x46}}; + +static const GUID IID_ITestActiveX = + {0x178fc663,0xf585,0x4e24,{0x9c,0x13,0x4b,0xb7,0xf6,0x68,0x07,0x46}}; + +static const char object_ax_str[] = + "" + "" + "" + "" + "" + "" + ""; + +static const char event_binding_str[] = + "" + "" + "" + "" + "" + "" + "" + ""; + +static REFIID pluginhost_iids[] = { + &IID_IOleClientSite, + &IID_IAdviseSink, + &IID_IAdviseSinkEx, + &IID_IPropertyNotifySink, + &IID_IDispatch, + &IID_IOleWindow, + &IID_IOleInPlaceSite, + &IID_IOleInPlaceSiteEx, + &IID_IOleControlSite, + &IID_IBindHost, + &IID_IServiceProvider, + NULL +}; + +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; +} + +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(iface2, &IID_IUnknown, (void**)&unk2); + IUnknown_Release(unk2); + + return unk1 == unk2; +} + +#define test_ifaces(i,ids) _test_ifaces(__LINE__,i,ids) +static void _test_ifaces(unsigned line, IUnknown *iface, REFIID *iids) +{ + const IID * const *piid; + IUnknown *unk; + HRESULT hres; + + for(piid = iids; *piid; piid++) { + hres = IUnknown_QueryInterface(iface, *piid, (void**)&unk); + ok_(__FILE__,line) (hres == S_OK, "Could not get %s interface: %08x\n", debugstr_guid(*piid), hres); + if(SUCCEEDED(hres)) + IUnknown_Release(unk); + } +} + +static int strcmp_wa(LPCWSTR strw, const char *stra) +{ + CHAR buf[512]; + WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL); + return lstrcmpA(stra, buf); +} + +static BSTR a2bstr(const char *str) +{ + BSTR ret; + int len; + + len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + ret = SysAllocStringLen(NULL, len); + MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); + + return ret; +} + +static IOleClientSite *client_site; +static IDispatch *sink_disp; +static READYSTATE plugin_readystate = READYSTATE_UNINITIALIZED; + +static void set_plugin_readystate(READYSTATE state) +{ + IPropertyNotifySink *prop_notif; + HRESULT hres; + + plugin_readystate = state; + + hres = IOleClientSite_QueryInterface(client_site, &IID_IPropertyNotifySink, (void**)&prop_notif); + ok(hres == S_OK, "Could not get IPropertyNotifySink iface: %08x\n", hres); + + hres = IPropertyNotifySink_OnChanged(prop_notif, DISPID_READYSTATE); + ok(hres == S_OK, "OnChanged(DISPID_READYSTATE) failed: %08x\n", hres); + + IPropertyNotifySink_Release(prop_notif); +} + +static void test_mon_displayname(IMoniker *mon, const char *exname, const char *broken_name) +{ + LPOLESTR display_name; + DWORD mksys; + HRESULT hres; + + hres = IMoniker_GetDisplayName(mon, NULL, NULL, &display_name); + ok(hres == S_OK, "GetDisplayName failed: %08x\n", hres); + ok(!strcmp_wa(display_name, exname) || broken(broken_name && !strcmp_wa(display_name, broken_name)), + "display_name = %s\n", wine_dbgstr_w(display_name)); + CoTaskMemFree(display_name); + + hres = IMoniker_IsSystemMoniker(mon, &mksys); + ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres); + ok(mksys == MKSYS_URLMONIKER, "mksys = %d\n", mksys); +} + +static LRESULT WINAPI plugin_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) { + case WM_PAINT: { + PAINTSTRUCT ps; + HBRUSH brush; + RECT rect; + HDC dc; + + GetClientRect(hwnd, &rect); + + dc = BeginPaint(hwnd, &ps); + brush = CreateSolidBrush(RGB(255,0,0)); + SelectObject(dc, brush); + Rectangle(dc, rect.left, rect.top, rect.right, rect.bottom); + DeleteObject(brush); + EndPaint(hwnd, &ps); + break; + } + } + + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +static void create_plugin_window(HWND parent, const RECT *rect) +{ + static const WCHAR plugin_testW[] = + {'p','l','u','g','i','n',' ','t','e','s','t',0}; + static WNDCLASSEXW wndclass = { + sizeof(WNDCLASSEXW), + 0, + plugin_proc, + 0, 0, NULL, NULL, NULL, NULL, NULL, + plugin_testW, + NULL + }; + + RegisterClassExW(&wndclass); + plugin_hwnd = CreateWindowW(plugin_testW, plugin_testW, + WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN, rect->left, rect->top, + rect->right-rect->left, rect->bottom-rect->top, parent, NULL, NULL, NULL); +} + +static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface, REFIID riid, void **ppv) +{ + ok(0, "unexpected QI call %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface) +{ + return 2; +} + +static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface) +{ + return 1; +} + +static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *pIID) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface, + IConnectionPointContainer **ppCPC) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink, DWORD *pdwCookie) +{ + DispActiveXTest *ax_test; + IDispatchEx *dispex; + HRESULT hres; + + CHECK_EXPECT(Advise); + + hres = IUnknown_QueryInterface(pUnkSink, &IID_IDispatch, (void**)&sink_disp); + ok(hres == S_OK, "Could not get IDispatch iface: %08x\n", hres); + + hres = IUnknown_QueryInterface(pUnkSink, &IID_IDispatchEx, (void**)&dispex); + ok(hres == E_NOINTERFACE, "QueryInterface(IID_IDispatchEx) returned: %08x\n", hres); + + hres = IUnknown_QueryInterface(pUnkSink, &DIID_DispActiveXTest, (void**)&ax_test); + ok(hres == S_OK, "Could not get DispActiveXTest iface: %08x\n", hres); + DispActiveXTest_Release(ax_test); + + *pdwCookie = 0xdeadbeef; + return S_OK; +} + +static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD dwCookie) +{ + CHECK_EXPECT(Unadvise); + + ok(dwCookie == 0xdeadbeef, "dwCookie = %x\n", dwCookie); + + if(sink_disp) { + IDispatch_Release(sink_disp); + sink_disp = NULL; + } + + return S_OK; +} + +static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface, IEnumConnections **ppEnum) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const IConnectionPointVtbl ConnectionPointVtbl = { + ConnectionPoint_QueryInterface, + ConnectionPoint_AddRef, + ConnectionPoint_Release, + ConnectionPoint_GetConnectionInterface, + ConnectionPoint_GetConnectionPointContainer, + ConnectionPoint_Advise, + ConnectionPoint_Unadvise, + ConnectionPoint_EnumConnections +}; + +static IConnectionPoint ConnectionPoint = { &ConnectionPointVtbl }; + +static HRESULT ax_qi(REFIID,void**); + +static HRESULT WINAPI OleControl_QueryInterface(IOleControl *iface, REFIID riid, void **ppv) +{ + return ax_qi(riid, ppv); +} + +static ULONG WINAPI OleControl_AddRef(IOleControl *iface) +{ + return 2; +} + +static ULONG WINAPI OleControl_Release(IOleControl *iface) +{ + return 1; +} + +static HRESULT WINAPI OleControl_GetControlInfo(IOleControl *iface, CONTROLINFO *pCI) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleControl_OnMnemonic(IOleControl *iface, MSG *mMsg) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleControl_OnAmbientPropertyChange(IOleControl *iface, DISPID dispID) +{ + switch(dispID) { + case DISPID_UNKNOWN: + CHECK_EXPECT2(OnAmbientPropertyChange_UNKNOWN); + break; + default: + ok(0, "unexpected call %d\n", dispID); + } + + return S_OK; +} + +static HRESULT WINAPI OleControl_FreezeEvents(IOleControl *iface, BOOL bFreeze) +{ + if(bFreeze) + CHECK_EXPECT2(FreezeEvents_TRUE); + else + CHECK_EXPECT2(FreezeEvents_FALSE); + return S_OK; +} + +static const IOleControlVtbl OleControlVtbl = { + OleControl_QueryInterface, + OleControl_AddRef, + OleControl_Release, + OleControl_GetControlInfo, + OleControl_OnMnemonic, + OleControl_OnAmbientPropertyChange, + OleControl_FreezeEvents +}; + +static IOleControl OleControl = { &OleControlVtbl }; + +static HRESULT WINAPI QuickActivate_QueryInterface(IQuickActivate *iface, REFIID riid, void **ppv) +{ + return ax_qi(riid, ppv); +} + +static ULONG WINAPI QuickActivate_AddRef(IQuickActivate *iface) +{ + return 2; +} + +static ULONG WINAPI QuickActivate_Release(IQuickActivate *iface) +{ + return 1; +} + +static HRESULT WINAPI QuickActivate_QuickActivate(IQuickActivate *iface, QACONTAINER *container, QACONTROL *control) +{ + CHECK_EXPECT(QuickActivate); + + ok(container != NULL, "container == NULL\n"); + ok(container->cbSize == sizeof(*container), "container->cbSize = %d\n", container->cbSize); + ok(container->pClientSite != NULL, "container->pClientSite == NULL\n"); + ok(container->pAdviseSink != NULL, "container->pAdviseSink == NULL\n"); + ok(container->pPropertyNotifySink != NULL, "container->pPropertyNotifySink == NULL\n"); + ok(!container->pUnkEventSink, "container->pUnkEventSink != NULL\n"); + ok(container->dwAmbientFlags == (QACONTAINER_SUPPORTSMNEMONICS|QACONTAINER_MESSAGEREFLECT|QACONTAINER_USERMODE), + "container->dwAmbientFlags = %x\n", container->dwAmbientFlags); + ok(!container->colorFore, "container->colorFore == 0\n"); /* FIXME */ + todo_wine + ok(container->colorBack, "container->colorBack == 0\n"); /* FIXME */ + todo_wine + ok(container->pFont != NULL, "container->pFont == NULL\n"); + todo_wine + ok(container->pUndoMgr != NULL, "container->pUndoMgr == NULL\n"); + ok(!container->dwAppearance, "container->dwAppearance = %x\n", container->dwAppearance); + ok(!container->lcid, "container->lcid = %x\n", container->lcid); + ok(!container->hpal, "container->hpal = %p\n", container->hpal); + ok(!container->pBindHost, "container->pBindHost != NULL\n"); + ok(!container->pOleControlSite, "container->pOleControlSite != NULL\n"); + ok(!container->pServiceProvider, "container->pServiceProvider != NULL\n"); + + ok(control->cbSize == sizeof(*control), "control->cbSize = %d\n", control->cbSize); + ok(!control->dwMiscStatus, "control->dwMiscStatus = %x\n", control->dwMiscStatus); + ok(!control->dwViewStatus, "control->dwViewStatus = %x\n", control->dwViewStatus); + ok(!control->dwEventCookie, "control->dwEventCookie = %x\n", control->dwEventCookie); + ok(!control->dwPropNotifyCookie, "control->dwPropNotifyCookie = %x\n", control->dwPropNotifyCookie); + ok(!control->dwPointerActivationPolicy, "control->dwPointerActivationPolicy = %x\n", control->dwPointerActivationPolicy); + + ok(iface_cmp((IUnknown*)container->pClientSite, (IUnknown*)container->pAdviseSink), + "container->pClientSite != container->pAdviseSink\n"); + ok(iface_cmp((IUnknown*)container->pClientSite, (IUnknown*)container->pPropertyNotifySink), + "container->pClientSite != container->pPropertyNotifySink\n"); + test_ifaces((IUnknown*)container->pClientSite, pluginhost_iids); + + IOleClientSite_AddRef(container->pClientSite); + client_site = container->pClientSite; + + control->dwMiscStatus = OLEMISC_SETCLIENTSITEFIRST|OLEMISC_ACTIVATEWHENVISIBLE|OLEMISC_INSIDEOUT + |OLEMISC_CANTLINKINSIDE|OLEMISC_RECOMPOSEONRESIZE; + control->dwViewStatus = 0x18; + control->dwPropNotifyCookie = 1; + + return S_OK; +} + +static HRESULT WINAPI QuickActivate_SetContentExtent(IQuickActivate *iface, LPSIZEL pSizel) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI QuickActivate_GetContentExtent(IQuickActivate *iface, LPSIZEL pSizel) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const IQuickActivateVtbl QuickActivateVtbl = { + QuickActivate_QueryInterface, + QuickActivate_AddRef, + QuickActivate_Release, + QuickActivate_QuickActivate, + QuickActivate_GetContentExtent, + QuickActivate_SetContentExtent +}; + +static IQuickActivate QuickActivate = { &QuickActivateVtbl }; + +static HRESULT WINAPI PersistPropertyBag_QueryInterface(IPersistPropertyBag *iface, REFIID riid, void **ppv) +{ + return ax_qi(riid, ppv); +} + +static ULONG WINAPI PersistPropertyBag_AddRef(IPersistPropertyBag *iface) +{ + return 2; +} + +static ULONG WINAPI PersistPropertyBag_Release(IPersistPropertyBag *iface) +{ + return 1; +} + +static HRESULT WINAPI PersistPropertyBag_GetClassID(IPersistPropertyBag *face, CLSID *pClassID) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI PersistPropertyBag_InitNew(IPersistPropertyBag *face) +{ + CHECK_EXPECT(IPersistPropertyBag_InitNew); + return S_OK; +} + +static HRESULT WINAPI PersistPropertyBag_Load(IPersistPropertyBag *face, IPropertyBag *pPropBag, IErrorLog *pErrorLog) +{ + IBindHost *bind_host, *bind_host2; + IServiceProvider *sp; + IMoniker *mon; + VARIANT v; + HRESULT hres; + + static const WCHAR param_nameW[] = {'p','a','r','a','m','_','n','a','m','e',0}; + static const WCHAR num_paramW[] = {'n','u','m','_','p','a','r','a','m',0}; + static const WCHAR no_paramW[] = {'n','o','_','p','a','r','a','m',0}; + static WCHAR test_swfW[] = {'t','e','s','t','.','s','w','f',0}; + + static const IID *propbag_ifaces[] = { + &IID_IPropertyBag, + &IID_IPropertyBag2, + NULL + }; + + CHECK_EXPECT(IPersistPropertyBag_Load); + + ok(pPropBag != NULL, "pPropBag == NULL\n"); + ok(!pErrorLog, "pErrorLog != NULL\n"); + + test_ifaces((IUnknown*)pPropBag, propbag_ifaces); + + V_VT(&v) = VT_BSTR; + hres = IPropertyBag_Read(pPropBag, param_nameW, &v, NULL); + ok(hres == S_OK, "Read failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "param_value"), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + + V_VT(&v) = VT_I4; + V_I4(&v) = 0xdeadbeef; + hres = IPropertyBag_Read(pPropBag, param_nameW, &v, NULL); + ok(hres == DISP_E_TYPEMISMATCH, "Read failed: %08x, expected DISP_E_TYPEMISMATCH\n", hres); + ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v)); + ok(V_I4(&v) == 0xdeadbeef, "V_I4(v) = %x\n", V_I4(&v)); + + V_VT(&v) = VT_BSTR; + hres = IPropertyBag_Read(pPropBag, num_paramW, &v, NULL); + ok(hres == S_OK, "Read failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "3"), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + SysFreeString(V_BSTR(&v)); + + V_VT(&v) = VT_I4; + V_I4(&v) = 0xdeadbeef; + hres = IPropertyBag_Read(pPropBag, num_paramW, &v, NULL); + ok(hres == S_OK, "Read failed: %08x\n", hres); + ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v)); + ok(V_I4(&v) == 3, "V_I4(v) = %x\n", V_I4(&v)); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = (BSTR)0xdeadbeef; + hres = IPropertyBag_Read(pPropBag, no_paramW, &v, NULL); + ok(hres == E_INVALIDARG, "Read failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v)); + ok(V_BSTR(&v) == (BSTR)0xdeadbeef, "V_BSTR(v) = %p\n", V_BSTR(&v)); + + set_plugin_readystate(READYSTATE_INTERACTIVE); + + hres = IOleClientSite_QueryInterface(client_site, &IID_IBindHost, (void**)&bind_host); + ok(hres == S_OK, "Could not get IBindHost iface: %08x\n", hres); + + hres = IOleClientSite_QueryInterface(client_site, &IID_IServiceProvider, (void**)&sp); + ok(hres == S_OK, "Could not get IServiceProvider iface: %08x\n", hres); + + hres = IServiceProvider_QueryService(sp, &SID_SBindHost, &IID_IBindHost, (void**)&bind_host2); + ok(hres == S_OK, "QueryService(SID_SBindHost) failed: %08x\n", hres); + IServiceProvider_Release(sp); + + ok(iface_cmp((IUnknown*)bind_host, (IUnknown*)bind_host2), "bind_host != bind_host2\n"); + IBindHost_Release(bind_host2); + + mon = NULL; + hres = IBindHost_CreateMoniker(bind_host, test_swfW, NULL, &mon, 0); + ok(hres == S_OK, "CreateMoniker failed: %08x\n", hres); + ok(mon != NULL, "mon == NULL\n"); + test_mon_displayname(mon, "about:test.swf", "about:blanktest.swf"); + IMoniker_Release(mon); + + IBindHost_Release(bind_host); + + mon = NULL; + hres = IOleClientSite_GetMoniker(client_site, OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_CONTAINER, &mon); + ok(hres == S_OK, "GetMoniker failed: %08x\n", hres); + ok(mon != NULL, "mon == NULL\n"); + test_mon_displayname(mon, "about:blank", NULL); + IMoniker_Release(mon); + + set_plugin_readystate(READYSTATE_COMPLETE); + + return S_OK; +} + +static HRESULT WINAPI PersistPropertyBag_Save(IPersistPropertyBag *face, IPropertyBag *pPropBag, BOOL fClearDisrty, BOOL fSaveAllProperties) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const IPersistPropertyBagVtbl PersistPropertyBagVtbl = { + PersistPropertyBag_QueryInterface, + PersistPropertyBag_AddRef, + PersistPropertyBag_Release, + PersistPropertyBag_GetClassID, + PersistPropertyBag_InitNew, + PersistPropertyBag_Load, + PersistPropertyBag_Save + +}; + +static IPersistPropertyBag PersistPropertyBag = { &PersistPropertyBagVtbl }; + +static HRESULT WINAPI Dispatch_QueryInterface(IDispatch *iface, REFIID riid, void **ppv) +{ + return ax_qi(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) +{ + CHECK_EXPECT(GetTypeInfo); + + ITypeInfo_AddRef(actxtest_typeinfo); + *ppTInfo = actxtest_typeinfo; + return S_OK; +} + +static HRESULT WINAPI Dispatch_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *rgszNames, + UINT cNames, LCID lcid, DISPID *rgDispId) +{ + ok(IsEqualGUID(riid, &IID_NULL), "riid = %s\n", debugstr_guid(riid)); + ok(cNames == 1, "cNames = %d\n", cNames); + ok(rgszNames != NULL, "rgszNames == NULL\n"); + ok(rgDispId != NULL, "rgDispId == NULL\n"); + + if(!strcmp_wa(rgszNames[0], "scriptprop")) { + CHECK_EXPECT(GetIDsOfNames_scriptprop); + *rgDispId = DISPID_SCRIPTPROP; + }else if(!strcmp_wa(rgszNames[0], "scriptCall")) { + *rgDispId = DISPID_SCRIPTCALL; + }else { + ok(0, "rgszNames[0] = %s\n", wine_dbgstr_w(rgszNames[0])); + } + + return S_OK; +} + +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(riid, &IID_NULL), "riid = %s\n", debugstr_guid(riid)); + ok(pDispParams != NULL, "pDispParams == NULL\n"); + ok(!pDispParams->cNamedArgs, "pDispParams->cNamedArgs = %d\n", pDispParams->cNamedArgs); + ok(!pDispParams->rgdispidNamedArgs, "pDispParams->rgdispidNamedArgs != NULL\n"); + + switch(dispIdMember) { + case DISPID_READYSTATE: + CHECK_EXPECT2(Invoke_READYSTATE); + ok(wFlags == DISPATCH_PROPERTYGET, "wFlags = %x\n", wFlags); + ok(!pDispParams->cArgs, "pDispParams->cArgs = %d\n", pDispParams->cArgs); + ok(!pDispParams->rgvarg, "pDispParams->rgvarg != NULL\n"); + ok(!pExcepInfo, "pExcepInfo != NULL\n"); + ok(puArgErr != NULL, "puArgErr == NULL\n"); + ok(pVarResult != NULL, "pVarResult == NULL\n"); + + V_VT(pVarResult) = VT_I4; + V_I4(pVarResult) = plugin_readystate; + return S_OK; + case DISPID_ENABLED: + CHECK_EXPECT2(Invoke_ENABLED); + ok(wFlags == DISPATCH_PROPERTYGET, "wFlags = %x\n", wFlags); + ok(!pDispParams->cArgs, "pDispParams->cArgs = %d\n", pDispParams->cArgs); + ok(!pDispParams->rgvarg, "pDispParams->rgvarg != NULL\n"); + ok(!pExcepInfo, "pExcepInfo != NULL\n"); + ok(puArgErr != NULL, "puArgErr == NULL\n"); + ok(pVarResult != NULL, "pVarResult == NULL\n"); + return DISP_E_MEMBERNOTFOUND; + case DISPID_VALID: + CHECK_EXPECT(Invoke_VALID); + ok(wFlags == DISPATCH_PROPERTYGET, "wFlags = %x\n", wFlags); + ok(!pDispParams->cArgs, "pDispParams->cArgs = %d\n", pDispParams->cArgs); + ok(!pDispParams->rgvarg, "pDispParams->rgvarg != NULL\n"); + ok(!pExcepInfo, "pExcepInfo != NULL\n"); + ok(puArgErr != NULL, "puArgErr == NULL\n"); + ok(pVarResult != NULL, "pVarResult == NULL\n"); + return DISP_E_MEMBERNOTFOUND; + case DISPID_SECURITYCTX: + CHECK_EXPECT(Invoke_SECURITYCTX); + ok(wFlags == DISPATCH_PROPERTYGET, "wFlags = %x\n", wFlags); + ok(!pDispParams->cArgs, "pDispParams->cArgs = %d\n", pDispParams->cArgs); + ok(!pDispParams->rgvarg, "pDispParams->rgvarg != NULL\n"); + ok(!pExcepInfo, "pExcepInfo != NULL\n"); + ok(puArgErr != NULL, "puArgErr == NULL\n"); + ok(pVarResult != NULL, "pVarResult == NULL\n"); + return DISP_E_MEMBERNOTFOUND; + case DISPID_SCRIPTPROP: + CHECK_EXPECT(Invoke_SCRIPTPROP); + ok(wFlags == DISPATCH_PROPERTYGET, "wFlags = %x\n", wFlags); + ok(!pDispParams->cArgs, "pDispParams->cArgs = %d\n", pDispParams->cArgs); + ok(!pDispParams->rgvarg, "pDispParams->rgvarg != NULL\n"); + ok(pExcepInfo != NULL, "pExcepInfo == NULL\n"); + ok(!puArgErr, "puArgErr != NULL\n"); + ok(pVarResult != NULL, "pVarResult == NULL\n"); + + V_VT(pVarResult) = VT_I4; + V_I4(pVarResult) = 4; + return S_OK; + case DISPID_SCRIPTCALL: + CHECK_EXPECT(Invoke_SCRIPTCALL); + ok(wFlags == DISPATCH_METHOD, "wFlags = %x\n", wFlags); + ok(!pDispParams->cArgs, "pDispParams->cArgs = %d\n", pDispParams->cArgs); + ok(pExcepInfo != NULL, "pExcepInfo == NULL\n"); + ok(!puArgErr, "puArgErr != NULL\n"); + ok(!pVarResult, "pVarResult != NULL\n"); + /* + V_VT(pVarResult) = VT_I4; + V_I4(pVarResult) = 4; + */ + return S_OK; + default: + ok(0, "unexpected call %d\n", dispIdMember); + } + + return E_NOTIMPL; +} + +static const IDispatchVtbl DispatchVtbl = { + Dispatch_QueryInterface, + Dispatch_AddRef, + Dispatch_Release, + Dispatch_GetTypeInfoCount, + Dispatch_GetTypeInfo, + Dispatch_GetIDsOfNames, + Dispatch_Invoke +}; + +static IDispatch Dispatch = { &DispatchVtbl }; + +static HRESULT WINAPI ProvideClassInfo_QueryInterface(IProvideClassInfo *iface, REFIID riid, void **ppv) +{ + return ax_qi(riid, ppv); +} + +static ULONG WINAPI ProvideClassInfo_AddRef(IProvideClassInfo *iface) +{ + return 2; +} + +static ULONG WINAPI ProvideClassInfo_Release(IProvideClassInfo *iface) +{ + return 1; +} + +static HRESULT WINAPI ProvideClassInfo_GetClassInfo(IProvideClassInfo *iface, ITypeInfo **ppTI) +{ + CHECK_EXPECT(GetClassInfo); + + ITypeInfo_AddRef(class_typeinfo); + *ppTI = class_typeinfo; + return S_OK; +} + +static const IProvideClassInfoVtbl ProvideClassInfoVtbl = { + ProvideClassInfo_QueryInterface, + ProvideClassInfo_AddRef, + ProvideClassInfo_Release, + ProvideClassInfo_GetClassInfo +}; + +static IProvideClassInfo ProvideClassInfo = { &ProvideClassInfoVtbl }; + +static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface, REFIID riid, void **ppv) +{ + return ax_qi(riid, ppv); +} + +static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface) +{ + return 2; +} + +static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface) +{ + return 1; +} + +static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface, + IEnumConnectionPoints **ppEnum) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface, + REFIID riid, IConnectionPoint **ppCP) +{ + if(IsEqualGUID(riid, &IID_IPropertyNotifySink)) { + /* TODO */ + trace("FindConnectionPoint(IID_IPropertyNotifySink)\n"); + return CONNECT_E_NOCONNECTION; + } + + CHECK_EXPECT(FindConnectionPoint); + ok(IsEqualGUID(riid, &DIID_DispActiveXTest), "riid = %s\n", debugstr_guid(riid)); + + *ppCP = &ConnectionPoint; + return S_OK; +} + +static const IConnectionPointContainerVtbl ConnectionPointContainerVtbl = { + ConnectionPointContainer_QueryInterface, + ConnectionPointContainer_AddRef, + ConnectionPointContainer_Release, + ConnectionPointContainer_EnumConnectionPoints, + ConnectionPointContainer_FindConnectionPoint +}; + +static IConnectionPointContainer ConnectionPointContainer = { &ConnectionPointContainerVtbl }; + +static HRESULT WINAPI ViewObjectEx_QueryInterface(IViewObjectEx *iface, REFIID riid, void **ppv) +{ + return ax_qi(riid, ppv); +} + +static ULONG WINAPI ViewObjectEx_AddRef(IViewObjectEx *iface) +{ + return 2; +} + +static ULONG WINAPI ViewObjectEx_Release(IViewObjectEx *iface) +{ + return 1; +} + +static HRESULT WINAPI ViewObjectEx_Draw(IViewObjectEx *iface, DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, + HDC hdcTargetDev, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBoungs, BOOL (WINAPI*pfnContinue)(ULONG_PTR), ULONG_PTR dwContinue) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ViewObjectEx_GetColorSet(IViewObjectEx *iface, DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, + HDC hicTargetDev, LOGPALETTE **ppColorSet) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ViewObjectEx_Freeze(IViewObjectEx *iface, DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ViewObjectEx_Unfreeze(IViewObjectEx *iface, DWORD dwFreeze) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ViewObjectEx_SetAdvise(IViewObjectEx *iface, DWORD aspects, DWORD advf, IAdviseSink *pAdvSink) +{ + CHECK_EXPECT(SetAdvise); + + ok(aspects == DVASPECT_CONTENT, "aspects = %x\n", aspects); + ok(!advf, "advf = %x\n", advf); + ok(pAdvSink != NULL, "pAdvSink = NULL\n"); + + return S_OK; +} + +static HRESULT WINAPI ViewObjectEx_GetAdvise(IViewObjectEx *iface, DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ViewObjectEx_GetExtent(IViewObjectEx *iface, DWORD dwDrawAspect, LONG lindex, DVTARGETDEVICE *ptd, LPSIZEL lpsizel) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ViewObjectEx_GetRect(IViewObjectEx *iface, DWORD dwAspect, LPRECTL pRect) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ViewObjectEx_GetViewStatus(IViewObjectEx *iface, DWORD *pdwStatus) +{ + CHECK_EXPECT(GetViewStatus); + + *pdwStatus = VIEWSTATUS_OPAQUE|VIEWSTATUS_SOLIDBKGND; + return S_OK; +} + +static HRESULT WINAPI ViewObjectEx_QueryHitPoint(IViewObjectEx *iface, DWORD dwAspect, LPCRECT pRectBounds, POINT ptlLoc, + LONG lCloseHint, DWORD *pHitResult) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ViewObjectEx_QueryHitRect(IViewObjectEx *iface, DWORD dwAspect, LPCRECT pRectBounds, LPCRECT pRectLoc, + LONG lCloseHint, DWORD *pHitResult) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ViewObjectEx_GetNaturalExtent(IViewObjectEx *iface, DWORD dwAspect, LONG lindex, DVTARGETDEVICE *ptd, + HDC hicTargetDev, DVEXTENTINFO *pExtentIngo, LPSIZEL pSizel) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const IViewObjectExVtbl ViewObjectExVtbl = { + ViewObjectEx_QueryInterface, + ViewObjectEx_AddRef, + ViewObjectEx_Release, + ViewObjectEx_Draw, + ViewObjectEx_GetColorSet, + ViewObjectEx_Freeze, + ViewObjectEx_Unfreeze, + ViewObjectEx_SetAdvise, + ViewObjectEx_GetAdvise, + ViewObjectEx_GetExtent, + ViewObjectEx_GetRect, + ViewObjectEx_GetViewStatus, + ViewObjectEx_QueryHitPoint, + ViewObjectEx_QueryHitRect, + ViewObjectEx_GetNaturalExtent +}; + +static IViewObjectEx ViewObjectEx = { &ViewObjectExVtbl }; + +static HRESULT WINAPI OleObject_QueryInterface(IOleObject *iface, REFIID riid, void **ppv) +{ + return ax_qi(riid, ppv); +} + +static ULONG WINAPI OleObject_AddRef(IOleObject *iface) +{ + return 2; +} + +static ULONG WINAPI OleObject_Release(IOleObject *iface) +{ + return 1; +} + +static HRESULT WINAPI OleObject_SetClientSite(IOleObject *iface, IOleClientSite *pClientSite) +{ + if(!pClientSite) { + CHECK_EXPECT(SetClientSite_NULL); + return S_OK; + } + + CHECK_EXPECT(SetClientSite); + + IOleClientSite_AddRef(pClientSite); + client_site = pClientSite; + return S_OK; +} + +static HRESULT WINAPI OleObject_GetClientSite(IOleObject *iface, IOleClientSite **ppClientSite) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleObject_SetHostNames(IOleObject *iface, LPCOLESTR szContainerApp, LPCOLESTR szContainerObj) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleObject_Close(IOleObject *iface, DWORD dwSaveOption) +{ + CHECK_EXPECT(Close); + + ok(dwSaveOption == OLECLOSE_NOSAVE, "dwSaveOption = %d\n", dwSaveOption); + return S_OK; +} + +static HRESULT WINAPI OleObject_SetMoniker(IOleObject *iface, DWORD dwWhichMoniker, IMoniker *pmk) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleObject_GetMoniker(IOleObject *iface, DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleObject_InitFromData(IOleObject *iface, IDataObject *pDataObject, BOOL fCreation, + DWORD dwReserved) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleObject_GetClipboardData(IOleObject *iface, DWORD dwReserved, IDataObject **ppDataObject) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleObject_DoVerb(IOleObject *iface, LONG iVerb, LPMSG lpmsg, IOleClientSite *pActiveSite, + LONG lindex, HWND hwndParent, LPCRECT lprcPosRect) +{ + OLEINPLACEFRAMEINFO frame_info = {0xdeadbeef}; + IOleInPlaceUIWindow *ip_uiwindow; + IOleInPlaceFrame *ip_frame; + IOleInPlaceSiteEx *ip_site; + RECT pos_rect, clip_rect; + BOOL no_redraw; + HWND hwnd; + HRESULT hres; + + CHECK_EXPECT(DoVerb); + + ok(iVerb == OLEIVERB_INPLACEACTIVATE, "iVerb = %d\n", iVerb); + ok(!lpmsg, "lpmsg != NULL\n"); + ok(pActiveSite != NULL, "pActiveSite == NULL\n"); + ok(!lindex, "lindex = %d\n", lindex); + ok(hwndParent != NULL, "hwndParent == NULL\n"); + ok(lprcPosRect != NULL, "lprcPosRect == NULL\n"); + + hres = IOleClientSite_QueryInterface(pActiveSite, &IID_IOleInPlaceSiteEx, (void**)&ip_site); + ok(hres == S_OK, "Could not get IOleInPlaceSiteEx iface: %08x\n", hres); + + hres = IOleInPlaceSiteEx_CanInPlaceActivate(ip_site); + ok(hres == S_OK, "CanInPlaceActivate failed: %08x\n", hres); + + SET_EXPECT(InPlaceObject_GetWindow); + no_redraw = 0xdeadbeef; + hres = IOleInPlaceSiteEx_OnInPlaceActivateEx(ip_site, &no_redraw, 0); + ok(hres == S_OK, "InPlaceActivateEx failed: %08x\n", hres); + ok(!no_redraw, "no_redraw = %x\n", no_redraw); + CHECK_CALLED(InPlaceObject_GetWindow); + + no_redraw = 0xdeadbeef; + hres = IOleInPlaceSiteEx_OnInPlaceActivateEx(ip_site, &no_redraw, 0); + ok(hres == S_OK, "InPlaceActivateEx failed: %08x\n", hres); + ok(no_redraw == 0xdeadbeef, "no_redraw = %x\n", no_redraw); + + hwnd = NULL; + hres = IOleInPlaceSiteEx_GetWindow(ip_site, &hwnd); + ok(hres == S_OK, "GetWindow failed: %08x\n", hres); + ok(hwnd != NULL, "hwnd == NULL\n"); + ok(hwnd == hwndParent, "hwnd != hwndParent\n"); + + create_plugin_window(hwnd, lprcPosRect); + + ip_frame = NULL; + ip_uiwindow = NULL; + frame_info.cb = sizeof(OLEINPLACEFRAMEINFO); + hres = IOleInPlaceSiteEx_GetWindowContext(ip_site, &ip_frame, &ip_uiwindow, &pos_rect, &clip_rect, &frame_info); + ok(hres == S_OK, "GetWindowContext failed: %08x\n", hres); + ok(ip_frame != NULL, "ip_frame == NULL\n"); + ok(ip_uiwindow != NULL, "ip_uiwindow == NULL\n"); + ok((IOleInPlaceUIWindow*)ip_frame != ip_uiwindow, "ip_frame == ip_uiwindow\n"); + ok(!memcmp(&pos_rect, lprcPosRect, sizeof(RECT)), "pos_rect != lpecPosRect\n"); + ok(!memcmp(&clip_rect, lprcPosRect, sizeof(RECT)), "clip_rect != lpecPosRect\n"); + ok(frame_info.cb == sizeof(frame_info), "frame_info.cb = %d\n", frame_info.cb); + ok(!frame_info.fMDIApp, "frame_info.fMDIApp = %x\n", frame_info.fMDIApp); + ok(frame_info.hwndFrame != NULL, "frame_info.hwnd == NULL\n"); + ok(frame_info.hwndFrame == container_hwnd, "frame_info.hwnd != container_hwnd\n"); + ok(!frame_info.haccel, "frame_info.haccel != 0\n"); + ok(!frame_info.cAccelEntries, "frame_info.cAccelEntried != 0\n"); + + IOleInPlaceFrame_Release(ip_frame); + IOleInPlaceUIWindow_Release(ip_uiwindow); + + + IOleInPlaceSiteEx_Release(ip_site); + + hres = IOleClientSite_ShowObject(client_site); + ok(hres == S_OK, "ShowObject failed: %08x\n", hres); + + SET_EXPECT(InPlaceObject_GetWindow); + SET_EXPECT(SetObjectRects); + + return S_OK; +} + +static HRESULT WINAPI OleObject_EnumVerbs(IOleObject *iface, IEnumOLEVERB **ppEnumOleVerb) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleObject_Update(IOleObject *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleObject_IsUpToDate(IOleObject *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleObject_GetUserClassID(IOleObject *iface, CLSID *pClsid) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleObject_GetUserType(IOleObject *iface, DWORD dwFormOfType, LPOLESTR *pszUserType) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleObject_SetExtent(IOleObject *iface, DWORD dwDrawAspect, SIZEL *psizel) +{ + CHECK_EXPECT(SetExtent); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleObject_GetExtent(IOleObject *iface, DWORD dwDrawAspect, SIZEL *psizel) +{ + CHECK_EXPECT(GetExtent); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleObject_Advise(IOleObject *iface, IAdviseSink *pAdvSink, DWORD *pdwConnection) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleObject_Unadvise(IOleObject *iface, DWORD dwConnection) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleObject_EnumAdvise(IOleObject *iface, IEnumSTATDATA **ppenumAdvise) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleObject_GetMiscStatus(IOleObject *iface, DWORD dwAspect, DWORD *pdwStatus) +{ + CHECK_EXPECT(GetMiscStatus); + ok(dwAspect == DVASPECT_CONTENT, "dwAspect = %d\n", dwAspect); + ok(pdwStatus != NULL, "pdwStatus == NULL\n"); + *pdwStatus = OLEMISC_SETCLIENTSITEFIRST|OLEMISC_ACTIVATEWHENVISIBLE + |OLEMISC_INSIDEOUT|OLEMISC_CANTLINKINSIDE|OLEMISC_RECOMPOSEONRESIZE; + return S_OK; +} + +static HRESULT WINAPI OleObject_SetColorScheme(IOleObject *iface, LOGPALETTE *pLogpal) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const IOleObjectVtbl OleObjectVtbl = { + OleObject_QueryInterface, + OleObject_AddRef, + OleObject_Release, + OleObject_SetClientSite, + OleObject_GetClientSite, + OleObject_SetHostNames, + OleObject_Close, + OleObject_SetMoniker, + OleObject_GetMoniker, + OleObject_InitFromData, + OleObject_GetClipboardData, + OleObject_DoVerb, + OleObject_EnumVerbs, + OleObject_Update, + OleObject_IsUpToDate, + OleObject_GetUserClassID, + OleObject_GetUserType, + OleObject_SetExtent, + OleObject_GetExtent, + OleObject_Advise, + OleObject_Unadvise, + OleObject_EnumAdvise, + OleObject_GetMiscStatus, + OleObject_SetColorScheme +}; + +static IOleObject OleObject = { &OleObjectVtbl }; + +static HRESULT WINAPI OleInPlaceObject_QueryInterface(IOleInPlaceObjectWindowless *iface, + REFIID riid, void **ppv) +{ + return ax_qi(riid, ppv); +} + +static ULONG WINAPI OleInPlaceObject_AddRef(IOleInPlaceObjectWindowless *iface) +{ + return 2; +} + +static ULONG WINAPI OleInPlaceObject_Release(IOleInPlaceObjectWindowless *iface) +{ + return 1; +} + +static HRESULT WINAPI OleInPlaceObject_GetWindow(IOleInPlaceObjectWindowless *iface, + HWND *phwnd) +{ + CHECK_EXPECT2(InPlaceObject_GetWindow); + + ok(phwnd != NULL, "phwnd == NULL\n"); + + *phwnd = plugin_hwnd; + return *phwnd ? S_OK : E_UNEXPECTED; +} + +static HRESULT WINAPI OleInPlaceObject_ContextSensitiveHelp(IOleInPlaceObjectWindowless *iface, + BOOL fEnterMode) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleInPlaceObject_InPlaceDeactivate(IOleInPlaceObjectWindowless *iface) +{ + IOleInPlaceSite *ip_site; + HRESULT hres; + + CHECK_EXPECT(InPlaceDeactivate); + + hres = IOleClientSite_QueryInterface(client_site, &IID_IOleInPlaceSite, (void**)&ip_site); + ok(hres == S_OK, "Could not get IOleInPlaceSite iface: %08x\n", hres); + + hres = IOleInPlaceSite_OnInPlaceDeactivate(ip_site); + ok(hres == S_OK, "OnInPlaceDeactivate failed: %08x\n", hres); + + IOleInPlaceSite_Release(ip_site); + return S_OK; +} + +static HRESULT WINAPI OleInPlaceObject_UIDeactivate(IOleInPlaceObjectWindowless *iface) +{ + CHECK_EXPECT2(UIDeactivate); + return S_OK; +} + +static HRESULT WINAPI OleInPlaceObject_SetObjectRects(IOleInPlaceObjectWindowless *iface, + LPCRECT lprcPosRect, LPCRECT lprcClipRect) +{ + CHECK_EXPECT(SetObjectRects); + return S_OK; +} + +static HRESULT WINAPI OleInPlaceObjectWindowless_ReactivateAndUndo(IOleInPlaceObjectWindowless *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleInPlaceObjectWindowless_OnWindowMessage(IOleInPlaceObjectWindowless *iface, + UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *lpResult) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleInPlaceObjectWindowless_GetDropTarget(IOleInPlaceObjectWindowless *iface, + IDropTarget **ppDropTarget) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const IOleInPlaceObjectWindowlessVtbl OleInPlaceObjectWindowlessVtbl = { + OleInPlaceObject_QueryInterface, + OleInPlaceObject_AddRef, + OleInPlaceObject_Release, + OleInPlaceObject_GetWindow, + OleInPlaceObject_ContextSensitiveHelp, + OleInPlaceObject_InPlaceDeactivate, + OleInPlaceObject_UIDeactivate, + OleInPlaceObject_SetObjectRects, + OleInPlaceObjectWindowless_ReactivateAndUndo, + OleInPlaceObjectWindowless_OnWindowMessage, + OleInPlaceObjectWindowless_GetDropTarget +}; + +static IOleInPlaceObjectWindowless OleInPlaceObjectWindowless = { &OleInPlaceObjectWindowlessVtbl }; + +static void *wrapped_iface_vtbl[100]; +static IUnknown wrapped_iface = { (IUnknownVtbl*)wrapped_iface_vtbl }; + +static HRESULT WINAPI wrapped_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) +{ + ok(0, "unexpected wrapped_QueryInterface call\n"); + *ppv = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI wrapped_AddRef(IUnknown *iface) +{ + CHECK_EXPECT(wrapped_AddRef); + return 2; +} + +static ULONG WINAPI wrapped_Release(IUnknown *iface) +{ + CHECK_EXPECT(wrapped_Release); + return 1; +} + +static HRESULT WINAPI wrapped_func_nocall(IUnknown *iface, int i, double d) +{ + ok(0, "unexpected call\n"); + return E_FAIL; +} + +static HRESULT WINAPI wrapped_func(IUnknown *iface, int i, double d) +{ + CHECK_EXPECT(wrapped_func); + ok(iface == &wrapped_iface, "iface != wrapped_iface\n"); + ok(i == 10, "i = %d\n", i); + ok(d == 32.0, "d = %lf\n", d); + return S_OK; +} + +static void init_wrapped_iface(void) +{ + unsigned i; + + wrapped_iface_vtbl[0] = wrapped_QueryInterface; + wrapped_iface_vtbl[1] = wrapped_AddRef; + wrapped_iface_vtbl[2] = wrapped_Release; + + for(i=3; i<100; i++) + wrapped_iface_vtbl[i] = wrapped_func_nocall; + + wrapped_iface_vtbl[63] = wrapped_func; +} + +static HRESULT ax_qi(REFIID riid, void **ppv) +{ + if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IOleControl)) { + *ppv = plugin_behavior == TEST_DISPONLY ? NULL : &OleControl; + }else if(IsEqualGUID(riid, &IID_IQuickActivate)) { + *ppv = no_quickact ? NULL : &QuickActivate; + }else if(IsEqualGUID(riid, &IID_IPersistPropertyBag)) { + *ppv = no_quickact ? NULL : &PersistPropertyBag; + }else if(IsEqualGUID(riid, &IID_IDispatch)) { + *ppv = &Dispatch; + }else if(IsEqualGUID(riid, &IID_IProvideClassInfo)) { + *ppv = &ProvideClassInfo; + }else if(IsEqualGUID(riid, &IID_IConnectionPointContainer)) { + *ppv = plugin_behavior != TEST_DISPONLY ? &ConnectionPointContainer : NULL; + }else if(IsEqualGUID(riid, &IID_IViewObject) || IsEqualGUID(riid, &IID_IViewObject2) + || IsEqualGUID(riid, &IID_IViewObjectEx)) { + *ppv = plugin_behavior == TEST_DISPONLY ? NULL : &ViewObjectEx; + }else if(IsEqualGUID(riid, &IID_IOleObject)) { + *ppv = plugin_behavior == TEST_DISPONLY ? NULL : &OleObject; + }else if(IsEqualGUID(riid, &IID_ITestActiveX)) { + CHECK_EXPECT(QI_ITestActiveX); + *ppv = &wrapped_iface; + }else if(IsEqualGUID(riid, &IID_IOleWindow) || IsEqualGUID(riid, &IID_IOleInPlaceObject) + || IsEqualGUID(&IID_IOleInPlaceObjectWindowless, riid)) { + *ppv = plugin_behavior == TEST_DISPONLY ? NULL : &OleInPlaceObjectWindowless; + }else { + trace("QI %s\n", debugstr_guid(riid)); + *ppv = NULL; + } + + return *ppv ? S_OK : E_NOINTERFACE; +} + +static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IClassFactory, riid)) { + *ppv = iface; + return S_OK; + } + + if(IsEqualGUID(&IID_IMarshal, riid)) + return E_NOINTERFACE; + if(IsEqualGUID(&CLSID_IdentityUnmarshal, riid)) + return E_NOINTERFACE; + if(IsEqualGUID(&IID_IClassFactoryEx, riid)) + return E_NOINTERFACE; /* TODO */ + + ok(0, "unexpected riid %s\n", debugstr_guid(riid)); + return E_NOTIMPL; +} + +static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface) +{ + return 2; +} + +static ULONG WINAPI ClassFactory_Release(IClassFactory *iface) +{ + return 1; +} + +static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv) +{ + CHECK_EXPECT(CreateInstance); + + ok(!outer, "outer = %p\n", outer); + ok(IsEqualGUID(riid, &IID_IUnknown), "riid = %s\n", debugstr_guid(riid)); + + *ppv = &OleControl; + return S_OK; +} + +static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock) +{ + ok(0, "unexpected call\n"); + return S_OK; +} + +static const IClassFactoryVtbl ClassFactoryVtbl = { + ClassFactory_QueryInterface, + ClassFactory_AddRef, + ClassFactory_Release, + ClassFactory_CreateInstance, + ClassFactory_LockServer +}; + +static IClassFactory activex_cf = { &ClassFactoryVtbl }; + +static void test_elem_dispex(IDispatchEx *dispex) +{ + DISPPARAMS dp; + EXCEPINFO ei; + VARIANT v; + DISPID id; + BSTR str; + HRESULT hres; + + str = a2bstr("scriptprop"); + SET_EXPECT(GetIDsOfNames_scriptprop); + hres = IDispatchEx_GetDispID(dispex, str, 0, &id); + CHECK_CALLED(GetIDsOfNames_scriptprop); + SysFreeString(str); + ok(hres == S_OK, "GetDispID failed: %08x\n", hres); + todo_wine + ok(id == DISPID_SCRIPTPROP, "id = %d\n", id); + + SET_EXPECT(Invoke_SECURITYCTX); + SET_EXPECT(Invoke_SCRIPTPROP); + memset(&dp, 0, sizeof(dp)); + memset(&ei, 0, sizeof(ei)); + V_VT(&v) = VT_EMPTY; + hres = IDispatchEx_InvokeEx(dispex, id, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dp, &v, &ei, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&v) == VT_I4, "V_VT(v) = %d\n", V_VT(&v)); + ok(V_I4(&v) == 4, "V_I4(v) = %d\n", V_I4(&v)); + CHECK_CALLED(Invoke_SECURITYCTX); + CHECK_CALLED(Invoke_SCRIPTPROP); +} + +static void test_iface_wrapping(IHTMLObjectElement *elem) +{ + IHTMLObjectElement *elem2; + IUnknown *unk, *unk2; + ULONG ref; + void **vtbl; + HRESULT hres; + + SET_EXPECT(QI_ITestActiveX); + SET_EXPECT(wrapped_AddRef); + SET_EXPECT(wrapped_Release); + unk = (void*)0xdeadbeef; + hres = IHTMLObjectElement_QueryInterface(elem, &IID_ITestActiveX, (void**)&unk); + ok(hres == S_OK, "QueryInerface(IID_ITestActiveX failed: %08x\n", hres); + CHECK_CALLED(QI_ITestActiveX); + CHECK_CALLED(wrapped_AddRef); + CHECK_CALLED(wrapped_Release); + + /* See dlls/mshtml/ifacewrap.c */ + ok(unk != &wrapped_iface, "Unexpected unk %p, expected %p (%p, %p)\n", unk, &ViewObjectEx, unk->lpVtbl, &ViewObjectExVtbl); + ok(unk->lpVtbl != wrapped_iface.lpVtbl, "unk->lpVtbl == wrapped_iface->lpVtbl\n"); + ok(unk->lpVtbl->QueryInterface != wrapped_QueryInterface, "QueryInterface not wrapped\n"); + ok(unk->lpVtbl->AddRef != wrapped_AddRef, "AddRef not wrapped\n"); + ok(unk->lpVtbl->Release != wrapped_Release, "Release not wrapped\n"); + + vtbl = (void**)unk->lpVtbl; + ok(vtbl[4] != wrapped_func_nocall, "func not wrapped\n"); + ok(vtbl[63] != wrapped_func, "func not wrapped\n"); + + SET_EXPECT(wrapped_func); + hres = ((HRESULT (WINAPI*)(IUnknown*,int,double))vtbl[63])(unk, 10, 32.0); + ok(hres == S_OK, "wrapped_func returned %08x\n", hres); + CHECK_CALLED(wrapped_func); + + hres = IUnknown_QueryInterface(unk, &IID_IHTMLObjectElement, (void**)&elem2); + ok(hres == S_OK, "Could not get IHTMLObjectElement from wrapped iface: %08x\n", hres); + ok(iface_cmp((IUnknown*)elem2, (IUnknown*)elem), "elem2 != elem\n"); + IHTMLObjectElement_Release(elem2); + + SET_EXPECT(wrapped_Release); + ref = IUnknown_Release(unk); + ok(!ref, "ref=%d\n", ref); + CHECK_CALLED(wrapped_Release); + + SET_EXPECT(QI_ITestActiveX); + SET_EXPECT(wrapped_AddRef); + SET_EXPECT(wrapped_Release); + unk = (void*)0xdeadbeef; + hres = IHTMLObjectElement_QueryInterface(elem, &IID_ITestActiveX, (void**)&unk2); + ok(hres == S_OK, "QueryInerface(IID_ITestActiveX failed: %08x\n", hres); + CHECK_CALLED(QI_ITestActiveX); + CHECK_CALLED(wrapped_AddRef); + CHECK_CALLED(wrapped_Release); + + ok(unk != unk2, "unk == unk2\n"); + + SET_EXPECT(wrapped_Release); + ref = IUnknown_Release(unk2); + ok(!ref, "ref=%d\n", ref); + CHECK_CALLED(wrapped_Release); +} + +static void test_object_elem(IHTMLDocument2 *doc) +{ + IHTMLObjectElement *objelem; + IHTMLDocument3 *doc3; + IDispatchEx *dispex; + IHTMLElement *elem; + IDispatch *disp; + VARIANT v; + BSTR str; + HRESULT hres; + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3); + ok(hres == S_OK, "Could not get IHTMLDocument3 iface: %08x\n", hres); + + str = a2bstr("objid"); + elem = (void*)0xdeadbeef; + hres = IHTMLDocument3_getElementById(doc3, str, &elem); + IHTMLDocument3_Release(doc3); + SysFreeString(str); + ok(hres == S_OK, "getElementById failed: %08x\n", hres); + ok(elem != NULL, "elem == NULL\n"); + + hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLObjectElement, (void**)&objelem); + IHTMLElement_Release(elem); + ok(hres == S_OK, "Could not get IHTMLObjectElement iface: %08x\n", hres); + + SET_EXPECT(Invoke_SECURITYCTX); + hres = IHTMLObjectElement_get_object(objelem, &disp); + ok(hres == S_OK, "get_object failed: %08x\n", hres); + ok(disp == &Dispatch, "disp != Dispatch\n"); + CHECK_CALLED(Invoke_SECURITYCTX); + + hres = IHTMLObjectElement_QueryInterface(objelem, &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "QueryInterface failed: %08x\n", hres); + test_elem_dispex(dispex); + IDispatchEx_Release(dispex); + + test_iface_wrapping(objelem); + + hres = IHTMLObjectElement_get_width(objelem, &v); + ok(hres == S_OK, "get_width failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(width) = %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "300"), "V_BSTR(width) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLObjectElement_get_height(objelem, &v); + ok(hres == S_OK, "get_height failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(height) = %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "200"), "V_BSTR(height) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + V_VT(&v) = VT_I4; + V_I4(&v) = 400; + SET_EXPECT(OnAmbientPropertyChange_UNKNOWN); + SET_EXPECT(Invoke_ENABLED); + hres = IHTMLObjectElement_put_width(objelem, v); + ok(hres == S_OK, "put_width failed: %08x\n", hres); + CHECK_CALLED(OnAmbientPropertyChange_UNKNOWN); + CHECK_CALLED(Invoke_ENABLED); + + hres = IHTMLObjectElement_get_width(objelem, &v); + ok(hres == S_OK, "get_width failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(width) = %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "400"), "V_BSTR(width) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + V_VT(&v) = VT_I4; + V_I4(&v) = 250; + SET_EXPECT(OnAmbientPropertyChange_UNKNOWN); + SET_EXPECT(Invoke_ENABLED); + hres = IHTMLObjectElement_put_height(objelem, v); + ok(hres == S_OK, "put_height failed: %08x\n", hres); + CHECK_CALLED(OnAmbientPropertyChange_UNKNOWN); + CHECK_CALLED(Invoke_ENABLED); + + hres = IHTMLObjectElement_get_height(objelem, &v); + ok(hres == S_OK, "get_height failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(height) = %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "250"), "V_BSTR(height) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + IHTMLObjectElement_Release(objelem); +} + +static void test_container(IHTMLDocument2 *doc_obj) +{ + IHTMLWindow2 *parent_window, *html_window; + IServiceProvider *serv_prov; + IOleContainer *container; + IHTMLDocument2 *doc; + IUnknown *unk; + HRESULT hres; + + container = NULL; + hres = IOleClientSite_GetContainer(client_site, &container); + ok(hres == S_OK, "GetContainer failed: %08x\n", hres); + ok(container != NULL, "container == NULL\n"); + + hres = IHTMLDocument2_get_parentWindow(doc_obj, &parent_window); + ok(hres == S_OK, "get_parentWindow failed: %08x\n", hres); + ok(parent_window != NULL, "parentWindow == NULL\n"); + + hres = IHTMLWindow2_get_document(parent_window, &doc); + ok(hres == S_OK, "get_document failed: %08x\n", hres); + ok(doc != NULL, "doc == NULL\n"); + ok(iface_cmp((IUnknown*)doc, (IUnknown*)container), "container != doc\n"); + IHTMLDocument2_Release(doc); + + hres = IOleClientSite_QueryInterface(client_site, &IID_IServiceProvider, (void**)&serv_prov); + ok(hres == S_OK, "Could not get IServiceProvider iface: %08x\n", hres); + + hres = IServiceProvider_QueryService(serv_prov, &IID_IHTMLWindow2, &IID_IHTMLWindow2, (void**)&html_window); + ok(hres == S_OK, "Could not get IHTMLWindow2 service: %08x\n", hres); + todo_wine + ok(!iface_cmp((IUnknown*)html_window, (IUnknown*)parent_window), "html_window != parent_window\n"); + IHTMLWindow2_Release(html_window); + + SET_EXPECT(QueryService_TestActiveX); + hres = IServiceProvider_QueryService(serv_prov, &CLSID_TestActiveX, &IID_IUnknown, (void**)&unk); + ok(hres == S_OK, "QueryService(CLSID_TestActiveX) failed: %08x\n", hres); + ok(unk == (IUnknown*)&OleObject, "unexpected unk %p\n", unk); + CHECK_CALLED(QueryService_TestActiveX); + + IServiceProvider_Release(serv_prov); + + IHTMLWindow2_Release(parent_window); + IOleContainer_Release(container); +} + +static void test_ui_activate(void) +{ + IOleInPlaceSite *ip_site; + HRESULT hres; + + hres = IOleClientSite_QueryInterface(client_site, &IID_IOleInPlaceSite, (void**)&ip_site); + ok(hres == S_OK, "Could not get IOleInPlaceSite iface: %08x\n", hres); + + SET_EXPECT(Invoke_ENABLED); + hres = IOleInPlaceSite_OnUIActivate(ip_site); + ok(hres == S_OK, "OnUIActivate failed: %08x\n", hres); + CHECK_CALLED(Invoke_ENABLED); + + IOleInPlaceSite_Release(ip_site); +} + +static HRESULT cs_qi(REFIID,void **); +static IOleDocumentView *view; + +static HRESULT WINAPI InPlaceFrame_QueryInterface(IOleInPlaceFrame *iface, REFIID riid, void **ppv) +{ + static const GUID undocumented_frame_iid = {0xfbece6c9,0x48d7,0x4a37,{0x8f,0xe3,0x6a,0xd4,0x27,0x2f,0xdd,0xac}}; + + if(!IsEqualGUID(&undocumented_frame_iid, riid)) + ok(0, "unexpected riid %s\n", debugstr_guid(riid)); + + *ppv = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI InPlaceFrame_AddRef(IOleInPlaceFrame *iface) +{ + return 2; +} + +static ULONG WINAPI InPlaceFrame_Release(IOleInPlaceFrame *iface) +{ + return 1; +} + +static HRESULT WINAPI InPlaceFrame_GetWindow(IOleInPlaceFrame *iface, HWND *phwnd) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceFrame_ContextSensitiveHelp(IOleInPlaceFrame *iface, BOOL fEnterMode) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceFrame_GetBorder(IOleInPlaceFrame *iface, LPRECT lprectBorder) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceFrame_RequestBorderSpace(IOleInPlaceFrame *iface, + LPCBORDERWIDTHS pborderwidths) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceFrame_SetBorderSpace(IOleInPlaceFrame *iface, + LPCBORDERWIDTHS pborderwidths) +{ + return S_OK; +} + +static HRESULT WINAPI InPlaceUIWindow_SetActiveObject(IOleInPlaceFrame *iface, + IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName) +{ + return S_OK; +} + +static HRESULT WINAPI InPlaceFrame_SetActiveObject(IOleInPlaceFrame *iface, + IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName) +{ + return S_OK; +} + +static HRESULT WINAPI InPlaceFrame_InsertMenus(IOleInPlaceFrame *iface, HMENU hmenuShared, + LPOLEMENUGROUPWIDTHS lpMenuWidths) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceFrame_SetMenu(IOleInPlaceFrame *iface, HMENU hmenuShared, + HOLEMENU holemenu, HWND hwndActiveObject) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceFrame_RemoveMenus(IOleInPlaceFrame *iface, HMENU hmenuShared) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceFrame_SetStatusText(IOleInPlaceFrame *iface, LPCOLESTR pszStatusText) +{ + return S_OK; +} + +static HRESULT WINAPI InPlaceFrame_EnableModeless(IOleInPlaceFrame *iface, BOOL fEnable) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceFrame_TranslateAccelerator(IOleInPlaceFrame *iface, LPMSG lpmsg, WORD wID) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const IOleInPlaceFrameVtbl InPlaceFrameVtbl = { + InPlaceFrame_QueryInterface, + InPlaceFrame_AddRef, + InPlaceFrame_Release, + InPlaceFrame_GetWindow, + InPlaceFrame_ContextSensitiveHelp, + InPlaceFrame_GetBorder, + InPlaceFrame_RequestBorderSpace, + InPlaceFrame_SetBorderSpace, + InPlaceFrame_SetActiveObject, + InPlaceFrame_InsertMenus, + InPlaceFrame_SetMenu, + InPlaceFrame_RemoveMenus, + InPlaceFrame_SetStatusText, + InPlaceFrame_EnableModeless, + InPlaceFrame_TranslateAccelerator +}; + +static IOleInPlaceFrame InPlaceFrame = { &InPlaceFrameVtbl }; + +static const IOleInPlaceFrameVtbl InPlaceUIWindowVtbl = { + InPlaceFrame_QueryInterface, + InPlaceFrame_AddRef, + InPlaceFrame_Release, + InPlaceFrame_GetWindow, + InPlaceFrame_ContextSensitiveHelp, + InPlaceFrame_GetBorder, + InPlaceFrame_RequestBorderSpace, + InPlaceFrame_SetBorderSpace, + InPlaceUIWindow_SetActiveObject, +}; + +static IOleInPlaceFrame InPlaceUIWindow = { &InPlaceUIWindowVtbl }; + +static HRESULT WINAPI InPlaceSite_QueryInterface(IOleInPlaceSite *iface, REFIID riid, void **ppv) +{ + return cs_qi(riid, ppv); +} + +static ULONG WINAPI InPlaceSite_AddRef(IOleInPlaceSite *iface) +{ + return 2; +} + +static ULONG WINAPI InPlaceSite_Release(IOleInPlaceSite *iface) +{ + return 1; +} + +static HRESULT WINAPI InPlaceSite_GetWindow(IOleInPlaceSite *iface, HWND *phwnd) +{ + *phwnd = container_hwnd; + return S_OK; +} + +static HRESULT WINAPI InPlaceSite_ContextSensitiveHelp(IOleInPlaceSite *iface, BOOL fEnterMode) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceSite_CanInPlaceActivate(IOleInPlaceSite *iface) +{ + return S_OK; +} + +static HRESULT WINAPI InPlaceSite_OnInPlaceActivate(IOleInPlaceSite *iface) +{ + return S_OK; +} + +static HRESULT WINAPI InPlaceSite_OnUIActivate(IOleInPlaceSite *iface) +{ + return S_OK; +} + +static HRESULT WINAPI InPlaceSite_GetWindowContext(IOleInPlaceSite *iface, + IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect, + LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo) +{ + static const RECT rect = {0,0,500,500}; + + *ppFrame = &InPlaceFrame; + *ppDoc = (IOleInPlaceUIWindow*)&InPlaceUIWindow; + *lprcPosRect = rect; + *lprcClipRect = rect; + + lpFrameInfo->fMDIApp = FALSE; + lpFrameInfo->hwndFrame = container_hwnd; + lpFrameInfo->haccel = NULL; + lpFrameInfo->cAccelEntries = 0; + + return S_OK; +} + +static HRESULT WINAPI InPlaceSite_Scroll(IOleInPlaceSite *iface, SIZE scrollExtant) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceSite_OnUIDeactivate(IOleInPlaceSite *iface, BOOL fUndoable) +{ + return S_OK; +} + +static HRESULT WINAPI InPlaceSite_OnInPlaceDeactivate(IOleInPlaceSite *iface) +{ + return S_OK; +} + +static HRESULT WINAPI InPlaceSite_DiscardUndoState(IOleInPlaceSite *iface) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceSite_DeactivateAndUndo(IOleInPlaceSite *iface) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI InPlaceSite_OnPosRectChange(IOleInPlaceSite *iface, LPCRECT lprcPosRect) +{ + return E_NOTIMPL; +} + +static const IOleInPlaceSiteVtbl InPlaceSiteVtbl = { + InPlaceSite_QueryInterface, + InPlaceSite_AddRef, + InPlaceSite_Release, + InPlaceSite_GetWindow, + InPlaceSite_ContextSensitiveHelp, + InPlaceSite_CanInPlaceActivate, + InPlaceSite_OnInPlaceActivate, + InPlaceSite_OnUIActivate, + InPlaceSite_GetWindowContext, + InPlaceSite_Scroll, + InPlaceSite_OnUIDeactivate, + InPlaceSite_OnInPlaceDeactivate, + InPlaceSite_DiscardUndoState, + InPlaceSite_DeactivateAndUndo, + InPlaceSite_OnPosRectChange, +}; + +static IOleInPlaceSite InPlaceSite = { &InPlaceSiteVtbl }; + +static HRESULT WINAPI ClientSite_QueryInterface(IOleClientSite *iface, REFIID riid, void **ppv) +{ + return cs_qi(riid, ppv); +} + +static ULONG WINAPI ClientSite_AddRef(IOleClientSite *iface) +{ + return 2; +} + +static ULONG WINAPI ClientSite_Release(IOleClientSite *iface) +{ + return 1; +} + +static HRESULT WINAPI ClientSite_SaveObject(IOleClientSite *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ClientSite_GetMoniker(IOleClientSite *iface, DWORD dwAssign, DWORD dwWhichMoniker, + IMoniker **ppmon) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ClientSite_GetContainer(IOleClientSite *iface, IOleContainer **ppContainer) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ClientSite_ShowObject(IOleClientSite *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI 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 DocumentSite_QueryInterface(IOleDocumentSite *iface, REFIID riid, void **ppv) +{ + return cs_qi(riid, ppv); +} + +static ULONG WINAPI DocumentSite_AddRef(IOleDocumentSite *iface) +{ + return 2; +} + +static ULONG WINAPI DocumentSite_Release(IOleDocumentSite *iface) +{ + return 1; +} + +static HRESULT WINAPI DocumentSite_ActivateMe(IOleDocumentSite *iface, IOleDocumentView *pViewToActivate) +{ + RECT rect = {0,0,400,500}; + IOleDocument *document; + HRESULT hres; + + hres = IOleDocumentView_QueryInterface(pViewToActivate, &IID_IOleDocument, (void**)&document); + ok(hres == S_OK, "could not get IOleDocument: %08x\n", hres); + + hres = IOleDocument_CreateView(document, &InPlaceSite, NULL, 0, &view); + IOleDocument_Release(document); + ok(hres == S_OK, "CreateView failed: %08x\n", hres); + + hres = IOleDocumentView_SetInPlaceSite(view, &InPlaceSite); + ok(hres == S_OK, "SetInPlaceSite failed: %08x\n", hres); + + hres = IOleDocumentView_UIActivate(view, TRUE); + ok(hres == S_OK, "UIActivate failed: %08x\n", hres); + + hres = IOleDocumentView_SetRect(view, &rect); + ok(hres == S_OK, "SetRect failed: %08x\n", hres); + + hres = IOleDocumentView_Show(view, TRUE); + ok(hres == S_OK, "Show failed: %08x\n", hres); + + return S_OK; +} + +static const IOleDocumentSiteVtbl DocumentSiteVtbl = { + DocumentSite_QueryInterface, + DocumentSite_AddRef, + DocumentSite_Release, + DocumentSite_ActivateMe +}; + +static IOleDocumentSite DocumentSite = { &DocumentSiteVtbl }; + +static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, + REFIID riid, void **ppv) +{ + return cs_qi(riid, ppv); +} + +static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface) +{ + return 2; +} + +static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface) +{ + return 1; +} + +static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService, + REFIID riid, void **ppv) +{ + if(IsEqualGUID(&CLSID_TestActiveX, guidService)) { + CHECK_EXPECT(QueryService_TestActiveX); + ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid %s\n", debugstr_guid(riid)); + *ppv = &OleObject; + return S_OK; + } + + *ppv = NULL; + return E_NOINTERFACE; +} + +static const IServiceProviderVtbl ServiceProviderVtbl = { + ServiceProvider_QueryInterface, + ServiceProvider_AddRef, + ServiceProvider_Release, + ServiceProvider_QueryService +}; + +static IServiceProvider ServiceProvider = { &ServiceProviderVtbl }; + +static HRESULT cs_qi(REFIID riid, void **ppv) +{ + *ppv = NULL; + + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IOleClientSite, riid)) + *ppv = &ClientSite; + else if(IsEqualGUID(&IID_IOleDocumentSite, riid)) + *ppv = &DocumentSite; + else if(IsEqualGUID(&IID_IOleWindow, riid) || IsEqualGUID(&IID_IOleInPlaceSite, riid)) + *ppv = &InPlaceSite; + else if(IsEqualGUID(riid, &IID_IServiceProvider)) + *ppv = &ServiceProvider; + + return *ppv ? S_OK : E_NOINTERFACE; +} + +static IHTMLDocument2 *notif_doc; +static BOOL doc_complete; + +static HRESULT WINAPI PropertyNotifySink_QueryInterface(IPropertyNotifySink *iface, + REFIID riid, void**ppv) +{ + if(IsEqualGUID(&IID_IPropertyNotifySink, riid)) { + *ppv = iface; + return S_OK; + } + + ok(0, "unexpected call\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI PropertyNotifySink_AddRef(IPropertyNotifySink *iface) +{ + return 2; +} + +static ULONG WINAPI PropertyNotifySink_Release(IPropertyNotifySink *iface) +{ + return 1; +} + +static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, DISPID dispID) +{ + if(dispID == DISPID_READYSTATE){ + BSTR state; + HRESULT hres; + + static const WCHAR completeW[] = {'c','o','m','p','l','e','t','e',0}; + + hres = IHTMLDocument2_get_readyState(notif_doc, &state); + ok(hres == S_OK, "get_readyState failed: %08x\n", hres); + + if(!lstrcmpW(state, completeW)) + doc_complete = TRUE; + + SysFreeString(state); + } + + return S_OK; +} + +static HRESULT WINAPI PropertyNotifySink_OnRequestEdit(IPropertyNotifySink *iface, DISPID dispID) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = { + PropertyNotifySink_QueryInterface, + PropertyNotifySink_AddRef, + PropertyNotifySink_Release, + PropertyNotifySink_OnChanged, + PropertyNotifySink_OnRequestEdit +}; + +static IPropertyNotifySink PropertyNotifySink = { &PropertyNotifySinkVtbl }; + +static void doc_load_string(IHTMLDocument2 *doc, const char *str) +{ + IPersistStreamInit *init; + IStream *stream; + HGLOBAL mem; + SIZE_T len; + + notif_doc = doc; + + doc_complete = FALSE; + len = strlen(str); + mem = GlobalAlloc(0, len); + memcpy(mem, str, len); + CreateStreamOnHGlobal(mem, TRUE, &stream); + + IHTMLDocument2_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&init); + + IPersistStreamInit_Load(init, stream); + IPersistStreamInit_Release(init); + IStream_Release(stream); +} + +static void do_advise(IUnknown *unk, REFIID riid, IUnknown *unk_advise) +{ + IConnectionPointContainer *container; + IConnectionPoint *cp; + DWORD cookie; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IConnectionPointContainer, (void**)&container); + ok(hres == S_OK, "QueryInterface(IID_IConnectionPointContainer) failed: %08x\n", hres); + + hres = IConnectionPointContainer_FindConnectionPoint(container, riid, &cp); + IConnectionPointContainer_Release(container); + ok(hres == S_OK, "FindConnectionPoint failed: %08x\n", hres); + + hres = IConnectionPoint_Advise(cp, unk_advise, &cookie); + IConnectionPoint_Release(cp); + ok(hres == S_OK, "Advise failed: %08x\n", hres); +} + +static void set_client_site(IHTMLDocument2 *doc, BOOL set) +{ + IOleObject *oleobj; + HRESULT hres; + + if(!set && view) { + IOleDocumentView_Show(view, FALSE); + IOleDocumentView_CloseView(view, 0); + IOleDocumentView_SetInPlaceSite(view, NULL); + IOleDocumentView_Release(view); + view = NULL; + } + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj); + ok(hres == S_OK, "Could not et IOleObject: %08x\n", hres); + + hres = IOleObject_SetClientSite(oleobj, set ? &ClientSite : NULL); + ok(hres == S_OK, "SetClientSite failed: %08x\n", hres); + + if(set) { + IHlinkTarget *hlink; + + hres = IOleObject_QueryInterface(oleobj, &IID_IHlinkTarget, (void**)&hlink); + ok(hres == S_OK, "Could not get IHlinkTarget iface: %08x\n", hres); + + hres = IHlinkTarget_Navigate(hlink, 0, NULL); + ok(hres == S_OK, "Navgate failed: %08x\n", hres); + + IHlinkTarget_Release(hlink); + } + + IOleObject_Release(oleobj); +} +static IHTMLDocument2 *create_document(void) +{ + IHTMLDocument2 *doc; + 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); + + return doc; +} + +static IHTMLDocument2 *create_doc(const char *str) +{ + IHTMLDocument2 *doc; + MSG msg; + + doc = create_document(); + set_client_site(doc, TRUE); + doc_load_string(doc, str); + do_advise((IUnknown*)doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink); + + while(!doc_complete && GetMessage(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + return doc; +} + +static void release_doc(IHTMLDocument2 *doc) +{ + ULONG ref; + + set_client_site(doc, FALSE); + ref = IHTMLDocument2_Release(doc); + ok(!ref || broken(ref == 1) /* Vista */, "ref = %d\n", ref); + + if(client_site) { + IOleClientSite_Release(client_site); + client_site = NULL; + } + + if(plugin_hwnd) { + DestroyWindow(plugin_hwnd); + plugin_hwnd = NULL; + } +} + +static void init_test(int behavior) +{ + plugin_behavior = behavior; + + no_quickact = behavior == TEST_NOQUICKACT || behavior == TEST_DISPONLY; +} + +static void test_event_call(void) +{ + VARIANT res, args[2]; + DISPPARAMS dp = {args}; + EXCEPINFO ei = {0}; + HRESULT hres; + + V_VT(&res) = VT_EMPTY; + hres = IDispatch_Invoke(sink_disp, 1, &IID_NULL, 0, DISPATCH_METHOD, &dp, &res, &ei, NULL); + ok(hres == S_OK, "Invoke failed: %08x\n", hres); + ok(V_VT(&res) == VT_I4 && V_I4(&res) == 6, "unexpected result\n"); + + V_VT(args) = VT_I4; + V_I4(args) = 2; + V_VT(args+1) = VT_I4; + V_I4(args+1) = 3; + dp.cArgs = 2; + V_VT(&res) = VT_EMPTY; + hres = IDispatch_Invoke(sink_disp, 2, &IID_NULL, 0, DISPATCH_METHOD, &dp, &res, &ei, NULL); + ok(hres == S_OK, "Invoke failed: %08x\n", hres); + ok(V_VT(&res) == VT_I4 && V_I4(&res) == 7, "unexpected result: %d\n", V_I4(&res)); + + V_VT(&res) = VT_ERROR; + hres = IDispatch_Invoke(sink_disp, 10, &IID_NULL, 0, DISPATCH_METHOD, &dp, &res, &ei, NULL); + ok(hres == S_OK, "Invoke failed: %08x\n", hres); + ok(V_VT(&res) == VT_EMPTY, "V_VT(res) = %d\n", V_VT(&res)); +} + +static void test_flash_ax(void) +{ + IHTMLDocument2 *doc; + + init_test(TEST_FLASH); + + SET_EXPECT(CreateInstance); + SET_EXPECT(FreezeEvents_TRUE); + SET_EXPECT(QuickActivate); + SET_EXPECT(FreezeEvents_FALSE); + SET_EXPECT(IPersistPropertyBag_Load); + SET_EXPECT(Invoke_READYSTATE); + SET_EXPECT(Invoke_SECURITYCTX); + SET_EXPECT(Invoke_SCRIPTCALL); + SET_EXPECT(SetExtent); + SET_EXPECT(GetExtent); + SET_EXPECT(DoVerb); + + doc = create_doc(object_ax_str); + + CHECK_CALLED(CreateInstance); + todo_wine + CHECK_CALLED(FreezeEvents_TRUE); + CHECK_CALLED(QuickActivate); + todo_wine + CHECK_CALLED(FreezeEvents_FALSE); + CHECK_CALLED(IPersistPropertyBag_Load); + CHECK_CALLED(Invoke_READYSTATE); + CHECK_CALLED(Invoke_SECURITYCTX); + CHECK_CALLED(Invoke_SCRIPTCALL); + todo_wine + CHECK_CALLED(SetExtent); + todo_wine + CHECK_CALLED(GetExtent); + CHECK_CALLED(DoVerb); + + /* Set in DoVerb */ + CHECK_CALLED(InPlaceObject_GetWindow); + CHECK_CALLED(SetObjectRects); + + test_ui_activate(); + test_container(notif_doc); + test_object_elem(notif_doc); + + SET_EXPECT(UIDeactivate); + SET_EXPECT(Invoke_ENABLED); + SET_EXPECT(Invoke_VALID); + SET_EXPECT(InPlaceDeactivate); + SET_EXPECT(Close); + SET_EXPECT(SetClientSite_NULL); + release_doc(doc); + CHECK_CALLED(UIDeactivate); + todo_wine + CHECK_CALLED(Invoke_ENABLED); + todo_wine + CHECK_CALLED(Invoke_VALID); + CHECK_CALLED(InPlaceDeactivate); + CHECK_CALLED(Close); + CHECK_CALLED(SetClientSite_NULL); +} + +static void test_noquickact_ax(void) +{ + IHTMLDocument2 *doc; + + init_test(TEST_NOQUICKACT); + + SET_EXPECT(CreateInstance); + SET_EXPECT(FreezeEvents_TRUE); + SET_EXPECT(GetMiscStatus); + SET_EXPECT(SetClientSite); + SET_EXPECT(SetAdvise); + SET_EXPECT(GetViewStatus); + SET_EXPECT(FreezeEvents_FALSE); + SET_EXPECT(Invoke_READYSTATE); + SET_EXPECT(Invoke_SECURITYCTX); + SET_EXPECT(Invoke_SCRIPTCALL); + SET_EXPECT(SetExtent); + SET_EXPECT(GetExtent); + SET_EXPECT(DoVerb); + + doc = create_doc(object_ax_str); + + CHECK_CALLED(CreateInstance); + todo_wine CHECK_CALLED(FreezeEvents_TRUE); + CHECK_CALLED(GetMiscStatus); + CHECK_CALLED(SetClientSite); + CHECK_CALLED(SetAdvise); + CHECK_CALLED(GetViewStatus); + todo_wine CHECK_CALLED(FreezeEvents_FALSE); + CHECK_CALLED(Invoke_READYSTATE); + CHECK_CALLED(Invoke_SECURITYCTX); + CHECK_CALLED(Invoke_SCRIPTCALL); + todo_wine CHECK_CALLED(SetExtent); + todo_wine CHECK_CALLED(GetExtent); + CHECK_CALLED(DoVerb); + + /* Set in DoVerb */ + CHECK_CALLED(InPlaceObject_GetWindow); + CHECK_CALLED(SetObjectRects); + + SET_EXPECT(InPlaceDeactivate); + SET_EXPECT(Close); + SET_EXPECT(SetClientSite_NULL); + release_doc(doc); + CHECK_CALLED(InPlaceDeactivate); + CHECK_CALLED(Close); + CHECK_CALLED(SetClientSite_NULL); +} + +static void test_event_binding(void) +{ + IHTMLDocument2 *doc; + + init_test(TEST_FLASH); + + SET_EXPECT(CreateInstance); + SET_EXPECT(FreezeEvents_TRUE); + SET_EXPECT(QuickActivate); + SET_EXPECT(FreezeEvents_FALSE); + SET_EXPECT(IPersistPropertyBag_Load); + SET_EXPECT(Invoke_READYSTATE); + SET_EXPECT(SetExtent); + SET_EXPECT(GetExtent); + SET_EXPECT(DoVerb); + + SET_EXPECT(GetClassInfo); + SET_EXPECT(OnAmbientPropertyChange_UNKNOWN); + SET_EXPECT(FindConnectionPoint); + SET_EXPECT(Advise); + + doc = create_doc(event_binding_str); + + CHECK_CALLED(CreateInstance); + todo_wine + CHECK_CALLED(FreezeEvents_TRUE); + CHECK_CALLED(QuickActivate); + todo_wine + CHECK_CALLED(FreezeEvents_FALSE); + CHECK_CALLED(IPersistPropertyBag_Load); + CHECK_CALLED(Invoke_READYSTATE); + todo_wine + CHECK_CALLED(SetExtent); + todo_wine + CHECK_CALLED(GetExtent); + CHECK_CALLED(DoVerb); + + /* Set in DoVerb */ + CHECK_CALLED(InPlaceObject_GetWindow); + CHECK_CALLED(SetObjectRects); + + CHECK_CALLED(GetClassInfo); + todo_wine + CHECK_CALLED(OnAmbientPropertyChange_UNKNOWN); + CHECK_CALLED(FindConnectionPoint); + CHECK_CALLED(Advise); + + test_event_call(); + + SET_EXPECT(InPlaceDeactivate); + SET_EXPECT(Close); + SET_EXPECT(SetClientSite_NULL); + SET_EXPECT(FindConnectionPoint); + SET_EXPECT(Unadvise); + release_doc(doc); + CHECK_CALLED(InPlaceDeactivate); + CHECK_CALLED(Close); + CHECK_CALLED(SetClientSite_NULL); + CHECK_CALLED(FindConnectionPoint); + CHECK_CALLED(Unadvise); +} + +static void test_nooleobj_ax(void) +{ + IHTMLDocument2 *doc; + + init_test(TEST_DISPONLY); + + SET_EXPECT(CreateInstance); + SET_EXPECT(Invoke_READYSTATE); + SET_EXPECT(Invoke_SECURITYCTX); + SET_EXPECT(Invoke_SCRIPTCALL); + + doc = create_doc(object_ax_str); + + CHECK_CALLED(CreateInstance); + CHECK_CALLED(Invoke_READYSTATE); + CHECK_CALLED(Invoke_SECURITYCTX); + CHECK_CALLED(Invoke_SCRIPTCALL); + + release_doc(doc); +} + +static LRESULT WINAPI wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +static HWND create_container_window(void) +{ + static const WCHAR html_document_testW[] = + {'H','T','M','L','D','o','c','u','m','e','n','t','T','e','s','t',0}; + static WNDCLASSEXW wndclass = { + sizeof(WNDCLASSEXW), + 0, + wnd_proc, + 0, 0, NULL, NULL, NULL, NULL, NULL, + html_document_testW, + NULL + }; + + RegisterClassExW(&wndclass); + return CreateWindowW(html_document_testW, html_document_testW, + WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, + 515, 530, NULL, NULL, NULL, NULL); +} + +static void load_typelib(void) +{ + WCHAR path[MAX_PATH]; + ITypeLib *typelib; + HRESULT hres; + + GetModuleFileNameW(NULL, path, MAX_PATH); + + hres = LoadTypeLib(path, &typelib); + ok(hres == S_OK, "LoadTypeLib failed: %08x\n", hres); + + hres = ITypeLib_GetTypeInfoOfGuid(typelib, &DIID_DispActiveXTest, &actxtest_typeinfo); + ok(hres == S_OK, "GetTypeInfoOfGuid(DIID_DispActiveXTest) failed: %08x\n", hres); + + hres = ITypeLib_GetTypeInfoOfGuid(typelib, &CLSID_ActiveXTest, &class_typeinfo); + ok(hres == S_OK, "GetTypeInfoOfGuid(CLSID_ActiveXTest) failed: %08x\n", hres); + + ITypeLib_Release(typelib); +} + +static BOOL init_key(const char *key_name, const char *def_value, BOOL init) +{ + HKEY hkey; + DWORD res; + + if(!init) { + RegDeleteKey(HKEY_CLASSES_ROOT, key_name); + return TRUE; + } + + res = RegCreateKeyA(HKEY_CLASSES_ROOT, key_name, &hkey); + if(res != ERROR_SUCCESS) + return FALSE; + + if(def_value) + res = RegSetValueA(hkey, NULL, REG_SZ, def_value, strlen(def_value)); + + RegCloseKey(hkey); + + return res == ERROR_SUCCESS; +} + +static BOOL init_registry(BOOL init) +{ + return init_key("TestActiveX\\CLSID", TESTACTIVEX_CLSID, init) + && init_key("CLSID\\"TESTACTIVEX_CLSID"\\Implemented Categories\\{7dd95801-9882-11cf-9fa9-00aa006c42c4}", + NULL, init) + && init_key("CLSID\\"TESTACTIVEX_CLSID"\\Implemented Categories\\{7dd95802-9882-11cf-9fa9-00aa006c42c4}", + NULL, init); +} + +static BOOL register_activex(void) +{ + DWORD regid; + HRESULT hres; + + if(!init_registry(TRUE)) { + init_registry(FALSE); + return FALSE; + } + + hres = CoRegisterClassObject(&CLSID_TestActiveX, (IUnknown*)&activex_cf, + CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, ®id); + ok(hres == S_OK, "Could not register control: %08x\n", hres); + + return TRUE; +} + +static BOOL check_ie(void) +{ + IHTMLDocument5 *doc; + HRESULT hres; + + static const WCHAR xW[] = {'x',0}; + static const WCHAR yW[] = {'y',0}; + + if(!lstrcmpW(xW, yW)) + return FALSE; + + hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, + &IID_IHTMLDocument5, (void**)&doc); + if(FAILED(hres)) + return FALSE; + + IHTMLDocument5_Release(doc); + return TRUE; +} + +START_TEST(activex) +{ + CoInitialize(NULL); + + if(!check_ie()) { + CoUninitialize(); + win_skip("Too old IE\n"); + return; + } + + if(is_ie_hardened()) { + CoUninitialize(); + win_skip("IE running in Enhanced Security Configuration\n"); + return; + } + + init_wrapped_iface(); + load_typelib(); + container_hwnd = create_container_window(); + ShowWindow(container_hwnd, SW_SHOW); + + if(register_activex()) { + trace("Testing emulated flash embedding...\n"); + test_flash_ax(); + trace("Testing plugin without IQuickActivate iface...\n"); + test_noquickact_ax(); + trace("Testing plugin with IDispatch iface only...\n"); + test_nooleobj_ax(); + trace("Testing event object binding...\n"); + test_event_binding(); + init_registry(FALSE); + }else { + skip("Could not register ActiveX\n"); + } + + if(actxtest_typeinfo) + ITypeInfo_Release(actxtest_typeinfo); + if(class_typeinfo) + ITypeInfo_Release(class_typeinfo); + DestroyWindow(container_hwnd); + CoUninitialize(); +} diff --git a/rostests/winetests/mshtml/dom.c b/rostests/winetests/mshtml/dom.c index 4f954a8ba30..4791d0622df 100644 --- a/rostests/winetests/mshtml/dom.c +++ b/rostests/winetests/mshtml/dom.c @@ -1,5 +1,5 @@ /* - * Copyright 2007-2008 Jacek Caban for CodeWeavers + * Copyright 2007-2011 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 @@ -20,18 +20,24 @@ #define CONST_VTABLE #include -#include +//#include #include -#include "windef.h" -#include "winbase.h" -#include "ole2.h" -#include "mshtml.h" -#include "mshtmcid.h" -#include "mshtmhst.h" -#include "docobj.h" -#include "dispex.h" +//#include "windef.h" +//#include "winbase.h" +//#include "ole2.h" +#include +#include +#include +//#include "docobj.h" +//#include "dispex.h" #include "mshtml_test.h" +#include +#include +#include + +static INT (WINAPI *pLCIDToLocaleName)(LCID,LPWSTR,INT,DWORD); +static LANGID (WINAPI *pGetUserDefaultUILanguage)(void); static const char doc_blank[] = ""; static const char doc_str1[] = "test"; @@ -40,22 +46,28 @@ static const char range_test_str[] = static const char range_test2_str[] = "abc
123

def"; static const char elem_test_str[] = - "test" + "test" + "" + "" "text test" "link" + "" "" + "" "" "" "
td1 texttd2 text
" "" - "" + "" "" "" "
" + "
" ""; static const char elem_test2_str[] = "test" - "
" + "" + "
" ""; static const char indent_test_str[] = @@ -69,6 +81,16 @@ static const char frameset_str[] = "" "" ""; +static const char emptydiv_str[] = + "emptydiv test" + "
"; +static const char noscript_str[] = + "noscript test" + ""; +static const char doctype_str[] = + "" + "emptydiv test" + "
"; static WCHAR characterW[] = {'c','h','a','r','a','c','t','e','r',0}; static WCHAR texteditW[] = {'t','e','x','t','e','d','i','t',0}; @@ -100,7 +122,15 @@ typedef enum { ET_TD, ET_IFRAME, ET_FORM, - ET_FRAME + ET_FRAME, + ET_OBJECT, + ET_EMBED, + ET_DIV, + ET_META, + ET_NOSCRIPT, + ET_LINK, + ET_LABEL, + ET_BUTTON } elem_type_t; static const IID * const none_iids[] = { @@ -119,6 +149,9 @@ static const IID * const doc_node_iids[] = { &IID_IDispatchEx, &IID_IConnectionPointContainer, &IID_IInternetHostSecurityManager, + &IID_IOleContainer, + &IID_IObjectSafety, + &IID_IProvideClassInfo, NULL }; @@ -131,114 +164,98 @@ static const IID * const doc_obj_iids[] = { &IID_IDispatchEx, &IID_IConnectionPointContainer, &IID_ICustomDoc, + &IID_IOleContainer, + &IID_IObjectSafety, + &IID_IProvideClassInfo, + &IID_ITargetContainer, NULL }; +#define ELEM_IFACES \ + &IID_IHTMLDOMNode, \ + &IID_IHTMLDOMNode2, \ + &IID_IHTMLElement, \ + &IID_IHTMLElement2, \ + &IID_IHTMLElement3, \ + &IID_IHTMLElement4, \ + &IID_IDispatchEx + static const IID * const elem_iids[] = { - &IID_IHTMLDOMNode, - &IID_IHTMLDOMNode2, - &IID_IHTMLElement, - &IID_IHTMLElement2, - &IID_IHTMLElement3, - &IID_IDispatchEx, + ELEM_IFACES, &IID_IConnectionPointContainer, NULL }; static const IID * const body_iids[] = { - &IID_IHTMLDOMNode, - &IID_IHTMLDOMNode2, - &IID_IHTMLElement, - &IID_IHTMLElement2, - &IID_IHTMLElement3, + ELEM_IFACES, &IID_IHTMLTextContainer, &IID_IHTMLBodyElement, - &IID_IDispatchEx, &IID_IConnectionPointContainer, NULL }; static const IID * const anchor_iids[] = { - &IID_IHTMLDOMNode, - &IID_IHTMLDOMNode2, - &IID_IHTMLElement, - &IID_IHTMLElement2, - &IID_IHTMLElement3, + ELEM_IFACES, &IID_IHTMLAnchorElement, - &IID_IDispatchEx, &IID_IConnectionPointContainer, NULL }; static const IID * const input_iids[] = { - &IID_IHTMLDOMNode, - &IID_IHTMLDOMNode2, - &IID_IHTMLElement, - &IID_IHTMLElement2, - &IID_IHTMLElement3, + ELEM_IFACES, &IID_IHTMLInputElement, &IID_IHTMLInputTextElement, - &IID_IDispatchEx, + &IID_IConnectionPointContainer, + NULL +}; + +static const IID *const button_iids[] = { + ELEM_IFACES, + &IID_IHTMLButtonElement, + &IID_IConnectionPointContainer, + NULL +}; + +static const IID * const label_iids[] = { + ELEM_IFACES, + &IID_IHTMLLabelElement, &IID_IConnectionPointContainer, NULL }; static const IID * const select_iids[] = { - &IID_IHTMLDOMNode, - &IID_IHTMLDOMNode2, - &IID_IHTMLElement, - &IID_IHTMLElement2, - &IID_IHTMLElement3, + ELEM_IFACES, &IID_IHTMLSelectElement, - &IID_IDispatchEx, &IID_IConnectionPointContainer, NULL }; static const IID * const textarea_iids[] = { - &IID_IHTMLDOMNode, - &IID_IHTMLDOMNode2, - &IID_IHTMLElement, - &IID_IHTMLElement2, - &IID_IHTMLElement3, + ELEM_IFACES, &IID_IHTMLTextAreaElement, - &IID_IDispatchEx, &IID_IConnectionPointContainer, NULL }; static const IID * const option_iids[] = { - &IID_IHTMLDOMNode, - &IID_IHTMLDOMNode2, - &IID_IHTMLElement, - &IID_IHTMLElement2, - &IID_IHTMLElement3, + ELEM_IFACES, &IID_IHTMLOptionElement, - &IID_IDispatchEx, &IID_IConnectionPointContainer, NULL }; static const IID * const table_iids[] = { - &IID_IHTMLDOMNode, - &IID_IHTMLDOMNode2, - &IID_IHTMLElement, - &IID_IHTMLElement2, - &IID_IHTMLElement3, + ELEM_IFACES, &IID_IHTMLTable, - &IID_IDispatchEx, + &IID_IHTMLTable2, + &IID_IHTMLTable3, &IID_IConnectionPointContainer, NULL }; static const IID * const script_iids[] = { - &IID_IHTMLDOMNode, - &IID_IHTMLDOMNode2, - &IID_IHTMLElement, - &IID_IHTMLElement2, - &IID_IHTMLElement3, + ELEM_IFACES, &IID_IHTMLScriptElement, - &IID_IDispatchEx, &IID_IConnectionPointContainer, NULL }; @@ -250,6 +267,12 @@ static const IID * const text_iids[] = { NULL }; +static const IID * const attr_iids[] = { + &IID_IHTMLDOMAttribute, + &IID_IDispatchEx, + NULL +}; + static const IID * const location_iids[] = { &IID_IDispatch, &IID_IHTMLLocation, @@ -261,103 +284,116 @@ static const IID * const window_iids[] = { &IID_IHTMLWindow2, &IID_IHTMLWindow3, &IID_IDispatchEx, + &IID_IServiceProvider, NULL }; static const IID * const comment_iids[] = { - &IID_IHTMLDOMNode, - &IID_IHTMLDOMNode2, - &IID_IHTMLElement, - &IID_IHTMLElement2, - &IID_IHTMLElement3, + ELEM_IFACES, &IID_IHTMLCommentElement, - &IID_IDispatchEx, &IID_IConnectionPointContainer, NULL }; static const IID * const img_iids[] = { - &IID_IHTMLDOMNode, - &IID_IHTMLDOMNode2, - &IID_IHTMLElement, - &IID_IHTMLElement2, - &IID_IHTMLElement3, - &IID_IDispatchEx, + ELEM_IFACES, &IID_IHTMLImgElement, &IID_IConnectionPointContainer, NULL }; static const IID * const tr_iids[] = { - &IID_IHTMLDOMNode, - &IID_IHTMLDOMNode2, - &IID_IHTMLElement, - &IID_IHTMLElement2, - &IID_IHTMLElement3, - &IID_IDispatchEx, + ELEM_IFACES, &IID_IHTMLTableRow, &IID_IConnectionPointContainer, NULL }; static const IID * const td_iids[] = { - &IID_IHTMLDOMNode, - &IID_IHTMLDOMNode2, - &IID_IHTMLElement, - &IID_IHTMLElement2, - &IID_IHTMLElement3, - &IID_IDispatchEx, + ELEM_IFACES, + &IID_IHTMLTableCell, &IID_IConnectionPointContainer, NULL }; static const IID * const frame_iids[] = { - &IID_IHTMLDOMNode, - &IID_IHTMLDOMNode2, - &IID_IHTMLElement, - &IID_IHTMLElement2, - &IID_IHTMLElement3, + ELEM_IFACES, &IID_IHTMLFrameBase, &IID_IHTMLFrameBase2, - &IID_IDispatchEx, &IID_IConnectionPointContainer, NULL }; +static const IID * const head_iids[] = { + ELEM_IFACES, + &IID_IHTMLHeadElement, + &IID_IConnectionPointContainer, + NULL +}; + +static const IID * const title_iids[] = { + ELEM_IFACES, + &IID_IHTMLTitleElement, + &IID_IConnectionPointContainer, + NULL +}; + +static const IID * const meta_iids[] = { + ELEM_IFACES, + &IID_IHTMLMetaElement, + &IID_IConnectionPointContainer, + NULL +}; + +static const IID * const link_iids[] = { + ELEM_IFACES, + &IID_IHTMLLinkElement, + &IID_IConnectionPointContainer, + NULL +}; + +static const IID * const object_iids[] = { + ELEM_IFACES, + &IID_IHTMLObjectElement, + &IID_IHTMLObjectElement2, + /* FIXME: No IConnectionPointContainer */ + NULL +}; + +static const IID * const embed_iids[] = { + ELEM_IFACES, + &IID_IHTMLEmbedElement, + /* FIXME: No IConnectionPointContainer */ + NULL +}; + static const IID * const iframe_iids[] = { - &IID_IHTMLDOMNode, - &IID_IHTMLDOMNode2, - &IID_IHTMLElement, - &IID_IHTMLElement2, - &IID_IHTMLElement3, + ELEM_IFACES, &IID_IHTMLFrameBase, &IID_IHTMLFrameBase2, &IID_IHTMLIFrameElement, - &IID_IDispatchEx, + &IID_IHTMLIFrameElement2, &IID_IConnectionPointContainer, NULL }; static const IID * const form_iids[] = { - &IID_IHTMLDOMNode, - &IID_IHTMLDOMNode2, - &IID_IHTMLElement, - &IID_IHTMLElement2, - &IID_IHTMLElement3, + ELEM_IFACES, &IID_IHTMLFormElement, - &IID_IDispatchEx, + &IID_IConnectionPointContainer, + NULL +}; + +static const IID * const styleelem_iids[] = { + ELEM_IFACES, + &IID_IHTMLStyleElement, &IID_IConnectionPointContainer, NULL }; static const IID * const generic_iids[] = { - &IID_IHTMLDOMNode, - &IID_IHTMLDOMNode2, - &IID_IHTMLElement, - &IID_IHTMLElement2, - &IID_IHTMLElement3, + ELEM_IFACES, &IID_IHTMLGenericElement, - &IID_IDispatchEx, &IID_IConnectionPointContainer, NULL }; @@ -378,6 +414,8 @@ static const IID * const cstyle_iids[] = { &IID_IDispatch, &IID_IDispatchEx, &IID_IHTMLCurrentStyle, + &IID_IHTMLCurrentStyle2, + &IID_IHTMLCurrentStyle3, NULL }; @@ -398,15 +436,15 @@ typedef struct { static const elem_type_info_t elem_type_infos[] = { {"", none_iids, NULL}, {"HTML", elem_iids, NULL}, - {"HEAD", elem_iids, NULL}, - {"TITLE", elem_iids, NULL}, + {"HEAD", head_iids, &DIID_DispHTMLHeadElement}, + {"TITLE", title_iids, &DIID_DispHTMLTitleElement}, {"BODY", body_iids, &DIID_DispHTMLBody}, {"A", anchor_iids, &DIID_DispHTMLAnchorElement}, {"INPUT", input_iids, &DIID_DispHTMLInputElement}, {"SELECT", select_iids, &DIID_DispHTMLSelectElement}, {"TEXTAREA", textarea_iids, &DIID_DispHTMLTextAreaElement}, {"OPTION", option_iids, &DIID_DispHTMLOptionElement}, - {"STYLE", elem_iids, NULL}, + {"STYLE", styleelem_iids, &DIID_DispHTMLStyleElement}, {"BLOCKQUOTE",elem_iids, NULL}, {"P", elem_iids, NULL}, {"BR", elem_iids, NULL}, @@ -418,10 +456,18 @@ static const elem_type_info_t elem_type_infos[] = { {"!", comment_iids, &DIID_DispHTMLCommentElement}, {"IMG", img_iids, &DIID_DispHTMLImg}, {"TR", tr_iids, &DIID_DispHTMLTableRow}, - {"TD", td_iids, NULL}, + {"TD", td_iids, &DIID_DispHTMLTableCell}, {"IFRAME", iframe_iids, &DIID_DispHTMLIFrame}, {"FORM", form_iids, &DIID_DispHTMLFormElement}, - {"FRAME", frame_iids, &DIID_DispHTMLFrameElement} + {"FRAME", frame_iids, &DIID_DispHTMLFrameElement}, + {"OBJECT", object_iids, &DIID_DispHTMLObjectElement}, + {"EMBED", embed_iids, &DIID_DispHTMLEmbed}, + {"DIV", elem_iids, NULL}, + {"META", meta_iids, &DIID_DispHTMLMetaElement}, + {"NOSCRIPT", elem_iids, NULL /*&DIID_DispHTMLNoShowElement*/}, + {"LINK", link_iids, &DIID_DispHTMLLinkElement}, + {"LABEL", label_iids, &DIID_DispHTMLLabelElement}, + {"BUTTON", button_iids, &DIID_DispHTMLButtonElement} }; static const char *dbgstr_guid(REFIID riid) @@ -448,6 +494,9 @@ static BSTR a2bstr(const char *str) BSTR ret; int len; + if(!str) + return NULL; + len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); ret = SysAllocStringLen(NULL, len); MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); @@ -493,6 +542,17 @@ static IHTMLDocument2 *create_document(void) return doc; } +#define get_dispex_iface(u) _get_dispex_iface(__LINE__,u) +static IDispatchEx *_get_dispex_iface(unsigned line, IUnknown *unk) +{ + IDispatchEx *dispex; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IDispatchEx, (void**)&dispex); + ok_(__FILE__,line) (hres == S_OK, "Could not get IDispatchEx: %08x\n", hres); + return dispex; +} + #define test_ifaces(i,ids) _test_ifaces(__LINE__,i,ids) static void _test_ifaces(unsigned line, IUnknown *iface, REFIID *iids) { @@ -501,27 +561,34 @@ static void _test_ifaces(unsigned line, IUnknown *iface, REFIID *iids) HRESULT hres; for(piid = iids; *piid; piid++) { - hres = IDispatch_QueryInterface(iface, *piid, (void**)&unk); + hres = IUnknown_QueryInterface(iface, *piid, (void**)&unk); ok_(__FILE__,line) (hres == S_OK, "Could not get %s interface: %08x\n", dbgstr_guid(*piid), hres); if(SUCCEEDED(hres)) IUnknown_Release(unk); } } +#define test_no_iface(a,b) _test_no_iface(__LINE__,a,b) +static void _test_no_iface(unsigned line, IUnknown *iface, REFIID iid) +{ + IUnknown *unk; + HRESULT hres; + + unk = (void*)0xdeadbeef; + hres = IUnknown_QueryInterface(iface, iid, (void**)&unk); + ok_(__FILE__,line)(hres == E_NOINTERFACE, "hres = %08x, expected E_NOINTERFACE\n", hres); + ok_(__FILE__,line)(!unk, "unk = %p\n", unk); +} + #define test_get_dispid(u,id) _test_get_dispid(__LINE__,u,id) static BOOL _test_get_dispid(unsigned line, IUnknown *unk, IID *iid) { - IDispatchEx *dispex; + IDispatchEx *dispex = _get_dispex_iface(line, unk); ITypeInfo *typeinfo; BOOL ret = FALSE; UINT ticnt; HRESULT hres; - hres = IUnknown_QueryInterface(unk, &IID_IDispatchEx, (void**)&dispex); - ok_(__FILE__,line) (hres == S_OK, "Could not get IDispatchEx: %08x\n", hres); - if(FAILED(hres)) - return FALSE; - ticnt = 0xdeadbeef; hres = IDispatchEx_GetTypeInfoCount(dispex, &ticnt); ok_(__FILE__,line) (hres == S_OK, "GetTypeInfoCount failed: %08x\n", hres); @@ -551,17 +618,12 @@ static BOOL _test_get_dispid(unsigned line, IUnknown *unk, IID *iid) #define test_disp_value(u) _test_disp_value(__LINE__,u,v) static void _test_disp_value(unsigned line, IUnknown *unk, const char *val) { + IDispatchEx *dispex = _get_dispex_iface(line, unk); DISPPARAMS dp = {NULL,NULL,0,0}; - IDispatchEx *dispex; EXCEPINFO ei; VARIANT var; HRESULT hres; - hres = IUnknown_QueryInterface(unk, &IID_IDispatchEx, (void**)&dispex); - ok_(__FILE__,line)(hres == S_OK, "Could not get IDispatchEx interface: %08x\n", hres); - if(FAILED(hres)) - return; - hres = IDispatchEx_InvokeEx(dispex, DISPID_VALUE, 0, DISPATCH_PROPERTYGET, &dp, &var, &ei, NULL); IDispatchEx_Release(dispex); ok_(__FILE__,line)(hres == S_OK, "InvokeEx(DISPID_VALUE) returned: %08x\n", hres); @@ -596,6 +658,63 @@ static void _test_disp2(unsigned line, IUnknown *unk, const IID *diid, const IID _test_disp_value(line, unk, val); } +#define test_class_info(u) _test_class_info(__LINE__,u) +static void _test_class_info(unsigned line, IUnknown *unk) +{ + IProvideClassInfo *classinfo; + ITypeInfo *typeinfo; + TYPEATTR *type_attr; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IProvideClassInfo, (void**)&classinfo); + ok_(__FILE__,line)(hres == S_OK, "Could not get IProvideClassInfo interface: %08x\n", hres); + if(FAILED(hres)) + return; + + hres = IProvideClassInfo_GetClassInfo(classinfo, &typeinfo); + ok_(__FILE__,line)(hres == S_OK, "Could not get ITypeInfo interface: %08x\n", hres); + if(FAILED(hres)) + { + IProvideClassInfo_Release(classinfo); + return; + } + + hres = ITypeInfo_GetTypeAttr(typeinfo, &type_attr); + ok_(__FILE__,line)(hres == S_OK, "GetTypeAttr failed: %08x\n", hres); + if(SUCCEEDED(hres)) + { + ok_(__FILE__,line)(IsEqualGUID(&type_attr->guid, &CLSID_HTMLDocument), + "unexpected guid %s\n", dbgstr_guid(&type_attr->guid)); + ok_(__FILE__,line)(type_attr->typekind == TKIND_COCLASS, + "unexpected typekind %d\n", type_attr->typekind); + ITypeInfo_ReleaseTypeAttr(typeinfo, type_attr); + } + + ITypeInfo_Release(typeinfo); + IProvideClassInfo_Release(classinfo); +} + +#define set_dispex_value(a,b,c) _set_dispex_value(__LINE__,a,b,c) +static void _set_dispex_value(unsigned line, IUnknown *unk, const char *name, VARIANT *val) +{ + IDispatchEx *dispex = _get_dispex_iface(line, unk); + DISPPARAMS dp = {val, NULL, 1, 0}; + EXCEPINFO ei; + DISPID id; + BSTR str; + HRESULT hres; + + str = a2bstr(name); + hres = IDispatchEx_GetDispID(dispex, str, fdexNameEnsure|fdexNameCaseInsensitive, &id); + SysFreeString(str); + ok_(__FILE__,line)(hres == S_OK, "GetDispID failed: %08x\n", hres); + + memset(&ei, 0, sizeof(ei)); + hres = IDispatchEx_InvokeEx(dispex, id, LOCALE_NEUTRAL, INVOKE_PROPERTYPUT, &dp, NULL, &ei, NULL); + ok_(__FILE__,line)(hres == S_OK, "InvokeEx failed: %08x\n", hres); + +} + #define get_elem_iface(u) _get_elem_iface(__LINE__,u) static IHTMLElement *_get_elem_iface(unsigned line, IUnknown *unk) { @@ -629,6 +748,17 @@ static IHTMLElement3 *_get_elem3_iface(unsigned line, IUnknown *unk) return elem; } +#define get_elem4_iface(u) _get_elem4_iface(__LINE__,u) +static IHTMLElement4 *_get_elem4_iface(unsigned line, IUnknown *unk) +{ + IHTMLElement4 *elem; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IHTMLElement4, (void**)&elem); + ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLElement4: %08x\n", hres); + return elem; +} + #define get_node_iface(u) _get_node_iface(__LINE__,u) static IHTMLDOMNode *_get_node_iface(unsigned line, IUnknown *unk) { @@ -728,6 +858,61 @@ static IHTMLCommentElement *_get_comment_iface(unsigned line, IUnknown *unk) return comment; } +#define get_object_iface(u) _get_object_iface(__LINE__,u) +static IHTMLObjectElement *_get_object_iface(unsigned line, IUnknown *unk) +{ + IHTMLObjectElement *obj; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IHTMLObjectElement, (void**)&obj); + ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLObjectElement: %08x\n", hres); + return obj; +} + +#define get_style_iface(u) _get_style_iface(__LINE__,u) +static IHTMLStyleElement *_get_style_iface(unsigned line, IUnknown *unk) +{ + IHTMLStyleElement *obj; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IHTMLStyleElement, (void**)&obj); + ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLStyleElement: %08x\n", hres); + return obj; +} + +#define get_metaelem_iface(u) _get_metaelem_iface(__LINE__,u) +static IHTMLMetaElement *_get_metaelem_iface(unsigned line, IUnknown *unk) +{ + IHTMLMetaElement *ret; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IHTMLMetaElement, (void**)&ret); + ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLMetaElement: %08x\n", hres); + return ret; +} + +#define get_link_iface(u) _get_link_iface(__LINE__,u) +static IHTMLLinkElement *_get_link_iface(unsigned line, IUnknown *unk) +{ + IHTMLLinkElement *ret; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IHTMLLinkElement, (void**)&ret); + ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLLinkElement: %08x\n", hres); + return ret; +} + +#define get_iframe2_iface(u) _get_iframe2_iface(__LINE__,u) +static IHTMLIFrameElement2 *_get_iframe2_iface(unsigned line, IUnknown *unk) +{ + IHTMLIFrameElement2 *ret; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IHTMLIFrameElement2, (void**)&ret); + ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLIFrameElement: %08x\n", hres); + return ret; +} + #define test_node_name(u,n) _test_node_name(__LINE__,u,n) static void _test_node_name(unsigned line, IUnknown *unk, const char *exname) { @@ -895,10 +1080,11 @@ static void _test_elem_attr(unsigned line, IHTMLElement *elem, const char *name, VariantClear(&value); } -#define test_elem_offset(u) _test_elem_offset(__LINE__,u) -static void _test_elem_offset(unsigned line, IUnknown *unk) +#define test_elem_offset(a,b) _test_elem_offset(__LINE__,a,b) +static void _test_elem_offset(unsigned line, IUnknown *unk, const char *parent_tag) { IHTMLElement *elem = _get_elem_iface(line, unk); + IHTMLElement *off_parent; LONG l; HRESULT hres; @@ -911,6 +1097,15 @@ static void _test_elem_offset(unsigned line, IUnknown *unk) hres = IHTMLElement_get_offsetWidth(elem, &l); ok_(__FILE__,line) (hres == S_OK, "get_offsetWidth failed: %08x\n", hres); + hres = IHTMLElement_get_offsetLeft(elem, &l); + ok_(__FILE__,line) (hres == S_OK, "get_offsetLeft failed: %08x\n", hres); + + hres = IHTMLElement_get_offsetParent(elem, &off_parent); + ok_(__FILE__,line) (hres == S_OK, "get_offsetParent failed: %08x\n", hres); + + _test_elem_tag(line, (IUnknown*)off_parent, parent_tag); + IHTMLElement_Release(off_parent); + IHTMLElement_Release(elem); } @@ -943,6 +1138,7 @@ static void _test_window_name(unsigned line, IHTMLWindow2 *window, const char *e ok_(__FILE__,line)(!strcmp_wa(name, exname), "name = %s\n", wine_dbgstr_w(name)); else ok_(__FILE__,line)(!name, "name = %s\n", wine_dbgstr_w(name)); + SysFreeString(name); } #define set_window_name(w,n) _set_window_name(__LINE__,w,n) @@ -959,6 +1155,31 @@ static void _set_window_name(unsigned line, IHTMLWindow2 *window, const char *na _test_window_name(line, window, name); } +#define test_window_status(d) _test_window_status(__LINE__,d) +static void _test_window_status(unsigned line, IHTMLWindow2 *window) +{ + BSTR status; + HRESULT hres; + + status = (void*)0xdeadbeef; + hres = IHTMLWindow2_get_status(window, &status); + ok_(__FILE__,line)(hres == S_OK, "get_status failed: %08x\n", hres); + ok_(__FILE__,line)(!status, "status = %s\n", wine_dbgstr_w(status)); + SysFreeString(status); +} + +#define set_window_status(w,n) _set_window_status(__LINE__,w,n) +static void _set_window_status(unsigned line, IHTMLWindow2 *window, const char *status) +{ + BSTR str; + HRESULT hres; + + str = a2bstr(status); + hres = IHTMLWindow2_put_status(window, str); + SysFreeString(str); + ok_(__FILE__,line)(hres == S_OK, "put_status failed: %08x\n", hres); +} + #define test_window_length(w,l) _test_window_length(__LINE__,w,l) static void _test_window_length(unsigned line, IHTMLWindow2 *window, LONG exlen) { @@ -1094,6 +1315,97 @@ static void _test_anchor_href(unsigned line, IUnknown *unk, const char *exhref) _test_disp_value(line, unk, exhref); } +#define test_anchor_put_href(a,h) _test_anchor_put_href(__LINE__,a,h) +static void _test_anchor_put_href(unsigned line, IUnknown *unk, const char *exhref) +{ + IHTMLAnchorElement *anchor = _get_anchor_iface(line, unk); + BSTR str; + HRESULT hres; + + str = a2bstr(exhref); + hres = IHTMLAnchorElement_put_href(anchor, str); + ok_(__FILE__,line)(hres == S_OK, "get_href failed: %08x\n", hres); + SysFreeString(str); + + _test_disp_value(line, unk, exhref); +} + +#define test_anchor_get_target(a,h) _test_anchor_get_target(__LINE__,a,h) +static void _test_anchor_get_target(unsigned line, IUnknown *unk, const char *target) +{ + IHTMLAnchorElement *anchor = _get_anchor_iface(line, unk); + BSTR str; + HRESULT hres; + + hres = IHTMLAnchorElement_get_target(anchor, &str); + ok_(__FILE__,line)(hres == S_OK, "get_target failed: %08x\n", hres); + if(target) + ok_(__FILE__,line)(!strcmp_wa(str, target), "target = %s, expected %s\n", wine_dbgstr_w(str), target); + else + ok_(__FILE__,line)(str == NULL, "target = %s, expected NULL\n", wine_dbgstr_w(str)); + SysFreeString(str); +} + +#define test_anchor_put_target(a,h) _test_anchor_put_target(__LINE__,a,h) +static void _test_anchor_put_target(unsigned line, IUnknown *unk, const char *target) +{ + IHTMLAnchorElement *anchor = _get_anchor_iface(line, unk); + BSTR str; + HRESULT hres; + + str = target ? a2bstr(target) : NULL; + hres = IHTMLAnchorElement_put_target(anchor, str); + ok_(__FILE__,line)(hres == S_OK, "put_target failed: %08x\n", hres); + SysFreeString(str); +} + +#define test_anchor_name(a,h) _test_anchor_name(__LINE__,a,h) +static void _test_anchor_name(unsigned line, IUnknown *unk, const char *name) +{ + IHTMLAnchorElement *anchor = _get_anchor_iface(line, unk); + BSTR str; + HRESULT hres; + + hres = IHTMLAnchorElement_get_name(anchor, &str); + ok_(__FILE__,line)(hres == S_OK, "get_name failed: %08x\n", hres); + if(name) + ok_(__FILE__,line)(!strcmp_wa(str, name), "name = %s, expected %s\n", wine_dbgstr_w(str), name); + else + ok_(__FILE__,line)(str == NULL, "name = %s, expected NULL\n", wine_dbgstr_w(str)); + SysFreeString(str); +} + +#define test_anchor_put_name(a,h) _test_anchor_put_name(__LINE__,a,h) +static void _test_anchor_put_name(unsigned line, IUnknown *unk, const char *name) +{ + IHTMLAnchorElement *anchor = _get_anchor_iface(line, unk); + BSTR str; + HRESULT hres; + + str = name ? a2bstr(name) : NULL; + hres = IHTMLAnchorElement_put_name(anchor, str); + ok_(__FILE__,line)(hres == S_OK, "put_name failed: %08x\n", hres); + SysFreeString(str); + + _test_anchor_name(line, unk, name); +} + +#define test_anchor_hostname(a,h) _test_anchor_hostname(__LINE__,a,h) +static void _test_anchor_hostname(unsigned line, IUnknown *unk, const char *hostname) +{ + IHTMLAnchorElement *anchor = _get_anchor_iface(line, unk); + BSTR str; + HRESULT hres; + + hres = IHTMLAnchorElement_get_hostname(anchor, &str); + ok_(__FILE__,line)(hres == S_OK, "get_name failed: %08x\n", hres); + if(hostname) + ok_(__FILE__,line)(!strcmp_wa(str, hostname), "hostname = %s, expected %s\n", wine_dbgstr_w(str), hostname); + else + ok_(__FILE__,line)(str == NULL, "hostname = %s, expected NULL\n", wine_dbgstr_w(str)); + SysFreeString(str); +} + #define test_option_text(o,t) _test_option_text(__LINE__,o,t) static void _test_option_text(unsigned line, IHTMLOptionElement *option, const char *text) { @@ -1225,6 +1537,20 @@ static void _test_textarea_put_readonly(unsigned line, IUnknown *unk, VARIANT_BO _test_textarea_readonly(line, unk, b); } +#define test_textarea_type(t) _test_textarea_type(__LINE__,t) +static void _test_textarea_type(unsigned line, IUnknown *unk) +{ + IHTMLTextAreaElement *textarea = _get_textarea_iface(line, unk); + BSTR type = (void*)0xdeadbeef; + HRESULT hres; + + hres = IHTMLTextAreaElement_get_type(textarea, &type); + IHTMLTextAreaElement_Release(textarea); + ok_(__FILE__,line)(hres == S_OK, "get_type failed: %08x\n", hres); + ok_(__FILE__,line)(!strcmp_wa(type, "textarea"), "type = %s, expected textarea\n", wine_dbgstr_w(type)); + SysFreeString(type); +} + #define test_comment_text(c,t) _test_comment_text(__LINE__,c,t) static void _test_comment_text(unsigned line, IUnknown *unk, const char *extext) { @@ -1241,6 +1567,85 @@ static void _test_comment_text(unsigned line, IUnknown *unk, const char *extext) SysFreeString(text); } +#define test_comment_attrs(c) _test_comment_attrs(__LINE__,c) +static void _test_comment_attrs(unsigned line, IUnknown *unk) +{ + IHTMLCommentElement *comment = _get_comment_iface(__LINE__,unk); + IHTMLElement *elem = _get_elem_iface(__LINE__,unk); + IHTMLElement4 *elem4 = _get_elem4_iface(__LINE__,unk); + IHTMLDOMAttribute *attr; + BSTR name = a2bstr("test"); + VARIANT val; + HRESULT hres; + + hres = IHTMLElement4_getAttributeNode(elem4, name, &attr); + ok(hres == S_OK, "getAttributeNode failed: %08x\n", hres); + ok(attr == NULL, "attr != NULL\n"); + + V_VT(&val) = VT_I4; + V_I4(&val) = 1234; + hres = IHTMLElement_setAttribute(elem, name, val, 0); + ok(hres == S_OK, "setAttribute failed: %08x\n", hres); + + hres = IHTMLElement4_getAttributeNode(elem4, name, &attr); + ok(hres == S_OK, "getAttributeNode failed: %08x\n", hres); + ok(attr != NULL, "attr == NULL\n"); + + IHTMLDOMAttribute_Release(attr); + IHTMLCommentElement_Release(comment); + IHTMLElement_Release(elem); + IHTMLElement4_Release(elem4); + SysFreeString(name); +} + +#define test_object_vspace(u,s) _test_object_vspace(__LINE__,u,s) +static void _test_object_vspace(unsigned line, IUnknown *unk, LONG exl) +{ + IHTMLObjectElement *object = _get_object_iface(line, unk); + LONG l; + HRESULT hres; + + l = 0xdeadbeef; + hres = IHTMLObjectElement_get_vspace(object, &l); + ok_(__FILE__,line)(hres == S_OK, "get_vspace failed: %08x\n", hres); + ok_(__FILE__,line)(l == exl, "vspace=%d, expected %d\n", l, exl); + IHTMLObjectElement_Release(object); +} + +#define test_object_name(a,b) _test_object_name(__LINE__,a,b) +static void _test_object_name(unsigned line, IHTMLElement *elem, const char *exname) +{ + IHTMLObjectElement *object = _get_object_iface(line, (IUnknown*)elem); + BSTR str; + HRESULT hres; + + str = (void*)0xdeadbeef; + hres = IHTMLObjectElement_get_name(object, &str); + ok_(__FILE__,line)(hres == S_OK, "get_name failed: %08x\n", hres); + if(exname) + ok_(__FILE__,line)(!strcmp_wa(str, exname), "name=%s, expected %s\n", wine_dbgstr_w(str), exname); + else + ok_(__FILE__,line)(!str, "name=%s, expected NULL\n", wine_dbgstr_w(str)); + SysFreeString(str); + IHTMLObjectElement_Release(object); +} + +#define set_object_name(a,b) _set_object_name(__LINE__,a,b) +static void _set_object_name(unsigned line, IHTMLElement *elem, const char *name) +{ + IHTMLObjectElement *object = _get_object_iface(line, (IUnknown*)elem); + BSTR str; + HRESULT hres; + + str = a2bstr(name); + hres = IHTMLObjectElement_put_name(object, str); + ok_(__FILE__,line)(hres == S_OK, "put_name failed: %08x\n", hres); + SysFreeString(str); + IHTMLObjectElement_Release(object); + + _test_object_name(line, elem, name); +} + #define create_option_elem(d,t,v) _create_option_elem(__LINE__,d,t,v) static IHTMLOptionElement *_create_option_elem(unsigned line, IHTMLDocument2 *doc, const char *txt, const char *val) @@ -1433,6 +1838,7 @@ static void _test_select_value(unsigned line, IHTMLSelectElement *select, const ok_(__FILE__,line) (!strcmp_wa(val, exval), "unexpected value %s\n", wine_dbgstr_w(val)); else ok_(__FILE__,line) (val == NULL, "val=%s, expected NULL\n", wine_dbgstr_w(val)); + SysFreeString(val); } #define test_select_set_value(s,v) _test_select_set_value(__LINE__,s,v) @@ -1456,6 +1862,7 @@ static void _test_select_type(unsigned line, IHTMLSelectElement *select, const c hres = IHTMLSelectElement_get_type(select, &type); ok_(__FILE__,line) (hres == S_OK, "get_type failed: %08x\n", hres); ok_(__FILE__,line) (!strcmp_wa(type, extype), "type=%s, expected %s\n", wine_dbgstr_w(type), extype); + SysFreeString(type); } #define test_range_text(r,t) _test_range_text(__LINE__,r,t) @@ -1607,6 +2014,8 @@ static void _test_elem_collection(unsigned line, IUnknown *unk, IDispatch *disp, *disp2; HRESULT hres; + ok(1,"[_test_elem_collection]\n"); + hres = IUnknown_QueryInterface(unk, &IID_IHTMLElementCollection, (void**)&col); ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLElementCollection: %08x\n", hres); @@ -1679,8 +2088,21 @@ static void _test_elem_all(unsigned line, IUnknown *unk, const elem_type_t *elem IDispatch_Release(disp); } -#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) +#define test_doc_all(a,b,c) _test_doc_all(__LINE__,a,b,c) +static void _test_doc_all(unsigned line, IHTMLDocument2 *doc, const elem_type_t *elem_types, LONG exlen) +{ + IHTMLElementCollection *col; + HRESULT hres; + + hres = IHTMLDocument2_get_all(doc, &col); + ok_(__FILE__,line)(hres == S_OK, "get_all failed: %08x\n", hres); + + _test_elem_collection(line, (IUnknown*)col, elem_types, exlen); + IHTMLElementCollection_Release(col); +} + +#define test_elem_getelembytag(a,b,c,d) _test_elem_getelembytag(__LINE__,a,b,c,d) +static void _test_elem_getelembytag(unsigned line, IUnknown *unk, elem_type_t type, LONG exlen, IHTMLElement **ret) { IHTMLElement2 *elem = _get_elem2_iface(line, unk); IHTMLElementCollection *col = NULL; @@ -1705,6 +2127,22 @@ static void _test_elem_getelembytag(unsigned line, IUnknown *unk, elem_type_t ty _test_elem_collection(line, (IUnknown*)col, types, exlen); HeapFree(GetProcessHeap(), 0, types); + + if(ret) { + IDispatch *disp; + VARIANT v; + + V_VT(&v) = VT_I4; + V_I4(&v) = 0; + disp = NULL; + hres = IHTMLElementCollection_item(col, v, v, &disp); + ok(hres == S_OK, "item failed: %08x\n", hres); + ok(disp != NULL, "disp == NULL\n"); + *ret = _get_elem_iface(line, (IUnknown*)disp); + IDispatch_Release(disp); + } + + IHTMLElementCollection_Release(col); } #define test_elem_innertext(e,t) _test_elem_innertext(__LINE__,e,t) @@ -1715,8 +2153,11 @@ static void _test_elem_innertext(unsigned line, IHTMLElement *elem, const char * hres = IHTMLElement_get_innerText(elem, &text); ok_(__FILE__,line) (hres == S_OK, "get_innerText failed: %08x\n", hres); - ok_(__FILE__,line) (!strcmp_wa(text, extext), "get_innerText returned %s expected %s\n", - wine_dbgstr_w(text), extext); + if(extext) + ok_(__FILE__,line) (!strcmp_wa(text, extext), "get_innerText returned %s expected %s\n", + wine_dbgstr_w(text), extext); + else + ok_(__FILE__,line) (!text, "get_innerText returned %s expected NULL\n", wine_dbgstr_w(text)); SysFreeString(text); } @@ -1821,6 +2262,18 @@ static void _test_elem_outerhtml(unsigned line, IUnknown *unk, const char *outer SysFreeString(html); } +#define test_elem_contains(a,b,c) _test_elem_contains(__LINE__,a,b,c) +static void _test_elem_contains(unsigned line, IHTMLElement *elem, IHTMLElement *elem2, VARIANT_BOOL exval) +{ + VARIANT_BOOL b; + HRESULT hres; + + b = 100; + hres = IHTMLElement_contains(elem, elem2, &b); + ok_(__FILE__,line)(hres == S_OK, "contains failed: %08x\n", hres); + ok_(__FILE__,line)(b == exval, "contains returned %x, expected %x\n", b, exval); +} + #define get_first_child(n) _get_first_child(__LINE__,n) static IHTMLDOMNode *_get_first_child(unsigned line, IUnknown *unk) { @@ -1877,6 +2330,20 @@ static IHTMLDOMNode *_node_get_next(unsigned line, IUnknown *unk) return next; } +#define node_get_prev(u) _node_get_prev(__LINE__,u) +static IHTMLDOMNode *_node_get_prev(unsigned line, IUnknown *unk) +{ + IHTMLDOMNode *node = _get_node_iface(line, unk); + IHTMLDOMNode *prev; + HRESULT hres; + + hres = IHTMLDOMNode_get_previousSibling(node, &prev); + IHTMLDOMNode_Release(node); + ok_(__FILE__,line) (hres == S_OK, "get_previousSibling failed: %08x\n", hres); + + return prev; +} + #define test_elem_get_parent(u) _test_elem_get_parent(__LINE__,u) static IHTMLElement *_test_elem_get_parent(unsigned line, IUnknown *unk) { @@ -2049,8 +2516,8 @@ static void _elem_get_scroll_left(unsigned line, IUnknown *unk) ok(l == l2, "unexpected left %d, expected %d\n", l2, l); } -#define test_img_src(i,s) _test_img_src(__LINE__,i,s) -static void _test_img_src(unsigned line, IUnknown *unk, const char *exsrc) +#define test_img_src(a,b,c) _test_img_src(__LINE__,a,b,c) +static void _test_img_src(unsigned line, IUnknown *unk, const char *exsrc, const char *broken_src) { IHTMLImgElement *img = _get_img_iface(line, unk); BSTR src; @@ -2059,7 +2526,8 @@ static void _test_img_src(unsigned line, IUnknown *unk, const char *exsrc) hres = IHTMLImgElement_get_src(img, &src); IHTMLImgElement_Release(img); ok_(__FILE__,line) (hres == S_OK, "get_src failed: %08x\n", hres); - ok_(__FILE__,line) (!strcmp_wa(src, exsrc), "get_src returned %s expected %s\n", wine_dbgstr_w(src), exsrc); + ok_(__FILE__,line) (!strcmp_wa(src, exsrc) || (broken_src && broken(!strcmp_wa(src, broken_src))), + "get_src returned %s expected %s\n", wine_dbgstr_w(src), exsrc); SysFreeString(src); } @@ -2075,8 +2543,6 @@ static void _test_img_set_src(unsigned line, IUnknown *unk, const char *src) IHTMLImgElement_Release(img); SysFreeString(tmp); ok_(__FILE__,line) (hres == S_OK, "put_src failed: %08x\n", hres); - - _test_img_src(line, unk, src); } #define test_img_alt(u,a) _test_img_alt(__LINE__,u,a) @@ -2124,6 +2590,241 @@ static void _test_img_name(unsigned line, IUnknown *unk, const char *pValue) SysFreeString(sName); } +#define test_img_complete(a,b) _test_img_complete(__LINE__,a,b) +static void _test_img_complete(unsigned line, IHTMLElement *elem, VARIANT_BOOL exb) +{ + IHTMLImgElement *img = _get_img_iface(line, (IUnknown*)elem); + VARIANT_BOOL b = 100; + HRESULT hres; + + hres = IHTMLImgElement_get_complete(img, &b); + ok_(__FILE__,line) (hres == S_OK, "get_complete failed: %08x\n", hres); + ok_(__FILE__,line) (b == exb, "complete = %x, expected %x\n", b, exb); + IHTMLImgElement_Release(img); +} + +static void test_dynamic_properties(IHTMLElement *elem) +{ + static const WCHAR attr1W[] = {'a','t','t','r','1',0}; + IDispatchEx *dispex; + BSTR name, attr1 = SysAllocString(attr1W); + VARIANT_BOOL succ; + VARIANT val; + int checked_no = 0; + DISPID id = DISPID_STARTENUM; + HRESULT hres; + + hres = IHTMLElement_QueryInterface(elem, &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "QueryInterface failed: %08x\n", hres); + + hres = IHTMLElement_removeAttribute(elem, attr1, 0, &succ); + ok(hres == S_OK, "removeAttribute failed: %08x\n", hres); + ok(succ, "removeAttribute set succ to FALSE\n"); + + while(1) { + hres = IDispatchEx_GetNextDispID(dispex, fdexEnumAll, id, &id); + ok(hres==S_OK || hres==S_FALSE, "GetNextDispID failed: %08x\n", hres); + if(hres != S_OK) + break; + + hres = IDispatchEx_GetMemberName(dispex, id, &name); + ok(hres == S_OK, "GetMemberName failed: %08x\n", hres); + + if(!strcmp_wa(name, "attr1")) + ok(0, "attr1 should be removed\n"); + else if(!strcmp_wa(name, "attr2") || !strcmp_wa(name, "attr3")) + checked_no++; + SysFreeString(name); + } + ok(checked_no == 2, "checked_no=%d, expected 2\n", checked_no); + IDispatchEx_Release(dispex); + + V_VT(&val) = VT_BSTR; + V_BSTR(&val) = attr1; + hres = IHTMLElement_setAttribute(elem, attr1, val, 0); + ok(hres == S_OK, "setAttribute failed: %08x\n", hres); + SysFreeString(attr1); +} + +#define test_attr_node_name(a,b) _test_attr_node_name(__LINE__,a,b) +static void _test_attr_node_name(unsigned line, IHTMLDOMAttribute *attr, const char *exname) +{ + BSTR str; + HRESULT hres; + + hres = IHTMLDOMAttribute_get_nodeName(attr, &str); + ok_(__FILE__,line)(hres == S_OK, "get_nodeName failed: %08x\n", hres); + ok_(__FILE__,line)(!strcmp_wa(str, exname), "node name is %s, expected %s\n", wine_dbgstr_w(str), exname); + SysFreeString(str); +} + +static void test_attr_collection_disp(IDispatch *disp) +{ + IDispatchEx *dispex; + IHTMLDOMAttribute *attr; + DISPPARAMS dp = {NULL, NULL, 0, 0}; + VARIANT var; + EXCEPINFO ei; + DISPID id; + BSTR bstr; + HRESULT hres; + + hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "QueryInterface failed: %08x\n", hres); + + bstr = a2bstr("0"); + hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &id); + ok(hres == S_OK, "GetDispID failed: %08x\n", hres); + SysFreeString(bstr); + + VariantInit(&var); + hres = IDispatchEx_InvokeEx(dispex, id, LOCALE_NEUTRAL, INVOKE_PROPERTYGET, &dp, &var, &ei, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&var) == VT_DISPATCH, "V_VT(var)=%d\n", V_VT(&var)); + ok(V_DISPATCH(&var) != NULL, "V_DISPATCH(var) == NULL\n"); + VariantClear(&var); + + bstr = a2bstr("attr1"); + hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &id); + ok(hres == S_OK, "GetDispID failed: %08x\n", hres); + SysFreeString(bstr); + + VariantInit(&var); + hres = IDispatchEx_InvokeEx(dispex, id, LOCALE_NEUTRAL, INVOKE_PROPERTYGET, &dp, &var, &ei, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&var) == VT_DISPATCH, "V_VT(var)=%d\n", V_VT(&var)); + ok(V_DISPATCH(&var) != NULL, "V_DISPATCH(var) == NULL\n"); + hres = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IHTMLDOMAttribute, (void**)&attr); + ok(hres == S_OK, "QueryInterface failed: %08x\n", hres); + + test_attr_node_name(attr, "attr1"); + + IHTMLDOMAttribute_Release(attr); + VariantClear(&var); + + IDispatchEx_Release(dispex); +} + +static void test_attr_collection(IHTMLElement *elem) +{ + static const WCHAR testW[] = {'t','e','s','t',0}; + + IHTMLDOMNode *node; + IDispatch *disp, *attr; + IHTMLDOMAttribute *dom_attr; + IHTMLAttributeCollection *attr_col; + BSTR name = SysAllocString(testW); + VARIANT id, val; + LONG i, len, checked; + HRESULT hres; + + hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLDOMNode, (void**)&node); + ok(hres == S_OK, "QueryInterface failed: %08x\n", hres); + + hres = IHTMLDOMNode_get_attributes(node, &disp); + ok(hres == S_OK, "get_attributes failed: %08x\n", hres); + + hres = IHTMLDOMNode_get_attributes(node, &attr); + ok(hres == S_OK, "get_attributes failed: %08x\n", hres); + ok(iface_cmp((IUnknown*)disp, (IUnknown*)attr), "disp != attr\n"); + IDispatch_Release(attr); + IHTMLDOMNode_Release(node); + + hres = IDispatch_QueryInterface(disp, &IID_IHTMLAttributeCollection, (void**)&attr_col); + ok(hres == S_OK, "QueryInterface failed: %08x\n", hres); + + hres = IHTMLAttributeCollection_get_length(attr_col, &i); + ok(hres == S_OK, "get_length failed: %08x\n", hres); + + V_VT(&val) = VT_I4; + V_I4(&val) = 1; + hres = IHTMLElement_setAttribute(elem, name, val, 0); + ok(hres == S_OK, "setAttribute failed: %08x\n", hres); + SysFreeString(name); + + hres = IHTMLAttributeCollection_get_length(attr_col, &len); + ok(hres == S_OK, "get_length failed: %08x\n", hres); + ok(len == i+1, "get_length returned %d, expected %d\n", len, i+1); + + checked = 0; + for(i=0; i"); + SafeArrayUnaccessData(sa); + + hres = IHTMLDocument2_write(doc, sa); + ok(hres == S_OK, "write failed: %08x\n", hres); + SafeArrayDestroy(sa); } @@ -5528,6 +5472,7 @@ static void test_frame_doc(IUnknown *frame_elem, BOOL iframe) HRESULT hres; content_window = get_frame_content_window(frame_elem); + test_ifaces((IUnknown*)content_window, window_iids); window_doc = get_window_doc(content_window); IHTMLWindow2_Release(content_window); @@ -5555,11 +5500,79 @@ static void test_frame_doc(IUnknown *frame_elem, BOOL iframe) IHTMLDocument2_Release(window_doc); } +#define test_iframe_height(a,b) _test_iframe_height(__LINE__,a,b) +static void _test_iframe_height(unsigned line, IHTMLElement *elem, const char *exval) +{ + IHTMLIFrameElement2 *iframe = _get_iframe2_iface(line, (IUnknown*)elem); + VARIANT v; + HRESULT hres; + + hres = IHTMLIFrameElement2_get_height(iframe, &v); + ok_(__FILE__,line)(hres == S_OK, "get_height failed: %08x\n", hres); + ok_(__FILE__,line)(V_VT(&v) == VT_BSTR, "V_VT(height) = %d\n", V_VT(&v)); + if(exval) + ok_(__FILE__,line)(!strcmp_wa(V_BSTR(&v), exval), "height = %s, expected %s\n", wine_dbgstr_w(V_BSTR(&v)), exval); + else + ok_(__FILE__,line)(!V_BSTR(&v), "height = %s, expected NULL\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + IHTMLIFrameElement2_Release(iframe); +} + +#define set_iframe_height(a,b) _set_iframe_height(__LINE__,a,b) +static void _set_iframe_height(unsigned line, IHTMLElement *elem, const char *val) +{ + IHTMLIFrameElement2 *iframe = _get_iframe2_iface(line, (IUnknown*)elem); + VARIANT v; + HRESULT hres; + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr(val); + hres = IHTMLIFrameElement2_put_height(iframe, v); + ok_(__FILE__,line)(hres == S_OK, "put_height failed: %08x\n", hres); + VariantClear(&v); + IHTMLIFrameElement2_Release(iframe); +} + +#define test_iframe_width(a,b) _test_iframe_width(__LINE__,a,b) +static void _test_iframe_width(unsigned line, IHTMLElement *elem, const char *exval) +{ + IHTMLIFrameElement2 *iframe = _get_iframe2_iface(line, (IUnknown*)elem); + VARIANT v; + HRESULT hres; + + hres = IHTMLIFrameElement2_get_width(iframe, &v); + ok_(__FILE__,line)(hres == S_OK, "get_width failed: %08x\n", hres); + ok_(__FILE__,line)(V_VT(&v) == VT_BSTR, "V_VT(width) = %d\n", V_VT(&v)); + if(exval) + ok_(__FILE__,line)(!strcmp_wa(V_BSTR(&v), exval), "width = %s, expected %s\n", wine_dbgstr_w(V_BSTR(&v)), exval); + else + ok_(__FILE__,line)(!V_BSTR(&v), "width = %s, expected NULL\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + IHTMLIFrameElement2_Release(iframe); +} + +#define set_iframe_width(a,b) _set_iframe_width(__LINE__,a,b) +static void _set_iframe_width(unsigned line, IHTMLElement *elem, const char *val) +{ + IHTMLIFrameElement2 *iframe = _get_iframe2_iface(line, (IUnknown*)elem); + VARIANT v; + HRESULT hres; + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr(val); + hres = IHTMLIFrameElement2_put_width(iframe, v); + ok_(__FILE__,line)(hres == S_OK, "put_width failed: %08x\n", hres); + VariantClear(&v); + IHTMLIFrameElement2_Release(iframe); +} + static void test_iframe_elem(IHTMLElement *elem) { IHTMLDocument2 *content_doc, *owner_doc; + IHTMLIFrameElement3 *iframe3; IHTMLElementCollection *col; IHTMLWindow2 *content_window; + IHTMLElement *body; IDispatch *disp; VARIANT errv; BSTR str; @@ -5574,13 +5587,37 @@ static void test_iframe_elem(IHTMLElement *elem) }; test_frame_doc((IUnknown*)elem, TRUE); + test_framebase((IUnknown*)elem); content_window = get_frame_content_window((IUnknown*)elem); + test_ifaces((IUnknown*)content_window, window_iids); test_window_length(content_window, 0); content_doc = get_window_doc(content_window); IHTMLWindow2_Release(content_window); + hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLIFrameElement3, (void**)&iframe3); + if(SUCCEEDED(hres)) { + hres = IHTMLIFrameElement3_get_contentDocument(iframe3, &disp); + ok(hres == S_OK, "get_contentDocument failed: %08x\n", hres); + ok(iface_cmp((IUnknown*)content_doc, (IUnknown*)disp), "content_doc != disp\n"); + IDispatch_Release(disp); + + IHTMLIFrameElement3_Release(iframe3); + }else { + win_skip("IHTMLIFrameElement3 not supported\n"); + } + + test_iframe_height(elem, NULL); + set_iframe_height(elem, "100px"); + set_iframe_height(elem, "50%"); + test_iframe_height(elem, "50%"); + + test_iframe_width(elem, NULL); + set_iframe_width(elem, "150px"); + set_iframe_width(elem, "70%"); + test_iframe_width(elem, "70%"); + str = a2bstr("text/html"); V_VT(&errv) = VT_ERROR; disp = NULL; @@ -5591,7 +5628,9 @@ static void test_iframe_elem(IHTMLElement *elem) ok(iface_cmp((IUnknown*)disp, (IUnknown*)content_window), "disp != content_window\n"); IDispatch_Release(disp); - doc_write(content_doc, FALSE, "test
"); + doc_write(content_doc, FALSE, "test"); + doc_complex_write(content_doc); + doc_write(content_doc, TRUE, "
"); doc_write(content_doc, TRUE, ""); hres = IHTMLDocument2_get_all(content_doc, &col); @@ -5599,6 +5638,11 @@ static void test_iframe_elem(IHTMLElement *elem) test_elem_collection((IUnknown*)col, all_types, sizeof(all_types)/sizeof(all_types[0])); IHTMLElementCollection_Release(col); + body = doc_get_body(content_doc); + test_elem_attr(body, "i4val", "4"); + test_elem_attr(body, "r8val", "3.14"); + IHTMLElement_Release(body); + hres = IHTMLDocument2_close(content_doc); ok(hres == S_OK, "close failed: %08x\n", hres); @@ -5636,6 +5680,8 @@ static void test_stylesheets(IHTMLDocument2 *doc) ok(hres == S_OK, "get_styleSheets failed: %08x\n", hres); ok(col != NULL, "col == NULL\n"); + test_disp2((IUnknown*)col, &DIID_DispHTMLStyleSheetsCollection, &IID_IHTMLStyleSheetsCollection, "[object]"); + hres = IHTMLStyleSheetsCollection_get_length(col, &len); ok(hres == S_OK, "get_length failed: %08x\n", hres); ok(len == 1, "len=%d\n", len); @@ -5727,10 +5773,14 @@ static void test_elems(IHTMLDocument2 *doc) ET_HEAD, ET_TITLE, ET_STYLE, + ET_META, + ET_LINK, ET_BODY, ET_COMMENT, ET_A, + ET_LABEL, ET_INPUT, + ET_BUTTON, ET_SELECT, ET_OPTION, ET_OPTION, @@ -5743,9 +5793,12 @@ static void test_elems(IHTMLDocument2 *doc) ET_TD, ET_SCRIPT, ET_TEST, + ET_OBJECT, + ET_EMBED, ET_IMG, ET_IFRAME, - ET_FORM + ET_FORM, + ET_DIV }; static const elem_type_t item_types[] = { @@ -5790,6 +5843,8 @@ static void test_elems(IHTMLDocument2 *doc) IHTMLElementCollection_Release(collection); } + test_plugins_col(doc); + elem = get_doc_elem(doc); test_elem_all((IUnknown*)elem, all_types+1, sizeof(all_types)/sizeof(all_types[0])-1); IHTMLElement_Release(elem); @@ -5834,17 +5889,27 @@ static void test_elems(IHTMLDocument2 *doc) 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_contains(elem3, elem2, VARIANT_TRUE); + test_elem_contains(elem3, elem, VARIANT_TRUE); + test_elem_contains(elem2, elem, VARIANT_TRUE); + test_elem_contains(elem2, elem3, VARIANT_FALSE); + test_elem_contains(elem, elem3, VARIANT_FALSE); + test_elem_contains(elem, elem2, VARIANT_FALSE); + test_elem_contains(elem, elem, VARIANT_TRUE); + IHTMLElement_Release(elem2); + + elem2 = test_elem_get_parent((IUnknown*)elem3); + ok(elem2 == NULL, "elem2 != NULL\n"); + IHTMLElement_Release(elem3); + + test_elem_getelembytag((IUnknown*)elem, ET_OPTION, 2, NULL); + test_elem_getelembytag((IUnknown*)elem, ET_SELECT, 0, NULL); + test_elem_getelembytag((IUnknown*)elem, ET_HTML, 0, NULL); test_elem_innertext(elem, "opt1opt2"); @@ -5861,7 +5926,8 @@ static void test_elems(IHTMLDocument2 *doc) test_elem_title((IUnknown*)select, NULL); test_elem_set_title((IUnknown*)select, "Title"); test_elem_title((IUnknown*)select, "Title"); - test_elem_offset((IUnknown*)select); + test_elem_offset((IUnknown*)select, "BODY"); + test_elem_bounding_client_rect((IUnknown*)select); node = get_first_child((IUnknown*)select); ok(node != NULL, "node == NULL\n"); @@ -5908,9 +5974,10 @@ static void test_elems(IHTMLDocument2 *doc) hres = IHTMLScriptElement_get_type(script, &type); ok(hres == S_OK, "get_type failed: %08x\n", hres); ok(!strcmp_wa(type, "text/javascript"), "Unexpected type %s\n", wine_dbgstr_w(type)); - SysFreeString(type); + test_script_text(script, "\n"); + /* test defer */ hres = IHTMLScriptElement_put_defer(script, VARIANT_TRUE); ok(hres == S_OK, "put_defer failed: %08x\n", hres); @@ -5921,6 +5988,11 @@ static void test_elems(IHTMLDocument2 *doc) hres = IHTMLScriptElement_put_defer(script, VARIANT_FALSE); ok(hres == S_OK, "put_defer failed: %08x\n", hres); + + str = (BSTR)0xdeadbeef; + hres = IHTMLScriptElement_get_src(script, &str); + ok(hres == S_OK, "get_src failed: %08x\n", hres); + ok(!str, "src = %s\n", wine_dbgstr_w(str)); } IHTMLScriptElement_Release(script); @@ -5949,8 +6021,9 @@ static void test_elems(IHTMLDocument2 *doc) test_node_put_value_str((IUnknown*)elem, "test"); test_node_get_value_str((IUnknown*)elem, NULL); test_input_value((IUnknown*)elem, NULL); + test_input_defaultValue((IUnknown*)elem, NULL); test_input_put_value((IUnknown*)elem, "test"); - test_input_value((IUnknown*)elem, NULL); + test_input_defaultValue((IUnknown*)elem, NULL); test_elem_class((IUnknown*)elem, "testclass"); test_elem_tabindex((IUnknown*)elem, 2); test_elem_set_tabindex((IUnknown*)elem, 3); @@ -5964,6 +6037,9 @@ static void test_elems(IHTMLDocument2 *doc) test_input_set_checked(input, VARIANT_TRUE); test_input_set_checked(input, VARIANT_FALSE); + test_input_maxlength(input, 0x7fffffff); + test_input_set_maxlength(input, 30); + test_input_name(input, NULL); test_input_set_name(input, "test"); @@ -5976,11 +6052,29 @@ static void test_elems(IHTMLDocument2 *doc) elem = get_elem_by_id(doc, "imgid", TRUE); if(elem) { - test_img_src((IUnknown*)elem, ""); + test_img_src((IUnknown*)elem, "", NULL); test_img_set_src((IUnknown*)elem, "about:blank"); + test_img_src((IUnknown*)elem, "about:blank", NULL); test_img_alt((IUnknown*)elem, NULL); test_img_set_alt((IUnknown*)elem, "alt test"); test_img_name((IUnknown*)elem, "WineImg"); + test_img_complete(elem, VARIANT_FALSE); + IHTMLElement_Release(elem); + } + + elem = get_elem_by_id(doc, "attr", TRUE); + if(elem) { + test_dynamic_properties(elem); + test_attr_collection(elem); + IHTMLElement_Release(elem); + } + + elem = get_elem_by_id(doc, "styleid", TRUE); + if(elem) { + test_style_media((IUnknown*)elem, NULL); + test_style_put_media((IUnknown*)elem, "screen"); + test_style_type((IUnknown*)elem, NULL); + test_style_put_type((IUnknown*)elem, "text/css"); IHTMLElement_Release(elem); } @@ -6005,14 +6099,58 @@ static void test_elems(IHTMLDocument2 *doc) IHTMLElement_Release(elem); } - elem = get_elem_by_id(doc, "a", TRUE); + elem = get_doc_elem_by_id(doc, "objid"); + ok(elem != NULL, "elem == NULL\n"); if(elem) { - test_anchor_href((IUnknown*)elem, "http://test/"); + test_object_vspace((IUnknown*)elem, 100); + test_object_name(elem, "objname"); + set_object_name(elem, "test"); + set_object_name(elem, NULL); IHTMLElement_Release(elem); } - hres = IHTMLDocument2_get_body(doc, &elem); - ok(hres == S_OK, "get_body failed: %08x\n", hres); + elem = get_elem_by_id(doc, "a", TRUE); + if(elem) { + test_anchor_href((IUnknown*)elem, "http://test/"); + + /* Change the href */ + test_anchor_put_href((IUnknown*)elem, "http://test1/"); + test_anchor_href((IUnknown*)elem, "http://test1/"); + test_anchor_hostname((IUnknown*)elem, "test1"); + + /* Restore the href */ + test_anchor_put_href((IUnknown*)elem, "http://test/"); + test_anchor_href((IUnknown*)elem, "http://test/"); + test_anchor_hostname((IUnknown*)elem, "test"); + + /* target */ + test_anchor_get_target((IUnknown*)elem, NULL); + + /* Change the target */ + test_anchor_put_target((IUnknown*)elem, "wine"); + test_anchor_get_target((IUnknown*)elem, "wine"); + + /* Restore the target */ + test_anchor_put_target((IUnknown*)elem, NULL); + test_anchor_get_target((IUnknown*)elem, NULL); + + test_anchor_name((IUnknown*)elem, "x"); + test_anchor_put_name((IUnknown*)elem, "anchor name"); + test_anchor_put_name((IUnknown*)elem, NULL); + test_anchor_put_name((IUnknown*)elem, "x"); + + IHTMLElement_Release(elem); + } + + elem = get_doc_elem_by_id(doc, "metaid"); + if(elem) { + test_meta_name((IUnknown*)elem, "meta name"); + test_meta_content((IUnknown*)elem, "text/html; charset=utf-8"); + test_meta_httpequiv((IUnknown*)elem, "Content-Type"); + IHTMLElement_Release(elem); + } + + elem = doc_get_body(doc); node = get_first_child((IUnknown*)elem); ok(node != NULL, "node == NULL\n"); @@ -6030,6 +6168,10 @@ static void test_elems(IHTMLDocument2 *doc) test_node_put_value_str((IUnknown*)elem, "test text"); test_node_get_value_str((IUnknown*)node, "text test"); + hres = IHTMLDOMNode_get_attributes(node, &disp); + ok(hres == S_OK, "get_attributes failed: %08x\n", hres); + ok(!disp, "disp != NULL\n"); + IHTMLDOMNode_Release(node); } @@ -6048,9 +6190,16 @@ static void test_elems(IHTMLDocument2 *doc) node = get_child_item(child_col, 0); ok(node != NULL, "node == NULL\n"); if(node) { + IHTMLDOMNode *prev; + type = get_node_type((IUnknown*)node); ok(type == 3, "type=%d\n", type); node2 = node_get_next((IUnknown*)node); + + prev = node_get_prev((IUnknown*)node2); + ok(iface_cmp((IUnknown*)node, (IUnknown*)prev), "node != prev\n"); + IHTMLDOMNode_Release(prev); + IHTMLDOMNode_Release(node); } @@ -6093,6 +6242,7 @@ static void test_elems(IHTMLDocument2 *doc) ok(elem != NULL, "elem == NULL\n"); if(elem) { test_form_length((IUnknown*)elem, 0); + test_form_elements((IUnknown*)elem); IHTMLElement_Release(elem); } @@ -6133,7 +6283,7 @@ static void test_elems(IHTMLDocument2 *doc) hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3); ok(hres == S_OK, "Could not get IHTMLDocument3 iface: %08x\n", hres); - str = a2bstr("img"); + str = a2bstr("Img"); hres = IHTMLDocument3_getElementsByTagName(doc3, str, &col); ok(hres == S_OK, "getElementsByTagName(%s) failed: %08x\n", wine_dbgstr_w(str), hres); SysFreeString(str); @@ -6180,6 +6330,76 @@ static void test_elems(IHTMLDocument2 *doc) IHTMLWindow2_Release(window); } +static void test_attr(IHTMLElement *elem) +{ + IHTMLDOMAttribute *attr, *attr2; + VARIANT v; + + get_elem_attr_node((IUnknown*)elem, "noattr", FALSE); + + attr = get_elem_attr_node((IUnknown*)elem, "id", TRUE); + + test_disp((IUnknown*)attr, &DIID_DispHTMLDOMAttribute, "[object]"); + test_ifaces((IUnknown*)attr, attr_iids); + test_no_iface((IUnknown*)attr, &IID_IHTMLDOMNode); + test_attr_specified(attr, VARIANT_TRUE); + + attr2 = get_elem_attr_node((IUnknown*)elem, "id", TRUE); + ok(iface_cmp((IUnknown*)attr, (IUnknown*)attr2), "attr != attr2\n"); + IHTMLDOMAttribute_Release(attr2); + + get_attr_node_value(attr, &v, VT_BSTR); + ok(!strcmp_wa(V_BSTR(&v), "divid"), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + IHTMLDOMAttribute_Release(attr); + + attr = get_elem_attr_node((IUnknown*)elem, "emptyattr", TRUE); + get_attr_node_value(attr, &v, VT_BSTR); + ok(!V_BSTR(&v), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + test_attr_specified(attr, VARIANT_TRUE); + IHTMLDOMAttribute_Release(attr); + + V_VT(&v) = VT_I4; + V_I4(&v) = 100; + set_dispex_value((IUnknown*)elem, "dispprop", &v); + attr = get_elem_attr_node((IUnknown*)elem, "dispprop", TRUE); + get_attr_node_value(attr, &v, VT_I4); + ok(V_I4(&v) == 100, "V_I4(v) = %d\n", V_I4(&v)); + test_attr_specified(attr, VARIANT_TRUE); + IHTMLDOMAttribute_Release(attr); + + attr = get_elem_attr_node((IUnknown*)elem, "tabIndex", TRUE); + test_attr_specified(attr, VARIANT_FALSE); + IHTMLDOMAttribute_Release(attr); +} + +static void test_blocked(IHTMLDocument2 *doc, IHTMLElement *outer_elem) +{ + IHTMLElement *elem; + + test_elem_set_innerhtml((IUnknown*)outer_elem, + ""); + elem = get_elem_by_id(doc, "imgid", TRUE); + if(elem) { + test_img_src((IUnknown*)elem, "BLOCKED::", "blocked::http://www.winehq.org/img.png"); + IHTMLElement_Release(elem); + } + + test_elem_set_innerhtml((IUnknown*)outer_elem, + ""); + elem = get_elem_by_id(doc, "imgid", TRUE); + if(elem) { + test_img_src((IUnknown*)elem, "blocke::http://www.winehq.org/img.png", NULL); + test_img_set_src((IUnknown*)elem, "BLOCKED:http://www.winehq.org/img.png"); + test_img_src((IUnknown*)elem, "blocked:http://www.winehq.org/img.png", NULL); + test_img_set_src((IUnknown*)elem, "blocked::http://www.winehq.org/img.png"); + test_img_src((IUnknown*)elem, "BLOCKED::", "blocked::http://www.winehq.org/img.png"); + IHTMLElement_Release(elem); + } +} + static void test_elems2(IHTMLDocument2 *doc) { IHTMLElement *elem, *elem2, *div; @@ -6191,6 +6411,19 @@ static void test_elems2(IHTMLDocument2 *doc) div = get_doc_elem_by_id(doc, "divid"); + elem = get_elem_by_id(doc, "linkid", TRUE); + if(elem) { + test_link_disabled(elem, VARIANT_FALSE); + test_link_rel(elem, "stylesheet"); + test_link_type(elem, "text/css"); + test_link_href(elem, "about:blank"); + link_put_disabled(elem, VARIANT_TRUE); + link_put_rel(elem, "prev"); + link_put_type(elem, "text/plain"); + link_put_href(elem, "about:prev"); + IHTMLElement_Release(elem); + } + test_elem_set_innerhtml((IUnknown*)div, "
"); elem2 = get_doc_elem_by_id(doc, "innerid"); ok(elem2 != NULL, "elem2 == NULL\n"); @@ -6212,20 +6445,50 @@ static void test_elems2(IHTMLDocument2 *doc) test_textarea_readonly((IUnknown*)elem, VARIANT_FALSE); test_textarea_put_readonly((IUnknown*)elem, VARIANT_TRUE); test_textarea_put_readonly((IUnknown*)elem, VARIANT_FALSE); + test_textarea_type((IUnknown*)elem); IHTMLElement_Release(elem); } test_elem_set_innerhtml((IUnknown*)div, - "
"); + ""); + elem = get_elem_by_id(doc, "inputid", TRUE); + if(elem) { + test_input_defaultValue((IUnknown*)elem, "val"); + test_input_put_value((IUnknown*)elem, "test"); + test_input_put_defaultValue((IUnknown*)elem, "new val"); + test_input_value((IUnknown*)elem, "test"); + IHTMLElement_Release(elem); + } + + test_elem_set_innerhtml((IUnknown*)div, ""); + test_insert_adjacent_elems(doc, div); + + test_elem_set_innerhtml((IUnknown*)div, + "
"); elem = get_elem_by_id(doc, "form", TRUE); if(elem) { test_form_length((IUnknown*)elem, 2); test_form_item(elem); test_form_action((IUnknown*)elem, NULL); test_form_put_action((IUnknown*)elem, "about:blank"); + test_form_method((IUnknown*)elem, "get"); + test_form_put_method((IUnknown*)elem, S_OK, "post"); + test_form_put_method((IUnknown*)elem, E_INVALIDARG, "put"); + test_form_method((IUnknown*)elem, "post"); + test_form_name((IUnknown*)elem, NULL); + test_form_put_name((IUnknown*)elem, "Name"); + test_form_encoding((IUnknown*)elem, "application/x-www-form-urlencoded"); + test_form_put_encoding((IUnknown*)elem, S_OK, "text/plain"); + test_form_put_encoding((IUnknown*)elem, S_OK, "multipart/form-data"); + test_form_put_encoding((IUnknown*)elem, E_INVALIDARG, "image/png"); + test_form_encoding((IUnknown*)elem, "multipart/form-data"); + test_form_elements((IUnknown*)elem); IHTMLElement_Release(elem); } + test_attr(div); + test_blocked(doc, div); + IHTMLElement_Release(div); } @@ -6233,6 +6496,7 @@ static void test_create_elems(IHTMLDocument2 *doc) { IHTMLElement *elem, *body, *elem2; IHTMLDOMNode *node, *node2, *node3, *comment; + IHTMLDOMAttribute *attr; IHTMLDocument5 *doc5; IDispatch *disp; VARIANT var; @@ -6249,8 +6513,7 @@ static void test_create_elems(IHTMLDocument2 *doc) test_ifaces((IUnknown*)elem, elem_iids); test_disp((IUnknown*)elem, &DIID_DispHTMLGenericElement, "[object]"); - hres = IHTMLDocument2_get_body(doc, &body); - ok(hres == S_OK, "get_body failed: %08x\n", hres); + body = doc_get_body(doc); test_node_has_child((IUnknown*)body, VARIANT_FALSE); node = test_node_append_child((IUnknown*)body, (IUnknown*)elem); @@ -6295,6 +6558,13 @@ static void test_create_elems(IHTMLDocument2 *doc) test_elem_innertext(body, "insert test"); test_elem_innerhtml((IUnknown*)body, "insert test"); + node = test_create_text(doc, " Test"); + V_VT(&var) = VT_DISPATCH; + V_DISPATCH(&var) = NULL; + test_node_insertbefore((IUnknown*)body, node, &var); + test_elem_innertext(body, "insert test Test"); + IHTMLDOMNode_Release(node); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument5, (void**)&doc5); if(hres == S_OK) { @@ -6313,16 +6583,115 @@ static void test_create_elems(IHTMLDocument2 *doc) test_elem_title((IUnknown*)comment, "comment title"); test_comment_text((IUnknown*)comment, ""); test_elem_outerhtml((IUnknown*)comment, ""); + test_comment_attrs((IUnknown*)comment); IHTMLDOMNode_Release(comment); } + str = a2bstr("Test"); + hres = IHTMLDocument5_createAttribute(doc5, str, &attr); + ok(hres == S_OK, "createAttribute dailed: %08x\n", hres); + SysFreeString(str); + if(SUCCEEDED(hres)) { + test_disp((IUnknown*)attr, &DIID_DispHTMLDOMAttribute, "[object]"); + test_ifaces((IUnknown*)attr, attr_iids); + test_no_iface((IUnknown*)attr, &IID_IHTMLDOMNode); + + test_attr_node_name(attr, "Test"); + + IHTMLDOMAttribute_Release(attr); + } + IHTMLDocument5_Release(doc5); } IHTMLElement_Release(body); } +static void test_replacechild_elems(IHTMLDocument2 *doc) +{ + IHTMLElement *body; + IHTMLDOMNode *node, *node2, *node3; + IHTMLDOMNode *nodeBody, *nodeNew; + HRESULT hres; + VARIANT var; + + body = doc_get_body(doc); + + node = test_create_text(doc, "insert"); + + V_VT(&var) = VT_NULL; + V_DISPATCH(&var) = NULL; + node2 = test_node_insertbefore((IUnknown*)body, node, &var); + IHTMLDOMNode_Release(node); + + test_elem_innertext(body, "insert"); + + node3 = test_create_text(doc, "replaced"); + + nodeBody = _get_node_iface(__LINE__, (IUnknown *)body); + + hres = IHTMLDOMNode_replaceChild(nodeBody, node3, node2, &nodeNew); + ok(hres == S_OK, "Expected S_OK, got 0x%08x\n", hres); + + test_elem_innertext(body, "replaced"); + + IHTMLDOMNode_Release(node2); + IHTMLDOMNode_Release(node3); + IHTMLDOMNode_Release(nodeBody); + + IHTMLElement_Release(body); +} + +static void test_noscript(IHTMLDocument2 *doc) +{ + IHTMLElementCollection *col; + IHTMLElement *body; + HRESULT hres; + + static const elem_type_t all_types[] = { + ET_HTML, + ET_HEAD, + ET_TITLE, + ET_NOSCRIPT, + ET_BODY, + ET_NOSCRIPT + }; + + static const elem_type_t body_all_types[] = { + ET_DIV, + ET_NOSCRIPT + }; + + 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); + + body = doc_get_body(doc); + test_elem_set_innerhtml((IUnknown*)body, "
test
"); + test_elem_all((IUnknown*)body, body_all_types, sizeof(body_all_types)/sizeof(*body_all_types)); + IHTMLElement_Release(body); +} + +static void test_doctype(IHTMLDocument2 *doc) +{ + IHTMLDocument2 *doc_node; + IHTMLDOMNode *doctype; + int type; + + doc_node = get_doc_node(doc); + doctype = get_first_child((IUnknown*)doc_node); + IHTMLDocument2_Release(doc_node); + + type = get_node_type((IUnknown*)doctype); + ok(type == 8, "type = %d\n", type); + + test_comment_text((IUnknown*)doctype, ""); + test_elem_type((IUnknown*)doctype, ET_COMMENT); + IHTMLDOMNode_Release(doctype); +} + static void test_null_write(IHTMLDocument2 *doc) { HRESULT hres; @@ -6339,12 +6708,64 @@ static void test_null_write(IHTMLDocument2 *doc) "Expected IHTMLDocument2::writeln to return S_OK, got 0x%08x\n", hres); } +static void test_create_stylesheet(IHTMLDocument2 *doc) +{ + IHTMLStyleSheet *stylesheet, *stylesheet2; + IHTMLStyleElement *style_elem; + IHTMLElement *doc_elem, *elem; + HRESULT hres; + + static const elem_type_t all_types[] = { + ET_HTML, + ET_HEAD, + ET_TITLE, + ET_BODY, + ET_DIV + }; + + static const elem_type_t all_types2[] = { + ET_HTML, + ET_HEAD, + ET_TITLE, + ET_STYLE, + ET_BODY, + ET_DIV + }; + + test_doc_all(doc, all_types, sizeof(all_types)/sizeof(*all_types)); + + hres = IHTMLDocument2_createStyleSheet(doc, NULL, -1, &stylesheet); + ok(hres == S_OK, "createStyleSheet failed: %08x\n", hres); + + test_doc_all(doc, all_types2, sizeof(all_types2)/sizeof(*all_types2)); + + doc_elem = get_doc_elem(doc); + + test_elem_getelembytag((IUnknown*)doc_elem, ET_STYLE, 1, &elem); + IHTMLElement_Release(doc_elem); + + hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLStyleElement, (void**)&style_elem); + IHTMLElement_Release(elem); + ok(hres == S_OK, "Could not get IHTMLStyleElement iface: %08x\n", hres); + + stylesheet2 = NULL; + hres = IHTMLStyleElement_get_styleSheet(style_elem, &stylesheet2); + ok(hres == S_OK, "get_styleSheet failed: %08x\n", hres); + ok(stylesheet2 != NULL, "stylesheet2 == NULL\n"); + ok(iface_cmp((IUnknown*)stylesheet, (IUnknown*)stylesheet2), "stylesheet != stylesheet2\n"); + + IHTMLStyleSheet_Release(stylesheet2); + IHTMLStyleSheet_Release(stylesheet); + + IHTMLStyleElement_Release(style_elem); +} + static void test_exec(IUnknown *unk, const GUID *grpid, DWORD cmdid, VARIANT *in, VARIANT *out) { IOleCommandTarget *cmdtrg; HRESULT hres; - hres = IHTMLTxtRange_QueryInterface(unk, &IID_IOleCommandTarget, (void**)&cmdtrg); + hres = IUnknown_QueryInterface(unk, &IID_IOleCommandTarget, (void**)&cmdtrg); ok(hres == S_OK, "Could not get IOleCommandTarget interface: %08x\n", hres); hres = IOleCommandTarget_Exec(cmdtrg, grpid, cmdid, 0, in, out); @@ -6435,7 +6856,7 @@ static void test_frame(IDispatch *disp, const char *exp_id) test_elem_type((IUnknown*)frame_elem, ET_FRAME); test_frame_doc((IUnknown*)frame_elem, FALSE); test_elem_id((IUnknown*)frame_elem, exp_id); - IHTMLElement_Release(frame_elem); + IHTMLFrameBase_Release(frame_elem); hres = IDispatch_QueryInterface(disp, &IID_IHTMLWindow2, (void**)&frame2); ok(hres == S_OK, "Could not get IHTMLWindow2 interface: 0x%08x\n", hres); @@ -6477,27 +6898,12 @@ static void test_frame(IDispatch *disp, const char *exp_id) IHTMLDocument2_Release(top_doc); } -static void test_frameset(IHTMLDocument2 *doc) +static void test_frames_collection(IHTMLFramesCollection2 *frames, const char *frid) { - IHTMLWindow2 *window; - IHTMLFramesCollection2 *frames; - IHTMLElement *elem; - IHTMLFrameBase *fbase; - LONG length; VARIANT index_var, result_var; - BSTR str; + LONG length; HRESULT hres; - window = get_doc_window(doc); - - /* test using IHTMLFramesCollection object */ - - hres = IHTMLWindow2_get_frames(window, &frames); - ok(hres == S_OK, "IHTMLWindow2_get_frames failed: 0x%08x\n", hres); - IHTMLWindow2_Release(window); - if(FAILED(hres)) - return; - /* test result length */ hres = IHTMLFramesCollection2_get_length(frames, &length); ok(hres == S_OK, "IHTMLFramesCollection2_get_length failed: 0x%08x\n", hres); @@ -6533,12 +6939,12 @@ static void test_frameset(IHTMLDocument2 *doc) /* string argument (element id lookup) */ V_VT(&index_var) = VT_BSTR; - V_BSTR(&index_var) = a2bstr("fr1"); + V_BSTR(&index_var) = a2bstr(frid); hres = IHTMLFramesCollection2_item(frames, &index_var, &result_var); ok(hres == S_OK, "IHTMLFramesCollection2_item failed: 0x%08x\n", hres); if(SUCCEEDED(hres)) { ok(V_VT(&result_var) == VT_DISPATCH, "result type should have been VT_DISPATCH, was: 0x%x\n", V_VT(&result_var)); - test_frame(V_DISPATCH(&result_var), "fr1"); + test_frame(V_DISPATCH(&result_var), frid); } VariantClear(&result_var); VariantClear(&index_var); @@ -6550,119 +6956,129 @@ static void test_frameset(IHTMLDocument2 *doc) ok(hres == E_INVALIDARG, "IHTMLFramesCollection2_item should have" "failed with E_INVALIDARG, instead: 0x%08x\n", hres); VariantClear(&result_var); +} +static void test_frameset(IHTMLDocument2 *doc) +{ + IHTMLWindow2 *window; + IHTMLFramesCollection2 *frames; + IHTMLElement *elem; + HRESULT hres; + + window = get_doc_window(doc); + + /* test using IHTMLFramesCollection object */ + + hres = IHTMLWindow2_get_frames(window, &frames); + ok(hres == S_OK, "IHTMLWindow2_get_frames failed: 0x%08x\n", hres); + if(FAILED(hres)) + return; + + test_frames_collection(frames, "fr1"); + IHTMLFramesCollection2_Release(frames); + + hres = IHTMLDocument2_get_frames(doc, &frames); + ok(hres == S_OK, "IHTMLDocument2_get_frames failed: 0x%08x\n", hres); + if(FAILED(hres)) + return; + + test_frames_collection(frames, "fr1"); IHTMLFramesCollection2_Release(frames); /* test using IHTMLWindow2 inheritance */ - - /* test result length */ - hres = IHTMLWindow2_get_length(window, &length); - ok(hres == S_OK, "IHTMLWindow2_get_length failed: 0x%08x\n", hres); - ok(length == 3, "IHTMLWindow2_get_length should have been 3, was: %d\n", length); - - /* test first frame */ - V_VT(&index_var) = VT_I4; - V_I4(&index_var) = 0; - hres = IHTMLWindow2_item(window, &index_var, &result_var); - ok(hres == S_OK, "IHTMLWindow2_item failed: 0x%08x\n", hres); - if(SUCCEEDED(hres)) { - ok(V_VT(&result_var) == VT_DISPATCH, "result type should have been VT_DISPATCH, was: 0x%x\n", V_VT(&result_var)); - test_frame((IDispatch*)V_DISPATCH(&result_var), "fr1"); - } - VariantClear(&result_var); - - /* test second frame */ - V_I4(&index_var) = 1; - hres = IHTMLWindow2_item(window, &index_var, &result_var); - ok(hres == S_OK, "IHTMLWindow2_item failed: 0x%08x\n", hres); - if(SUCCEEDED(hres)) { - ok(V_VT(&result_var) == VT_DISPATCH, "result type should have been VT_DISPATCH, was: 0x%x\n", V_VT(&result_var)); - test_frame((IDispatch*)V_DISPATCH(&result_var), "fr2"); - } - VariantClear(&result_var); - - /* fail on next frame */ - V_I4(&index_var) = 3; - hres = IHTMLWindow2_item(window, &index_var, &result_var); - ok(hres == DISP_E_MEMBERNOTFOUND, "IHTMLWindow2_item should have" - "failed with DISP_E_MEMBERNOTFOUND, instead: 0x%08x\n", hres); - VariantClear(&result_var); - - /* string argument (element id lookup) */ - V_VT(&index_var) = VT_BSTR; - V_BSTR(&index_var) = a2bstr("fr2"); - hres = IHTMLWindow2_item(window, &index_var, &result_var); - ok(hres == S_OK, "IHTMLWindow2_item failed: 0x%08x\n", hres); - if(SUCCEEDED(hres)) { - ok(V_VT(&result_var) == VT_DISPATCH, "result type should have been VT_DISPATCH, was: 0x%x\n", V_VT(&result_var)); - test_frame((IDispatch*)V_DISPATCH(&result_var), "fr2"); - } - VariantClear(&result_var); - VariantClear(&index_var); - - /* invalid argument */ - V_VT(&index_var) = VT_BOOL; - V_BOOL(&index_var) = VARIANT_TRUE; - hres = IHTMLWindow2_item(window, &index_var, &result_var); - ok(hres == E_INVALIDARG, "IHTMLWindow2_item should have" - "failed with E_INVALIDARG, instead: 0x%08x\n", hres); - VariantClear(&result_var); + test_frames_collection((IHTMLFramesCollection2*)window, "fr2"); /* getElementById with node name attributes */ elem = get_doc_elem_by_id(doc, "nm1"); test_elem_id((IUnknown*)elem, "fr1"); - /* get/put scrolling */ - hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLFrameBase, (void**)&fbase); - ok(hres == S_OK, "Could not get IHTMLFrameBase interface: 0x%08x\n", hres); - - hres = IHTMLFrameBase_get_scrolling(fbase, &str); - ok(hres == S_OK, "IHTMLFrameBase_get_scrolling failed: 0x%08x\n", hres); - ok(!strcmp_wa(str, "auto"), "get_scrolling should have given 'auto', gave: %s\n", wine_dbgstr_w(str)); - SysFreeString(str); - - str = a2bstr("no"); - hres = IHTMLFrameBase_put_scrolling(fbase, str); - ok(hres == S_OK, "IHTMLFrameBase_put_scrolling failed: 0x%08x\n", hres); - SysFreeString(str); - - hres = IHTMLFrameBase_get_scrolling(fbase, &str); - ok(hres == S_OK, "IHTMLFrameBase_get_scrolling failed: 0x%08x\n", hres); - ok(!strcmp_wa(str, "no"), "get_scrolling should have given 'no', gave: %s\n", wine_dbgstr_w(str)); - SysFreeString(str); - - str = a2bstr("junk"); - hres = IHTMLFrameBase_put_scrolling(fbase, str); - ok(hres == E_INVALIDARG, "IHTMLFrameBase_put_scrolling should have failed " - "with E_INVALIDARG, instead: 0x%08x\n", hres); - SysFreeString(str); - - hres = IHTMLFrameBase_get_scrolling(fbase, &str); - ok(hres == S_OK, "IHTMLFrameBase_get_scrolling failed: 0x%08x\n", hres); - ok(!strcmp_wa(str, "no"), "get_scrolling should have given 'no', gave: %s\n", wine_dbgstr_w(str)); - SysFreeString(str); - - /* get_name */ - hres = IHTMLFrameBase_get_name(fbase, &str); - ok(hres == S_OK, "IHTMLFrameBase_get_name failed: 0x%08x\n", hres); - ok(!strcmp_wa(str, "nm1"), "get_name should have given 'nm1', gave: %s\n", wine_dbgstr_w(str)); - SysFreeString(str); - - IHTMLFrameBase_Release(fbase); + test_framebase((IUnknown*)elem); + test_framebase_name(elem, "nm1"); + test_framebase_put_name(elem, "frame name"); + test_framebase_put_name(elem, NULL); + test_framebase_put_name(elem, "nm1"); IHTMLElement_Release(elem); /* get_name with no name attr */ elem = get_doc_elem_by_id(doc, "fr3"); - hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLFrameBase, (void**)&fbase); - ok(hres == S_OK, "Could not get IHTMLFrameBase interface: 0x%08x\n", hres); - - hres = IHTMLFrameBase_get_name(fbase, &str); - ok(hres == S_OK, "IHTMLFrameBase_get_name failed: 0x%08x\n", hres); - ok(str == NULL, "get_name should have given 'null', gave: %s\n", wine_dbgstr_w(str)); - SysFreeString(str); - - IHTMLFrameBase_Release(fbase); + test_framebase_name(elem, NULL); + test_framebase_put_name(elem, "frame name"); + test_framebase_put_name(elem, NULL); IHTMLElement_Release(elem); + + IHTMLWindow2_Release(window); +} + +static IHTMLDocument2 *create_docfrag(IHTMLDocument2 *doc) +{ + IHTMLDocument2 *frag; + IHTMLDocument3 *doc3; + HRESULT hres; + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3); + ok(hres == S_OK, "Could not get IHTMLDocument3 iface: %08x\n", hres); + + hres = IHTMLDocument3_createDocumentFragment(doc3, &frag); + IHTMLDocument3_Release(doc3); + ok(hres == S_OK, "createDocumentFragment failed: %08x\n", hres); + ok(frag != NULL, "frag == NULL\n"); + + return frag; +} + +static void test_docfrag(IHTMLDocument2 *doc) +{ + IHTMLDocument2 *frag, *owner_doc, *doc_node; + IHTMLElement *div, *body, *br; + IHTMLElementCollection *col; + IHTMLLocation *location; + HRESULT hres; + + static const elem_type_t all_types[] = { + ET_HTML, + ET_HEAD, + ET_TITLE, + ET_BODY, + ET_DIV, + ET_BR + }; + + frag = create_docfrag(doc); + + test_disp((IUnknown*)frag, &DIID_DispHTMLDocument, "[object]"); + + body = (void*)0xdeadbeef; + hres = IHTMLDocument2_get_body(frag, &body); + ok(hres == S_OK, "get_body failed: %08x\n", hres); + ok(!body, "body != NULL\n"); + + location = (void*)0xdeadbeef; + hres = IHTMLDocument2_get_location(frag, &location); + ok(hres == E_UNEXPECTED, "get_location failed: %08x\n", hres); + ok(location == (void*)0xdeadbeef, "location changed\n"); + + br = test_create_elem(doc, "BR"); + test_node_append_child((IUnknown*)frag, (IUnknown*)br); + IHTMLElement_Release(br); + + div = get_elem_by_id(doc, "divid", TRUE); + test_node_append_child((IUnknown*)div, (IUnknown*)frag); + IHTMLElement_Release(div); + + 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); + + div = test_create_elem(frag, "div"); + owner_doc = get_owner_doc((IUnknown*)div); + doc_node = get_doc_node(doc); + ok(iface_cmp((IUnknown*)owner_doc, (IUnknown*)doc_node), "owner_doc != doc_node\n"); + IHTMLDocument2_Release(doc_node); + IHTMLDocument2_Release(owner_doc); + IHTMLElement_Release(div); + + IHTMLDocument2_Release(frag); } static IHTMLDocument2 *notif_doc; @@ -6792,13 +7208,16 @@ static void run_domtest(const char *str, domtest_t test) test(doc); ref = IHTMLDocument2_Release(doc); - ok(!ref || - ref == 1, /* Vista */ + ok(!ref || broken(ref == 1), /* Vista */ "ref = %d\n", ref); } START_TEST(dom) { + HMODULE hkernel32 = GetModuleHandleA("kernel32.dll"); + pLCIDToLocaleName = (void*)GetProcAddress(hkernel32, "LCIDToLocaleName"); + pGetUserDefaultUILanguage = (void*)GetProcAddress(hkernel32, "GetUserDefaultUILanguage"); + CoInitialize(NULL); run_domtest(doc_str1, test_doc_elem); @@ -6807,16 +7226,21 @@ START_TEST(dom) run_domtest(range_test2_str, test_txtrange2); if (winetest_interactive || ! is_ie_hardened()) { run_domtest(elem_test_str, test_elems); + run_domtest(elem_test2_str, test_elems2); + run_domtest(noscript_str, test_noscript); }else { skip("IE running in Enhanced Security Configuration\n"); } - run_domtest(elem_test2_str, test_elems2); run_domtest(doc_blank, test_create_elems); run_domtest(doc_blank, test_defaults); run_domtest(doc_blank, test_null_write); + run_domtest(emptydiv_str, test_create_stylesheet); run_domtest(indent_test_str, test_indent); run_domtest(cond_comment_str, test_cond_comment); run_domtest(frameset_str, test_frameset); + run_domtest(emptydiv_str, test_docfrag); + run_domtest(doc_blank, test_replacechild_elems); + run_domtest(doctype_str, test_doctype); CoUninitialize(); } diff --git a/rostests/winetests/mshtml/events.c b/rostests/winetests/mshtml/events.c index deafd54180c..142a7841810 100644 --- a/rostests/winetests/mshtml/events.c +++ b/rostests/winetests/mshtml/events.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2009 Jacek Caban for CodeWeavers + * Copyright 2008-2011 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 @@ -20,17 +20,17 @@ #define CONST_VTABLE #include -#include -#include +//#include +//#include -#include "windef.h" -#include "winbase.h" -#include "ole2.h" -#include "mshtml.h" -#include "mshtmdid.h" -#include "docobj.h" -#include "hlink.h" -#include "dispex.h" +//#include "windef.h" +//#include "winbase.h" +//#include "ole2.h" +#include +#include +#include +#include +//#include "dispex.h" #define DEFINE_EXPECT(func) \ static BOOL expect_ ## func = FALSE, called_ ## func = FALSE @@ -59,16 +59,30 @@ DEFINE_EXPECT(document_onclick); DEFINE_EXPECT(body_onclick); +DEFINE_EXPECT(doc_onclick_attached); DEFINE_EXPECT(div_onclick); DEFINE_EXPECT(div_onclick_attached); DEFINE_EXPECT(timeout); DEFINE_EXPECT(doccp_onclick); +DEFINE_EXPECT(doccp_onclick_cancel); DEFINE_EXPECT(div_onclick_disp); +DEFINE_EXPECT(invoke_onclick); DEFINE_EXPECT(iframe_onreadystatechange_loading); DEFINE_EXPECT(iframe_onreadystatechange_interactive); DEFINE_EXPECT(iframe_onreadystatechange_complete); DEFINE_EXPECT(iframedoc_onreadystatechange); DEFINE_EXPECT(img_onload); +DEFINE_EXPECT(img_onerror); +DEFINE_EXPECT(input_onfocus); +DEFINE_EXPECT(input_onblur); +DEFINE_EXPECT(form_onsubmit); +DEFINE_EXPECT(form_onclick); +DEFINE_EXPECT(submit_onclick); +DEFINE_EXPECT(submit_onclick_cancel); +DEFINE_EXPECT(submit_onclick_attached); +DEFINE_EXPECT(submit_onclick_attached_check_cancel); +DEFINE_EXPECT(submit_onclick_setret); +DEFINE_EXPECT(elem2_cp_onclick); static HWND container_hwnd = NULL; static IHTMLWindow2 *window; @@ -99,6 +113,18 @@ static const char readystate_doc_str[] = static const char img_doc_str[] = ""; +static const char input_doc_str[] = + ""; + +static const char iframe_doc_str[] = + ""; + +static const char form_doc_str[] = + "" + "" + "" + ""; + static const char *debugstr_guid(REFIID riid) { static char buf[50]; @@ -406,6 +432,7 @@ static void _test_event_shiftkey(unsigned line, IHTMLEventObj *event, VARIANT_BO ok_(__FILE__,line)(b == exval, "shiftKey = %x, expected %x\n", b, exval); } +#define test_event_cancelbubble(a,b) _test_event_cancelbubble(__LINE__,a,b) static void _test_event_cancelbubble(unsigned line, IHTMLEventObj *event, VARIANT_BOOL exval) { VARIANT_BOOL b; @@ -625,6 +652,7 @@ static void _test_event_obj(unsigned line, const char *type, const xy_test_t *xy _test_event_screenx(line, event, -10); _test_event_screeny(line, event, -10); + V_VT(&v) = VT_NULL; hres = IHTMLEventObj_get_returnValue(event, &v); ok_(__FILE__,line)(hres == S_OK, "get_returnValue failed: %08x\n", hres); ok_(__FILE__,line)(V_VT(&v) == VT_EMPTY, "V_VT(returnValue) = %d\n", V_VT(&v)); @@ -662,6 +690,36 @@ static void _elem_detach_event(unsigned line, IUnknown *unk, const char *namea, ok_(__FILE__,line)(hres == S_OK, "detachEvent failed: %08x\n", hres); } +#define doc_attach_event(a,b,c) _doc_attach_event(__LINE__,a,b,c) +static void _doc_attach_event(unsigned line, IHTMLDocument2 *doc, const char *namea, IDispatch *disp) +{ + IHTMLDocument3 *doc3 = _get_doc3_iface(line, (IUnknown*)doc); + VARIANT_BOOL res; + BSTR name; + HRESULT hres; + + name = a2bstr(namea); + hres = IHTMLDocument3_attachEvent(doc3, name, disp, &res); + IHTMLDocument3_Release(doc3); + SysFreeString(name); + ok_(__FILE__,line)(hres == S_OK, "attachEvent failed: %08x\n", hres); + ok_(__FILE__,line)(res == VARIANT_TRUE, "attachEvent returned %x\n", res); +} + +#define doc_detach_event(a,b,c) _doc_detach_event(__LINE__,a,b,c) +static void _doc_detach_event(unsigned line, IHTMLDocument2 *doc, const char *namea, IDispatch *disp) +{ + IHTMLDocument3 *doc3 = _get_doc3_iface(line, (IUnknown*)doc); + BSTR name; + HRESULT hres; + + name = a2bstr(namea); + hres = IHTMLDocument3_detachEvent(doc3, name, disp); + IHTMLDocument3_Release(doc3); + SysFreeString(name); + ok_(__FILE__,line)(hres == S_OK, "detachEvent failed: %08x\n", hres); +} + static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) { *ppv = NULL; @@ -841,6 +899,18 @@ static HRESULT WINAPI div_onclick_attached(IDispatchEx *iface, DISPID id, LCID l EVENT_HANDLER_FUNC_OBJ(div_onclick_attached); +static HRESULT WINAPI doc_onclick_attached(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + CHECK_EXPECT(doc_onclick_attached); + + test_attached_event_args(id, wFlags, pdp, pvarRes, pei); + test_event_src("DIV"); + return S_OK; +} + +EVENT_HANDLER_FUNC_OBJ(doc_onclick_attached); + static HRESULT WINAPI body_onclick(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { @@ -863,6 +933,167 @@ static HRESULT WINAPI img_onload(IDispatchEx *iface, DISPID id, LCID lcid, WORD EVENT_HANDLER_FUNC_OBJ(img_onload); +static HRESULT WINAPI img_onerror(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + CHECK_EXPECT(img_onerror); + test_event_args(&DIID_DispHTMLImg, id, wFlags, pdp, pvarRes, pei, pspCaller); + test_event_src("IMG"); + return S_OK; +} + +EVENT_HANDLER_FUNC_OBJ(img_onerror); + +static HRESULT WINAPI input_onfocus(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + CHECK_EXPECT(input_onfocus); + test_event_args(&DIID_DispHTMLInputElement, id, wFlags, pdp, pvarRes, pei, pspCaller); + test_event_src("INPUT"); + return S_OK; +} + +EVENT_HANDLER_FUNC_OBJ(input_onfocus); + +static HRESULT WINAPI input_onblur(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + CHECK_EXPECT(input_onblur); + test_event_args(&DIID_DispHTMLInputElement, id, wFlags, pdp, pvarRes, pei, pspCaller); + test_event_src("INPUT"); + return S_OK; +} + +EVENT_HANDLER_FUNC_OBJ(input_onblur); + +static HRESULT WINAPI form_onsubmit(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + CHECK_EXPECT(form_onsubmit); + test_event_args(NULL, id, wFlags, pdp, pvarRes, pei, pspCaller); + test_event_src("FORM"); + + V_VT(pvarRes) = VT_BOOL; + V_BOOL(pvarRes) = VARIANT_FALSE; + return S_OK; +} + +EVENT_HANDLER_FUNC_OBJ(form_onsubmit); + +static HRESULT WINAPI form_onclick(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + CHECK_EXPECT(form_onclick); + test_event_args(NULL, id, wFlags, pdp, pvarRes, pei, pspCaller); + + return S_OK; +} + +EVENT_HANDLER_FUNC_OBJ(form_onclick); + +static HRESULT WINAPI submit_onclick(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + CHECK_EXPECT(submit_onclick); + test_event_args(NULL, id, wFlags, pdp, pvarRes, pei, pspCaller); + test_event_src("INPUT"); + + V_VT(pvarRes) = VT_BOOL; + V_BOOL(pvarRes) = VARIANT_FALSE; + return S_OK; +} + +EVENT_HANDLER_FUNC_OBJ(submit_onclick); + +static HRESULT WINAPI submit_onclick_attached(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + CHECK_EXPECT(submit_onclick_attached); + test_attached_event_args(id, wFlags, pdp, pvarRes, pei); + test_event_src("INPUT"); + + V_VT(pvarRes) = VT_BOOL; + V_BOOL(pvarRes) = VARIANT_FALSE; + return S_OK; +} + +EVENT_HANDLER_FUNC_OBJ(submit_onclick_attached); + +static HRESULT WINAPI submit_onclick_attached_check_cancel(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + IHTMLEventObj *event; + HRESULT hres; + + CHECK_EXPECT(submit_onclick_attached_check_cancel); + test_attached_event_args(id, wFlags, pdp, pvarRes, pei); + test_event_src("INPUT"); + + event = NULL; + hres = IHTMLWindow2_get_event(window, &event); + ok(hres == S_OK, "get_event failed: %08x\n", hres); + ok(event != NULL, "event == NULL\n"); + + test_event_cancelbubble(event, VARIANT_TRUE); + return S_OK; +} + +EVENT_HANDLER_FUNC_OBJ(submit_onclick_attached_check_cancel); + +static VARIANT onclick_retval, onclick_event_retval; + +static HRESULT WINAPI submit_onclick_setret(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + IHTMLEventObj *event; + HRESULT hres; + + CHECK_EXPECT(submit_onclick_setret); + test_event_args(NULL, id, wFlags, pdp, pvarRes, pei, pspCaller); + test_event_src("INPUT"); + + event = NULL; + hres = IHTMLWindow2_get_event(window, &event); + ok(hres == S_OK, "get_event failed: %08x\n", hres); + ok(event != NULL, "event == NULL\n"); + + hres = IHTMLEventObj_put_returnValue(event, onclick_event_retval); + ok(hres == S_OK, "put_returnValue failed: %08x\n", hres); + IHTMLEventObj_Release(event); + + *pvarRes = onclick_retval; + return S_OK; +} + +EVENT_HANDLER_FUNC_OBJ(submit_onclick_setret); + +static HRESULT WINAPI submit_onclick_cancel(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + IHTMLEventObj *event; + HRESULT hres; + + CHECK_EXPECT(submit_onclick_cancel); + test_event_args(NULL, id, wFlags, pdp, pvarRes, pei, pspCaller); + test_event_src("INPUT"); + + event = NULL; + hres = IHTMLWindow2_get_event(window, &event); + ok(hres == S_OK, "get_event failed: %08x\n", hres); + ok(event != NULL, "event == NULL\n"); + + test_event_cancelbubble(event, VARIANT_FALSE); + + hres = IHTMLEventObj_put_cancelBubble(event, VARIANT_TRUE); + ok(hres == S_OK, "put_returnValue failed: %08x\n", hres); + IHTMLEventObj_Release(event); + + test_event_cancelbubble(event, VARIANT_TRUE); + return S_OK; +} + +EVENT_HANDLER_FUNC_OBJ(submit_onclick_cancel); + static HRESULT WINAPI iframedoc_onreadystatechange(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { @@ -912,7 +1143,6 @@ static HRESULT WINAPI iframe_onreadystatechange(IDispatchEx *iface, DISPID id, L str = NULL; hres = IHTMLFrameBase2_get_readyState(iframe, &str); - IHTMLFrameBase2_Release(iframe); ok(hres == S_OK, "get_readyState failed: %08x\n", hres); ok(str != NULL, "readyState == NULL\n"); ok(!lstrcmpW(str, V_BSTR(&v)), "ready states differ\n"); @@ -926,6 +1156,7 @@ static HRESULT WINAPI iframe_onreadystatechange(IDispatchEx *iface, DISPID id, L ok(hres == S_OK, "get_document failed: %08x\n", hres); hres = IHTMLDocument2_get_readyState(iframe_doc, &str2); + ok(hres == S_OK, "get_document failed: %08x\n", hres); ok(!lstrcmpW(str, str2), "unexpected document readyState %s\n", wine_dbgstr_w(str2)); SysFreeString(str2); @@ -943,6 +1174,7 @@ static HRESULT WINAPI iframe_onreadystatechange(IDispatchEx *iface, DISPID id, L else ok(0, "unexpected state %s\n", wine_dbgstr_w(str)); + SysFreeString(str); IHTMLDocument2_Release(iframe_doc); IHTMLFrameBase2_Release(iframe); return S_OK; @@ -1008,6 +1240,31 @@ static void _test_cp_args(unsigned line, REFIID riid, WORD flags, DISPPARAMS *dp ok_(__FILE__,line)(argerr != NULL, "argerr == NULL\n"); } +#define test_cp_eventarg(a,b,c,d,e,f) _test_cp_eventarg(__LINE__,a,b,c,d,e,f) +static void _test_cp_eventarg(unsigned line, REFIID riid, WORD flags, DISPPARAMS *dp, VARIANT *vres, EXCEPINFO *ei, UINT *argerr) +{ + IHTMLEventObj *event; + + ok_(__FILE__,line)(IsEqualGUID(&IID_NULL, riid), "riid = %s\n", debugstr_guid(riid)); + ok_(__FILE__,line)(flags == DISPATCH_METHOD, "flags = %x\n", flags); + ok_(__FILE__,line)(dp != NULL, "dp == NULL\n"); + ok_(__FILE__,line)(dp->cArgs == 1, "dp->cArgs = %d\n", dp->cArgs); + ok_(__FILE__,line)(dp->rgvarg != NULL, "dp->rgvarg = %p\n", dp->rgvarg); + ok_(__FILE__,line)(!dp->cNamedArgs, "dp->cNamedArgs = %d\n", dp->cNamedArgs); + ok_(__FILE__,line)(!dp->rgdispidNamedArgs, "dp->rgdispidNamedArgs = %p\n", dp->rgdispidNamedArgs); + ok_(__FILE__,line)(vres != NULL, "vres == NULL\n"); + ok_(__FILE__,line)(V_VT(vres) == VT_EMPTY, "V_VT(vres) = %d\n", V_VT(vres)); + ok_(__FILE__,line)(ei != NULL, "ei == NULL\n"); + ok_(__FILE__,line)(argerr != NULL, "argerr == NULL\n"); + + ok(V_VT(dp->rgvarg) == VT_DISPATCH, "V_VT(dp->rgvarg) = %d\n", V_VT(dp->rgvarg)); + ok(V_DISPATCH(dp->rgvarg) != NULL, "V_DISPATCH(dp->rgvarg) = %p\n", V_DISPATCH(dp->rgvarg)); + + event = _get_event_obj(line); + ok(iface_cmp((IUnknown*)event, (IUnknown*)V_DISPATCH(dp->rgvarg)), "event != arg0\n"); + IHTMLEventObj_Release(event); +} + static HRESULT WINAPI doccp(IDispatchEx *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pVarResult, EXCEPINFO *pei, UINT *puArgErr) @@ -1027,6 +1284,44 @@ static HRESULT WINAPI doccp(IDispatchEx *iface, DISPID dispIdMember, CONNECTION_POINT_OBJ(doccp, DIID_HTMLDocumentEvents); +static HRESULT WINAPI doccp_onclick_cancel(IDispatchEx *iface, DISPID dispIdMember, + REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pVarResult, EXCEPINFO *pei, UINT *puArgErr) +{ + switch(dispIdMember) { + case DISPID_HTMLDOCUMENTEVENTS_ONCLICK: + CHECK_EXPECT(doccp_onclick_cancel); + test_cp_args(riid, wFlags, pdp, pVarResult, pei, puArgErr); + V_VT(pVarResult) = VT_BOOL; + V_BOOL(pVarResult) = VARIANT_FALSE; + break; + default: + ok(0, "unexpected call %d\n", dispIdMember); + return E_NOTIMPL; + } + + return S_OK; +} + +CONNECTION_POINT_OBJ(doccp_onclick_cancel, DIID_HTMLDocumentEvents); + +static HRESULT WINAPI elem2_cp(IDispatchEx *iface, DISPID dispIdMember, REFIID riid, LCID lcid, + WORD wFlags, DISPPARAMS *pdp, VARIANT *pVarResult, EXCEPINFO *pei, UINT *puArgErr) +{ + switch(dispIdMember) { + case DISPID_HTMLDOCUMENTEVENTS_ONCLICK: + CHECK_EXPECT(elem2_cp_onclick); + test_cp_eventarg(riid, wFlags, pdp, pVarResult, pei, puArgErr); + break; + default: + ok(0, "unexpected call %d\n", dispIdMember); + return E_NOTIMPL; + } + + return S_OK; +} + +CONNECTION_POINT_OBJ(elem2_cp, DIID_HTMLElementEvents2); + static HRESULT WINAPI timeoutFunc_Invoke(IDispatchEx *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) @@ -1050,7 +1345,7 @@ static HRESULT WINAPI timeoutFunc_Invoke(IDispatchEx *iface, DISPID dispIdMember return S_OK; } -static IDispatchExVtbl timeoutFuncVtbl = { +static const IDispatchExVtbl timeoutFuncVtbl = { DispatchEx_QueryInterface, DispatchEx_AddRef, DispatchEx_Release, @@ -1084,7 +1379,7 @@ static HRESULT WINAPI div_onclick_disp_Invoke(IDispatchEx *iface, DISPID id, return S_OK; } -static IDispatchExVtbl div_onclick_dispVtbl = { +static const IDispatchExVtbl div_onclick_dispVtbl = { Dispatch_QueryInterface, DispatchEx_AddRef, DispatchEx_Release, @@ -1099,9 +1394,17 @@ static IDispatchEx div_onclick_disp = { &div_onclick_dispVtbl }; static void pump_msgs(BOOL *b) { MSG msg; - while(!*b && GetMessage(&msg, NULL, 0, 0)) { - TranslateMessage(&msg); - DispatchMessage(&msg); + + if(b) { + while(!*b && GetMessageW(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + }else { + while(!b && PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } } } @@ -1146,13 +1449,100 @@ static void unregister_cp(IUnknown *unk, REFIID riid, DWORD cookie) ok(hres == S_OK, "Unadvise failed: %08x\n", hres); } +static HRESULT WINAPI EventDispatch_QueryInterface(IDispatch *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IDispatch, riid)) { + *ppv = iface; + return S_OK; + } + + ok(0, "Unexpected call\n"); + return E_NOINTERFACE; +} + +static DWORD WINAPI EventDispatch_AddRef(IDispatch *iface) +{ + return 2; +} + +static DWORD WINAPI EventDispatch_Release(IDispatch *iface) +{ + return 1; +} + +static HRESULT WINAPI EventDispatch_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo) +{ + ok(0, "Unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI EventDispatch_GetTypeInfo(IDispatch *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) +{ + ok(0, "Unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI EventDispatch_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *rgszNames, + UINT cNames, LCID lcid, DISPID *rgDispId) +{ + ok(0, "Unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI EventDispatch_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 = %s\n", debugstr_guid(riid)); + ok(pDispParams != NULL, "pDispParams == NULL\n"); + ok(pExcepInfo != NULL, "pExcepInfo == NULL\n"); + ok(puArgErr != NULL, "puArgErr == NULL\n"); + ok(V_VT(pVarResult) == 0, "V_VT(pVarResult) = %d\n", V_VT(pVarResult)); + ok(wFlags == DISPATCH_METHOD, "wFlags = %d\n", wFlags); + + switch(dispIdMember) { + case DISPID_HTMLDOCUMENTEVENTS_ONCLICK: + CHECK_EXPECT2(invoke_onclick); + break; + case DISPID_HTMLDOCUMENTEVENTS2_ONPROPERTYCHANGE: + case DISPID_HTMLDOCUMENTEVENTS2_ONREADYSTATECHANGE: + case 1027: + case 1034: + case 1037: + case 1044: + case 1045: + case 1047: + case 1048: + case 1049: + break; /* TODO */ + default: + ok(0, "Unexpected call: %d\n", dispIdMember); + } + + return S_OK; +} + +static const IDispatchVtbl EventDispatchVtbl = { + EventDispatch_QueryInterface, + EventDispatch_AddRef, + EventDispatch_Release, + EventDispatch_GetTypeInfoCount, + EventDispatch_GetTypeInfo, + EventDispatch_GetIDsOfNames, + EventDispatch_Invoke +}; + +static IDispatch EventDispatch = { &EventDispatchVtbl }; + static void test_onclick(IHTMLDocument2 *doc) { + DWORD cp_cookie, elem2_cp_cookie; IHTMLElement *div, *body; - DWORD cp_cookie; VARIANT v; HRESULT hres; + register_cp((IUnknown*)doc, &IID_IDispatch, (IUnknown*)&EventDispatch); + div = get_elem_id(doc, "clickdiv"); elem_attach_event((IUnknown*)div, "abcde", (IDispatch*)&nocall_obj); @@ -1167,6 +1557,20 @@ static void test_onclick(IHTMLDocument2 *doc) hres = IHTMLElement_put_onclick(div, v); ok(hres == E_NOTIMPL, "put_onclick failed: %08x\n", hres); + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("function();"); + hres = IHTMLElement_put_onclick(div, v); + todo_wine ok(hres == S_OK, "put_onclick failed: %08x\n", hres); + + if(hres == S_OK) { + V_VT(&v) = VT_EMPTY; + hres = IHTMLElement_get_onclick(div, &v); + ok(hres == S_OK, "get_onclick failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(onclick) = %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "function();"), "V_BSTR(onclick) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + } + VariantClear(&v); + V_VT(&v) = VT_DISPATCH; V_DISPATCH(&v) = (IDispatch*)&div_onclick_obj; hres = IHTMLElement_put_onclick(div, v); @@ -1212,11 +1616,13 @@ static void test_onclick(IHTMLDocument2 *doc) SET_EXPECT(div_onclick_attached); SET_EXPECT(body_onclick); SET_EXPECT(document_onclick); + SET_EXPECT(invoke_onclick); pump_msgs(&called_document_onclick); CHECK_CALLED(div_onclick); CHECK_CALLED(div_onclick_attached); CHECK_CALLED(body_onclick); CHECK_CALLED(document_onclick); + CHECK_CALLED(invoke_onclick); } xy_todo = TRUE; @@ -1225,6 +1631,7 @@ static void test_onclick(IHTMLDocument2 *doc) SET_EXPECT(div_onclick_attached); SET_EXPECT(body_onclick); SET_EXPECT(document_onclick); + SET_EXPECT(invoke_onclick); hres = IHTMLElement_click(div); ok(hres == S_OK, "click failed: %08x\n", hres); @@ -1233,11 +1640,13 @@ static void test_onclick(IHTMLDocument2 *doc) CHECK_CALLED(div_onclick_attached); CHECK_CALLED(body_onclick); CHECK_CALLED(document_onclick); + CHECK_CALLED(invoke_onclick); SET_EXPECT(div_onclick); SET_EXPECT(div_onclick_attached); SET_EXPECT(body_onclick); SET_EXPECT(document_onclick); + SET_EXPECT(invoke_onclick); V_VT(&v) = VT_EMPTY; elem_fire_event((IUnknown*)div, "onclick", &v); @@ -1246,16 +1655,20 @@ static void test_onclick(IHTMLDocument2 *doc) CHECK_CALLED(div_onclick_attached); CHECK_CALLED(body_onclick); CHECK_CALLED(document_onclick); + CHECK_CALLED(invoke_onclick); cp_cookie = register_cp((IUnknown*)doc, &DIID_HTMLDocumentEvents, (IUnknown*)&doccp_obj); elem_attach_event((IUnknown*)div, "onclick", (IDispatch*)&div_onclick_disp); + doc_attach_event(doc, "onclick", (IDispatch*)&doc_onclick_attached_obj); SET_EXPECT(div_onclick); SET_EXPECT(div_onclick_disp); SET_EXPECT(div_onclick_attached); SET_EXPECT(body_onclick); SET_EXPECT(document_onclick); + SET_EXPECT(doc_onclick_attached); SET_EXPECT(doccp_onclick); + SET_EXPECT(invoke_onclick); hres = IHTMLElement_click(div); ok(hres == S_OK, "click failed: %08x\n", hres); @@ -1265,8 +1678,38 @@ static void test_onclick(IHTMLDocument2 *doc) CHECK_CALLED(div_onclick_attached); CHECK_CALLED(body_onclick); CHECK_CALLED(document_onclick); + CHECK_CALLED(doc_onclick_attached); CHECK_CALLED(doccp_onclick); + CHECK_CALLED(invoke_onclick); + elem2_cp_cookie = register_cp((IUnknown*)div, &DIID_HTMLElementEvents2, (IUnknown*)&elem2_cp_obj); + + SET_EXPECT(div_onclick); + SET_EXPECT(div_onclick_disp); + SET_EXPECT(div_onclick_attached); + SET_EXPECT(elem2_cp_onclick); + SET_EXPECT(body_onclick); + SET_EXPECT(document_onclick); + SET_EXPECT(doc_onclick_attached); + SET_EXPECT(doccp_onclick); + SET_EXPECT(invoke_onclick); + + trace("click >>>\n"); + hres = IHTMLElement_click(div); + ok(hres == S_OK, "click failed: %08x\n", hres); + trace("click <<<\n"); + + CHECK_CALLED(div_onclick); + CHECK_CALLED(div_onclick_disp); + CHECK_CALLED(div_onclick_attached); + CHECK_CALLED(elem2_cp_onclick); + CHECK_CALLED(body_onclick); + CHECK_CALLED(document_onclick); + CHECK_CALLED(doc_onclick_attached); + CHECK_CALLED(doccp_onclick); + CHECK_CALLED(invoke_onclick); + + unregister_cp((IUnknown*)div, &DIID_HTMLElementEvents2, elem2_cp_cookie); unregister_cp((IUnknown*)doc, &DIID_HTMLDocumentEvents, cp_cookie); V_VT(&v) = VT_NULL; @@ -1280,10 +1723,12 @@ static void test_onclick(IHTMLDocument2 *doc) elem_detach_event((IUnknown*)div, "onclick", (IDispatch*)&div_onclick_disp); elem_detach_event((IUnknown*)div, "onclick", (IDispatch*)&div_onclick_disp); elem_detach_event((IUnknown*)div, "test", (IDispatch*)&div_onclick_disp); + doc_detach_event(doc, "onclick", (IDispatch*)&doc_onclick_attached_obj); SET_EXPECT(div_onclick_attached); SET_EXPECT(body_onclick); SET_EXPECT(document_onclick); + SET_EXPECT(invoke_onclick); hres = IHTMLElement_click(div); ok(hres == S_OK, "click failed: %08x\n", hres); @@ -1291,6 +1736,7 @@ static void test_onclick(IHTMLDocument2 *doc) CHECK_CALLED(div_onclick_attached); CHECK_CALLED(body_onclick); CHECK_CALLED(document_onclick); + CHECK_CALLED(invoke_onclick); IHTMLElement_Release(div); IHTMLElement_Release(body); @@ -1376,6 +1822,18 @@ static void test_imgload(IHTMLDocument2 *doc) ok(V_DISPATCH(&v) == (IDispatch*)&img_onload_obj, "V_DISPATCH(onload) != onloadkFunc\n"); VariantClear(&v); + V_VT(&v) = VT_DISPATCH; + V_DISPATCH(&v) = (IDispatch*)&img_onerror_obj; + hres = IHTMLImgElement_put_onerror(img, v); + ok(hres == S_OK, "put_onerror failed: %08x\n", hres); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLImgElement_get_onerror(img, &v); + ok(hres == S_OK, "get_onerror failed: %08x\n", hres); + ok(V_VT(&v) == VT_DISPATCH, "V_VT(onerror) = %d\n", V_VT(&v)); + ok(V_DISPATCH(&v) == (IDispatch*)&img_onerror_obj, "V_DISPATCH(onerror) != onerrorFunc\n"); + VariantClear(&v); + str = a2bstr("http://www.winehq.org/images/winehq_logo_text.png"); hres = IHTMLImgElement_put_src(img, str); ok(hres == S_OK, "put_src failed: %08x\n", hres); @@ -1385,9 +1843,236 @@ static void test_imgload(IHTMLDocument2 *doc) pump_msgs(&called_img_onload); CHECK_CALLED(img_onload); + SET_EXPECT(img_onerror); + + str = a2bstr("about:blank"); + hres = IHTMLImgElement_put_src(img, str); + ok(hres == S_OK, "put_src failed: %08x\n", hres); + SysFreeString(str); + + pump_msgs(&called_img_onerror); /* FIXME: should not be needed */ + + CHECK_CALLED(img_onerror); + IHTMLImgElement_Release(img); } +static void test_focus(IHTMLDocument2 *doc) +{ + IHTMLElement2 *elem2; + IHTMLElement *elem; + VARIANT v; + HRESULT hres; + + elem = get_elem_id(doc, "inputid"); + elem2 = get_elem2_iface((IUnknown*)elem); + IHTMLElement_Release(elem); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLElement2_get_onfocus(elem2, &v); + ok(hres == S_OK, "get_onfocus failed: %08x\n", hres); + ok(V_VT(&v) == VT_NULL, "V_VT(onfocus) = %d\n", V_VT(&v)); + + V_VT(&v) = VT_DISPATCH; + V_DISPATCH(&v) = (IDispatch*)&input_onfocus_obj; + hres = IHTMLElement2_put_onfocus(elem2, v); + ok(hres == S_OK, "put_onfocus failed: %08x\n", hres); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLElement2_get_onfocus(elem2, &v); + ok(hres == S_OK, "get_onfocus failed: %08x\n", hres); + ok(V_VT(&v) == VT_DISPATCH, "V_VT(onfocus) = %d\n", V_VT(&v)); + ok(V_DISPATCH(&v) == (IDispatch*)&input_onfocus_obj, "V_DISPATCH(onfocus) != onfocusFunc\n"); + VariantClear(&v); + + if(!winetest_interactive) + ShowWindow(container_hwnd, SW_SHOW); + + SetFocus(NULL); + ok(!IsChild(container_hwnd, GetFocus()), "focus belongs to document window\n"); + + hres = IHTMLWindow2_focus(window); + ok(hres == S_OK, "focus failed: %08x\n", hres); + + ok(IsChild(container_hwnd, GetFocus()), "focus does not belong to document window\n"); + pump_msgs(NULL); + + SET_EXPECT(input_onfocus); + hres = IHTMLElement2_focus(elem2); + pump_msgs(NULL); + CHECK_CALLED(input_onfocus); + ok(hres == S_OK, "focus failed: %08x\n", hres); + + V_VT(&v) = VT_DISPATCH; + V_DISPATCH(&v) = (IDispatch*)&input_onblur_obj; + hres = IHTMLElement2_put_onblur(elem2, v); + ok(hres == S_OK, "put_onblur failed: %08x\n", hres); + + SET_EXPECT(input_onblur); + hres = IHTMLElement2_blur(elem2); + pump_msgs(NULL); + CHECK_CALLED(input_onblur); + ok(hres == S_OK, "blur failed: %08x\n", hres); + + if(!winetest_interactive) + ShowWindow(container_hwnd, SW_HIDE); + + IHTMLElement2_Release(elem2); +} + +static void test_submit(IHTMLDocument2 *doc) +{ + IHTMLElement *elem, *submit; + IHTMLFormElement *form; + VARIANT v; + DWORD cp_cookie; + HRESULT hres; + + elem = get_elem_id(doc, "formid"); + + V_VT(&v) = VT_DISPATCH; + V_DISPATCH(&v) = (IDispatch*)&form_onclick_obj; + hres = IHTMLElement_put_onclick(elem, v); + ok(hres == S_OK, "put_onclick failed: %08x\n", hres); + + hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLFormElement, (void**)&form); + IHTMLElement_Release(elem); + ok(hres == S_OK, "Could not get IHTMLFormElement iface: %08x\n", hres); + + V_VT(&v) = VT_DISPATCH; + V_DISPATCH(&v) = (IDispatch*)&form_onsubmit_obj; + hres = IHTMLFormElement_put_onsubmit(form, v); + ok(hres == S_OK, "put_onsubmit failed: %08x\n", hres); + + IHTMLFormElement_Release(form); + + submit = get_elem_id(doc, "submitid"); + + SET_EXPECT(form_onclick); + SET_EXPECT(form_onsubmit); + hres = IHTMLElement_click(submit); + ok(hres == S_OK, "click failed: %08x\n", hres); + CHECK_CALLED(form_onclick); + CHECK_CALLED(form_onsubmit); + + V_VT(&v) = VT_DISPATCH; + V_DISPATCH(&v) = (IDispatch*)&submit_onclick_obj; + hres = IHTMLElement_put_onclick(submit, v); + ok(hres == S_OK, "put_onclick failed: %08x\n", hres); + + SET_EXPECT(form_onclick); + SET_EXPECT(submit_onclick); + hres = IHTMLElement_click(submit); + ok(hres == S_OK, "click failed: %08x\n", hres); + CHECK_CALLED(form_onclick); + CHECK_CALLED(submit_onclick); + + elem_attach_event((IUnknown*)submit, "onclick", (IDispatch*)&submit_onclick_attached_obj); + + SET_EXPECT(form_onclick); + SET_EXPECT(submit_onclick); + SET_EXPECT(submit_onclick_attached); + hres = IHTMLElement_click(submit); + ok(hres == S_OK, "click failed: %08x\n", hres); + CHECK_CALLED(form_onclick); + CHECK_CALLED(submit_onclick); + CHECK_CALLED(submit_onclick_attached); + + V_VT(&v) = VT_NULL; + hres = IHTMLElement_put_onclick(submit, v); + ok(hres == S_OK, "put_onclick failed: %08x\n", hres); + + SET_EXPECT(form_onclick); + SET_EXPECT(submit_onclick_attached); + hres = IHTMLElement_click(submit); + ok(hres == S_OK, "click failed: %08x\n", hres); + CHECK_CALLED(form_onclick); + CHECK_CALLED(submit_onclick_attached); + + elem_detach_event((IUnknown*)submit, "onclick", (IDispatch*)&submit_onclick_attached_obj); + + cp_cookie = register_cp((IUnknown*)doc, &DIID_HTMLDocumentEvents, (IUnknown*)&doccp_onclick_cancel_obj); + + SET_EXPECT(form_onclick); + SET_EXPECT(doccp_onclick_cancel); + hres = IHTMLElement_click(submit); + ok(hres == S_OK, "click failed: %08x\n", hres); + CHECK_CALLED(form_onclick); + CHECK_CALLED(doccp_onclick_cancel); + + unregister_cp((IUnknown*)doc, &DIID_HTMLDocumentEvents, cp_cookie); + + V_VT(&v) = VT_DISPATCH; + V_DISPATCH(&v) = (IDispatch*)&submit_onclick_setret_obj; + hres = IHTMLElement_put_onclick(submit, v); + ok(hres == S_OK, "put_onclick failed: %08x\n", hres); + + V_VT(&onclick_retval) = VT_BOOL; + V_BOOL(&onclick_retval) = VARIANT_TRUE; + V_VT(&onclick_event_retval) = VT_BOOL; + V_BOOL(&onclick_event_retval) = VARIANT_TRUE; + + SET_EXPECT(submit_onclick_setret); + SET_EXPECT(form_onclick); + SET_EXPECT(form_onsubmit); + hres = IHTMLElement_click(submit); + ok(hres == S_OK, "click failed: %08x\n", hres); + CHECK_CALLED(submit_onclick_setret); + CHECK_CALLED(form_onclick); + CHECK_CALLED(form_onsubmit); + + V_VT(&onclick_event_retval) = VT_BOOL; + V_BOOL(&onclick_event_retval) = VARIANT_FALSE; + + SET_EXPECT(submit_onclick_setret); + SET_EXPECT(form_onclick); + hres = IHTMLElement_click(submit); + ok(hres == S_OK, "click failed: %08x\n", hres); + CHECK_CALLED(submit_onclick_setret); + CHECK_CALLED(form_onclick); + + V_VT(&onclick_retval) = VT_BOOL; + V_BOOL(&onclick_retval) = VARIANT_FALSE; + V_VT(&onclick_event_retval) = VT_BOOL; + V_BOOL(&onclick_event_retval) = VARIANT_TRUE; + + SET_EXPECT(submit_onclick_setret); + SET_EXPECT(form_onclick); + hres = IHTMLElement_click(submit); + ok(hres == S_OK, "click failed: %08x\n", hres); + CHECK_CALLED(submit_onclick_setret); + CHECK_CALLED(form_onclick); + + V_VT(&onclick_event_retval) = VT_BOOL; + V_BOOL(&onclick_event_retval) = VARIANT_FALSE; + + SET_EXPECT(submit_onclick_setret); + SET_EXPECT(form_onclick); + hres = IHTMLElement_click(submit); + ok(hres == S_OK, "click failed: %08x\n", hres); + CHECK_CALLED(submit_onclick_setret); + CHECK_CALLED(form_onclick); + + elem_attach_event((IUnknown*)submit, "onclick", (IDispatch*)&submit_onclick_attached_obj); + elem_attach_event((IUnknown*)submit, "onclick", (IDispatch*)&submit_onclick_attached_check_cancel_obj); + + V_VT(&v) = VT_DISPATCH; + V_DISPATCH(&v) = (IDispatch*)&submit_onclick_cancel_obj; + hres = IHTMLElement_put_onclick(submit, v); + ok(hres == S_OK, "put_onclick failed: %08x\n", hres); + + SET_EXPECT(submit_onclick_cancel); + SET_EXPECT(submit_onclick_attached_check_cancel); + SET_EXPECT(submit_onclick_attached); + hres = IHTMLElement_click(submit); + ok(hres == S_OK, "click failed: %08x\n", hres); + CHECK_CALLED(submit_onclick_cancel); + CHECK_CALLED(submit_onclick_attached_check_cancel); + CHECK_CALLED(submit_onclick_attached); + + IHTMLElement_Release(submit); +} + static void test_timeout(IHTMLDocument2 *doc) { IHTMLWindow3 *win3; @@ -1424,6 +2109,77 @@ static void test_timeout(IHTMLDocument2 *doc) IHTMLWindow3_Release(win3); } +static IHTMLElement* find_element_by_id(IHTMLDocument2 *doc, const char *id) +{ + HRESULT hres; + IHTMLDocument3 *doc3; + IHTMLElement *result; + BSTR idW = a2bstr(id); + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3); + ok(hres == S_OK, "QueryInterface(IID_IHTMLDocument3) failed: %08x\n", hres); + + hres = IHTMLDocument3_getElementById(doc3, idW, &result); + ok(hres == S_OK, "getElementById failed: %08x\n", hres); + ok(result != NULL, "result == NULL\n"); + SysFreeString(idW); + + IHTMLDocument3_Release(doc3); + return result; +} + +static IHTMLDocument2* get_iframe_doc(IHTMLIFrameElement *iframe) +{ + HRESULT hres; + IHTMLFrameBase2 *base; + IHTMLDocument2 *result = NULL; + + hres = IHTMLIFrameElement_QueryInterface(iframe, &IID_IHTMLFrameBase2, (void**)&base); + ok(hres == S_OK, "QueryInterface(IID_IHTMLFrameBase2) failed: %08x\n", hres); + if(hres == S_OK) { + IHTMLWindow2 *window; + + hres = IHTMLFrameBase2_get_contentWindow(base, &window); + ok(hres == S_OK, "get_contentWindow failed: %08x\n", hres); + ok(window != NULL, "window == NULL\n"); + if(window) { + hres = IHTMLWindow2_get_document(window, &result); + ok(hres == S_OK, "get_document failed: %08x\n", hres); + ok(result != NULL, "result == NULL\n"); + IHTMLWindow2_Release(window); + } + } + if(base) IHTMLFrameBase2_Release(base); + + return result; +} + +static void test_iframe_connections(IHTMLDocument2 *doc) +{ + HRESULT hres; + IHTMLIFrameElement *iframe; + IHTMLDocument2 *iframes_doc; + DWORD cookie; + IConnectionPoint *cp; + IHTMLElement *element = find_element_by_id(doc, "ifr"); + + hres = IHTMLElement_QueryInterface(element, &IID_IHTMLIFrameElement, (void**)&iframe); + IHTMLElement_Release(element); + ok(hres == S_OK, "QueryInterface(IID_IHTMLIFrameElement) failed: %08x\n", hres); + + iframes_doc = get_iframe_doc(iframe); + IHTMLIFrameElement_Release(iframe); + + cookie = register_cp((IUnknown*)iframes_doc, &IID_IDispatch, (IUnknown*)&div_onclick_disp); + + cp = get_cp((IUnknown*)doc, &IID_IDispatch); + hres = IConnectionPoint_Unadvise(cp, cookie); + IConnectionPoint_Release(cp); + ok(hres == CONNECT_E_NOCONNECTION, "Unadvise returned %08x, expected CONNECT_E_NOCONNECTION\n", hres); + + IHTMLDocument2_Release(iframes_doc); +} + static HRESULT QueryInterface(REFIID,void**); static HRESULT WINAPI InPlaceFrame_QueryInterface(IOleInPlaceFrame *iface, REFIID riid, void **ppv) @@ -1602,7 +2358,7 @@ static HRESULT WINAPI InPlaceSite_GetWindowContext(IOleInPlaceSite *iface, *lprcPosRect = rect; *lprcClipRect = rect; - lpFrameInfo->cb = sizeof(*lpFrameInfo); + ok(lpFrameInfo->cb == sizeof(*lpFrameInfo), "lpFrameInfo->cb = %u, expected %u\n", lpFrameInfo->cb, (unsigned)sizeof(*lpFrameInfo)); lpFrameInfo->fMDIApp = FALSE; lpFrameInfo->hwndFrame = container_hwnd; lpFrameInfo->haccel = NULL; @@ -1841,7 +2597,7 @@ static HRESULT WINAPI PropertyNotifySink_OnRequestEdit(IPropertyNotifySink *ifac return E_NOTIMPL; } -static IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = { +static const IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = { PropertyNotifySink_QueryInterface, PropertyNotifySink_AddRef, PropertyNotifySink_Release, @@ -2016,6 +2772,36 @@ static HWND create_container_window(void) 300, 300, NULL, NULL, NULL, NULL); } +static void test_empty_document(void) +{ + HRESULT hres; + IHTMLWindow2 *window; + IHTMLDocument2 *windows_doc, *doc; + IConnectionPoint *cp; + DWORD cookie; + + doc = create_document(); + if(!doc) + return; + + hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08x\n", hres); + + hres = IHTMLWindow2_get_document(window, &windows_doc); + IHTMLWindow2_Release(window); + ok(hres == S_OK, "get_document failed: %08x\n", hres); + + cookie = register_cp((IUnknown*)windows_doc, &IID_IDispatch, (IUnknown*)&div_onclick_disp); + + cp = get_cp((IUnknown*)doc, &IID_IDispatch); + hres = IConnectionPoint_Unadvise(cp, cookie); + IConnectionPoint_Release(cp); + ok(hres == S_OK, "Unadvise failed: %08x\n", hres); + + IHTMLDocument2_Release(windows_doc); + IHTMLDocument2_Release(doc); +} + START_TEST(events) { CoInitialize(NULL); @@ -2028,6 +2814,11 @@ START_TEST(events) run_test(click_doc_str, test_onclick); run_test(readystate_doc_str, test_onreadystatechange); run_test(img_doc_str, test_imgload); + run_test(input_doc_str, test_focus); + run_test(form_doc_str, test_submit); + run_test(iframe_doc_str, test_iframe_connections); + + test_empty_document(); DestroyWindow(container_hwnd); CoUninitialize(); diff --git a/rostests/winetests/mshtml/events.html b/rostests/winetests/mshtml/events.html new file mode 100644 index 00000000000..131ba19cfda --- /dev/null +++ b/rostests/winetests/mshtml/events.html @@ -0,0 +1,150 @@ + + + + + +
+
+ + + + + diff --git a/rostests/winetests/mshtml/exectest.html b/rostests/winetests/mshtml/exectest.html new file mode 100644 index 00000000000..ca06e3c3a2a --- /dev/null +++ b/rostests/winetests/mshtml/exectest.html @@ -0,0 +1,139 @@ + + +Script execution test +
+
+
+ + + + +
+
+
+ + diff --git a/rostests/winetests/mshtml/externscr.js b/rostests/winetests/mshtml/externscr.js new file mode 100644 index 00000000000..5861363a5b1 --- /dev/null +++ b/rostests/winetests/mshtml/externscr.js @@ -0,0 +1 @@ +extern_cnt++; diff --git a/rostests/winetests/mshtml/htmldoc.c b/rostests/winetests/mshtml/htmldoc.c index 65451b1793a..9b93dfc4152 100644 --- a/rostests/winetests/mshtml/htmldoc.c +++ b/rostests/winetests/mshtml/htmldoc.c @@ -20,30 +20,35 @@ #define CONST_VTABLE #include -#include -#include +//#include +//#include -#include "windef.h" -#include "winbase.h" -#include "initguid.h" -#include "ole2.h" -#include "mshtml.h" -#include "docobj.h" -#include "wininet.h" -#include "mshtmhst.h" -#include "mshtmdid.h" -#include "mshtmcid.h" -#include "hlink.h" -#include "dispex.h" -#include "idispids.h" -#include "shlguid.h" -#include "perhist.h" -#include "shobjidl.h" +//#include "windef.h" +//#include "winbase.h" +#include +//#include "ole2.h" +#include +//#include "docobj.h" +#include +#include +#include +#include +#include +//#include "hlink.h" +//#include "dispex.h" +#include +#include +#include +#include +//#include "shobjidl.h" +#include +#include #include "mshtml_test.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_GUID(SID_SContainerDispatch,0xb722be00,0x4e68,0x101b,0xa2,0xbc,0x00,0xaa,0x00,0x40,0x47,0x70); #define DEFINE_EXPECT(func) \ static BOOL expect_ ## func = FALSE, called_ ## func = FALSE @@ -72,8 +77,24 @@ DEFINE_OLEGUID(CGID_DocHostCmdPriv, 0x000214D4L, 0, 0); expect_ ## func = called_ ## func = FALSE; \ }while(0) +#define CHECK_NOT_CALLED(func) \ + do { \ + ok(!called_ ## func, "unexpected " #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 CLEAR_CALLED(func) \ + expect_ ## func = called_ ## func = FALSE + + static IOleDocumentView *view = NULL; -static HWND container_hwnd = NULL, hwnd = NULL, last_hwnd = NULL; +static HWND container_hwnd = NULL, doc_hwnd = NULL, last_hwnd = NULL; DEFINE_EXPECT(LockContainer); DEFINE_EXPECT(SetActiveObject); @@ -109,11 +130,14 @@ DEFINE_EXPECT(Exec_ShellDocView_67); DEFINE_EXPECT(Exec_ShellDocView_84); DEFINE_EXPECT(Exec_ShellDocView_103); DEFINE_EXPECT(Exec_ShellDocView_105); +DEFINE_EXPECT(Exec_ShellDocView_138); DEFINE_EXPECT(Exec_ShellDocView_140); +DEFINE_EXPECT(Exec_DocHostCommandHandler_2300); DEFINE_EXPECT(Exec_UPDATECOMMANDS); DEFINE_EXPECT(Exec_SETTITLE); DEFINE_EXPECT(Exec_HTTPEQUIV); DEFINE_EXPECT(Exec_MSHTML_PARSECOMPLETE); +DEFINE_EXPECT(Exec_Explorer_38); DEFINE_EXPECT(Exec_Explorer_69); DEFINE_EXPECT(Exec_DOCCANNAVIGATE); DEFINE_EXPECT(Invoke_AMBIENT_USERMODE); @@ -122,6 +146,9 @@ DEFINE_EXPECT(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); DEFINE_EXPECT(Invoke_AMBIENT_SILENT); DEFINE_EXPECT(Invoke_AMBIENT_USERAGENT); DEFINE_EXPECT(Invoke_AMBIENT_PALETTE); +DEFINE_EXPECT(Invoke_OnReadyStateChange_Interactive); +DEFINE_EXPECT(Invoke_OnReadyStateChange_Loading); +DEFINE_EXPECT(Invoke_OnReadyStateChange_Complete); DEFINE_EXPECT(GetDropTarget); DEFINE_EXPECT(UpdateUI); DEFINE_EXPECT(Navigate); @@ -157,17 +184,33 @@ DEFINE_EXPECT(TranslateUrl); DEFINE_EXPECT(Advise_Close); DEFINE_EXPECT(OnViewChange); DEFINE_EXPECT(EvaluateNewWindow); +DEFINE_EXPECT(GetTravelLog); +DEFINE_EXPECT(UpdateBackForwardState); +DEFINE_EXPECT(FireBeforeNavigate2); +DEFINE_EXPECT(FireNavigateComplete2); +DEFINE_EXPECT(FireDocumentComplete); +DEFINE_EXPECT(GetPendingUrl); +DEFINE_EXPECT(ActiveElementChanged); +DEFINE_EXPECT(IsErrorUrl); +DEFINE_EXPECT(get_LocationURL); +DEFINE_EXPECT(CountEntries); static IUnknown *doc_unk; static IMoniker *doc_mon; static BOOL expect_LockContainer_fLock; static BOOL expect_InPlaceUIWindow_SetActiveObject_active = TRUE; static BOOL ipsex, ipsw; -static BOOL set_clientsite, container_locked, navigated_load; +static BOOL set_clientsite, container_locked; static BOOL readystate_set_loading = FALSE, readystate_set_interactive = FALSE, load_from_stream; -static BOOL editmode = FALSE, show_failed; +static BOOL editmode = FALSE, ignore_external_qi; static BOOL inplace_deactivated, open_call; +static BOOL complete, loading_js, loading_hash, is_refresh; +static DWORD status_code = HTTP_STATUS_OK; +static BOOL asynchronous_binding = FALSE; +static BOOL support_wbapp, allow_new_window; +static BOOL report_mime; static int stream_read, protocol_read; +static IStream *history_stream; static enum load_state_t { LD_DOLOAD, LD_LOADING, @@ -178,22 +221,23 @@ static enum load_state_t { } load_state; static LPCOLESTR expect_status_text = NULL; +static const char *nav_url, *nav_serv_url, *prev_url; static const char html_page[] = "" "" -"test" +"
test
" ""; -static const char css_data[] = "body {color: red}"; +static const char css_data[] = "body {color: red; margin: 0}"; static const WCHAR http_urlW[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',0}; static const WCHAR doc_url[] = {'w','i','n','e','t','e','s','t',':','d','o','c',0}; -static const WCHAR about_blank_url[] = {'a','b','o','u','t',':','b','l','a','n','k',0}; #define DOCHOST_DOCCANNAVIGATE 0 +#define WM_CONTINUE_BINDING (WM_APP+1) static HRESULT QueryInterface(REFIID riid, void **ppv); static void test_MSHTML_QueryStatus(IHTMLDocument2*,DWORD); @@ -252,10 +296,42 @@ static BSTR a2bstr(const char *str) return ret; } -static BOOL is_english(void) +/* Returns true if the user interface is in English. Note that this does not + * presume of the formatting of dates, numbers, etc. + */ +static BOOL is_lang_english(void) { - return PRIMARYLANGID(GetSystemDefaultLangID()) == LANG_ENGLISH - && PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH; + static HMODULE hkernel32 = NULL; + static LANGID (WINAPI *pGetThreadUILanguage)(void) = NULL; + static LANGID (WINAPI *pGetUserDefaultUILanguage)(void) = NULL; + + if (!hkernel32) + { + hkernel32 = GetModuleHandleA("kernel32.dll"); + pGetThreadUILanguage = (void*)GetProcAddress(hkernel32, "GetThreadUILanguage"); + pGetUserDefaultUILanguage = (void*)GetProcAddress(hkernel32, "GetUserDefaultUILanguage"); + } + if (pGetThreadUILanguage) + return PRIMARYLANGID(pGetThreadUILanguage()) == LANG_ENGLISH; + if (pGetUserDefaultUILanguage) + return PRIMARYLANGID(pGetUserDefaultUILanguage()) == LANG_ENGLISH; + + return PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH; +} + +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(iface2, &IID_IUnknown, (void**)&unk2); + IUnknown_Release(unk2); + + return unk1 == unk2; } #define EXPECT_UPDATEUI 1 @@ -274,7 +350,7 @@ static void test_timer(DWORD flags) if(flags & EXPECT_SETTITLE) SET_EXPECT(Exec_SETTITLE); - while(!*b && GetMessage(&msg, hwnd, 0, 0)) { + while(!*b && GetMessage(&msg, doc_hwnd, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } @@ -290,12 +366,13 @@ static void test_timer(DWORD flags) static IMoniker Moniker; #define test_GetCurMoniker(u,m,v) _test_GetCurMoniker(__LINE__,u,m,v) -static void _test_GetCurMoniker(unsigned line, IUnknown *unk, IMoniker *exmon, LPCWSTR exurl) +static void _test_GetCurMoniker(unsigned line, IUnknown *unk, IMoniker *exmon, const char *exurl) { IHTMLDocument2 *doc; IPersistMoniker *permon; IMoniker *mon = (void*)0xdeadbeef; BSTR doc_url = (void*)0xdeadbeef; + const WCHAR *ptr; HRESULT hres; if(open_call) @@ -311,6 +388,7 @@ static void _test_GetCurMoniker(unsigned line, IUnknown *unk, IMoniker *exmon, L hres = IHTMLDocument2_get_URL(doc, &doc_url); ok(hres == S_OK, "get_URL failed: %08x\n", hres); + for(ptr = doc_url; *ptr && *ptr != '#'; ptr++); hres = IPersistMoniker_GetCurMoniker(permon, &mon); IPersistMoniker_Release(permon); @@ -332,7 +410,10 @@ static void _test_GetCurMoniker(unsigned line, IUnknown *unk, IMoniker *exmon, L expect_GetDisplayName = exb; called_GetDisplayName = clb; - ok(!lstrcmpW(url, doc_url), "url != doc_url\n"); + if(!*ptr) + ok(!lstrcmpW(url, doc_url), "url %s != doc_url %s\n", wine_dbgstr_w(url), wine_dbgstr_w(doc_url)); + else + ok(!strcmp_wa(url, nav_serv_url), "url = %s, expected %s\n", wine_dbgstr_w(url), nav_serv_url); CoTaskMemFree(url); }else if(exurl) { LPOLESTR url; @@ -342,23 +423,42 @@ static void _test_GetCurMoniker(unsigned line, IUnknown *unk, IMoniker *exmon, L hres = IMoniker_GetDisplayName(mon, NULL, NULL, &url); ok(hres == S_OK, "GetDisplayName failed: %08x\n", hres); - ok(!lstrcmpW(url, exurl), "unexpected url %s\n", wine_dbgstr_w(url)); - ok(!lstrcmpW(url, doc_url), "url != doc_url\n"); + ok_(__FILE__,line)(!strcmp_wa(url, exurl), "unexpected url %s\n", wine_dbgstr_w(url)); + if(!*ptr) + ok_(__FILE__,line)(!lstrcmpW(url, doc_url), "url %s != doc_url %s\n", wine_dbgstr_w(url), wine_dbgstr_w(doc_url)); CoTaskMemFree(url); }else { - ok(hres == E_UNEXPECTED, + ok_(__FILE__,line)(hres == E_UNEXPECTED, "GetCurrentMoniker failed: %08x, expected E_UNEXPECTED\n", hres); - ok(mon == (IMoniker*)0xdeadbeef, "mon=%p\n", mon); - ok(!lstrcmpW(doc_url, about_blank_url), "doc_url is not about:blank\n"); + ok_(__FILE__,line)(mon == (IMoniker*)0xdeadbeef, "mon=%p\n", mon); + ok_(__FILE__,line)(!strcmp_wa(doc_url, "about:blank"), "doc_url is not about:blank\n"); } SysFreeString(doc_url); - IHTMLDocument_Release(doc); + IHTMLDocument2_Release(doc); if(mon && mon != (void*)0xdeadbeef) IMoniker_Release(mon); } +#define test_current_url(a,b) _test_current_url(__LINE__,a,b) +static void _test_current_url(unsigned line, IUnknown *unk, const char *exurl) +{ + IHTMLDocument2 *doc; + BSTR url; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IHTMLDocument2, (void**)&doc); + ok_(__FILE__,line)(hres == S_OK, "QueryInterface(IID_IHTMLDocument2) failed: %08x\n", hres); + + hres = IHTMLDocument2_get_URL(doc, &url); + ok_(__FILE__,line)(hres == S_OK, "get_URL failed: %08x\n", hres); + ok_(__FILE__,line)(!strcmp_wa(url, exurl), "Unexpected URL %s, expected %s\n", wine_dbgstr_w(url), exurl); + SysFreeString(url); + + IHTMLDocument2_Release(doc); +} + DEFINE_GUID(IID_External_unk,0x30510406,0x98B5,0x11CF,0xBB,0x82,0x00,0xAA,0x00,0xBD,0xCE,0x0B); static HRESULT WINAPI External_QueryInterface(IDispatch *iface, REFIID riid, void **ppv) @@ -377,7 +477,8 @@ static HRESULT WINAPI External_QueryInterface(IDispatch *iface, REFIID riid, voi if(IsEqualGUID(&IID_External_unk, riid)) return E_NOINTERFACE; /* TODO */ - ok(0, "unexpected riid: %s\n", debugstr_guid(riid)); + if(!ignore_external_qi) + ok(0, "unexpected riid: %s\n", debugstr_guid(riid)); return E_NOINTERFACE; } @@ -498,10 +599,12 @@ static HRESULT WINAPI Protocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, BINDSTATUS_CACHEFILENAMEAVAILABLE, &empty_str); ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres); - hres = IInternetProtocolSink_ReportProgress(pOIProtSink, - BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, wszTextCss); - ok(hres == S_OK, - "ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE) failed: %08x\n", hres); + if(report_mime) { + hres = IInternetProtocolSink_ReportProgress(pOIProtSink, + BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, wszTextCss); + ok(hres == S_OK, + "ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE) failed: %08x\n", hres); + } hres = IInternetProtocolSink_ReportData(pOIProtSink, BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION, 13, 13); @@ -553,7 +656,7 @@ static HRESULT WINAPI Protocol_Read(IInternetProtocol *iface, void *pv, ok(pv != NULL, "pv == NULL\n"); ok(cb > sizeof(css_data), "cb < sizeof(css_data)\n"); ok(pcbRead != NULL, "pcbRead == NULL\n"); - ok(!*pcbRead, "*pcbRead=%d\n", *pcbRead); + ok(!*pcbRead || *pcbRead==sizeof(css_data)-1, "*pcbRead=%d\n", *pcbRead); if(protocol_read) return S_FALSE; @@ -696,7 +799,6 @@ static HRESULT WINAPI HlinkFrame_Navigate(IHlinkFrame *iface, DWORD grfHLNF, LPB DWORD site_data = 0xdeadbeef; hres = IHlink_GetTargetFrameName(pihlNavigate, &frame_name); - todo_wine ok(hres == S_FALSE, "GetTargetFrameName failed: %08x\n", hres); ok(frame_name == NULL, "frame_name = %p\n", frame_name); @@ -705,10 +807,15 @@ static HRESULT WINAPI HlinkFrame_Navigate(IHlinkFrame *iface, DWORD grfHLNF, LPB ok(location == NULL, "location = %p\n", location); ok(mon != NULL, "mon == NULL\n"); + hres = IMoniker_GetDisplayName(mon, NULL, NULL, &location); + ok(hres == S_OK, "GetDisplayName failed: %08x\n", hres); + ok(!strcmp_wa(location, nav_url), "unexpected display name %s, expected %s\n", wine_dbgstr_w(location), nav_url); + CoTaskMemFree(location); + IMoniker_Release(mon); + hres = IHlink_GetHlinkSite(pihlNavigate, &site, &site_data); ok(hres == S_OK, "GetHlinkSite failed: %08x\n", hres); ok(site == NULL, "site = %p\n, expected NULL\n", site); - todo_wine ok(site_data == 0xdeadbeef, "site_data = %x\n", site_data); } @@ -766,13 +873,13 @@ static HRESULT WINAPI NewWindowManager_EvaluateNewWindow(INewWindowManager *ifac ok(!strcmp_wa(pszUrl, "about:blank"), "pszUrl = %s\n", wine_dbgstr_w(pszUrl)); ok(!strcmp_wa(pszName, "test"), "pszName = %s\n", wine_dbgstr_w(pszName)); - ok(!strcmp_wa(pszUrlContext, "about:blank"), "pszUrlContext = %s\n", wine_dbgstr_w(pszUrlContext)); + ok(!strcmp_wa(pszUrlContext, prev_url), "pszUrlContext = %s\n", wine_dbgstr_w(pszUrlContext)); ok(!pszFeatures, "pszFeatures = %s\n", wine_dbgstr_w(pszFeatures)); ok(!fReplace, "fReplace = %x\n", fReplace); - ok(dwFlags == NWMF_FIRST, "dwFlags = %x\n", dwFlags); + ok(dwFlags == (allow_new_window ? 0 : NWMF_FIRST), "dwFlags = %x\n", dwFlags); ok(!dwUserActionTime, "dwUserActionime = %d\n", dwUserActionTime); - return E_FAIL; + return allow_new_window ? S_OK : E_FAIL; } static const INewWindowManagerVtbl NewWindowManagerVtbl = { @@ -825,17 +932,25 @@ static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, D test_readyState(NULL); return S_OK; case 1005: - CHECK_EXPECT(OnChanged_1005); + CHECK_EXPECT2(OnChanged_1005); if(!editmode) test_readyState(NULL); readystate_set_interactive = (load_state != LD_INTERACTIVE); return S_OK; case 1012: - CHECK_EXPECT(OnChanged_1012); + CHECK_EXPECT2(OnChanged_1012); return S_OK; case 1030: + case 3000022: + case 3000023: + case 3000024: + case 3000025: + case 3000026: + case 3000027: + case 3000028: case 3000029: case 3000030: + case 3000031: /* TODO */ return S_OK; } @@ -862,7 +977,13 @@ static IPropertyNotifySink PropertyNotifySink = { &PropertyNotifySinkVtbl }; static HRESULT WINAPI Stream_QueryInterface(IStream *iface, REFIID riid, void **ppv) { - ok(0, "unexpected call\n"); + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_ISequentialStream, riid) || IsEqualGUID(&IID_IStream, riid)) { + *ppv = iface; + return S_OK; + } + + ok(0, "unexpected call %s\n", debugstr_guid(riid)); + *ppv = NULL; return E_NOINTERFACE; } @@ -978,13 +1099,78 @@ static const IStreamVtbl StreamVtbl = { static IStream Stream = { &StreamVtbl }; +static HRESULT WINAPI WinInetHttpInfo_QueryInterface( + IWinInetHttpInfo* This, + REFIID riid, + void **ppvObject) +{ + ok(0, "unexpected call\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI WinInetHttpInfo_AddRef( + IWinInetHttpInfo* This) +{ + return 2; +} + +static ULONG WINAPI WinInetHttpInfo_Release( + IWinInetHttpInfo* This) +{ + return 1; +} + +static HRESULT WINAPI WinInetHttpInfo_QueryOption( + IWinInetHttpInfo* This, + DWORD dwOption, + LPVOID pBuffer, + DWORD *pcbBuf) +{ + return E_NOTIMPL; /* TODO */ +} + +static HRESULT WINAPI WinInetHttpInfo_QueryInfo( + IWinInetHttpInfo* This, + DWORD dwOption, + LPVOID pBuffer, + DWORD *pcbBuf, + DWORD *pdwFlags, + DWORD *pdwReserved) +{ + ok(pdwReserved == NULL, "pdwReserved != NULL\n"); + + if(dwOption == (HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER)) { + ok(pBuffer != NULL, "pBuffer == NULL\n"); + ok(*pcbBuf == sizeof(DWORD), "*pcbBuf = %d\n", *pcbBuf); + ok(pdwFlags == NULL, "*pdwFlags != NULL\n"); + *((DWORD*)pBuffer) = status_code; + return S_OK; + } + + return E_NOTIMPL; /* TODO */ +} + +static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = { + WinInetHttpInfo_QueryInterface, + WinInetHttpInfo_AddRef, + WinInetHttpInfo_Release, + WinInetHttpInfo_QueryOption, + WinInetHttpInfo_QueryInfo +}; + +static IWinInetHttpInfo WinInetHttpInfo = { &WinInetHttpInfoVtbl }; + static HRESULT WINAPI Binding_QueryInterface(IBinding *iface, REFIID riid, void **ppv) { - if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) - return E_NOINTERFACE; /* TODO */ + if(IsEqualGUID(&IID_IUnknown, riid)) { + *ppv = iface; + return S_OK; + } - if(IsEqualGUID(&IID_IWinInetInfo, riid)) - return E_NOINTERFACE; /* TODO */ + if(IsEqualGUID(&IID_IWinInetInfo, riid) || IsEqualGUID(&IID_IWinInetHttpInfo, riid)) { + *ppv = &WinInetHttpInfo; + return S_OK; + } ok(0, "unexpected call\n"); return E_NOINTERFACE; @@ -1003,6 +1189,8 @@ static ULONG WINAPI Binding_Release(IBinding *iface) static HRESULT WINAPI Binding_Abort(IBinding *iface) { CHECK_EXPECT(Abort); + if(asynchronous_binding) + PeekMessage(NULL, container_hwnd, WM_CONTINUE_BINDING, WM_CONTINUE_BINDING, PM_REMOVE); return S_OK; } @@ -1115,18 +1303,100 @@ static HRESULT WINAPI Moniker_BindToObject(IMoniker *iface, IBindCtx *pcb, IMoni return E_NOTIMPL; } +static void test_binding_ui(IUnknown *unk) +{ + IWindowForBindingUI *binding_ui; + IServiceProvider *serv_prov; + HWND binding_hwnd; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IServiceProvider, (void**)&serv_prov); + ok(hres == S_OK, "Could not get IServiceProvider: %08x\n", hres); + + hres = IServiceProvider_QueryService(serv_prov, &IID_IWindowForBindingUI, &IID_IWindowForBindingUI, + (void**)&binding_ui); + ok(hres == S_OK, "Could not get IWindowForBindingUI: %08x\n", hres); + + hres = IWindowForBindingUI_GetWindow(binding_ui, &IID_IHttpSecurity, &binding_hwnd); + ok(hres == S_OK, "GetWindow(IID_IHttpSecurity) failed: %08x\n", hres); + if(doc_hwnd) + ok(binding_hwnd == doc_hwnd, "binding_hwnd != doc_hwnd\n"); + else + todo_wine ok(binding_hwnd != NULL, "binding_hwnd == NULL\n"); + + hres = IWindowForBindingUI_GetWindow(binding_ui, &IID_IAuthenticate, &binding_hwnd); + ok(hres == S_OK, "GetWindow(IID_IHttpSecurity) failed: %08x\n", hres); + if(doc_hwnd) + ok(binding_hwnd == doc_hwnd, "binding_hwnd != doc_hwnd\n"); + else + todo_wine ok(binding_hwnd != NULL, "binding_hwnd == NULL\n"); + + hres = IWindowForBindingUI_GetWindow(binding_ui, &IID_IWindowForBindingUI, &binding_hwnd); + ok(hres == S_OK, "GetWindow(IID_IHttpSecurity) failed: %08x\n", hres); + if(doc_hwnd) + ok(binding_hwnd == doc_hwnd, "binding_hwnd != doc_hwnd\n"); + else + todo_wine ok(binding_hwnd != NULL, "binding_hwnd == NULL\n"); + + IWindowForBindingUI_Release(binding_ui); + IServiceProvider_Release(serv_prov); +} + +static void continue_binding(IBindStatusCallback *callback) +{ + FORMATETC formatetc = {0xc02d, NULL, 1, -1, TYMED_ISTREAM}; + STGMEDIUM stgmedium; + HRESULT hres; + + static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0}; + + test_binding_ui((IUnknown*)callback); + + if(report_mime) { + hres = IBindStatusCallback_OnProgress(callback, 0, 0, BINDSTATUS_MIMETYPEAVAILABLE, + wszTextHtml); + ok(hres == S_OK, "OnProgress(BINDSTATUS_MIMETYPEAVAILABLE) failed: %08x\n", hres); + } + + hres = IBindStatusCallback_OnProgress(callback, sizeof(html_page)-1, sizeof(html_page)-1, + BINDSTATUS_BEGINDOWNLOADDATA, doc_url); + ok(hres == S_OK, "OnProgress(BINDSTATUS_BEGINDOWNLOADDATA) failed: %08x\n", hres); + if(status_code != HTTP_STATUS_OK) { + CHECK_CALLED_BROKEN(IsErrorUrl); + SET_EXPECT(IsErrorUrl); + } + + SET_EXPECT(Read); + stgmedium.tymed = TYMED_ISTREAM; + U(stgmedium).pstm = &Stream; + stgmedium.pUnkForRelease = (IUnknown*)&Moniker; + hres = IBindStatusCallback_OnDataAvailable(callback, + BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION, + sizeof(html_page)-1, &formatetc, &stgmedium); + ok(hres == S_OK, "OnDataAvailable failed: %08x\n", hres); + CHECK_CALLED(Read); + + hres = IBindStatusCallback_OnProgress(callback, sizeof(html_page)-1, sizeof(html_page)-1, + 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); + CLEAR_CALLED(GetBindResult); /* IE7 */ + + IBindStatusCallback_Release(callback); +} + static HRESULT WINAPI Moniker_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, REFIID riid, void **ppv) { IBindStatusCallback *callback = NULL; - FORMATETC formatetc = {0xc02d, NULL, 1, -1, TYMED_ISTREAM}; - STGMEDIUM stgmedium; BINDINFO bindinfo; DWORD bindf; HRESULT hres; static OLECHAR BSCBHolder[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 }; - static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0}; CHECK_EXPECT(BindToStorage); @@ -1147,7 +1417,7 @@ static HRESULT WINAPI Moniker_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMon hres = IBindStatusCallback_GetBindInfo(callback, &bindf, &bindinfo); ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres); - ok(bindf == (BINDF_PULLDATA|BINDF_ASYNCSTORAGE|BINDF_ASYNCHRONOUS), "bindf = %08x\n", bindf); + ok((bindf & ~BINDF_HYPERLINK /* IE9 */) == (BINDF_PULLDATA|BINDF_ASYNCSTORAGE|BINDF_ASYNCHRONOUS), "bindf = %08x\n", bindf); ok(bindinfo.cbSize == sizeof(bindinfo), "bindinfo.cbSize=%d\n", bindinfo.cbSize); ok(bindinfo.szExtraInfo == NULL, "bindinfo.szExtraInfo=%p\n", bindinfo.szExtraInfo); /* TODO: test stgmedData */ @@ -1167,35 +1437,12 @@ static HRESULT WINAPI Moniker_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMon hres = IBindStatusCallback_OnStartBinding(callback, 0, &Binding); ok(hres == S_OK, "OnStartBinding failed: %08x\n", hres); - hres = IBindStatusCallback_OnProgress(callback, 0, 0, BINDSTATUS_MIMETYPEAVAILABLE, - wszTextHtml); - ok(hres == S_OK, "OnProgress(BINDSTATUS_MIMETYPEAVAILABLE) failed: %08x\n", hres); - - hres = IBindStatusCallback_OnProgress(callback, sizeof(html_page)-1, sizeof(html_page)-1, - BINDSTATUS_BEGINDOWNLOADDATA, doc_url); - ok(hres == S_OK, "OnProgress(BINDSTATUS_BEGINDOWNLOADDATA) failed: %08x\n", hres); - - SET_EXPECT(Read); - stgmedium.tymed = TYMED_ISTREAM; - U(stgmedium).pstm = &Stream; - stgmedium.pUnkForRelease = (IUnknown*)iface; - hres = IBindStatusCallback_OnDataAvailable(callback, - BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION, - sizeof(html_page)-1, &formatetc, &stgmedium); - ok(hres == S_OK, "OnDataAvailable failed: %08x\n", hres); - CHECK_CALLED(Read); - - hres = IBindStatusCallback_OnProgress(callback, sizeof(html_page)-1, sizeof(html_page)-1, - 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); + if(asynchronous_binding) { + PostMessageW(container_hwnd, WM_CONTINUE_BINDING, (WPARAM)callback, 0); + return MK_S_ASYNCHRONOUS; + } + continue_binding(callback); return S_OK; } @@ -1499,8 +1746,8 @@ static HRESULT WINAPI InPlaceUIWindow_SetActiveObject(IOleInPlaceFrame *iface, if(expect_InPlaceUIWindow_SetActiveObject_active) { ok(pActiveObject != NULL, "pActiveObject = NULL\n"); - if(pActiveObject && is_english()) - ok(!lstrcmpW(wszHTML_Document, pszObjName), "pszObjName != \"HTML Document\"\n"); + if(pActiveObject && is_lang_english()) + ok(!lstrcmpW(wszHTML_Document, pszObjName), "%s != \"HTML Document\"\n", wine_dbgstr_w(pszObjName)); } else { ok(pActiveObject == NULL, "pActiveObject=%p, expected NULL\n", pActiveObject); @@ -1519,8 +1766,8 @@ static HRESULT WINAPI InPlaceFrame_SetActiveObject(IOleInPlaceFrame *iface, if(pActiveObject) { CHECK_EXPECT2(SetActiveObject); - if(pActiveObject && is_english()) - ok(!lstrcmpW(wszHTML_Document, pszObjName), "pszObjName != \"HTML Document\"\n"); + if(pActiveObject && is_lang_english()) + ok(!lstrcmpW(wszHTML_Document, pszObjName), "%s != \"HTML Document\"\n", wine_dbgstr_w(pszObjName)); }else { CHECK_EXPECT(SetActiveObject_null); @@ -1698,7 +1945,7 @@ static HRESULT WINAPI InPlaceSiteWindowless_GetWindowContext( memcpy(lprcClipRect, &rect, sizeof(RECT)); ok(lpFrameInfo != NULL, "lpFrameInfo = NULL\n"); if(lpFrameInfo) { - lpFrameInfo->cb = sizeof(*lpFrameInfo); + ok(lpFrameInfo->cb == sizeof(*lpFrameInfo), "lpFrameInfo->cb = %u, expected %u\n", lpFrameInfo->cb, (unsigned)sizeof(*lpFrameInfo)); lpFrameInfo->fMDIApp = FALSE; lpFrameInfo->hwndFrame = container_hwnd; lpFrameInfo->haccel = NULL; @@ -1964,11 +2211,12 @@ static HRESULT WINAPI DocumentSite_ActivateMe(IOleDocumentSite *iface, IOleDocum ok(hres == S_OK, "Could not get IOleInPlaceActiveObject: %08x\n", hres); if(activeobj) { - IOleInPlaceActiveObject_GetWindow(activeobj, &hwnd); - ok(hres == S_OK, "GetWindow failed: %08x\n", hres); - ok(hwnd == NULL, "hwnd=%p, expeted NULL\n", hwnd); + HWND hwnd = (void*)0xdeadbeef; + hres = IOleInPlaceActiveObject_GetWindow(activeobj, &hwnd); + ok(hres == E_FAIL, "GetWindow returned %08x, expected E_FAIL\n", hres); + ok(hwnd == NULL, "hwnd=%p, expected NULL\n", hwnd); } - + if(call_UIActivate == CallUIActivate_ActivateMe) { SET_EXPECT(CanInPlaceActivate); SET_EXPECT(GetWindowContext); @@ -2003,11 +2251,11 @@ static HRESULT WINAPI DocumentSite_ActivateMe(IOleDocumentSite *iface, IOleDocum CHECK_CALLED(ShowUI); if(activeobj) { - hres = IOleInPlaceActiveObject_GetWindow(activeobj, &hwnd); + hres = IOleInPlaceActiveObject_GetWindow(activeobj, &doc_hwnd); ok(hres == S_OK, "GetWindow failed: %08x\n", hres); - ok(hwnd != NULL, "hwnd == NULL\n"); + ok(doc_hwnd != NULL, "hwnd == NULL\n"); if(last_hwnd) - ok(hwnd == last_hwnd, "hwnd != last_hwnd\n"); + ok(doc_hwnd == last_hwnd, "hwnd != last_hwnd\n"); } hres = IOleDocumentView_UIActivate(view, TRUE); @@ -2016,7 +2264,7 @@ static HRESULT WINAPI DocumentSite_ActivateMe(IOleDocumentSite *iface, IOleDocum if(activeobj) { hres = IOleInPlaceActiveObject_GetWindow(activeobj, &tmp_hwnd); ok(hres == S_OK, "GetWindow failed: %08x\n", hres); - ok(tmp_hwnd == hwnd, "tmp_hwnd=%p, expected %p\n", tmp_hwnd, hwnd); + ok(tmp_hwnd == doc_hwnd, "tmp_hwnd=%p, expected %p\n", tmp_hwnd, doc_hwnd); } } @@ -2041,14 +2289,6 @@ 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); @@ -2063,11 +2303,11 @@ static HRESULT WINAPI DocumentSite_ActivateMe(IOleDocumentSite *iface, IOleDocum CHECK_CALLED(Exec_SETPROGRESSPOS); if(activeobj) { - hres = IOleInPlaceActiveObject_GetWindow(activeobj, &hwnd); + hres = IOleInPlaceActiveObject_GetWindow(activeobj, &doc_hwnd); ok(hres == S_OK, "GetWindow failed: %08x\n", hres); - ok(hwnd != NULL, "hwnd == NULL\n"); + ok(doc_hwnd != NULL, "doc_hwnd == NULL\n"); if(last_hwnd) - ok(hwnd == last_hwnd, "hwnd != last_hwnd\n"); + ok(doc_hwnd == last_hwnd, "doc_hwnd != last_hwnd\n"); } } @@ -2169,6 +2409,8 @@ static const IOleControlSiteVtbl OleControlSiteVtbl = { static IOleControlSite OleControlSite = { &OleControlSiteVtbl }; +static IDocHostUIHandler2 *expect_uihandler_iface; + static HRESULT WINAPI DocHostUIHandler_QueryInterface(IDocHostUIHandler2 *iface, REFIID riid, void **ppv) { return QueryInterface(riid, ppv); @@ -2188,12 +2430,14 @@ static HRESULT WINAPI DocHostUIHandler_ShowContextMenu(IDocHostUIHandler2 *iface IUnknown *pcmdtReserved, IDispatch *pdicpReserved) { ok(0, "unexpected call\n"); + ok(iface == expect_uihandler_iface, "called on unexpected iface\n"); return E_NOTIMPL; } static HRESULT WINAPI DocHostUIHandler_GetHostInfo(IDocHostUIHandler2 *iface, DOCHOSTUIINFO *pInfo) { CHECK_EXPECT(GetHostInfo); + ok(iface == expect_uihandler_iface, "called on unexpected iface\n"); ok(pInfo != NULL, "pInfo=NULL\n"); if(pInfo) { ok(pInfo->cbSize == sizeof(DOCHOSTUIINFO), "pInfo->cbSize=%u\n", pInfo->cbSize); @@ -2213,6 +2457,7 @@ static HRESULT WINAPI DocHostUIHandler_ShowUI(IDocHostUIHandler2 *iface, DWORD d IOleInPlaceFrame *pFrame, IOleInPlaceUIWindow *pDoc) { CHECK_EXPECT(ShowUI); + ok(iface == expect_uihandler_iface, "called on unexpected iface\n"); if (editmode) ok(dwID == DOCHOSTUITYPE_AUTHOR, "dwID=%d, expected DOCHOSTUITYPE_AUTHOR\n", dwID); @@ -2232,17 +2477,20 @@ static HRESULT WINAPI DocHostUIHandler_ShowUI(IDocHostUIHandler2 *iface, DWORD d static HRESULT WINAPI DocHostUIHandler_HideUI(IDocHostUIHandler2 *iface) { CHECK_EXPECT(HideUI); + ok(iface == expect_uihandler_iface, "called on unexpected iface\n"); return S_OK; } static HRESULT WINAPI DocHostUIHandler_UpdateUI(IDocHostUIHandler2 *iface) { CHECK_EXPECT(UpdateUI); + ok(iface == expect_uihandler_iface, "called on unexpected iface\n"); return S_OK; } static HRESULT WINAPI DocHostUIHandler_EnableModeless(IDocHostUIHandler2 *iface, BOOL fEnable) { + ok(iface == expect_uihandler_iface, "called on unexpected iface\n"); if(fEnable) CHECK_EXPECT2(EnableModeless_TRUE); else @@ -2253,6 +2501,7 @@ static HRESULT WINAPI DocHostUIHandler_EnableModeless(IDocHostUIHandler2 *iface, static HRESULT WINAPI DocHostUIHandler_OnDocWindowActivate(IDocHostUIHandler2 *iface, BOOL fActivate) { ok(0, "unexpected call\n"); + ok(iface == expect_uihandler_iface, "called on unexpected iface\n"); return E_NOTIMPL; } @@ -2260,6 +2509,7 @@ static BOOL expect_OnFrameWindowActivate_fActivate; static HRESULT WINAPI DocHostUIHandler_OnFrameWindowActivate(IDocHostUIHandler2 *iface, BOOL fActivate) { CHECK_EXPECT2(OnFrameWindowActivate); + ok(iface == expect_uihandler_iface, "called on unexpected iface\n"); ok(fActivate == expect_OnFrameWindowActivate_fActivate, "fActivate=%x\n", fActivate); return S_OK; } @@ -2275,6 +2525,7 @@ static HRESULT WINAPI DocHostUIHandler_TranslateAccelerator(IDocHostUIHandler2 * const GUID *pguidCmdGroup, DWORD nCmdID) { ok(0, "unexpected call\n"); + ok(iface == expect_uihandler_iface, "called on unexpected iface\n"); return E_NOTIMPL; } @@ -2282,6 +2533,7 @@ static HRESULT WINAPI DocHostUIHandler_GetOptionKeyPath(IDocHostUIHandler2 *ifac LPOLESTR *pchKey, DWORD dw) { CHECK_EXPECT(GetOptionKeyPath); + ok(iface == expect_uihandler_iface, "called on unexpected iface\n"); ok(pchKey != NULL, "pchKey = NULL\n"); ok(!dw, "dw=%d, expected 0\n", dw); if(pchKey) @@ -2293,6 +2545,7 @@ static HRESULT WINAPI DocHostUIHandler_GetDropTarget(IDocHostUIHandler2 *iface, IDropTarget *pDropTarget, IDropTarget **ppDropTarget) { CHECK_EXPECT(GetDropTarget); + ok(iface == expect_uihandler_iface, "called on unexpected iface\n"); /* TODO */ return E_NOTIMPL; } @@ -2300,6 +2553,7 @@ static HRESULT WINAPI DocHostUIHandler_GetDropTarget(IDocHostUIHandler2 *iface, static HRESULT WINAPI DocHostUIHandler_GetExternal(IDocHostUIHandler2 *iface, IDispatch **ppDispatch) { CHECK_EXPECT(GetExternal); + ok(iface == expect_uihandler_iface, "called on unexpected iface\n"); *ppDispatch = &External; return S_FALSE; } @@ -2308,8 +2562,12 @@ static HRESULT WINAPI DocHostUIHandler_TranslateUrl(IDocHostUIHandler2 *iface, D OLECHAR *pchURLIn, OLECHAR **ppchURLOut) { CHECK_EXPECT(TranslateUrl); + ok(iface == expect_uihandler_iface, "called on unexpected iface\n"); ok(!dwTranslate, "dwTranslate = %x\n", dwTranslate); - ok(!strcmp_wa(pchURLIn, "about:blank"), "pchURLIn = %s\n", wine_dbgstr_w(pchURLIn)); + if(!loading_hash) + ok(!strcmp_wa(pchURLIn, nav_serv_url), "pchURLIn = %s, expected %s\n", wine_dbgstr_w(pchURLIn), nav_serv_url); + else + todo_wine ok(!strcmp_wa(pchURLIn, nav_serv_url), "pchURLIn = %s, expected %s\n", wine_dbgstr_w(pchURLIn), nav_serv_url); ok(ppchURLOut != NULL, "ppchURLOut == NULL\n"); ok(!*ppchURLOut, "*ppchURLOut = %p\n", *ppchURLOut); @@ -2320,6 +2578,7 @@ static HRESULT WINAPI DocHostUIHandler_FilterDataObject(IDocHostUIHandler2 *ifac IDataObject **ppPORet) { ok(0, "unexpected call\n"); + ok(iface == expect_uihandler_iface, "called on unexpected iface\n"); return E_NOTIMPL; } @@ -2327,6 +2586,7 @@ static HRESULT WINAPI DocHostUIHandler_GetOverrideKeyPath(IDocHostUIHandler2 *if LPOLESTR *pchKey, DWORD dw) { CHECK_EXPECT(GetOverrideKeyPath); + ok(iface == expect_uihandler_iface, "called on unexpected iface\n"); ok(pchKey != NULL, "pchKey = NULL\n"); if(pchKey) ok(!*pchKey, "*pchKey=%p, expected NULL\n", *pchKey); @@ -2358,6 +2618,47 @@ static const IDocHostUIHandler2Vtbl DocHostUIHandlerVtbl = { static IDocHostUIHandler2 DocHostUIHandler = { &DocHostUIHandlerVtbl }; +static HRESULT WINAPI CustomDocHostUIHandler_QueryInterface(IDocHostUIHandler2 *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(&IID_IDocHostUIHandler2, riid)) { + *ppv = iface; + return S_OK; + } + + if(IsEqualGUID(&IID_IOleCommandTarget, riid)) + return E_NOINTERFACE; + + else if(IsEqualGUID(&IID_IDocHostShowUI, riid)) + return E_NOINTERFACE; /* TODO */ + + ok(0, "unexpected call %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static const IDocHostUIHandler2Vtbl CustomDocHostUIHandlerVtbl = { + CustomDocHostUIHandler_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 CustomDocHostUIHandler = { &CustomDocHostUIHandlerVtbl }; + static HRESULT WINAPI OleCommandTarget_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppv) { @@ -2401,11 +2702,35 @@ static HRESULT WINAPI OleCommandTarget_QueryStatus(IOleCommandTarget *iface, con return E_FAIL; } +static void test_save_history(IUnknown *unk) +{ + IPersistHistory *per_hist; + LARGE_INTEGER li; + IStream *stream; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IPersistHistory, (void**)&per_hist); + ok(hres == S_OK, "Could not get IPersistHistory iface: %08x\n", hres); + + hres = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres); + + hres = IPersistHistory_SaveHistory(per_hist, stream); + ok(hres == S_OK, "SaveHistory failed: %08x\n", hres); + IPersistHistory_Release(per_hist); + + li.QuadPart = 0; + hres = IStream_Seek(stream, li, STREAM_SEEK_SET, NULL); + ok(hres == S_OK, "Stat failed: %08x\n", hres); + history_stream = stream; +} + static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) { if((!pguidCmdGroup || !IsEqualGUID(pguidCmdGroup, &CGID_Explorer)) - && (!pguidCmdGroup || !IsEqualGUID(&CGID_ShellDocView, pguidCmdGroup) || nCmdID != 63)) + && (!pguidCmdGroup || !IsEqualGUID(&CGID_ShellDocView, pguidCmdGroup) + || (nCmdID != 63 && (!is_refresh || nCmdID != 37)))) test_readyState(NULL); if(!pguidCmdGroup) { @@ -2450,7 +2775,8 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID switch(V_I4(pvaIn)) { case 0: CHECK_EXPECT(Exec_SETDOWNLOADSTATE_0); - load_state = LD_INTERACTIVE; + if(!loading_js) + load_state = LD_INTERACTIVE; break; case 1: CHECK_EXPECT(Exec_SETDOWNLOADSTATE_1); @@ -2485,6 +2811,7 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID test_readyState(NULL); return S_OK; case OLECMDID_UPDATETRAVELENTRY_DATARECOVERY: + case 6058: return E_FAIL; /* FIXME */ default: ok(0, "unexpected command %d\n", nCmdID); @@ -2499,10 +2826,20 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID case 37: CHECK_EXPECT2(Exec_ShellDocView_37); - if(load_from_stream || navigated_load) - test_GetCurMoniker(doc_unk, NULL, about_blank_url); - else if(!editmode) - test_GetCurMoniker(doc_unk, doc_mon, NULL); + if(is_refresh && load_state == LD_COMPLETE) { + load_state = LD_DOLOAD; + test_readyState(NULL); + }else if(is_refresh && load_state == LD_DOLOAD) { + test_readyState(NULL); + load_state = LD_LOADING; + }else { + if(nav_url) + test_GetCurMoniker(doc_unk, NULL, nav_serv_url); + else if(load_from_stream) + test_GetCurMoniker(doc_unk, NULL, "about:blank"); + else if(!editmode) + test_GetCurMoniker(doc_unk, doc_mon, NULL); + } ok(pvaOut == NULL, "pvaOut=%p, expected NULL\n", pvaOut); ok(pvaIn != NULL, "pvaIn == NULL\n"); @@ -2528,7 +2865,7 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID if(SUCCEEDED(hres)) IHTMLPrivateWindow_Release(priv_window); - load_state = LD_LOADING; + load_state = loading_js ? LD_COMPLETE : LD_LOADING; return S_OK; /* TODO */ } @@ -2536,11 +2873,13 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID CHECK_EXPECT(Exec_ShellDocView_67); ok(pvaIn != NULL, "pvaIn == NULL\n"); ok(V_VT(pvaIn) == VT_BSTR, "V_VT(pvaIn) = %d\n", V_VT(pvaIn)); - ok(!strcmp_wa(V_BSTR(pvaIn), "about:blank"), "V_BSTR(pvaIn) = %s\n", wine_dbgstr_w(V_BSTR(pvaIn))); + ok(!strcmp_wa(V_BSTR(pvaIn), nav_serv_url), "V_BSTR(pvaIn) = %s, expected %s\n", + wine_dbgstr_w(V_BSTR(pvaIn)), nav_serv_url); ok(pvaOut != NULL, "pvaOut == NULL\n"); ok(V_VT(pvaOut) == VT_BOOL, "V_VT(pvaOut) = %d\n", V_VT(pvaOut)); ok(V_BOOL(pvaOut) == VARIANT_TRUE, "V_BOOL(pvaOut) = %x\n", V_BOOL(pvaOut)); - load_state = LD_DOLOAD; + if(!loading_hash) + load_state = LD_DOLOAD; return S_OK; case 84: @@ -2569,6 +2908,12 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID return E_NOTIMPL; + case 138: + CHECK_EXPECT2(Exec_ShellDocView_138); + ok(!pvaIn, "pvaIn != NULL\n"); + ok(!pvaOut, "pvaOut != NULL\n"); + return S_OK; + case 140: CHECK_EXPECT2(Exec_ShellDocView_140); @@ -2577,6 +2922,10 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID return E_NOTIMPL; + case 143: /* TODO */ + case 144: /* TODO */ + return E_NOTIMPL; + default: ok(0, "unexpected command %d\n", nCmdID); return E_FAIL; @@ -2606,6 +2955,58 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID ok(V_VT(pvaIn) == VT_UNKNOWN, "V_VT(pvaIn) != VT_UNKNOWN\n"); /* FIXME: test V_UNKNOWN(pvaIn) == window */ return S_OK; + case 1: { + SAFEARRAY *sa; + UINT dim; + LONG ind=0; + VARIANT var; + HRESULT hres; + + ok(pvaIn != NULL, "pvaIn == NULL\n"); + ok(pvaOut != NULL || broken(!pvaOut), "pvaOut != NULL\n"); + ok(V_VT(pvaIn) == VT_ARRAY, "V_VT(pvaIn) = %d\n", V_VT(pvaIn)); + if(pvaOut) + ok(V_VT(pvaOut) == VT_BOOL, "V_VT(pvaOut) = %d\n", V_VT(pvaOut)); + sa = V_ARRAY(pvaIn); + + dim = SafeArrayGetDim(sa); + ok(dim == 1, "dim = %d\n", dim); + hres = SafeArrayGetLBound(sa, 1, &ind); + ok(hres == S_OK, "SafeArrayGetLBound failed: %x\n", hres); + ok(ind == 0, "Lower bound = %d\n", ind); + hres = SafeArrayGetUBound(sa, 1, &ind); + ok(hres == S_OK, "SafeArrayGetUBound failed: %x\n", hres); + ok(ind == 7 || broken(ind == 5), "Upper bound = %d\n", ind); + + ind = 0; + SafeArrayGetElement(sa, &ind, &var); + ok(V_VT(&var) == VT_I4, "Incorrect data type: %d\n", V_VT(&var)); + ok(V_I4(&var) == status_code, "Incorrect error code: %d\n", V_I4(&var)); + VariantClear(&var); + ind = 1; + SafeArrayGetElement(sa, &ind, &var); + ok(V_VT(&var) == VT_BSTR, "Incorrect data type: %d\n", V_VT(&var)); + ok(!strcmp_wa(V_BSTR(&var), "winetest:doc"), "Page address: %s\n", wine_dbgstr_w(V_BSTR(&var))); + VariantClear(&var); + ind = 2; + SafeArrayGetElement(sa, &ind, &var); + ok(V_VT(&var) == VT_UNKNOWN, "Incorrect data type: %d\n", V_VT(&var)); + VariantClear(&var); + ind = 3; + SafeArrayGetElement(sa, &ind, &var); + ok(V_VT(&var) == VT_UNKNOWN, "Incorrect data type: %d\n", V_VT(&var)); + VariantClear(&var); + ind = 4; + SafeArrayGetElement(sa, &ind, &var); + ok(V_VT(&var) == VT_BOOL, "Incorrect data type: %d\n", V_VT(&var)); + ok(!V_BOOL(&var), "Unknown value is incorrect\n"); + VariantClear(&var); + ind = 5; + SafeArrayGetElement(sa, &ind, &var); + ok(V_VT(&var) == VT_BOOL, "Incorrect data type: %d\n", V_VT(&var)); + ok(!V_BOOL(&var), "Unknown value is incorrect\n"); + VariantClear(&var); + } default: return E_FAIL; /* TODO */ } @@ -2615,11 +3016,25 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID ok(nCmdexecopt == 0, "nCmdexecopts=%08x\n", nCmdexecopt); switch(nCmdID) { + case 38: + CHECK_EXPECT2(Exec_Explorer_38); + ok(pvaIn != NULL, "pvaIn == NULL\n"); + ok(V_VT(pvaIn) == VT_I4 , "V_VT(pvaIn) = %d\n", V_VT(pvaIn)); + ok(!V_I4(pvaIn), "V_I4(pvaIn) = %d\n", V_I4(pvaIn)); + ok(!pvaOut, "pvaOut != NULL\n"); + + test_current_url(doc_unk, prev_url); + if(!history_stream) + test_save_history(doc_unk); + + return S_OK; case 69: CHECK_EXPECT2(Exec_Explorer_69); ok(pvaIn == NULL, "pvaIn != NULL\n"); ok(pvaOut != NULL, "pvaOut == NULL\n"); return E_NOTIMPL; + case 109: /* TODO */ + return E_NOTIMPL; default: ok(0, "unexpected cmd %d of CGID_Explorer\n", nCmdID); } @@ -2636,6 +3051,9 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID case OLECMDID_SHOWSCRIPTERROR: /* TODO */ return S_OK; + case 2300: + CHECK_EXPECT(Exec_DocHostCommandHandler_2300); + return E_NOTIMPL; default: ok(0, "unexpected command %d\n", nCmdID); return E_FAIL; @@ -2702,7 +3120,7 @@ static HRESULT WINAPI Dispatch_Invoke(IDispatch *iface, DISPID dispIdMember, REF return E_FAIL; } -static IDispatchVtbl DispatchVtbl = { +static const IDispatchVtbl DispatchVtbl = { Dispatch_QueryInterface, Dispatch_AddRef, Dispatch_Release, @@ -2714,6 +3132,1338 @@ static IDispatchVtbl DispatchVtbl = { static IDispatch Dispatch = { &DispatchVtbl }; +static HRESULT WINAPI EventDispatch_QueryInterface(IDispatch *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IDispatch, riid)) { + *ppv = iface; + return S_OK; + } + + ok(0, "Unexpected call\n"); + return E_NOINTERFACE; +} + +static HRESULT WINAPI EventDispatch_Invoke(IDispatch *iface, DISPID dispIdMember, REFIID riid, + LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, + EXCEPINFO *pExcepInfo, UINT *puArgErr) +{ + HRESULT hres; + IHTMLDocument2 *doc; + BSTR state; + + ok(IsEqualGUID(&IID_NULL, riid), "riid = %s\n", debugstr_guid(riid)); + ok(pDispParams != NULL, "pDispParams == NULL\n"); + ok(pExcepInfo != NULL, "pExcepInfo == NULL\n"); + ok(puArgErr != NULL, "puArgErr == NULL\n"); + ok(V_VT(pVarResult) == 0, "V_VT(pVarResult) = %d\n", V_VT(pVarResult)); + ok(wFlags == DISPATCH_METHOD, "wFlags = %d, expected DISPATCH_METHOD\n", wFlags); + + hres = IUnknown_QueryInterface(doc_unk, &IID_IHTMLDocument2, (void**)&doc); + ok(hres == S_OK, "QueryInterface(IID_IHTMLDocument2) failed: %08x\n", hres); + + switch(dispIdMember) { + case DISPID_HTMLDOCUMENTEVENTS2_ONREADYSTATECHANGE: + hres = IHTMLDocument2_get_readyState(doc, &state); + ok(hres == S_OK, "get_readyState failed: %08x\n", hres); + + if(!strcmp_wa(state, "interactive")) + CHECK_EXPECT(Invoke_OnReadyStateChange_Interactive); + else if(!strcmp_wa(state, "loading")) + CHECK_EXPECT(Invoke_OnReadyStateChange_Loading); + else if(!strcmp_wa(state, "complete")) { + CHECK_EXPECT(Invoke_OnReadyStateChange_Complete); + complete = TRUE; + } else + ok(0, "Unexpected readyState: %s\n", wine_dbgstr_w(state)); + + SysFreeString(state); + break; + case DISPID_HTMLDOCUMENTEVENTS2_ONPROPERTYCHANGE: + case 1026: + case 1027: + case 1034: + case 1035: + case 1037: + case 1047: + case 1045: + case 1044: + case 1048: + case 1049: + break; /* FIXME: Handle these events. */ + default: + ok(0, "Unexpected DISPID: %d\n", dispIdMember); + } + + IHTMLDocument2_Release(doc); + return S_OK; +} + +static const IDispatchVtbl EventDispatchVtbl = { + EventDispatch_QueryInterface, + Dispatch_AddRef, + Dispatch_Release, + Dispatch_GetTypeInfoCount, + Dispatch_GetTypeInfo, + Dispatch_GetIDsOfNames, + EventDispatch_Invoke +}; + +static IDispatch EventDispatch = { &EventDispatchVtbl }; + +static HRESULT WINAPI TravelLog_QueryInterface(ITravelLog *iface, REFIID riid, void **ppv) +{ + static const IID IID_IIETravelLog2 = {0xb67cefd2,0xe3f1,0x478a,{0x9b,0xfa,0xd8,0x93,0x70,0x37,0x5e,0x94}}; + + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_ITravelLog, riid)) { + *ppv = iface; + return S_OK; + } + + if(!IsEqualGUID(&IID_IIETravelLog2, riid)) + ok(0, "unexpected call %s\n", debugstr_guid(riid)); + + *ppv = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI TravelLog_AddRef(ITravelLog *iface) +{ + return 2; +} + +static ULONG WINAPI TravelLog_Release(ITravelLog *iface) +{ + return 1; +} + +static HRESULT WINAPI TravelLog_AddEntry(ITravelLog *iface, IUnknown *punk, BOOL fIsLocalAnchor) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TravelLog_UpdateEntry(ITravelLog *iface, IUnknown *punk, BOOL fIsLocalAnchor) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TravelLog_UpdateExternal(ITravelLog *iface, IUnknown *punk, IUnknown *punkHLBrowseContext) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TravelLog_Travel(ITravelLog *iface, IUnknown *punk, int iOffset) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TravelLog_GetTravelEntry(ITravelLog *iface, IUnknown *punk, int iOffset, ITravelEntry **ppte) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TravelLog_FindTravelEntry(ITravelLog *iface, IUnknown *punk, LPCITEMIDLIST pidl, ITravelEntry **ppte) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TravelLog_GetTooltipText(ITravelLog *iface, IUnknown *punk, int iOffset, int idsTemplate, + LPWSTR pwzText, DWORD cchText) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TravelLog_InsertMenuEntries(ITravelLog *iface, IUnknown *punk, HMENU hmenu, int nPos, + int idFirst, int idLast, DWORD dwFlags) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI TravelLog_Clone(ITravelLog *iface, ITravelLog **pptl) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static DWORD WINAPI TravelLog_CountEntries(ITravelLog *iface, IUnknown *punk) +{ + CHECK_EXPECT(CountEntries); + return E_NOTIMPL; +} + +static HRESULT WINAPI TravelLog_Revert(ITravelLog *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const ITravelLogVtbl TravelLogVtbl = { + TravelLog_QueryInterface, + TravelLog_AddRef, + TravelLog_Release, + TravelLog_AddEntry, + TravelLog_UpdateEntry, + TravelLog_UpdateExternal, + TravelLog_Travel, + TravelLog_GetTravelEntry, + TravelLog_FindTravelEntry, + TravelLog_GetTooltipText, + TravelLog_InsertMenuEntries, + TravelLog_Clone, + TravelLog_CountEntries, + TravelLog_Revert +}; + +static ITravelLog TravelLog = { &TravelLogVtbl }; + +static HRESULT browserservice_qi(REFIID,void**); + +static HRESULT WINAPI DocObjectService_QueryInterface(IDocObjectService* This, REFIID riid, void **ppv) +{ + return browserservice_qi(riid, ppv); +} + +static ULONG WINAPI DocObjectService_AddRef( + IDocObjectService* This) +{ + return 2; +} + +static ULONG WINAPI DocObjectService_Release( + IDocObjectService* This) +{ + return 1; +} + +static HRESULT WINAPI DocObjectService_FireBeforeNavigate2(IDocObjectService *iface, IDispatch *pDispatch, + LPCWSTR lpszUrl, DWORD dwFlags, LPCWSTR lpszFrameName, BYTE *pPostData, DWORD cbPostData, + LPCWSTR lpszHeaders, BOOL fPlayNavSound, BOOL *pfCancel) +{ + CHECK_EXPECT(FireBeforeNavigate2); + + ok(!pDispatch, "pDispatch = %p\n", pDispatch); + ok(!strcmp_wa(lpszUrl, nav_url), "lpszUrl = %s, expected %s\n", wine_dbgstr_w(lpszUrl), nav_url); + ok(dwFlags == 0x40 || !dwFlags, "dwFlags = %x\n", dwFlags); + ok(!lpszFrameName, "lpszFrameName = %s\n", wine_dbgstr_w(lpszFrameName)); + ok(!pPostData, "pPostData = %p\n", pPostData); + ok(!cbPostData, "cbPostData = %d\n", cbPostData); + ok(!lpszHeaders, "lpszHeaders = %s\n", wine_dbgstr_w(lpszHeaders)); + ok(fPlayNavSound, "fPlayNavSound = %x\n", fPlayNavSound); + ok(pfCancel != NULL, "pfCancel = NULL\n"); + ok(!*pfCancel, "*pfCancel = %x\n", *pfCancel); + + return S_OK; +} + +static HRESULT WINAPI DocObjectService_FireNavigateComplete2( + IDocObjectService* This, + IHTMLWindow2 *pHTMLWindow2, + DWORD dwFlags) +{ + CHECK_EXPECT(FireNavigateComplete2); + test_readyState(NULL); + + if(loading_hash) + ok(dwFlags == 0x10 || broken(!dwFlags), "dwFlags = %x, expected 0x10\n", dwFlags); + else + ok(!(dwFlags &~1), "dwFlags = %x\n", dwFlags); + + ok(pHTMLWindow2 != NULL, "pHTMLWindow2 = NULL\n"); + + return S_OK; +} + +static HRESULT WINAPI DocObjectService_FireDownloadBegin( + IDocObjectService* This) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DocObjectService_FireDownloadComplete( + IDocObjectService* This) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DocObjectService_FireDocumentComplete( + IDocObjectService* This, + IHTMLWindow2 *pHTMLWindow, + DWORD dwFlags) +{ + CHECK_EXPECT(FireDocumentComplete); + + ok(pHTMLWindow != NULL, "pHTMLWindow == NULL\n"); + ok(!dwFlags, "dwFlags = %x\n", dwFlags); + + return S_OK; +} + +static HRESULT WINAPI DocObjectService_UpdateDesktopComponent( + IDocObjectService* This, + IHTMLWindow2 *pHTMLWindow) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DocObjectService_GetPendingUrl( + IDocObjectService* This, + BSTR *pbstrPendingUrl) +{ + CHECK_EXPECT(GetPendingUrl); + return E_NOTIMPL; +} + +static HRESULT WINAPI DocObjectService_ActiveElementChanged( + IDocObjectService* This, + IHTMLElement *pHTMLElement) +{ + CHECK_EXPECT2(ActiveElementChanged); + return E_NOTIMPL; +} + +static HRESULT WINAPI DocObjectService_GetUrlSearchComponent( + IDocObjectService* This, + BSTR *pbstrSearch) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI DocObjectService_IsErrorUrl( + IDocObjectService* This, + LPCWSTR lpszUrl, + BOOL *pfIsError) +{ + CHECK_EXPECT(IsErrorUrl); + *pfIsError = FALSE; + return S_OK; +} + +static IDocObjectServiceVtbl DocObjectServiceVtbl = { + DocObjectService_QueryInterface, + DocObjectService_AddRef, + DocObjectService_Release, + DocObjectService_FireBeforeNavigate2, + DocObjectService_FireNavigateComplete2, + DocObjectService_FireDownloadBegin, + DocObjectService_FireDownloadComplete, + DocObjectService_FireDocumentComplete, + DocObjectService_UpdateDesktopComponent, + DocObjectService_GetPendingUrl, + DocObjectService_ActiveElementChanged, + DocObjectService_GetUrlSearchComponent, + DocObjectService_IsErrorUrl +}; + +static IDocObjectService DocObjectService = { &DocObjectServiceVtbl }; + +static HRESULT WINAPI ShellBrowser_QueryInterface(IShellBrowser *iface, REFIID riid, void **ppv) +{ + return browserservice_qi(riid, ppv); +} + +static ULONG WINAPI ShellBrowser_AddRef(IShellBrowser *iface) +{ + return 2; +} + +static ULONG WINAPI ShellBrowser_Release(IShellBrowser *iface) +{ + return 1; +} + +static HRESULT WINAPI ShellBrowser_GetWindow(IShellBrowser *iface, HWND *phwnd) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_ContextSensitiveHelp(IShellBrowser *iface, BOOL fEnterMode) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_InsertMenusSB(IShellBrowser *iface, HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_SetMenuSB(IShellBrowser *iface, HMENU hmenuShared, HOLEMENU holemenuReserved, + HWND hwndActiveObject) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_RemoveMenusSB(IShellBrowser *iface, HMENU hmenuShared) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_SetStatusTextSB(IShellBrowser *iface, LPCOLESTR pszStatusText) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_EnableModelessSB(IShellBrowser *iface, BOOL fEnable) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_TranslateAcceleratorSB(IShellBrowser *iface, MSG *pmsg, WORD wID) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_BrowseObject(IShellBrowser *iface, LPCITEMIDLIST pidl, UINT wFlags) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_GetViewStateStream(IShellBrowser *iface, DWORD grfMode, IStream **ppStrm) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_GetControlWindow(IShellBrowser *iface, UINT id, HWND *phwnd) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_SendControlMsg(IShellBrowser *iface, UINT id, UINT uMsg, WPARAM wParam, + LPARAM lParam, LRESULT *pret) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_QueryActiveShellView(IShellBrowser *iface, IShellView **ppshv) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_OnViewWindowActive(IShellBrowser* iface, IShellView *pshv) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_SetToolbarItems(IShellBrowser *iface, LPTBBUTTONSB lpButtons, + UINT nButtons, UINT uFlags) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const IShellBrowserVtbl ShellBrowserVtbl = { + ShellBrowser_QueryInterface, + ShellBrowser_AddRef, + ShellBrowser_Release, + ShellBrowser_GetWindow, + ShellBrowser_ContextSensitiveHelp, + ShellBrowser_InsertMenusSB, + ShellBrowser_SetMenuSB, + ShellBrowser_RemoveMenusSB, + ShellBrowser_SetStatusTextSB, + ShellBrowser_EnableModelessSB, + ShellBrowser_TranslateAcceleratorSB, + ShellBrowser_BrowseObject, + ShellBrowser_GetViewStateStream, + ShellBrowser_GetControlWindow, + ShellBrowser_SendControlMsg, + ShellBrowser_QueryActiveShellView, + ShellBrowser_OnViewWindowActive, + ShellBrowser_SetToolbarItems +}; + +static IShellBrowser ShellBrowser = { &ShellBrowserVtbl }; + +static HRESULT WINAPI BrowserService_QueryInterface(IBrowserService *iface, REFIID riid, void **ppv) +{ + return browserservice_qi(riid, ppv); +} + +static ULONG WINAPI BrowserService_AddRef( + IBrowserService* This) +{ + return 2; +} + +static ULONG WINAPI BrowserService_Release( + IBrowserService* This) +{ + return 1; +} + +static HRESULT WINAPI BrowserService_GetParentSite( + IBrowserService* This, + IOleInPlaceSite **ppipsite) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_SetTitle( + IBrowserService* This, + IShellView *psv, + LPCWSTR pszName) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_GetTitle( + IBrowserService* This, + IShellView *psv, + LPWSTR pszName, + DWORD cchName) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_GetOleObject( + IBrowserService* This, + IOleObject **ppobjv) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_GetTravelLog(IBrowserService* This, ITravelLog **pptl) +{ + CHECK_EXPECT(GetTravelLog); + + ok(pptl != NULL, "pptl = NULL\n"); + + if(!support_wbapp) + return E_NOTIMPL; + + *pptl = &TravelLog; + return S_OK; +} + +static HRESULT WINAPI BrowserService_ShowControlWindow( + IBrowserService* This, + UINT id, + BOOL fShow) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_IsControlWindowShown( + IBrowserService* This, + UINT id, + BOOL *pfShown) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_IEGetDisplayName( + IBrowserService* This, + PCIDLIST_ABSOLUTE pidl, + LPWSTR pwszName, + UINT uFlags) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_IEParseDisplayName( + IBrowserService* This, + UINT uiCP, + LPCWSTR pwszPath, + PIDLIST_ABSOLUTE *ppidlOut) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_DisplayParseError( + IBrowserService* This, + HRESULT hres, + LPCWSTR pwszPath) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_NavigateToPidl( + IBrowserService* This, + PCIDLIST_ABSOLUTE pidl, + DWORD grfHLNF) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_SetNavigateState( + IBrowserService* This, + BNSTATE bnstate) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_GetNavigateState( + IBrowserService* This, + BNSTATE *pbnstate) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_NotifyRedirect( + IBrowserService* This, + IShellView *psv, + PCIDLIST_ABSOLUTE pidl, + BOOL *pfDidBrowse) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_UpdateWindowList( + IBrowserService* This) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_UpdateBackForwardState( + IBrowserService* This) +{ + CHECK_EXPECT(UpdateBackForwardState); + return S_OK; +} + +static HRESULT WINAPI BrowserService_SetFlags( + IBrowserService* This, + DWORD dwFlags, + DWORD dwFlagMask) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_GetFlags( + IBrowserService* This, + DWORD *pdwFlags) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_CanNavigateNow( + IBrowserService* This) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_GetPidl( + IBrowserService* This, + PIDLIST_ABSOLUTE *ppidl) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_SetReferrer( + IBrowserService* This, + PCIDLIST_ABSOLUTE pidl) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static DWORD WINAPI BrowserService_GetBrowserIndex( + IBrowserService* This) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_GetBrowserByIndex( + IBrowserService* This, + DWORD dwID, + IUnknown **ppunk) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_GetHistoryObject( + IBrowserService* This, + IOleObject **ppole, + IStream **pstm, + IBindCtx **ppbc) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_SetHistoryObject( + IBrowserService* This, + IOleObject *pole, + BOOL fIsLocalAnchor) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_CacheOLEServer( + IBrowserService* This, + IOleObject *pole) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_GetSetCodePage( + IBrowserService* This, + VARIANT *pvarIn, + VARIANT *pvarOut) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_OnHttpEquiv( + IBrowserService* This, + IShellView *psv, + BOOL fDone, + VARIANT *pvarargIn, + VARIANT *pvarargOut) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_GetPalette( + IBrowserService* This, + HPALETTE *hpal) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_RegisterWindow( + IBrowserService* This, + BOOL fForceRegister, + int swc) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static IBrowserServiceVtbl BrowserServiceVtbl = { + BrowserService_QueryInterface, + BrowserService_AddRef, + BrowserService_Release, + BrowserService_GetParentSite, + BrowserService_SetTitle, + BrowserService_GetTitle, + BrowserService_GetOleObject, + BrowserService_GetTravelLog, + BrowserService_ShowControlWindow, + BrowserService_IsControlWindowShown, + BrowserService_IEGetDisplayName, + BrowserService_IEParseDisplayName, + BrowserService_DisplayParseError, + BrowserService_NavigateToPidl, + BrowserService_SetNavigateState, + BrowserService_GetNavigateState, + BrowserService_NotifyRedirect, + BrowserService_UpdateWindowList, + BrowserService_UpdateBackForwardState, + BrowserService_SetFlags, + BrowserService_GetFlags, + BrowserService_CanNavigateNow, + BrowserService_GetPidl, + BrowserService_SetReferrer, + BrowserService_GetBrowserIndex, + BrowserService_GetBrowserByIndex, + BrowserService_GetHistoryObject, + BrowserService_SetHistoryObject, + BrowserService_CacheOLEServer, + BrowserService_GetSetCodePage, + BrowserService_OnHttpEquiv, + BrowserService_GetPalette, + BrowserService_RegisterWindow +}; + +static IBrowserService BrowserService = { &BrowserServiceVtbl }; + +DEFINE_GUID(IID_ITabBrowserService, 0x5E8FA523,0x83D4,0x4DBE,0x81,0x99,0x4C,0x18,0xE4,0x85,0x87,0x25); + +static HRESULT browserservice_qi(REFIID riid, void **ppv) +{ + if(IsEqualGUID(&IID_IShellBrowser, riid)) { + *ppv = &ShellBrowser; + return S_OK; + } + + if(IsEqualGUID(&IID_IDocObjectService, riid)) { + *ppv = &DocObjectService; + return S_OK; + } + + if(IsEqualGUID(&IID_IBrowserService, riid)) { + *ppv = &BrowserService; + return S_OK; + } + + *ppv = NULL; + return E_NOINTERFACE; +} + +static HRESULT WINAPI WebBrowser_QueryInterface(IWebBrowser2 *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IWebBrowser, riid) + || IsEqualGUID(&IID_IWebBrowserApp, riid) || IsEqualGUID(&IID_IWebBrowser2, riid)) { + *ppv = iface; + return S_OK; + } + + if(IsEqualGUID(riid, &IID_IOleObject)) + return E_NOINTERFACE; /* TODO */ + + ok(0, "unexpected call %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI WebBrowser_AddRef(IWebBrowser2 *iface) +{ + return 2; +} + +static ULONG WINAPI WebBrowser_Release(IWebBrowser2 *iface) +{ + return 1; +} + +static HRESULT WINAPI WebBrowser_GetTypeInfoCount(IWebBrowser2 *iface, UINT *pctinfo) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_GetTypeInfo(IWebBrowser2 *iface, UINT iTInfo, LCID lcid, + LPTYPEINFO *ppTInfo) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_GetIDsOfNames(IWebBrowser2 *iface, REFIID riid, + LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_Invoke(IWebBrowser2 *iface, DISPID dispIdMember, + REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, + EXCEPINFO *pExepInfo, UINT *puArgErr) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_GoBack(IWebBrowser2 *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_GoForward(IWebBrowser2 *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_GoHome(IWebBrowser2 *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_GoSearch(IWebBrowser2 *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_Navigate(IWebBrowser2 *iface, BSTR szUrl, + VARIANT *Flags, VARIANT *TargetFrameName, VARIANT *PostData, VARIANT *Headers) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_Refresh(IWebBrowser2 *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_Refresh2(IWebBrowser2 *iface, VARIANT *Level) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_Stop(IWebBrowser2 *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Application(IWebBrowser2 *iface, IDispatch **ppDisp) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Parent(IWebBrowser2 *iface, IDispatch **ppDisp) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Container(IWebBrowser2 *iface, IDispatch **ppDisp) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Document(IWebBrowser2 *iface, IDispatch **ppDisp) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_TopLevelContainer(IWebBrowser2 *iface, VARIANT_BOOL *pBool) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Type(IWebBrowser2 *iface, BSTR *Type) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Left(IWebBrowser2 *iface, LONG *pl) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_Left(IWebBrowser2 *iface, LONG Left) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Top(IWebBrowser2 *iface, LONG *pl) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_Top(IWebBrowser2 *iface, LONG Top) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Width(IWebBrowser2 *iface, LONG *pl) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_Width(IWebBrowser2 *iface, LONG Width) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Height(IWebBrowser2 *iface, LONG *pl) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_Height(IWebBrowser2 *iface, LONG Height) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_LocationName(IWebBrowser2 *iface, BSTR *LocationName) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_LocationURL(IWebBrowser2 *iface, BSTR *LocationURL) +{ + CHECK_EXPECT(get_LocationURL); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Busy(IWebBrowser2 *iface, VARIANT_BOOL *pBool) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_Quit(IWebBrowser2 *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_ClientToWindow(IWebBrowser2 *iface, int *pcx, int *pcy) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_PutProperty(IWebBrowser2 *iface, BSTR szProperty, VARIANT vtValue) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_GetProperty(IWebBrowser2 *iface, BSTR szProperty, VARIANT *pvtValue) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Name(IWebBrowser2 *iface, BSTR *Name) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_HWND(IWebBrowser2 *iface, LONG *pHWND) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_FullName(IWebBrowser2 *iface, BSTR *FullName) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Path(IWebBrowser2 *iface, BSTR *Path) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Visible(IWebBrowser2 *iface, VARIANT_BOOL *pBool) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_Visible(IWebBrowser2 *iface, VARIANT_BOOL Value) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_StatusBar(IWebBrowser2 *iface, VARIANT_BOOL *pBool) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_StatusBar(IWebBrowser2 *iface, VARIANT_BOOL Value) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_StatusText(IWebBrowser2 *iface, BSTR *StatusText) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_StatusText(IWebBrowser2 *iface, BSTR StatusText) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_ToolBar(IWebBrowser2 *iface, int *Value) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_ToolBar(IWebBrowser2 *iface, int Value) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_MenuBar(IWebBrowser2 *iface, VARIANT_BOOL *Value) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_MenuBar(IWebBrowser2 *iface, VARIANT_BOOL Value) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_FullScreen(IWebBrowser2 *iface, VARIANT_BOOL *pbFullScreen) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_FullScreen(IWebBrowser2 *iface, VARIANT_BOOL bFullScreen) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_Navigate2(IWebBrowser2 *iface, VARIANT *URL, VARIANT *Flags, + VARIANT *TargetFrameName, VARIANT *PostData, VARIANT *Headers) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_QueryStatusWB(IWebBrowser2 *iface, OLECMDID cmdID, OLECMDF *pcmdf) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_ExecWB(IWebBrowser2 *iface, OLECMDID cmdID, + OLECMDEXECOPT cmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_ShowBrowserBar(IWebBrowser2 *iface, VARIANT *pvaClsid, + VARIANT *pvarShow, VARIANT *pvarSize) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_ReadyState(IWebBrowser2 *iface, READYSTATE *lpReadyState) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Offline(IWebBrowser2 *iface, VARIANT_BOOL *pbOffline) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_Offline(IWebBrowser2 *iface, VARIANT_BOOL bOffline) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Silent(IWebBrowser2 *iface, VARIANT_BOOL *pbSilent) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_Silent(IWebBrowser2 *iface, VARIANT_BOOL bSilent) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_RegisterAsBrowser(IWebBrowser2 *iface, + VARIANT_BOOL *pbRegister) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_RegisterAsBrowser(IWebBrowser2 *iface, + VARIANT_BOOL bRegister) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_RegisterAsDropTarget(IWebBrowser2 *iface, + VARIANT_BOOL *pbRegister) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_RegisterAsDropTarget(IWebBrowser2 *iface, + VARIANT_BOOL bRegister) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_TheaterMode(IWebBrowser2 *iface, VARIANT_BOOL *pbRegister) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_TheaterMode(IWebBrowser2 *iface, VARIANT_BOOL bRegister) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_AddressBar(IWebBrowser2 *iface, VARIANT_BOOL *Value) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_AddressBar(IWebBrowser2 *iface, VARIANT_BOOL Value) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Resizable(IWebBrowser2 *iface, VARIANT_BOOL *Value) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_Resizable(IWebBrowser2 *iface, VARIANT_BOOL Value) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const IWebBrowser2Vtbl WebBrowser2Vtbl = +{ + WebBrowser_QueryInterface, + WebBrowser_AddRef, + WebBrowser_Release, + WebBrowser_GetTypeInfoCount, + WebBrowser_GetTypeInfo, + WebBrowser_GetIDsOfNames, + WebBrowser_Invoke, + WebBrowser_GoBack, + WebBrowser_GoForward, + WebBrowser_GoHome, + WebBrowser_GoSearch, + WebBrowser_Navigate, + WebBrowser_Refresh, + WebBrowser_Refresh2, + WebBrowser_Stop, + WebBrowser_get_Application, + WebBrowser_get_Parent, + WebBrowser_get_Container, + WebBrowser_get_Document, + WebBrowser_get_TopLevelContainer, + WebBrowser_get_Type, + WebBrowser_get_Left, + WebBrowser_put_Left, + WebBrowser_get_Top, + WebBrowser_put_Top, + WebBrowser_get_Width, + WebBrowser_put_Width, + WebBrowser_get_Height, + WebBrowser_put_Height, + WebBrowser_get_LocationName, + WebBrowser_get_LocationURL, + WebBrowser_get_Busy, + WebBrowser_Quit, + WebBrowser_ClientToWindow, + WebBrowser_PutProperty, + WebBrowser_GetProperty, + WebBrowser_get_Name, + WebBrowser_get_HWND, + WebBrowser_get_FullName, + WebBrowser_get_Path, + WebBrowser_get_Visible, + WebBrowser_put_Visible, + WebBrowser_get_StatusBar, + WebBrowser_put_StatusBar, + WebBrowser_get_StatusText, + WebBrowser_put_StatusText, + WebBrowser_get_ToolBar, + WebBrowser_put_ToolBar, + WebBrowser_get_MenuBar, + WebBrowser_put_MenuBar, + WebBrowser_get_FullScreen, + WebBrowser_put_FullScreen, + WebBrowser_Navigate2, + WebBrowser_QueryStatusWB, + WebBrowser_ExecWB, + WebBrowser_ShowBrowserBar, + WebBrowser_get_ReadyState, + WebBrowser_get_Offline, + WebBrowser_put_Offline, + WebBrowser_get_Silent, + WebBrowser_put_Silent, + WebBrowser_get_RegisterAsBrowser, + WebBrowser_put_RegisterAsBrowser, + WebBrowser_get_RegisterAsDropTarget, + WebBrowser_put_RegisterAsDropTarget, + WebBrowser_get_TheaterMode, + WebBrowser_put_TheaterMode, + WebBrowser_get_AddressBar, + WebBrowser_put_AddressBar, + WebBrowser_get_Resizable, + WebBrowser_put_Resizable +}; + +static IWebBrowser2 WebBrowser2 = { &WebBrowser2Vtbl }; + static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) { @@ -2752,7 +4502,6 @@ static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFG * STopLevelBrowser * IHTMLWindow2 * IInternetProtocol - * IWebBrowserApp * UrlHostory * IHTMLEditHost * IHlinkFrame @@ -2770,6 +4519,20 @@ static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFG return S_OK; } + if(IsEqualGUID(&IID_IShellBrowser, guidService)) { + ok(IsEqualGUID(&IID_IBrowserService, riid), "unexpected riid\n"); + *ppv = &BrowserService; + return S_OK; + } + + if(support_wbapp && IsEqualGUID(&IID_IWebBrowserApp, guidService)) { + if(IsEqualGUID(riid, &IID_IWebBrowser2)) { + *ppv = &WebBrowser2; + return S_OK; + } + ok(0, "unexpected riid %s\n", debugstr_guid(riid)); + } + return E_NOINTERFACE; } @@ -2941,6 +4704,11 @@ static HRESULT QueryInterface(REFIID riid, void **ppv) static LRESULT WINAPI wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + if(msg == WM_CONTINUE_BINDING) { + IBindStatusCallback *callback = (IBindStatusCallback*)wParam; + continue_binding(callback); + } + return DefWindowProc(hwnd, msg, wParam, lParam); } @@ -2963,7 +4731,7 @@ static void test_doscroll(IUnknown *unk) switch(load_state) { case LD_DOLOAD: case LD_NO: - if(!navigated_load) + if(!nav_url) ok(!elem, "elem != NULL\n"); default: break; @@ -3094,6 +4862,7 @@ static void test_ConnectionPoint(IConnectionPointContainer *container, REFIID ri IConnectionPoint *cp; IID iid; HRESULT hres; + DWORD cookie; hres = IConnectionPointContainer_FindConnectionPoint(container, riid, &cp); ok(hres == S_OK, "FindConnectionPoint failed: %08x\n", hres); @@ -3117,10 +4886,15 @@ static void test_ConnectionPoint(IConnectionPointContainer *container, REFIID ri ok(hres == E_POINTER, "GetConnectionPointContainer failed: %08x, expected E_POINTER\n", hres); if(IsEqualGUID(&IID_IPropertyNotifySink, riid)) { - DWORD cookie; - hres = IConnectionPoint_Advise(cp, (IUnknown*)&PropertyNotifySink, &cookie); ok(hres == S_OK, "Advise failed: %08x\n", hres); + hres = IConnectionPoint_Unadvise(cp, cookie); + ok(hres == S_OK, "Unadvise failed: %08x\n", hres); + hres = IConnectionPoint_Advise(cp, (IUnknown*)&PropertyNotifySink, NULL); + ok(hres == S_OK, "Advise failed: %08x\n", hres); + } else if(IsEqualGUID(&IID_IDispatch, riid)) { + hres = IConnectionPoint_Advise(cp, (IUnknown*)&EventDispatch, &cookie); + ok(hres == S_OK, "Advise failed: %08x\n", hres); } IConnectionPoint_Release(cp); @@ -3131,7 +4905,7 @@ static void test_ConnectionPointContainer(IHTMLDocument2 *doc) IConnectionPointContainer *container; HRESULT hres; - hres = IUnknown_QueryInterface(doc, &IID_IConnectionPointContainer, (void**)&container); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IConnectionPointContainer, (void**)&container); ok(hres == S_OK, "QueryInterface(IID_IConnectionPointContainer) failed: %08x\n", hres); if(FAILED(hres)) return; @@ -3144,6 +4918,21 @@ static void test_ConnectionPointContainer(IHTMLDocument2 *doc) IConnectionPointContainer_Release(container); } +static void set_custom_uihandler(IHTMLDocument2 *doc, IDocHostUIHandler2 *uihandler) +{ + ICustomDoc *custom_doc; + HRESULT hres; + + hres = IHTMLDocument2_QueryInterface(doc, &IID_ICustomDoc, (void**)&custom_doc); + ok(hres == S_OK, "Could not get ICustomDoc iface: %08x\n", hres); + + expect_uihandler_iface = uihandler; + + hres = ICustomDoc_SetUIHandler(custom_doc, (IDocHostUIHandler*)uihandler); + ICustomDoc_Release(custom_doc); + ok(hres == S_OK, "SetUIHandler failed: %08x\n", hres); +} + static void test_Load(IPersistMoniker *persist, IMoniker *mon) { IBindCtx *bind; @@ -3184,7 +4973,7 @@ static void test_Load(IPersistMoniker *persist, IMoniker *mon) SET_EXPECT(LockContainer); } SET_EXPECT(OnChanged_READYSTATE); - SET_EXPECT(Exec_ShellDocView_84); + SET_EXPECT(Invoke_OnReadyStateChange_Loading); SET_EXPECT(IsSystemMoniker); if(mon == &Moniker) SET_EXPECT(BindToStorage); @@ -3193,7 +4982,12 @@ static void test_Load(IPersistMoniker *persist, IMoniker *mon) SET_EXPECT(Invoke_AMBIENT_SILENT); SET_EXPECT(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); SET_EXPECT(Exec_ShellDocView_37); + SET_EXPECT(IsErrorUrl); + }else { + SET_EXPECT(GetTravelLog); } + SET_EXPECT(Exec_ShellDocView_84); + SET_EXPECT(GetPendingUrl); load_state = LD_DOLOAD; expect_LockContainer_fLock = TRUE; readystate_set_loading = TRUE; @@ -3210,8 +5004,8 @@ static void test_Load(IPersistMoniker *persist, IMoniker *mon) CHECK_CALLED(Invoke_AMBIENT_SILENT); CHECK_CALLED(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); CHECK_CALLED(Invoke_AMBIENT_USERAGENT); - CHECK_CALLED(Invoke_AMBIENT_PALETTE); - CHECK_CALLED(GetOptionKeyPath); + CLEAR_CALLED(Invoke_AMBIENT_PALETTE); /* not called on IE9 */ + CLEAR_CALLED(GetOptionKeyPath); /* not called on some IE9 */ CHECK_CALLED(GetOverrideKeyPath); CHECK_CALLED(GetWindow); CHECK_CALLED(Exec_DOCCANNAVIGATE); @@ -3226,16 +5020,21 @@ static void test_Load(IPersistMoniker *persist, IMoniker *mon) container_locked = TRUE; } CHECK_CALLED(OnChanged_READYSTATE); - SET_CALLED(IsSystemMoniker); /* IE7 */ - SET_CALLED(Exec_ShellDocView_84); + CHECK_CALLED(Invoke_OnReadyStateChange_Loading); + CLEAR_CALLED(IsSystemMoniker); /* IE7 */ if(mon == &Moniker) CHECK_CALLED(BindToStorage); - SET_CALLED(SetActiveObject); /* FIXME */ + CLEAR_CALLED(SetActiveObject); /* FIXME */ if(set_clientsite) { CHECK_CALLED(Invoke_AMBIENT_SILENT); CHECK_CALLED(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); CHECK_CALLED(Exec_ShellDocView_37); + todo_wine CHECK_CALLED_BROKEN(IsErrorUrl); + }else { + todo_wine CHECK_CALLED(GetTravelLog); } + CHECK_CALLED_BROKEN(Exec_ShellDocView_84); + todo_wine CHECK_CALLED(GetPendingUrl); set_clientsite = container_locked = TRUE; @@ -3246,32 +5045,48 @@ static void test_Load(IPersistMoniker *persist, IMoniker *mon) test_readyState((IUnknown*)persist); } -#define DWL_VERBDONE 0x0001 -#define DWL_CSS 0x0002 -#define DWL_TRYCSS 0x0004 -#define DWL_HTTP 0x0008 -#define DWL_EMPTY 0x0010 +#define DWL_VERBDONE 0x0001 +#define DWL_CSS 0x0002 +#define DWL_TRYCSS 0x0004 +#define DWL_HTTP 0x0008 +#define DWL_EMPTY 0x0010 +#define DWL_JAVASCRIPT 0x0020 +#define DWL_ONREADY_LOADING 0x0040 +#define DWL_EXPECT_HISTUPDATE 0x0080 +#define DWL_FROM_HISTORY 0x0100 +#define DWL_REFRESH 0x0200 static void test_download(DWORD flags) { + const BOOL is_js = (flags & DWL_JAVASCRIPT) != 0; HWND hwnd; + BOOL *b; MSG msg; + b = is_js ? &called_Exec_SETDOWNLOADSTATE_0 : &called_Exec_HTTPEQUIV_DONE; + is_refresh = (flags & DWL_REFRESH) != 0; + hwnd = FindWindowA("Internet Explorer_Hidden", NULL); ok(hwnd != NULL, "Could not find hidden window\n"); test_readyState(NULL); + if(flags & DWL_REFRESH) { + SET_EXPECT(Invoke_AMBIENT_SILENT); + SET_EXPECT(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); + } if(flags & (DWL_VERBDONE|DWL_HTTP)) SET_EXPECT(Exec_SETPROGRESSMAX); - if((flags & DWL_VERBDONE) && !load_from_stream) + if((flags & DWL_VERBDONE) && !load_from_stream && !is_js) SET_EXPECT(GetHostInfo); SET_EXPECT(SetStatusText); if(!(flags & DWL_EMPTY)) SET_EXPECT(Exec_SETDOWNLOADSTATE_1); + if(is_js) + SET_EXPECT(GetExternal); SET_EXPECT(OnViewChange); SET_EXPECT(GetDropTarget); - if(flags & DWL_TRYCSS) + if((flags & DWL_TRYCSS) && !(flags & DWL_EMPTY)) SET_EXPECT(Exec_ShellDocView_84); if(flags & DWL_CSS) { SET_EXPECT(CreateInstance); @@ -3281,19 +5096,27 @@ static void test_download(DWORD flags) SET_EXPECT(Protocol_Read); SET_EXPECT(UnlockRequest); } + if(flags & DWL_ONREADY_LOADING) + SET_EXPECT(Invoke_OnReadyStateChange_Loading); + if(!(flags & (DWL_EMPTY|DWL_JAVASCRIPT))) + SET_EXPECT(Invoke_OnReadyStateChange_Interactive); + if(!is_js) + SET_EXPECT(Invoke_OnReadyStateChange_Complete); 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 */ - if(navigated_load) + if((nav_url && !is_js) || (flags & (DWL_CSS|DWL_HTTP))) SET_EXPECT(Exec_ShellDocView_37); if(flags & DWL_HTTP) { - SET_EXPECT(OnChanged_1012); + if(!(flags & DWL_FROM_HISTORY)) + SET_EXPECT(OnChanged_1012); SET_EXPECT(Exec_HTTPEQUIV); SET_EXPECT(Exec_SETTITLE); } - SET_EXPECT(OnChanged_1005); + if(!is_js) + SET_EXPECT(OnChanged_1005); SET_EXPECT(OnChanged_READYSTATE); SET_EXPECT(Exec_SETPROGRESSPOS); if(!(flags & DWL_EMPTY)) @@ -3301,27 +5124,47 @@ static void test_download(DWORD flags) SET_EXPECT(Exec_ShellDocView_103); SET_EXPECT(Exec_ShellDocView_105); SET_EXPECT(Exec_ShellDocView_140); - SET_EXPECT(Exec_MSHTML_PARSECOMPLETE); - SET_EXPECT(Exec_HTTPEQUIV_DONE); + if(!is_js) { + SET_EXPECT(Exec_MSHTML_PARSECOMPLETE); + if(support_wbapp) /* Called on some Vista installations */ + SET_EXPECT(CountEntries); + SET_EXPECT(Exec_HTTPEQUIV_DONE); + } SET_EXPECT(SetStatusText); - if(navigated_load) { + if(nav_url || support_wbapp) { SET_EXPECT(UpdateUI); SET_EXPECT(Exec_UPDATECOMMANDS); SET_EXPECT(Exec_SETTITLE); + if(flags & DWL_EXPECT_HISTUPDATE) + SET_EXPECT(Exec_Explorer_38); + SET_EXPECT(UpdateBackForwardState); } + if(!is_js) { + if(!editmode && !(flags & DWL_REFRESH)) { + if(!(flags & DWL_EMPTY)) + SET_EXPECT(FireNavigateComplete2); + SET_EXPECT(FireDocumentComplete); + } + SET_EXPECT(ActiveElementChanged); + } + SET_EXPECT(IsErrorUrl); expect_status_text = (LPWSTR)0xdeadbeef; /* TODO */ - while(!called_Exec_HTTPEQUIV_DONE && GetMessage(&msg, NULL, 0, 0)) { + while(!*b && GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } + if(flags & DWL_REFRESH) { + CHECK_CALLED(Invoke_AMBIENT_SILENT); + CHECK_CALLED(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); + } if(flags & DWL_VERBDONE) CHECK_CALLED(Exec_SETPROGRESSMAX); if(flags & DWL_HTTP) SET_CALLED(Exec_SETPROGRESSMAX); - if((flags & DWL_VERBDONE) && !load_from_stream) { - if(navigated_load) + if((flags & DWL_VERBDONE) && !load_from_stream && !is_js) { + if(nav_url) todo_wine CHECK_CALLED(GetHostInfo); else CHECK_CALLED(GetHostInfo); @@ -3329,13 +5172,12 @@ static void test_download(DWORD flags) CHECK_CALLED(SetStatusText); if(!(flags & DWL_EMPTY)) CHECK_CALLED(Exec_SETDOWNLOADSTATE_1); + if(is_js) + CHECK_CALLED(GetExternal); CHECK_CALLED(OnViewChange); - if(navigated_load) - CHECK_CALLED(GetDropTarget); - else - SET_CALLED(GetDropTarget); - if(flags & DWL_TRYCSS) - SET_CALLED(Exec_ShellDocView_84); + CLEAR_CALLED(GetDropTarget); + if((flags & DWL_TRYCSS) && !(flags & DWL_EMPTY)) + todo_wine CHECK_CALLED_BROKEN(Exec_ShellDocView_84); if(flags & DWL_CSS) { CHECK_CALLED(CreateInstance); CHECK_CALLED(Start); @@ -3344,34 +5186,71 @@ static void test_download(DWORD flags) CHECK_CALLED(Protocol_Read); CHECK_CALLED(UnlockRequest); } + if(flags & DWL_ONREADY_LOADING) + CHECK_CALLED(Invoke_OnReadyStateChange_Loading); + if(!(flags & (DWL_EMPTY|DWL_JAVASCRIPT))) + CHECK_CALLED(Invoke_OnReadyStateChange_Interactive); + if(!is_js) + CHECK_CALLED(Invoke_OnReadyStateChange_Complete); 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 */ - if(navigated_load) + if(nav_url && !is_js && !(flags & DWL_REFRESH)) todo_wine CHECK_CALLED(Exec_ShellDocView_37); - if(flags & DWL_HTTP) todo_wine { - CHECK_CALLED(OnChanged_1012); - CHECK_CALLED(Exec_HTTPEQUIV); - CHECK_CALLED(Exec_SETTITLE); + else if(flags & (DWL_CSS|DWL_HTTP)) + CLEAR_CALLED(Exec_ShellDocView_37); /* Called by IE9 */ + if(flags & DWL_HTTP) { + if(!(flags & DWL_FROM_HISTORY)) + todo_wine CHECK_CALLED(OnChanged_1012); + todo_wine CHECK_CALLED(Exec_HTTPEQUIV); + if(!(flags & DWL_REFRESH)) + todo_wine CHECK_CALLED(Exec_SETTITLE); + else + CHECK_CALLED(Exec_SETTITLE); + } + if(!is_js) { + CHECK_CALLED(OnChanged_1005); + CHECK_CALLED(OnChanged_READYSTATE); + CHECK_CALLED(Exec_SETPROGRESSPOS); + }else { + CLEAR_CALLED(OnChanged_READYSTATE); /* sometimes called */ + todo_wine CHECK_CALLED(Exec_SETPROGRESSPOS); } - CHECK_CALLED(OnChanged_1005); - CHECK_CALLED(OnChanged_READYSTATE); - CHECK_CALLED(Exec_SETPROGRESSPOS); if(!(flags & DWL_EMPTY)) CHECK_CALLED(Exec_SETDOWNLOADSTATE_0); - SET_CALLED(Exec_ShellDocView_103); - SET_CALLED(Exec_ShellDocView_105); - SET_CALLED(Exec_ShellDocView_140); - CHECK_CALLED(Exec_MSHTML_PARSECOMPLETE); - CHECK_CALLED(Exec_HTTPEQUIV_DONE); - SET_CALLED(SetStatusText); - if(navigated_load) { /* avoiding race, FIXME: fund better way */ - SET_CALLED(UpdateUI); - SET_CALLED(Exec_UPDATECOMMANDS); - SET_CALLED(Exec_SETTITLE); + CLEAR_CALLED(Exec_ShellDocView_103); + CLEAR_CALLED(Exec_ShellDocView_105); + CLEAR_CALLED(Exec_ShellDocView_140); + if(!is_js) { + CHECK_CALLED(Exec_MSHTML_PARSECOMPLETE); + if(support_wbapp) /* Called on some Vista installations */ + CLEAR_CALLED(CountEntries); + CHECK_CALLED(Exec_HTTPEQUIV_DONE); } + SET_CALLED(SetStatusText); + if(nav_url || support_wbapp) { /* avoiding race, FIXME: find better way */ + CLEAR_CALLED(UpdateUI); + CLEAR_CALLED(Exec_UPDATECOMMANDS); + CLEAR_CALLED(Exec_SETTITLE); + if(flags & DWL_EXPECT_HISTUPDATE) + CHECK_CALLED(Exec_Explorer_38); + todo_wine CHECK_CALLED_BROKEN(UpdateBackForwardState); + } + if(!is_js) { + if(!editmode && !(flags & DWL_REFRESH)) { + if(!(flags & DWL_EMPTY)) { + if(support_wbapp) + CHECK_CALLED(FireNavigateComplete2); + else + todo_wine CHECK_CALLED(FireNavigateComplete2); + } + CHECK_CALLED(FireDocumentComplete); + } + todo_wine CHECK_CALLED(ActiveElementChanged); + } + todo_wine CHECK_CALLED_BROKEN(IsErrorUrl); load_state = LD_COMPLETE; @@ -3385,20 +5264,20 @@ static void test_Persist(IHTMLDocument2 *doc, IMoniker *mon) GUID guid; HRESULT hres; - hres = IUnknown_QueryInterface(doc, &IID_IPersistFile, (void**)&persist_file); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IPersistFile, (void**)&persist_file); ok(hres == S_OK, "QueryInterface(IID_IPersist) failed: %08x\n", hres); if(SUCCEEDED(hres)) { - hres = IPersist_GetClassID(persist_file, NULL); + hres = IPersistFile_GetClassID(persist_file, NULL); ok(hres == E_INVALIDARG, "GetClassID returned: %08x, expected E_INVALIDARG\n", hres); - hres = IPersist_GetClassID(persist_file, &guid); + hres = IPersistFile_GetClassID(persist_file, &guid); ok(hres == S_OK, "GetClassID failed: %08x\n", hres); ok(IsEqualGUID(&CLSID_HTMLDocument, &guid), "guid != CLSID_HTMLDocument\n"); - IPersist_Release(persist_file); + IPersistFile_Release(persist_file); } - hres = IUnknown_QueryInterface(doc, &IID_IPersistMoniker, (void**)&persist_mon); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IPersistMoniker, (void**)&persist_mon); ok(hres == S_OK, "QueryInterface(IID_IPersistMoniker) failed: %08x\n", hres); if(SUCCEEDED(hres)) { hres = IPersistMoniker_GetClassID(persist_mon, NULL); @@ -3417,30 +5296,104 @@ static void test_Persist(IHTMLDocument2 *doc, IMoniker *mon) } } -static void test_put_href(IHTMLDocument2 *doc) +static void test_put_href(IHTMLDocument2 *doc, BOOL use_replace, const char *href, const char *new_nav_url, BOOL is_js, + BOOL is_hash, DWORD dwl_flags) { + const char *prev_nav_url = NULL; IHTMLPrivateWindow *priv_window; - IHTMLWindow2 *window; IHTMLLocation *location; + IHTMLWindow2 *window; BSTR str, str2; - VARIANT vempty; HRESULT hres; + trace("put_href %s...\n", new_nav_url); + + loading_js = is_js; + loading_hash = is_hash; + location = NULL; hres = IHTMLDocument2_get_location(doc, &location); ok(hres == S_OK, "get_location failed: %08x\n", hres); ok(location != NULL, "location == NULL\n"); + prev_url = prev_nav_url = nav_url; + nav_url = new_nav_url; + if(!loading_hash) + nav_serv_url = new_nav_url; + if(!href) + href = new_nav_url; + + str = a2bstr(href); SET_EXPECT(TranslateUrl); - SET_EXPECT(Navigate); - str = a2bstr("about:blank"); - hres = IHTMLLocation_put_href(location, str); - ok(hres == S_OK, "put_href failed: %08x\n", hres); - CHECK_CALLED(TranslateUrl); - CHECK_CALLED(Navigate); + if(support_wbapp) { + SET_EXPECT(FireBeforeNavigate2); + SET_EXPECT(Exec_ShellDocView_67); + if(!is_hash) { + SET_EXPECT(Invoke_AMBIENT_SILENT); + SET_EXPECT(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); + SET_EXPECT(Exec_ShellDocView_63); + SET_EXPECT(Exec_ShellDocView_84); + }else { + SET_EXPECT(FireNavigateComplete2); + SET_EXPECT(FireDocumentComplete); + } + }else { + SET_EXPECT(Navigate); + } + if(use_replace) { + hres = IHTMLLocation_replace(location, str); + ok(hres == S_OK, "put_href failed: %08x\n", hres); + }else { + hres = IHTMLLocation_put_href(location, str); + if(is_js && hres == E_ACCESSDENIED) + win_skip("put_href: got E_ACCESSDENIED\n"); + else + ok(hres == S_OK, "put_href failed: %08x\n", hres); + } + SysFreeString(str); + if(hres == S_OK) { + CHECK_CALLED(TranslateUrl); + if(support_wbapp) { + CHECK_CALLED(FireBeforeNavigate2); + CHECK_CALLED(Exec_ShellDocView_67); + if(!is_hash) { + CHECK_CALLED(Invoke_AMBIENT_SILENT); + CHECK_CALLED(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); + CHECK_CALLED(Exec_ShellDocView_63); + CHECK_CALLED_BROKEN(Exec_ShellDocView_84); + }else { + CHECK_CALLED(FireNavigateComplete2); + CHECK_CALLED(FireDocumentComplete); + } + }else { + CHECK_CALLED(Navigate); + } + }else { + CLEAR_CALLED(TranslateUrl); + if(support_wbapp) { + CLEAR_CALLED(FireBeforeNavigate2); + SET_CALLED(Exec_ShellDocView_67); + if(!is_hash) { + CLEAR_CALLED(Invoke_AMBIENT_SILENT); + CLEAR_CALLED(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); + CLEAR_CALLED(Exec_ShellDocView_63); + todo_wine CLEAR_CALLED(Exec_ShellDocView_84); + }else { + CLEAR_CALLED(FireNavigateComplete2); + CLEAR_CALLED(FireDocumentComplete); + } + }else { + CLEAR_CALLED(Navigate); + } + } IHTMLLocation_Release(location); + if(is_js && hres == E_ACCESSDENIED) { + nav_url = prev_nav_url; + return; + } + hres = IHTMLDocument2_get_parentWindow(doc, &window); ok(hres == S_OK, "get_parentWindow failed: %08x\n", hres); @@ -3448,70 +5401,200 @@ static void test_put_href(IHTMLDocument2 *doc) IHTMLWindow2_Release(window); ok(hres == S_OK, "QueryInterface(IID_IHTMLPrivateWindow) failed: %08x\n", hres); - readystate_set_loading = TRUE; - navigated_load = TRUE; - SET_EXPECT(TranslateUrl); - SET_EXPECT(Exec_ShellDocView_67); - SET_EXPECT(Invoke_AMBIENT_SILENT); - SET_EXPECT(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); - SET_EXPECT(OnChanged_READYSTATE); - SET_EXPECT(Exec_ShellDocView_63); + if(!support_wbapp) { + VARIANT vempty; - str2 = a2bstr(""); - V_VT(&vempty) = VT_EMPTY; - hres = IHTMLPrivateWindow_SuperNavigate(priv_window, str, str2, NULL, NULL, &vempty, &vempty, 0); - SysFreeString(str); + readystate_set_loading = TRUE; + SET_EXPECT(TranslateUrl); + SET_EXPECT(Exec_ShellDocView_67); + SET_EXPECT(Invoke_AMBIENT_SILENT); + SET_EXPECT(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); + SET_EXPECT(Exec_ShellDocView_63); + SET_EXPECT(Exec_ShellDocView_84); + + str = a2bstr(nav_url); + str2 = a2bstr(""); + V_VT(&vempty) = VT_EMPTY; + hres = IHTMLPrivateWindow_SuperNavigate(priv_window, str, str2, NULL, NULL, &vempty, &vempty, 0); + SysFreeString(str); + SysFreeString(str2); + ok(hres == S_OK, "SuperNavigate failed: %08x\n", hres); + + CHECK_CALLED(TranslateUrl); + CHECK_CALLED(Exec_ShellDocView_67); + CHECK_CALLED(Invoke_AMBIENT_SILENT); + CHECK_CALLED(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); + CHECK_CALLED(Exec_ShellDocView_63); + CHECK_CALLED_BROKEN(Exec_ShellDocView_84); + } + + if(doc_mon) { + test_GetCurMoniker(doc_unk, doc_mon, NULL); + doc_mon = NULL; + } + + if(!is_hash) { + hres = IHTMLPrivateWindow_GetAddressBarUrl(priv_window, &str2); + ok(hres == S_OK, "GetAddressBarUrl failed: %08x\n", hres); + ok(!strcmp_wa(str2, prev_nav_url), "unexpected address bar url: %s, expected %s\n", wine_dbgstr_w(str2), prev_nav_url); + SysFreeString(str2); + + if(is_js) + ignore_external_qi = TRUE; + test_download(DWL_VERBDONE | (is_js ? DWL_JAVASCRIPT : DWL_ONREADY_LOADING) | dwl_flags); + if(is_js) + ignore_external_qi = FALSE; + + } + + hres = IHTMLPrivateWindow_GetAddressBarUrl(priv_window, &str2); + ok(hres == S_OK, "GetAddressBarUrl failed: %08x\n", hres); + if(is_js) + ok(!strcmp_wa(str2, prev_nav_url), "unexpected address bar url: %s\n", wine_dbgstr_w(str2)); + else + ok(!strcmp_wa(str2, nav_url), "unexpected address bar url: %s\n", wine_dbgstr_w(str2)); SysFreeString(str2); - ok(hres == S_OK, "SuperNavigate failed: %08x\n", hres); - - CHECK_CALLED(TranslateUrl); - CHECK_CALLED(Exec_ShellDocView_67); - CHECK_CALLED(Invoke_AMBIENT_SILENT); - CHECK_CALLED(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); - SET_CALLED(OnChanged_READYSTATE); /* not always called */ - CHECK_CALLED(Exec_ShellDocView_63); - - test_GetCurMoniker(doc_unk, doc_mon, NULL); IHTMLPrivateWindow_Release(priv_window); - test_download(DWL_VERBDONE); + loading_js = FALSE; + if(is_js) + nav_url = prev_nav_url; } -static void test_open_window(IHTMLDocument2 *doc) +static void test_load_history(IHTMLDocument2 *doc) +{ + IPersistHistory *per_hist; + HRESULT hres; + + trace("LoadHistory...\n"); + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IPersistHistory, (void**)&per_hist); + ok(hres == S_OK, "Could not get IPersistHistory iface: %08x\n", hres); + + prev_url = nav_url; + nav_url = "http://www.winehq.org/#test"; + nav_serv_url = "http://www.winehq.org/"; + + SET_EXPECT(Exec_ShellDocView_138); + SET_EXPECT(Exec_ShellDocView_67); + SET_EXPECT(FireBeforeNavigate2); + SET_EXPECT(Invoke_AMBIENT_SILENT); + SET_EXPECT(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); + + hres = IPersistHistory_LoadHistory(per_hist, history_stream, NULL); + ok(hres == S_OK, "LoadHistory failed: %08x\n", hres); + + CHECK_CALLED_BROKEN(Exec_ShellDocView_138); + CHECK_CALLED(Exec_ShellDocView_67); + CHECK_CALLED(FireBeforeNavigate2); + CHECK_CALLED(Invoke_AMBIENT_SILENT); + CHECK_CALLED(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); + + load_state = LD_LOADING; + test_timer(EXPECT_UPDATEUI|EXPECT_SETTITLE); + + test_download(DWL_VERBDONE|DWL_HTTP|DWL_EXPECT_HISTUPDATE|DWL_ONREADY_LOADING|DWL_FROM_HISTORY); + + IPersistHistory_Release(per_hist); + IStream_Release(history_stream); + history_stream = NULL; +} + +static void test_refresh(IHTMLDocument2 *doc) +{ + IOleCommandTarget *cmdtrg; + VARIANT vin, vout; + HRESULT hres; + + trace("Refresh...\n"); + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleCommandTarget, (void**)&cmdtrg); + ok(hres == S_OK, "Could not get IOleCommandTarget iface: %08x\n", hres); + + V_VT(&vin) = VT_EMPTY; + V_VT(&vout) = VT_EMPTY; + SET_EXPECT(Exec_DocHostCommandHandler_2300); + hres = IOleCommandTarget_Exec(cmdtrg, NULL, OLECMDID_REFRESH, OLECMDEXECOPT_PROMPTUSER, &vin, &vout); + ok(hres == S_OK, "Exec failed: %08x\n", hres); + ok(V_VT(&vout) == VT_EMPTY, "V_VT(vout) = %d\n", V_VT(&vout)); + CHECK_CALLED(Exec_DocHostCommandHandler_2300); + + IOleCommandTarget_Release(cmdtrg); + + test_download(DWL_VERBDONE|DWL_HTTP|DWL_ONREADY_LOADING|DWL_REFRESH); +} + +static void test_open_window(IHTMLDocument2 *doc, BOOL do_block) { IHTMLWindow2 *window, *new_window; BSTR name, url; HRESULT hres; + allow_new_window = !do_block; + hres = IHTMLDocument2_get_parentWindow(doc, &window); ok(hres == S_OK, "get_parentWindow failed: %08x\n", hres); - url = a2bstr("about:blank"); + url = a2bstr(nav_serv_url = nav_url = "about:blank"); name = a2bstr("test"); new_window = (void*)0xdeadbeef; + trace("open...\n"); open_call = TRUE; + if(support_wbapp) + SET_EXPECT(get_LocationURL); SET_EXPECT(TranslateUrl); SET_EXPECT(EvaluateNewWindow); hres = IHTMLWindow2_open(window, url, name, NULL, VARIANT_FALSE, &new_window); - todo_wine - ok(hres == S_OK, "open failed: %08x\n", hres); - todo_wine - ok(new_window == NULL, "new_window != NULL\n"); - - todo_wine - CHECK_CALLED(TranslateUrl); - todo_wine - CHECK_CALLED(EvaluateNewWindow); - open_call = FALSE; SysFreeString(url); SysFreeString(name); + if(support_wbapp) + todo_wine CHECK_CALLED_BROKEN(get_LocationURL); + todo_wine + CHECK_CALLED(TranslateUrl); + + if(!called_EvaluateNewWindow) { + win_skip("INewWindowManager not supported\n"); + if(SUCCEEDED(hres) && new_window) + IHTMLWindow2_Release(new_window); + IHTMLWindow2_Release(window); + return; + } + CHECK_CALLED(EvaluateNewWindow); + + ok(hres == S_OK, "open failed: %08x\n", hres); + + if(do_block) { + ok(!new_window, "new_window != NULL\n"); + }else { + ok(new_window != NULL, "new_window == NULL\n"); + + hres = IHTMLWindow2_close(new_window); + ok(hres == S_OK, "close failed: %08x\n", hres); + } + IHTMLWindow2_Release(window); - SysFreeString(name); +} + +static void test_elem_from_point(IHTMLDocument2 *doc) +{ + IHTMLElement *elem; + BSTR tag; + HRESULT hres; + + elem = NULL; + hres = IHTMLDocument2_elementFromPoint(doc, 3, 3, &elem); + ok(hres == S_OK, "elementFromPoint failed: %08x\n", hres); + ok(elem != NULL, "elem == NULL\n"); + + hres = IHTMLElement_get_tagName(elem, &tag); + IHTMLElement_Release(elem); + ok(hres == S_OK, "get_tagName failed: %08x\n", hres); + ok(!strcmp_wa(tag, "DIV"), "tag = %s\n", wine_dbgstr_w(tag)); } static void test_clear(IHTMLDocument2 *doc) @@ -3614,7 +5697,7 @@ static void test_OleCommandTarget(IHTMLDocument2 *doc) int i; HRESULT hres; - hres = IUnknown_QueryInterface(doc, &IID_IOleCommandTarget, (void**)&cmdtrg); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleCommandTarget, (void**)&cmdtrg); ok(hres == S_OK, "QueryInterface(IID_IOleCommandTarget failed: %08x\n", hres); if(FAILED(hres)) return; @@ -3656,7 +5739,7 @@ static void test_OleCommandTarget_fail(IHTMLDocument2 *doc) {OLECMDID_GETPRINTTEMPLATE+1, 0xf0f0} }; - hres = IUnknown_QueryInterface(doc, &IID_IOleCommandTarget, (void**)&cmdtrg); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleCommandTarget, (void**)&cmdtrg); ok(hres == S_OK, "QueryInterface(IIDIOleCommandTarget failed: %08x\n", hres); if(FAILED(hres)) return; @@ -3703,7 +5786,7 @@ static void test_exec_onunload(IHTMLDocument2 *doc) VARIANT var; HRESULT hres; - hres = IUnknown_QueryInterface(doc, &IID_IOleCommandTarget, (void**)&cmdtrg); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleCommandTarget, (void**)&cmdtrg); ok(hres == S_OK, "QueryInterface(IID_IOleCommandTarget) failed: %08x\n", hres); if(FAILED(hres)) return; @@ -3747,6 +5830,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(Invoke_OnReadyStateChange_Loading); SET_EXPECT(IsSystemMoniker); SET_EXPECT(Exec_ShellDocView_84); if(loaded) @@ -3773,8 +5857,9 @@ 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); + CHECK_CALLED(Invoke_OnReadyStateChange_Loading); + CLEAR_CALLED(IsSystemMoniker); /* IE7 */ + CHECK_CALLED_BROKEN(Exec_ShellDocView_84); if(loaded) CHECK_CALLED(BindToStorage); CHECK_CALLED(InPlaceUIWindow_SetActiveObject); @@ -3859,7 +5944,7 @@ static void test_IsDirty(IHTMLDocument2 *doc, HRESULT exhres) IPersistFile *perfile; HRESULT hres; - hres = IUnknown_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&perinit); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&perinit); ok(hres == S_OK, "QueryInterface(IID_IPersistStreamInit failed: %08x\n", hres); if(SUCCEEDED(hres)) { hres = IPersistStreamInit_IsDirty(perinit); @@ -3867,7 +5952,7 @@ static void test_IsDirty(IHTMLDocument2 *doc, HRESULT exhres) IPersistStreamInit_Release(perinit); } - hres = IUnknown_QueryInterface(doc, &IID_IPersistMoniker, (void**)&permon); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IPersistMoniker, (void**)&permon); ok(hres == S_OK, "QueryInterface(IID_IPersistMoniker failed: %08x\n", hres); if(SUCCEEDED(hres)) { hres = IPersistMoniker_IsDirty(permon); @@ -3875,7 +5960,7 @@ static void test_IsDirty(IHTMLDocument2 *doc, HRESULT exhres) IPersistMoniker_Release(permon); } - hres = IUnknown_QueryInterface(doc, &IID_IPersistFile, (void**)&perfile); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IPersistFile, (void**)&perfile); ok(hres == S_OK, "QueryInterface(IID_IPersistFile failed: %08x\n", hres); if(SUCCEEDED(hres)) { hres = IPersistFile_IsDirty(perfile); @@ -3937,10 +6022,16 @@ static void test_ClientSite(IOleObject *oleobj, DWORD flags) if(flags & CLIENTSITE_SETNULL) { hres = IOleObject_GetClientSite(oleobj, &clientsite); - ok(clientsite == &ClientSite, "clientsite=%p, expected %p\n", clientsite, &ClientSite); + ok(hres == S_OK, "SetClientSite failed: %08x\n", hres); + if(set_clientsite) + ok(clientsite == &ClientSite, "clientsite=%p, expected %p\n", clientsite, &ClientSite); + else + ok(!clientsite, "clientsite != NULL\n"); + SET_EXPECT(GetOverrideKeyPath); hres = IOleObject_SetClientSite(oleobj, NULL); ok(hres == S_OK, "SetClientSite failed: %08x\n", hres); + CLEAR_CALLED(GetOverrideKeyPath); /* IE9 sometimes calls it */ set_clientsite = FALSE; } @@ -3948,13 +6039,17 @@ static void test_ClientSite(IOleObject *oleobj, DWORD flags) if(flags & CLIENTSITE_DONTSET) return; + if(!expect_uihandler_iface) + expect_uihandler_iface = &DocHostUIHandler; + hres = IOleObject_GetClientSite(oleobj, &clientsite); ok(hres == S_OK, "GetClientSite failed: %08x\n", hres); ok(clientsite == (set_clientsite ? &ClientSite : NULL), "GetClientSite() = %p, expected %p\n", clientsite, set_clientsite ? &ClientSite : NULL); if(!set_clientsite) { - SET_EXPECT(GetHostInfo); + if(expect_uihandler_iface) + SET_EXPECT(GetHostInfo); if(flags & CLIENTSITE_EXPECTPATH) { SET_EXPECT(GetOptionKeyPath); SET_EXPECT(GetOverrideKeyPath); @@ -3971,13 +6066,17 @@ static void test_ClientSite(IOleObject *oleobj, DWORD flags) SET_EXPECT(Invoke_AMBIENT_SILENT); SET_EXPECT(Invoke_AMBIENT_USERAGENT); SET_EXPECT(Invoke_AMBIENT_PALETTE); + SET_EXPECT(GetOverrideKeyPath); + SET_EXPECT(GetTravelLog); + SET_EXPECT(Exec_ShellDocView_84); hres = IOleObject_SetClientSite(oleobj, &ClientSite); ok(hres == S_OK, "SetClientSite failed: %08x\n", hres); - CHECK_CALLED(GetHostInfo); + if(expect_uihandler_iface) + CHECK_CALLED(GetHostInfo); if(flags & CLIENTSITE_EXPECTPATH) { - CHECK_CALLED(GetOptionKeyPath); + CLEAR_CALLED(GetOptionKeyPath); /* not called on some IE9 */ CHECK_CALLED(GetOverrideKeyPath); } CHECK_CALLED(GetWindow); @@ -3991,7 +6090,10 @@ static void test_ClientSite(IOleObject *oleobj, DWORD flags) CHECK_CALLED(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); CHECK_CALLED(Invoke_AMBIENT_SILENT); CHECK_CALLED(Invoke_AMBIENT_USERAGENT); - CHECK_CALLED(Invoke_AMBIENT_PALETTE); + CLEAR_CALLED(Invoke_AMBIENT_PALETTE); /* not called on IE9 */ + CLEAR_CALLED(GetOverrideKeyPath); /* Called by IE9 */ + todo_wine CHECK_CALLED(GetTravelLog); + CHECK_CALLED_BROKEN(Exec_ShellDocView_84); set_clientsite = TRUE; } @@ -4009,7 +6111,7 @@ static void test_OnAmbientPropertyChange(IHTMLDocument2 *doc) IOleControl *control = NULL; HRESULT hres; - hres = IUnknown_QueryInterface(doc, &IID_IOleControl, (void**)&control); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleControl, (void**)&control); ok(hres == S_OK, "QueryInterface(IID_IOleControl failed: %08x\n", hres); if(FAILED(hres)) return; @@ -4046,7 +6148,7 @@ static void test_OnAmbientPropertyChange(IHTMLDocument2 *doc) SET_EXPECT(Invoke_AMBIENT_PALETTE); hres = IOleControl_OnAmbientPropertyChange(control, DISPID_AMBIENT_PALETTE); ok(hres == S_OK, "OnAmbientChange failed: %08x\n", hres); - CHECK_CALLED(Invoke_AMBIENT_PALETTE); + CLEAR_CALLED(Invoke_AMBIENT_PALETTE); /* not called on IE9 */ IOleControl_Release(control); } @@ -4058,7 +6160,7 @@ static void test_OnAmbientPropertyChange2(IHTMLDocument2 *doc) IOleControl *control = NULL; HRESULT hres; - hres = IUnknown_QueryInterface(doc, &IID_IOleControl, (void**)&control); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleControl, (void**)&control); ok(hres == S_OK, "QueryInterface(IID_IOleControl failed: %08x\n", hres); if(FAILED(hres)) return; @@ -4074,7 +6176,7 @@ static void test_Close(IHTMLDocument2 *doc, BOOL set_client) IOleObject *oleobj = NULL; HRESULT hres; - hres = IUnknown_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj); ok(hres == S_OK, "QueryInterface(IID_IOleObject) failed: %08x\n", hres); if(FAILED(hres)) return; @@ -4101,7 +6203,7 @@ static void test_Advise(IHTMLDocument2 *doc) DWORD conn; HRESULT hres; - hres = IUnknown_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj); ok(hres == S_OK, "QueryInterface(IID_IOleObject) failed: %08x\n", hres); if(FAILED(hres)) return; @@ -4191,13 +6293,14 @@ static void test_InPlaceDeactivate(IHTMLDocument2 *doc, BOOL expect_call) IOleInPlaceObjectWindowless *windowlessobj = NULL; HRESULT hres; - hres = IUnknown_QueryInterface(doc, &IID_IOleInPlaceObjectWindowless, + hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleInPlaceObjectWindowless, (void**)&windowlessobj); ok(hres == S_OK, "QueryInterface(IID_IOleInPlaceObjectWindowless) failed: %08x\n", hres); if(FAILED(hres)) return; if(expect_call) { + SET_EXPECT(SetStatusText); SET_EXPECT(OnFocus_FALSE); if(ipsex) SET_EXPECT(OnInPlaceDeactivateEx); @@ -4207,6 +6310,7 @@ static void test_InPlaceDeactivate(IHTMLDocument2 *doc, BOOL expect_call) hres = IOleInPlaceObjectWindowless_InPlaceDeactivate(windowlessobj); ok(hres == S_OK, "InPlaceDeactivate failed: %08x\n", hres); if(expect_call) { + CLEAR_CALLED(SetStatusText); /* Called by IE9 */ CHECK_CALLED(OnFocus_FALSE); if(ipsex) CHECK_CALLED(OnInPlaceDeactivateEx); @@ -4224,13 +6328,13 @@ static void test_Activate(IHTMLDocument2 *doc, DWORD flags) GUID guid; HRESULT hres; - last_hwnd = hwnd; + last_hwnd = doc_hwnd; if(view) IOleDocumentView_Release(view); view = NULL; - hres = IUnknown_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj); ok(hres == S_OK, "QueryInterface(IID_IOleObject) failed: %08x\n", hres); hres = IOleObject_GetUserClassID(oleobj, NULL); @@ -4289,10 +6393,10 @@ static void test_Window(IHTMLDocument2 *doc, BOOL expect_success) if(expect_success) { ok(hres == S_OK, "GetWindow failed: %08x\n", hres); - ok(tmp_hwnd == hwnd, "tmp_hwnd=%p, expected %p\n", tmp_hwnd, hwnd); + ok(tmp_hwnd == doc_hwnd, "tmp_hwnd=%p, expected %p\n", tmp_hwnd, doc_hwnd); }else { ok(hres == E_FAIL, "GetWindow returned %08x, expected E_FAIL\n", hres); - ok(IsWindow(hwnd), "hwnd is destroyed\n"); + ok(IsWindow(doc_hwnd), "hwnd is destroyed\n"); } IOleInPlaceActiveObject_Release(activeobject); @@ -4357,26 +6461,34 @@ static void test_Hide(void) ok(hres == S_OK, "Show failed: %08x\n", hres); } -static HRESULT create_document(IHTMLDocument2 **doc) +static IHTMLDocument2 *create_document(void) { - IHTMLDocument5 *doc5; + IHTMLDocument2 *doc; HRESULT hres; hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, - &IID_IHTMLDocument2, (void**)doc); + &IID_IHTMLDocument2, (void**)&doc); ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres); if(FAILED(hres)) - return hres; + return NULL; - hres = IHTMLDocument2_QueryInterface(*doc, &IID_IHTMLDocument5, (void**)&doc5); - if(SUCCEEDED(hres)) { - IHTMLDocument5_Release(doc5); - }else { - win_skip("Could not get IHTMLDocument5, probably too old IE\n"); - IHTMLDocument2_Release(*doc); - } + return doc; +} - return hres; +static void release_document(IHTMLDocument2 *doc) +{ + IUnknown *unk; + ULONG ref; + HRESULT hres; + + /* Some broken IEs don't like if the last released reference is IHTMLDocument2 iface. + * To workaround it, we release it via IUnknown iface */ + hres = IHTMLDocument2_QueryInterface(doc, &IID_IUnknown, (void**)&unk); + ok(hres == S_OK, "Could not get IUnknown iface: %08x\n", hres); + + IHTMLDocument2_Release(doc); + ref = IUnknown_Release(unk); + ok(!ref, "ref = %d\n", ref); } static void test_Navigate(IHTMLDocument2 *doc) @@ -4384,7 +6496,7 @@ static void test_Navigate(IHTMLDocument2 *doc) IHlinkTarget *hlink; HRESULT hres; - hres = IUnknown_QueryInterface(doc, &IID_IHlinkTarget, (void**)&hlink); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IHlinkTarget, (void**)&hlink); ok(hres == S_OK, "QueryInterface(IID_IHlinkTarget) failed: %08x\n", hres); SET_EXPECT(ActivateMe); @@ -4420,12 +6532,97 @@ static void test_external(IHTMLDocument2 *doc, BOOL initialized) IHTMLWindow2_Release(htmlwin); } +static void test_enum_objects(IOleContainer *container) +{ + IEnumUnknown *enum_unknown; + IUnknown *buf[100] = {(void*)0xdeadbeef}; + ULONG fetched; + HRESULT hres; + + enum_unknown = NULL; + hres = IOleContainer_EnumObjects(container, OLECONTF_EMBEDDINGS, &enum_unknown); + ok(hres == S_OK, "EnumObjects failed: %08x\n", hres); + ok(enum_unknown != NULL, "enum_unknown == NULL\n"); + + fetched = 0xdeadbeef; + hres = IEnumUnknown_Next(enum_unknown, sizeof(buf)/sizeof(*buf), buf, &fetched); + ok(hres == S_FALSE, "Next returned %08x\n", hres); + ok(!fetched, "fetched = %d\n", fetched); + ok(buf[0] == (void*)0xdeadbeef, "buf[0] = %p\n", buf[0]); + + fetched = 0xdeadbeef; + hres = IEnumUnknown_Next(enum_unknown, 1, buf, &fetched); + ok(hres == S_FALSE, "Next returned %08x\n", hres); + ok(!fetched, "fetched = %d\n", fetched); + + hres = IEnumUnknown_Next(enum_unknown, 1, buf, NULL); + ok(hres == S_FALSE, "Next returned %08x\n", hres); + + IEnumUnknown_Release(enum_unknown); +} + +static void test_target_container(IHTMLDocument2 *doc) +{ + IOleContainer *ole_container, *doc_ole_container; + ITargetContainer *target_container; + HRESULT hres; + + hres = IHTMLDocument2_QueryInterface(doc, &IID_ITargetContainer, (void**)&target_container); + ok(hres == S_OK, "Could not get ITargetContainer iface: %08x\n", hres); + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleContainer, (void**)&doc_ole_container); + ok(hres == S_OK, "Could not get ITargetContainer iface: %08x\n", hres); + + ole_container = (void*)0xdeadbeef; + hres = ITargetContainer_GetFramesContainer(target_container, &ole_container); + ok(hres == S_OK, "GetFramesContainer failed: %08x\n", hres); + ok(ole_container != NULL, "ole_container == NULL\n"); + ok(iface_cmp((IUnknown*)ole_container, (IUnknown*)doc_ole_container), "ole_container != doc_ole_container\n"); + test_enum_objects(ole_container); + IOleContainer_Release(ole_container); + + ITargetContainer_Release(target_container); + IOleContainer_Release(doc_ole_container); +} + +static void test_travellog(IHTMLDocument2 *doc) +{ + ITravelLogClient *travellog_client; + IHTMLWindow2 *window, *top_window; + IUnknown *unk; + HRESULT hres; + + window = NULL; + hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08x\n", hres); + ok(window != NULL, "window = NULL\n"); + + hres = IHTMLWindow2_get_top(window, &top_window); + IHTMLWindow2_Release(window); + ok(hres == S_OK, "get_top failed: %08x\n", hres); + + hres = IHTMLWindow2_QueryInterface(top_window, &IID_ITravelLogClient, (void**)&travellog_client); + IHTMLWindow2_Release(top_window); + if(hres == E_NOINTERFACE) { + win_skip("ITravelLogClient not supported\n"); + return; + } + ok(hres == S_OK, "Could not get ITraveLogClient iface: %08x\n", hres); + + unk = (void*)0xdeadbeef; + hres = ITravelLogClient_FindWindowByIndex(travellog_client, 0, &unk); + ok(hres == E_FAIL, "FindWindowByIndex failed: %08x\n", hres); + ok(!unk, "unk != NULL\n"); + + ITravelLogClient_Release(travellog_client); +} + static void test_StreamLoad(IHTMLDocument2 *doc) { IPersistStreamInit *init; HRESULT hres; - hres = IUnknown_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&init); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&init); ok(hres == S_OK, "QueryInterface(IID_IPersistStreamInit) failed: %08x\n", hres); if(FAILED(hres)) return; @@ -4434,7 +6631,9 @@ static void test_StreamLoad(IHTMLDocument2 *doc) SET_EXPECT(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); SET_EXPECT(Exec_ShellDocView_37); SET_EXPECT(OnChanged_READYSTATE); + SET_EXPECT(Invoke_OnReadyStateChange_Loading); SET_EXPECT(Read); + SET_EXPECT(GetPendingUrl); readystate_set_loading = TRUE; hres = IPersistStreamInit_Load(init, &Stream); @@ -4444,10 +6643,12 @@ static void test_StreamLoad(IHTMLDocument2 *doc) CHECK_CALLED(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); CHECK_CALLED(Exec_ShellDocView_37); CHECK_CALLED(OnChanged_READYSTATE); + CHECK_CALLED(Invoke_OnReadyStateChange_Loading); CHECK_CALLED(Read); + todo_wine CHECK_CALLED(GetPendingUrl); test_timer(EXPECT_SETTITLE); - test_GetCurMoniker((IUnknown*)doc, NULL, about_blank_url); + test_GetCurMoniker((IUnknown*)doc, NULL, "about:blank"); IPersistStreamInit_Release(init); } @@ -4457,7 +6658,7 @@ static void test_StreamInitNew(IHTMLDocument2 *doc) IPersistStreamInit *init; HRESULT hres; - hres = IUnknown_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&init); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&init); ok(hres == S_OK, "QueryInterface(IID_IPersistStreamInit) failed: %08x\n", hres); if(FAILED(hres)) return; @@ -4466,6 +6667,8 @@ static void test_StreamInitNew(IHTMLDocument2 *doc) SET_EXPECT(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); SET_EXPECT(Exec_ShellDocView_37); SET_EXPECT(OnChanged_READYSTATE); + SET_EXPECT(Invoke_OnReadyStateChange_Loading); + SET_EXPECT(GetPendingUrl); readystate_set_loading = TRUE; hres = IPersistStreamInit_InitNew(init); @@ -4475,16 +6678,18 @@ static void test_StreamInitNew(IHTMLDocument2 *doc) CHECK_CALLED(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); CHECK_CALLED(Exec_ShellDocView_37); CHECK_CALLED(OnChanged_READYSTATE); + CHECK_CALLED(Invoke_OnReadyStateChange_Loading); + todo_wine CHECK_CALLED(GetPendingUrl); test_timer(EXPECT_SETTITLE); - test_GetCurMoniker((IUnknown*)doc, NULL, about_blank_url); + test_GetCurMoniker((IUnknown*)doc, NULL, "about:blank"); IPersistStreamInit_Release(init); } -static void test_QueryInterface(IHTMLDocument2 *doc) +static void test_QueryInterface(IHTMLDocument2 *htmldoc) { - IUnknown *qi; + IUnknown *qi, *doc = (IUnknown*)htmldoc; HRESULT hres; static const IID IID_UndocumentedScriptIface = @@ -4530,6 +6735,11 @@ static void test_QueryInterface(IHTMLDocument2 *doc) ok(hres == E_NOINTERFACE, "QueryInterface returned %08x, expected E_NOINTERFACE\n", hres); ok(qi == NULL, "qi=%p, expected NULL\n", qi); + qi = (void*)0xdeadbeef; + hres = IUnknown_QueryInterface(doc, &IID_ITargetFrame, (void**)&qi); + ok(hres == E_NOINTERFACE, "QueryInterface returned %08x, expected E_NOINTERFACE\n", hres); + ok(qi == NULL, "qi=%p, expected NULL\n", qi); + hres = IUnknown_QueryInterface(doc, &IID_IDispatch, (void**)&qi); ok(hres == S_OK, "Could not get IDispatch interface: %08x\n", hres); ok(qi != (IUnknown*)doc, "disp == doc\n"); @@ -4538,7 +6748,7 @@ static void test_QueryInterface(IHTMLDocument2 *doc) static void init_test(enum load_state_t ls) { doc_unk = NULL; - hwnd = last_hwnd = NULL; + doc_hwnd = last_hwnd = NULL; set_clientsite = FALSE; load_from_stream = FALSE; call_UIActivate = CallUIActivate_None; @@ -4546,24 +6756,24 @@ static void init_test(enum load_state_t ls) { editmode = FALSE; stream_read = 0; protocol_read = 0; + nav_url = NULL; ipsex = FALSE; inplace_deactivated = FALSE; - navigated_load = FALSE; + complete = FALSE; + expect_uihandler_iface = &DocHostUIHandler; } -static void test_HTMLDocument(BOOL do_load) +static void test_HTMLDocument(BOOL do_load, BOOL mime) { IHTMLDocument2 *doc; - HRESULT hres; - ULONG ref; - trace("Testing HTMLDocument (%s)...\n", (do_load ? "load" : "no load")); + trace("Testing HTMLDocument (%s, %s)...\n", (do_load ? "load" : "no load"), + (report_mime ? "mime" : "no mime")); init_test(do_load ? LD_DOLOAD : LD_NO); + report_mime = mime; - hres = create_document(&doc); - if(FAILED(hres)) - return; + doc = create_document(); doc_unk = (IUnknown*)doc; test_QueryInterface(doc); @@ -4581,8 +6791,10 @@ static void test_HTMLDocument(BOOL do_load) test_Activate(doc, CLIENTSITE_EXPECTPATH); if(do_load) { + set_custom_uihandler(doc, &CustomDocHostUIHandler); test_download(DWL_CSS|DWL_TRYCSS); test_GetCurMoniker((IUnknown*)doc, &Moniker, NULL); + test_elem_from_point(doc); } test_MSHTML_QueryStatus(doc, OLECMDF_SUPPORTED); @@ -4591,6 +6803,7 @@ static void test_HTMLDocument(BOOL do_load) test_OnAmbientPropertyChange(doc); test_Window(doc, TRUE); test_external(doc, TRUE); + test_target_container(doc); test_UIDeactivate(); test_OleCommandTarget(doc); @@ -4619,6 +6832,10 @@ static void test_HTMLDocument(BOOL do_load) test_Activate(doc, CLIENTSITE_SETNULL); test_Window(doc, TRUE); + test_external(doc, TRUE); + set_custom_uihandler(doc, NULL); + test_external(doc, FALSE); + test_UIDeactivate(); test_InPlaceDeactivate(doc, TRUE); test_CloseView(); @@ -4643,41 +6860,33 @@ static void test_HTMLDocument(BOOL do_load) IOleDocumentView_Release(view); view = NULL; - ok(IsWindow(hwnd), "hwnd is destroyed\n"); - - ref = IHTMLDocument2_Release(doc); - ok(ref == 0, "ref=%d, expected 0\n", ref); - - ok(!IsWindow(hwnd), "hwnd is not destroyed\n"); + ok(IsWindow(doc_hwnd), "hwnd is destroyed\n"); + release_document(doc); + ok(!IsWindow(doc_hwnd), "hwnd is not destroyed\n"); } -static void test_HTMLDocument_hlink(void) +static void test_HTMLDocument_hlink(DWORD status) { IHTMLDocument2 *doc; - HRESULT hres; - ULONG ref; trace("Testing HTMLDocument (hlink)...\n"); init_test(LD_DOLOAD); ipsex = TRUE; - hres = create_document(&doc); - if(FAILED(hres)) - return; + doc = create_document(); doc_unk = (IUnknown*)doc; + set_custom_uihandler(doc, &CustomDocHostUIHandler); test_ViewAdviseSink(doc); test_ConnectionPointContainer(doc); test_GetCurMoniker((IUnknown*)doc, NULL, NULL); test_Persist(doc, &Moniker); test_Navigate(doc); - if(show_failed) { - IUnknown_Release(doc); - return; - } + status_code = status; test_download(DWL_CSS|DWL_TRYCSS); + status_code = HTTP_STATUS_OK; test_IsDirty(doc, S_FALSE); test_MSHTML_QueryStatus(doc, OLECMDF_SUPPORTED); @@ -4695,8 +6904,7 @@ static void test_HTMLDocument_hlink(void) IOleDocumentView_Release(view); view = NULL; - ref = IHTMLDocument2_Release(doc); - ok(ref == 0, "ref=%d, expected 0\n", ref); + release_document(doc); } static void test_cookies(IHTMLDocument2 *doc) @@ -4750,14 +6958,16 @@ static void test_cookies(IHTMLDocument2 *doc) SysFreeString(str2); } -static void test_HTMLDocument_http(void) +static void test_HTMLDocument_http(BOOL with_wbapp) { IMoniker *http_mon; IHTMLDocument2 *doc; ULONG ref; HRESULT hres; - trace("Testing HTMLDocument (http)...\n"); + trace("Testing HTMLDocument (http%s)...\n", with_wbapp ? " with IWebBrowserApp" : ""); + + support_wbapp = with_wbapp; if(!winetest_interactive && is_ie_hardened()) { win_skip("IE running in Enhanced Security Configuration\n"); @@ -4767,9 +6977,7 @@ static void test_HTMLDocument_http(void) init_test(LD_DOLOAD); ipsex = TRUE; - hres = create_document(&doc); - if(FAILED(hres)) - return; + doc = create_document(); doc_unk = (IUnknown*)doc; hres = CreateURLMoniker(NULL, http_urlW, &http_mon); @@ -4780,31 +6988,43 @@ static void test_HTMLDocument_http(void) test_GetCurMoniker((IUnknown*)doc, NULL, NULL); test_Persist(doc, http_mon); test_Navigate(doc); - if(show_failed) { - IUnknown_Release(doc); - return; - } - test_download(DWL_HTTP); test_cookies(doc); test_IsDirty(doc, S_FALSE); test_MSHTML_QueryStatus(doc, OLECMDF_SUPPORTED); test_GetCurMoniker((IUnknown*)doc, http_mon, NULL); + test_travellog(doc); + test_binding_ui((IUnknown*)doc); - test_put_href(doc); - test_open_window(doc); + nav_url = nav_serv_url = "http://www.winehq.org/"; /* for valid prev nav_url */ + if(support_wbapp) { + test_put_href(doc, FALSE, "#test", "http://www.winehq.org/#test", FALSE, TRUE, 0); + test_travellog(doc); + test_refresh(doc); + } + test_put_href(doc, FALSE, NULL, "javascript:external%20&&undefined", TRUE, FALSE, 0); + test_put_href(doc, FALSE, NULL, "about:blank", FALSE, FALSE, support_wbapp ? DWL_EXPECT_HISTUPDATE : 0); + test_put_href(doc, TRUE, NULL, "about:replace", FALSE, FALSE, 0); + if(support_wbapp) { + test_load_history(doc); + test_put_href(doc, FALSE, NULL, "about:blank", FALSE, FALSE, support_wbapp ? DWL_EXPECT_HISTUPDATE : 0); + } + + prev_url = nav_serv_url; + test_open_window(doc, TRUE); + if(!support_wbapp) /* FIXME */ + test_open_window(doc, FALSE); test_InPlaceDeactivate(doc, TRUE); test_Close(doc, FALSE); test_IsDirty(doc, S_FALSE); - test_GetCurMoniker((IUnknown*)doc, NULL, about_blank_url); + test_GetCurMoniker((IUnknown*)doc, NULL, prev_url); if(view) IOleDocumentView_Release(view); view = NULL; - ref = IHTMLDocument2_Release(doc); - ok(!ref, "ref=%d, expected 0\n", ref); + release_document(doc); ref = IMoniker_Release(http_mon); ok(!ref, "ref=%d, expected 0\n", ref); @@ -4812,20 +7032,45 @@ static void test_HTMLDocument_http(void) static void test_QueryService(IHTMLDocument2 *doc, BOOL success) { + IHTMLWindow2 *window, *sp_window; IServiceProvider *sp; IHlinkFrame *hf; HRESULT hres; - hres = IUnknown_QueryInterface(doc, &IID_IServiceProvider, (void**)&sp); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IServiceProvider, (void**)&sp); ok(hres == S_OK, "QueryService returned %08x\n", hres); hres = IServiceProvider_QueryService(sp, &IID_IHlinkFrame, &IID_IHlinkFrame, (void**)&hf); - if(SUCCEEDED(hres)) - IHlinkFrame_Release(hf); + if(!success) { + ok(hres == E_NOINTERFACE, "QueryService returned %08x, expected E_NOINTERFACE\n", hres); + IServiceProvider_Release(sp); + return; + } - ok(hres == (success?S_OK:E_NOINTERFACE), "QueryService returned %08x, expected %08x\n", hres, success?S_OK:E_NOINTERFACE); + ok(hres == S_OK, "QueryService(IID_IHlinkFrame) failed: %08x\n", hres); + ok(hf == &HlinkFrame, "hf != HlinkFrame\n"); + IHlinkFrame_Release(hf); IServiceProvider_Release(sp); + + hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08x\n", hres); + + hres = IHTMLWindow2_QueryInterface(window, &IID_IServiceProvider, (void**)&sp); + ok(hres == S_OK, "Could not get IServiceProvider iface: %08x\n", hres); + + hres = IServiceProvider_QueryService(sp, &IID_IHTMLWindow2, &IID_IHTMLWindow2, (void**)&sp_window); + ok(hres == S_OK, "QueryService(IID_IHTMLWindow2) failed: %08x\n", hres); + /* FIXME: test returned window */ + IHTMLWindow2_Release(sp_window); + + hres = IServiceProvider_QueryService(sp, &IID_IHlinkFrame, &IID_IHlinkFrame, (void**)&hf); + ok(hres == S_OK, "QueryService(IID_IHlinkFrame) failed: %08x\n", hres); + ok(hf == &HlinkFrame, "hf != HlinkFrame\n"); + IHlinkFrame_Release(hf); + + IServiceProvider_Release(sp); + IHTMLWindow2_Release(window); } static void test_HTMLDocument_StreamLoad(void) @@ -4834,19 +7079,16 @@ static void test_HTMLDocument_StreamLoad(void) IOleObject *oleobj; DWORD conn; HRESULT hres; - ULONG ref; trace("Testing HTMLDocument (IPersistStreamInit)...\n"); init_test(LD_DOLOAD); load_from_stream = TRUE; - hres = create_document(&doc); - if(FAILED(hres)) - return; + doc = create_document(); doc_unk = (IUnknown*)doc; - hres = IUnknown_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj); ok(hres == S_OK, "Could not get IOleObject: %08x\n", hres); hres = IOleObject_Advise(oleobj, (IAdviseSink*)&AdviseSink, &conn); @@ -4862,8 +7104,6 @@ static void test_HTMLDocument_StreamLoad(void) test_DoVerb(oleobj); test_MSHTML_QueryStatus(doc, OLECMDF_SUPPORTED); - IOleObject_Release(oleobj); - test_GetCurMoniker((IUnknown*)doc, NULL, NULL); test_StreamLoad(doc); test_download(DWL_VERBDONE|DWL_TRYCSS); @@ -4872,18 +7112,26 @@ static void test_HTMLDocument_StreamLoad(void) test_UIDeactivate(); test_InPlaceDeactivate(doc, TRUE); SET_EXPECT(Advise_Close); - test_Close(doc, FALSE); + test_Close(doc, TRUE); CHECK_CALLED(Advise_Close); + test_external(doc, FALSE); test_IsDirty(doc, S_FALSE); + set_custom_uihandler(doc, &CustomDocHostUIHandler); + test_ClientSite(oleobj, CLIENTSITE_SETNULL); + test_external(doc, TRUE); + test_ClientSite(oleobj, CLIENTSITE_SETNULL|CLIENTSITE_DONTSET); + test_external(doc, TRUE); + set_custom_uihandler(doc, NULL); + test_ClientSite(oleobj, CLIENTSITE_SETNULL|CLIENTSITE_DONTSET); + + IOleObject_Release(oleobj); if(view) { IOleDocumentView_Release(view); view = NULL; } - - ref = IHTMLDocument2_Release(doc); - ok(ref == 0, "ref=%d, expected 0\n", ref); + release_document(doc); } static void test_HTMLDocument_StreamInitNew(void) @@ -4892,19 +7140,16 @@ static void test_HTMLDocument_StreamInitNew(void) IOleObject *oleobj; DWORD conn; HRESULT hres; - ULONG ref; - trace("Testing HTMLDocument (IPersistStreamInit)...\n"); + trace("Testing HTMLDocument (IPersistStreamInit::InitNew)...\n"); init_test(LD_DOLOAD); load_from_stream = TRUE; - hres = create_document(&doc); - if(FAILED(hres)) - return; + doc = create_document(); doc_unk = (IUnknown*)doc; - hres = IUnknown_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj); ok(hres == S_OK, "Could not get IOleObject: %08x\n", hres); hres = IOleObject_Advise(oleobj, (IAdviseSink*)&AdviseSink, &conn); @@ -4922,7 +7167,11 @@ static void test_HTMLDocument_StreamInitNew(void) test_GetCurMoniker((IUnknown*)doc, NULL, NULL); test_StreamInitNew(doc); + + SET_EXPECT(Invoke_OnReadyStateChange_Interactive); test_download(DWL_VERBDONE|DWL_TRYCSS|DWL_EMPTY); + todo_wine CHECK_NOT_CALLED(Invoke_OnReadyStateChange_Interactive); + test_MSHTML_QueryStatus(doc, OLECMDF_SUPPORTED); test_UIDeactivate(); @@ -4937,9 +7186,7 @@ static void test_HTMLDocument_StreamInitNew(void) view = NULL; } - - ref = IHTMLDocument2_Release(doc); - ok(ref == 0, "ref=%d, expected 0\n", ref); + release_document(doc); } static void test_edit_uiactivate(IOleObject *oleobj) @@ -4976,19 +7223,16 @@ static void test_editing_mode(BOOL do_load) IOleObject *oleobj; DWORD conn; HRESULT hres; - ULONG ref; trace("Testing HTMLDocument (edit%s)...\n", do_load ? " load" : ""); init_test(do_load ? LD_DOLOAD : LD_NO); call_UIActivate = CallUIActivate_AfterShow; - hres = create_document(&doc); - if(FAILED(hres)) - return; + doc = create_document(); unk = doc_unk = (IUnknown*)doc; - hres = IUnknown_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj); ok(hres == S_OK, "Could not get IOleObject: %08x\n", hres); hres = IOleObject_Advise(oleobj, (IAdviseSink*)&AdviseSink, &conn); @@ -5015,12 +7259,11 @@ static void test_editing_mode(BOOL do_load) SET_EXPECT(SetStatusText); /* ignore race in native mshtml */ test_timer(EXPECT_UPDATEUI); - SET_CALLED(SetStatusText); + CLEAR_CALLED(SetStatusText); test_MSHTML_QueryStatus(doc, OLECMDF_SUPPORTED|OLECMDF_ENABLED); if(!do_load) { - test_exec_fontname(unk, NULL, wszTimesNewRoman); test_exec_fontname(unk, wszArial, wszTimesNewRoman); test_timer(EXPECT_UPDATEUI); test_exec_fontname(unk, NULL, wszArial); @@ -5054,8 +7297,7 @@ static void test_editing_mode(BOOL do_load) view = NULL; } - ref = IUnknown_Release(unk); - ok(ref == 0, "ref=%d, expected 0\n", ref); + release_document(doc); } static void test_UIActivate(BOOL do_load, BOOL use_ipsex, BOOL use_ipsw) @@ -5064,24 +7306,21 @@ static void test_UIActivate(BOOL do_load, BOOL use_ipsex, BOOL use_ipsw) IOleObject *oleobj; IOleInPlaceSite *inplacesite; HRESULT hres; - ULONG ref; trace("Running OleDocumentView_UIActivate tests (%d %d %d)\n", do_load, use_ipsex, use_ipsw); init_test(do_load ? LD_DOLOAD : LD_NO); - hres = create_document(&doc); - if(FAILED(hres)) - return; + doc = create_document(); doc_unk = (IUnknown*)doc; ipsex = use_ipsex; ipsw = use_ipsw; - hres = IUnknown_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj); ok(hres == S_OK, "QueryInterface(IID_IOleObject) failed: %08x\n", hres); - hres = IUnknown_QueryInterface(doc, &IID_IOleDocumentView, (void**)&view); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleDocumentView, (void**)&view); ok(hres == S_OK, "QueryInterface(IID_IOleDocumentView) failed: %08x\n", hres); SET_EXPECT(Invoke_AMBIENT_USERMODE); @@ -5098,9 +7337,12 @@ static void test_UIActivate(BOOL do_load, BOOL use_ipsex, BOOL use_ipsw) SET_EXPECT(QueryStatus_SETPROGRESSTEXT); SET_EXPECT(Exec_SETPROGRESSMAX); SET_EXPECT(Exec_SETPROGRESSPOS); + SET_EXPECT(GetTravelLog); + SET_EXPECT(Exec_ShellDocView_84); hres = IOleObject_SetClientSite(oleobj, &ClientSite); ok(hres == S_OK, "SetClientSite failed: %08x\n", hres); + set_clientsite = TRUE; CHECK_CALLED(Invoke_AMBIENT_USERMODE); CHECK_CALLED(GetHostInfo); @@ -5108,14 +7350,16 @@ static void test_UIActivate(BOOL do_load, BOOL use_ipsex, BOOL use_ipsw) CHECK_CALLED(Invoke_AMBIENT_SILENT); CHECK_CALLED(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED); CHECK_CALLED(Invoke_AMBIENT_USERAGENT); - CHECK_CALLED(Invoke_AMBIENT_PALETTE); - CHECK_CALLED(GetOptionKeyPath); + CLEAR_CALLED(Invoke_AMBIENT_PALETTE); /* not called on IE9 */ + CLEAR_CALLED(GetOptionKeyPath); /* not called on some IE9 */ CHECK_CALLED(GetOverrideKeyPath); CHECK_CALLED(GetWindow); CHECK_CALLED(Exec_DOCCANNAVIGATE); CHECK_CALLED(QueryStatus_SETPROGRESSTEXT); CHECK_CALLED(Exec_SETPROGRESSMAX); CHECK_CALLED(Exec_SETPROGRESSPOS); + todo_wine CHECK_CALLED(GetTravelLog); + CHECK_CALLED_BROKEN(Exec_ShellDocView_84); hres = IOleDocumentView_GetInPlaceSite(view, &inplacesite); ok(hres == S_OK, "GetInPlaceSite failed: %08x\n", hres); @@ -5186,6 +7430,7 @@ static void test_UIActivate(BOOL do_load, BOOL use_ipsex, BOOL use_ipsw) ok(inplacesite != NULL, "inplacesite = NULL\n"); IOleInPlaceSite_Release(inplacesite); + SET_EXPECT(SetStatusText); SET_EXPECT(OnFocus_FALSE); if(use_ipsex) SET_EXPECT(OnInPlaceDeactivateEx); @@ -5194,6 +7439,7 @@ static void test_UIActivate(BOOL do_load, BOOL use_ipsex, BOOL use_ipsw) test_CloseView(); + CLEAR_CALLED(SetStatusText); /* Called by IE9 */ CHECK_CALLED(OnFocus_FALSE); if(use_ipsex) CHECK_CALLED(OnInPlaceDeactivateEx); @@ -5206,8 +7452,7 @@ static void test_UIActivate(BOOL do_load, BOOL use_ipsex, BOOL use_ipsw) IOleDocumentView_Release(view); view = NULL; - ref = IHTMLDocument2_Release(doc); - ok(ref == 0, "ref=%d, expected 0\n", ref); + release_document(doc); } static void register_protocol(void) @@ -5232,70 +7477,115 @@ static void test_HTMLDoc_ISupportErrorInfo(void) IHTMLDocument2 *doc; HRESULT hres; ISupportErrorInfo *sinfo; - LONG ref; - hres = create_document(&doc); - if(FAILED(hres)) - return; + doc = create_document(); - hres = IUnknown_QueryInterface(doc, &IID_ISupportErrorInfo, (void**)&sinfo); + hres = IHTMLDocument2_QueryInterface(doc, &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); + ISupportErrorInfo_Release(sinfo); } - ref = IHTMLDocument2_Release(doc); - ok(ref == 0, "ref=%d, expected 0\n", ref); + release_document(doc); } -static void test_IPersistHistory(void) +static BOOL check_ie(void) { IHTMLDocument2 *doc; + IHTMLDocument5 *doc5; HRESULT hres; - LONG ref; - IPersistHistory *phist; - hres = create_document(&doc); - if(FAILED(hres)) + doc = create_document(); + if(!doc) + return FALSE; + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument5, (void**)&doc5); + if(SUCCEEDED(hres)) + IHTMLDocument5_Release(doc5); + + release_document(doc); + return SUCCEEDED(hres); +} + +static void test_ServiceProvider(void) +{ + IHTMLDocument3 *doc3, *doc3_2; + IServiceProvider *provider; + IHTMLDocument2 *doc, *doc2; + IUnknown *unk; + HRESULT hres; + + doc = create_document(); + if(!doc) return; - hres = IUnknown_QueryInterface(doc, &IID_IPersistHistory, (void**)&phist); - ok(hres == S_OK, "QueryInterface returned %08x, expected S_OK\n", hres); - if(hres == S_OK) - IPersistHistory_Release(phist); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IServiceProvider, (void**)&provider); + ok(hres == S_OK, "got 0x%08x\n", hres); - ref = IHTMLDocument2_Release(doc); - ok(ref == 0, "ref=%d, expected 0\n", ref); + hres = IServiceProvider_QueryService(provider, &SID_SContainerDispatch, &IID_IHTMLDocument2, (void**)&doc2); + ok(hres == S_OK, "got 0x%08x\n", hres); + ok(iface_cmp((IUnknown*)doc2, (IUnknown*)doc), "got wrong pointer\n"); + IHTMLDocument2_Release(doc2); + + hres = IServiceProvider_QueryService(provider, &SID_SContainerDispatch, &IID_IHTMLDocument3, (void**)&doc3); + ok(hres == S_OK, "got 0x%08x\n", hres); + ok(iface_cmp((IUnknown*)doc3, (IUnknown*)doc), "got wrong pointer\n"); + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3_2); + ok(hres == S_OK, "got 0x%08x\n", hres); + ok(iface_cmp((IUnknown*)doc3_2, (IUnknown*)doc), "got wrong pointer\n"); + ok(iface_cmp((IUnknown*)doc3_2, (IUnknown*)doc3), "got wrong pointer\n"); + IHTMLDocument3_Release(doc3); + IHTMLDocument3_Release(doc3_2); + + hres = IServiceProvider_QueryService(provider, &SID_SContainerDispatch, &IID_IUnknown, (void**)&unk); + ok(hres == S_OK, "got 0x%08x\n", hres); + ok(iface_cmp((IUnknown*)doc, unk), "got wrong pointer\n"); + + IUnknown_Release(unk); + IServiceProvider_Release(provider); + release_document(doc); } START_TEST(htmldoc) { CoInitialize(NULL); + + if(!check_ie()) { + CoUninitialize(); + win_skip("Too old IE\n"); + return; + } + container_hwnd = create_container_window(); register_protocol(); - test_HTMLDocument_hlink(); - if(!show_failed) { - test_HTMLDocument(FALSE); - test_HTMLDocument(TRUE); - test_HTMLDocument_StreamLoad(); - test_HTMLDocument_StreamInitNew(); - test_editing_mode(FALSE); - test_editing_mode(TRUE); - test_HTMLDocument_http(); - test_UIActivate(FALSE, FALSE, FALSE); - test_UIActivate(FALSE, TRUE, FALSE); - test_UIActivate(FALSE, TRUE, TRUE); - test_UIActivate(TRUE, FALSE, FALSE); - test_UIActivate(TRUE, TRUE, FALSE); - test_UIActivate(TRUE, TRUE, TRUE); - } + asynchronous_binding = TRUE; + test_HTMLDocument_hlink(HTTP_STATUS_NOT_FOUND); + + asynchronous_binding = FALSE; + test_HTMLDocument_hlink(HTTP_STATUS_OK); + test_HTMLDocument(FALSE, TRUE); + test_HTMLDocument(TRUE, FALSE); + test_HTMLDocument(TRUE, TRUE); + test_HTMLDocument_StreamLoad(); + test_HTMLDocument_StreamInitNew(); + test_editing_mode(FALSE); + test_editing_mode(TRUE); + test_HTMLDocument_http(FALSE); + test_HTMLDocument_http(TRUE); + test_UIActivate(FALSE, FALSE, FALSE); + test_UIActivate(FALSE, TRUE, FALSE); + test_UIActivate(FALSE, TRUE, TRUE); + test_UIActivate(TRUE, FALSE, FALSE); + test_UIActivate(TRUE, TRUE, FALSE); + test_UIActivate(TRUE, TRUE, TRUE); test_HTMLDoc_ISupportErrorInfo(); - test_IPersistHistory(); + test_ServiceProvider(); DestroyWindow(container_hwnd); CoUninitialize(); diff --git a/rostests/winetests/mshtml/htmllocation.c b/rostests/winetests/mshtml/htmllocation.c index 11a416e347b..88da3d35ef8 100644 --- a/rostests/winetests/mshtml/htmllocation.c +++ b/rostests/winetests/mshtml/htmllocation.c @@ -107,11 +107,8 @@ static int str_eq_wa(LPCWSTR strw, const char *stra) { CHAR buf[512]; - if(strw == NULL || stra == NULL){ - if((void*)strw == (void*)stra) - return 1; - return 0; - } + if(!strw || !stra) + return (void*)strw == (void*)stra; WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL); return !lstrcmpA(stra, buf); @@ -133,6 +130,13 @@ static void test_href(IHTMLLocation *loc, const struct location_test *test) ok(str_eq_wa(str, test->href), "%s: expected retrieved href to be L\"%s\", was: %s\n", test->name, test->href, wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLLocation_toString(loc, &str); + ok(hres == S_OK, "%s: toString failed: 0x%08x\n", test->name, hres); + ok(str_eq_wa(str, test->href), "%s: toString returned %s, expected %s\n", + test->name, wine_dbgstr_w(str), test->href); + SysFreeString(str); } static void test_protocol(IHTMLLocation *loc, const struct location_test *test) @@ -151,6 +155,7 @@ static void test_protocol(IHTMLLocation *loc, const struct location_test *test) ok(str_eq_wa(str, test->protocol), "%s: expected retrieved protocol to be L\"%s\", was: %s\n", test->name, test->protocol, wine_dbgstr_w(str)); + SysFreeString(str); } static void test_host(IHTMLLocation *loc, const struct location_test *test) @@ -169,9 +174,10 @@ static void test_host(IHTMLLocation *loc, const struct location_test *test) ok(str_eq_wa(str, test->host), "%s: expected retrieved host to be L\"%s\", was: %s\n", test->name, test->host, wine_dbgstr_w(str)); + SysFreeString(str); } -static void test_hostname(IHTMLLocation *loc, const struct location_test *test) +static void test_hostname(IHTMLLocation *loc, IHTMLDocument2 *doc, const struct location_test *test) { HRESULT hres; BSTR str; @@ -187,6 +193,15 @@ static void test_hostname(IHTMLLocation *loc, const struct location_test *test) ok(str_eq_wa(str, test->hostname), "%s: expected retrieved hostname to be L\"%s\", was: %s\n", test->name, test->hostname, wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLDocument2_get_domain(doc, &str); + ok(hres == S_OK, "%s: get_domain failed: 0x%08x\n", test->name, hres); + if(hres == S_OK) + ok(str_eq_wa(str, test->hostname ? test->hostname : ""), + "%s: expected retrieved domain to be L\"%s\", was: %s\n", + test->name, test->hostname, wine_dbgstr_w(str)); + SysFreeString(str); } static void test_port(IHTMLLocation *loc, const struct location_test *test) @@ -205,6 +220,7 @@ static void test_port(IHTMLLocation *loc, const struct location_test *test) ok(str_eq_wa(str, test->port), "%s: expected retrieved port to be L\"%s\", was: %s\n", test->name, test->port, wine_dbgstr_w(str)); + SysFreeString(str); } static void test_pathname(IHTMLLocation *loc, const struct location_test *test) @@ -223,6 +239,7 @@ static void test_pathname(IHTMLLocation *loc, const struct location_test *test) ok(str_eq_wa(str, test->pathname), "%s: expected retrieved pathname to be L\"%s\", was: %s\n", test->name, test->pathname, wine_dbgstr_w(str)); + SysFreeString(str); } static void test_search(IHTMLLocation *loc, const struct location_test *test) @@ -241,6 +258,7 @@ static void test_search(IHTMLLocation *loc, const struct location_test *test) ok(str_eq_wa(str, test->search), "%s: expected retrieved search to be L\"%s\", was: %s\n", test->name, test->search, wine_dbgstr_w(str)); + SysFreeString(str); } static void test_hash(IHTMLLocation *loc, const struct location_test *test) @@ -259,6 +277,7 @@ static void test_hash(IHTMLLocation *loc, const struct location_test *test) ok(str_eq_wa(str, test->hash), "%s: expected retrieved hash to be L\"%s\", was: %s\n", test->name, test->hash, wine_dbgstr_w(str)); + SysFreeString(str); } static void perform_test(const struct location_test* test) @@ -339,7 +358,7 @@ static void perform_test(const struct location_test* test) test_href(location, test); test_protocol(location, test); test_host(location, test); - test_hostname(location, test); + test_hostname(location, doc, test); test_port(location, test); test_pathname(location, test); test_search(location, test); diff --git a/rostests/winetests/mshtml/jstest.html b/rostests/winetests/mshtml/jstest.html index 3363c5ae8ca..ebf28618b89 100644 --- a/rostests/winetests/mshtml/jstest.html +++ b/rostests/winetests/mshtml/jstest.html @@ -31,7 +31,155 @@ function test_select_index() { ok(s[2] === null, "s[2] = " + s[2]); } -function runTest() { +function test_createDocumentFragment() { + var fragment = document.createDocumentFragment(); + + ok(typeof(fragment) === "object", "typeof(fragmend) = " + typeof(fragment)); + ok(fragment.nodeType === 11, "fragment.nodeType = " + fragment.nodeType); + ok(fragment.nodeName === "#document-fragment", "fragment.nodeName = " + fragment.nodeName); + + var cloned = fragment.cloneNode(true); + ok(cloned.nodeType === 11, "cloned.nodeType = " + cloned.nodeType); + ok(cloned.nodeName === "#document-fragment", "cloned.nodeName = " + cloned.nodeName); +} + +function test_document_name_as_index() { + document.body.innerHTML = '
'; + var e = document.getElementById("formname"); + ok(!!e, "e is null"); + + ok(document.formname === e, "document.formname != getElementById('formname')"); + ok("formname" in document, "formname' is not in document"); + + document.body.removeChild(e); + + ok(document.formname === undefined, "document.formname is not undefined"); + ok(!("formname" in document), "formname' is in document"); + + document.body.innerHTML = '
'; + var e = document.getElementById("formid"); + ok(!!e, "e is null"); + ok(!("formid" in document), "formid is in document"); + + document.body.innerHTML = '
'; + ok("formname" in window, "formname' is not in window"); + ok(typeof(window.formname) === "object", "typeof(window.formname) = " + typeof(window.formname)); + window.formname = 1; + ok(window.formname === 1, "window.formname = " + window.formname); + formname = 2; + ok(window.formname === 2, "window.formname = " + window.formname); + + document.body.innerHTML = ''; + ok("iframeid" in window, "iframeid is not in window"); + e = document.getElementById("iframeid"); + ok(!!e, "e is null"); + ok(iframeid != e, "iframeid == e"); + ok(iframeid.frameElement === e, "frameid != e.contentWindow"); +} + +function test_remove_style_attribute() { + var s = document.body.style, b; + + s.somevar = "test"; + b = s.removeAttribute("somevar", 1); + ok(b, "removeAttribute returned " + b + " expected true"); + b = s.removeAttribute("somevar", 1); + ok(b === false, "removeAttribute returned " + b + " expected false"); +} + +function test_clone_node() { + var elem, cloned; + + elem = document.getElementById("divid"); + elem.style.filter = "alpha(opacity=50)"; + ok(elem.style.filter === "alpha(opacity=50)", "elem.style.filter = " + elem.style.filter); + + cloned = elem.cloneNode(true); + ok(cloned.style.filter === "alpha(opacity=50)", "cloned.style.filter = " + cloned.style.filter); +} + +function test_setAttribute() { + var input; + + document.body.innerHTML = ''; + input = document.getElementById("inputid"); + ok(input.checked === false, "input.checked = " + input.checked); + + input.setAttribute("checked", "test"); + ok(input.checked === true, "input.checked = " + input.checked); + + input.setAttribute("checked", 0); + ok(input.checked === false, "input.checked = " + input.checked); + + input.setAttribute("checked", ""); + ok(input.checked === false, "input.checked = " + input.checked); +} + +function test_attribute_collection() { + var div, attr; + + document.body.innerHTML = '
'; + div = document.getElementById("divid"); + + attr = div.attributes["dir"]; + ok(attr === div.attributes["dir"], "attr !== div.attributes['dir']"); +} + +function test_getter_call() { + document.body.innerHTML = '
'; + + var e = document.getElementById("divid"); + + e.myfunc = function(x) { this.myfunc_called = x; }; + e.myfunc("test"); + ok(e.myfunc_called === "test", "e.myfunc_called = " + e.myfunc_called); + + e.onmousedown = function(x) { this.onmousedown_called = x; }; + e.onmousedown("test"); + ok(e.onmousedown_called === "test", "e.onmousedown_called = " + e.onmousedown_called); +} + +function test_arg_conv() { + /* this call would throw if the argument wasn't converted by JScript */ + window.clearInterval(""); + + navigator.javaEnabled(); +} + +function test_override_functions() { + function override_func() { return "test"; } + + ok(typeof(window.showModalDialog) === "object", "typeof(window.showModalDialog) = " + typeof(window.showModalDialog)); + window.showModalDialog = override_func; + ok(window.showModalDialog === override_func, "window.showModalDialog != override_func"); + ok(typeof(window.showModalDialog) === "function", "typeof(window.showModalDialog) = " + typeof(window.showModalDialog)); + + document.body.innerHTML = '
'; + var div = document.getElementById("divid"); + ok(typeof(div.addBehavior) === "object", "typeof(div.addBehavior) = " + typeof(div.addBehavior)); + div.addBehavior = override_func; + ok(div.addBehavior === override_func, "div.addBehavior != override_func"); + ok(typeof(div.addBehavior) === "function", "typeof(div.addBehavior) = " + typeof(div.addBehavior)); + + var tmp = div.addBehavior(); + ok(tmp === "test", "div.addBehavior() = " + tmp); +} + +function test_forin() { + var cnt=0; + + document.body.innerHTML = ''; + + for(var x in document.getElementById("aid")) { + cnt++; + } + + ok(cnt > 100, "cnt = " + cnt); +} + +var globalVar = false; + +function runTests() { obj = new Object(); ok(obj === window.obj, "obj !== window.obj"); @@ -40,6 +188,28 @@ function runTest() { test_removeAttribute(document.getElementById("divid")); test_removeAttribute(document.body); test_select_index(); + test_clone_node(); + test_createDocumentFragment(); + test_document_name_as_index(); + test_remove_style_attribute(); + test_getter_call(); + test_setAttribute(); + test_attribute_collection(); + test_arg_conv(); + test_override_functions(); + test_forin(); + + var r = window.execScript("globalVar = true;"); + ok(r === undefined, "execScript returned " + r); + ok(globalVar === true, "globalVar = " + globalVar); +} + +function runTest() { + try { + runTests(); + }catch(e) { + ok(false, "got exception"); + } external.reportSuccess(); } diff --git a/rostests/winetests/mshtml/misc.c b/rostests/winetests/mshtml/misc.c index ed8de36b9a3..d57aabc354e 100644 --- a/rostests/winetests/mshtml/misc.c +++ b/rostests/winetests/mshtml/misc.c @@ -19,13 +19,13 @@ #define COBJMACROS #include -#include +//#include -#include "windef.h" -#include "winbase.h" -#include "ole2.h" -#include "initguid.h" -#include "optary.h" +//#include "windef.h" +//#include "winbase.h" +//#include "ole2.h" +//#include "initguid.h" +#include static void test_HTMLLoadOptions(void) { diff --git a/rostests/winetests/mshtml/protocol.c b/rostests/winetests/mshtml/protocol.c index 1369ff73621..bc83604d727 100644 --- a/rostests/winetests/mshtml/protocol.c +++ b/rostests/winetests/mshtml/protocol.c @@ -19,16 +19,16 @@ #define COBJMACROS #include -#include +//#include #include -#include "windef.h" -#include "winbase.h" -#include "ole2.h" -#include "urlmon.h" -#include "shlwapi.h" +//#include "windef.h" +//#include "winbase.h" +//#include "ole2.h" +//#include "urlmon.h" +#include -#include "initguid.h" +#include #define DEFINE_EXPECT(func) \ static BOOL expect_ ## func = FALSE, called_ ## func = FALSE @@ -315,6 +315,8 @@ static void test_res_protocol(void) {'r','e','s',':','/','/','x','x','.','d','l','l','/','b','l','a','n','k','.','h','t','m',0}; static const WCHAR wrong_url5[] = {'r','e','s',':','/','/','s','h','t','m','l','.','d','l','l','/','b','l','a','n','k','.','h','t','m',0}; + static const WCHAR wrong_url6[] = + {'r','e','s',':','/','/','c',':','\\','d','i','r','\\','f','i','l','e','.','d','l','l','/','b','l','a','n','k','.','h','t','m',0}; static const WCHAR mshtml_dllW[] = {'m','s','h','t','m','l','.','d','l','l',0}; hres = CoGetClassObject(&CLSID_ResProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk); @@ -326,7 +328,7 @@ static void test_res_protocol(void) ok(hres == S_OK, "Could not get IInternetProtocolInfo interface: %08x\n", hres); if(SUCCEEDED(hres)) { WCHAR buf[128]; - DWORD size; + DWORD size, expected_size; int i; for(i = PARSE_CANONICALIZE; i <= PARSE_UNESCAPE; i++) { @@ -342,12 +344,20 @@ static void test_res_protocol(void) sizeof(buf)/sizeof(buf[0]), &size, 0); ok(hres == S_OK, "ParseUrl failed: %08x\n", hres); res_sec_url_cmp(buf, size, mshtml_dllW); + ok(size == lstrlenW(buf)+1, "size = %d\n", size); + expected_size = size; + + hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_SECURITY_URL, 0, buf, + expected_size, &size, 0); + ok(hres == S_OK, "ParseUrl failed: %08x\n", hres); + res_sec_url_cmp(buf, size, mshtml_dllW); + ok(size == expected_size, "size = %d\n", size); size = 0; hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_SECURITY_URL, 0, buf, 3, &size, 0); ok(hres == S_FALSE, "ParseUrl failed: %08x, expected S_FALSE\n", hres); - ok(size, "size=0\n"); + ok(size == expected_size, "size = %d\n", size); hres = IInternetProtocolInfo_ParseUrl(protocol_info, wrong_url1, PARSE_SECURITY_URL, 0, buf, sizeof(buf)/sizeof(buf[0]), &size, 0); @@ -358,6 +368,10 @@ static void test_res_protocol(void) sizeof(buf)/sizeof(buf[0]), &size, 0); ok(hres == MK_E_SYNTAX, "ParseUrl failed: %08x, expected MK_E_SYNTAX\n", hres); + hres = IInternetProtocolInfo_ParseUrl(protocol_info, wrong_url6, PARSE_SECURITY_URL, 0, buf, + sizeof(buf)/sizeof(buf[0]), &size, 0); + ok(hres == MK_E_SYNTAX, "ParseUrl failed: %08x, expected MK_E_SYNTAX\n", hres); + size = 0xdeadbeef; buf[0] = '?'; hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_DOMAIN, 0, buf, @@ -379,7 +393,7 @@ static void test_res_protocol(void) if (0) { - /* Crashes on win9x */ + /* Crashes on windows */ size = 0xdeadbeef; buf[0] = '?'; hres = IInternetProtocolInfo_ParseUrl(protocol_info, NULL, PARSE_DOMAIN, 0, buf, @@ -464,7 +478,6 @@ static void test_res_protocol(void) memset(buf, '?', sizeof(buf)); hres = IInternetProtocolInfo_QueryInfo(protocol_info, NULL, QUERY_USES_NETWORK, 0, buf, sizeof(buf), &size, 0); - ok(hres == S_OK, "QueryInfo(QUERY_USES_NETWORK) failed: %08x, expected E_FAIL\n", hres); ok(hres == S_OK, "QueryInfo(QUERY_USES_NETWORK) failed: %08x\n", hres); ok(size == sizeof(DWORD), "size=%d\n", size); ok(!*(DWORD*)buf, "buf=%d\n", *(DWORD*)buf); @@ -656,14 +669,17 @@ static void test_about_protocol(void) ok(hres == S_OK, "ParseUrl failed: %08x\n", hres); ok(!lstrcmpW(about_blank_url, buf), "buf != blank_url\n"); + size = 0xdeadbeef; hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, PARSE_SECURITY_URL, 0, buf, 3, &size, 0); ok(hres == S_FALSE, "ParseUrl failed: %08x, expected S_FALSE\n", hres); + ok(size == 12, "size = %d\n", size); hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_test_url, PARSE_SECURITY_URL, 0, buf, sizeof(buf)/sizeof(buf[0]), &size, 0); ok(hres == S_OK, "ParseUrl failed: %08x\n", hres); ok(!lstrcmpW(about_test_url, buf), "buf != test_url\n"); + ok(size == 11, "size = %d\n", size); size = 0xdeadbeef; buf[0] = '?'; @@ -677,7 +693,7 @@ static void test_about_protocol(void) if (0) { - /* Crashes on win9x */ + /* Crashes on windows */ size = 0xdeadbeef; buf[0] = '?'; hres = IInternetProtocolInfo_ParseUrl(protocol_info, NULL, PARSE_DOMAIN, 0, buf, @@ -738,6 +754,7 @@ static void test_about_protocol(void) case QUERY_IS_SECURE: case QUERY_IS_SAFE: case QUERY_USES_HISTORYFOLDER: + case QUERY_IS_CACHED_AND_USABLE_OFFLINE: break; default: hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, i, 0, diff --git a/rostests/winetests/mshtml/rsrc.rc b/rostests/winetests/mshtml/rsrc.rc index 70925ca8022..49aecdfb923 100644 --- a/rostests/winetests/mshtml/rsrc.rc +++ b/rostests/winetests/mshtml/rsrc.rc @@ -16,5 +16,20 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +/* @makedep: exectest.html */ +exectest.html HTML "exectest.html" + /* @makedep: jstest.html */ jstest.html HTML "jstest.html" + +/* @makedep: vbtest.html */ +vbtest.html HTML "vbtest.html" + +/* @makedep: events.html */ +events.html HTML "events.html" + +/* @makedep: externscr.js */ +externscr.js HTML "externscr.js" + +/* @makedep: test_tlb.tlb */ +1 TYPELIB test_tlb.tlb diff --git a/rostests/winetests/mshtml/script.c b/rostests/winetests/mshtml/script.c index 23f1ab861c7..3a07cc08598 100644 --- a/rostests/winetests/mshtml/script.c +++ b/rostests/winetests/mshtml/script.c @@ -20,23 +20,23 @@ #define CONST_VTABLE #include -#include -#include +//#include +//#include -#include "windef.h" -#include "winbase.h" -#include "ole2.h" -#include "wininet.h" -#include "docobj.h" -#include "dispex.h" -#include "hlink.h" -#include "mshtml.h" -#include "mshtmhst.h" -#include "initguid.h" -#include "activscp.h" -#include "activdbg.h" -#include "objsafe.h" -#include "mshtmdid.h" +//#include "windef.h" +//#include "winbase.h" +//#include "ole2.h" +#include +//#include "docobj.h" +//#include "dispex.h" +#include +#include +#include +//#include "initguid.h" +//#include "activscp.h" +#include +#include +#include #include "mshtml_test.h" DEFINE_GUID(CLSID_IdentityUnmarshal,0x0000001b,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46); @@ -50,12 +50,14 @@ const GUID GUID_CUSTOM_CONFIRMOBJECTSAFETY = #define CTXARG_T DWORDLONG #define IActiveScriptParseVtbl IActiveScriptParse64Vtbl #define IActiveScriptParseProcedure2Vtbl IActiveScriptParseProcedure2_64Vtbl +#define IActiveScriptSiteDebug_Release IActiveScriptSiteDebug64_Release #else #define CTXARG_T DWORD #define IActiveScriptParseVtbl IActiveScriptParse32Vtbl #define IActiveScriptParseProcedure2Vtbl IActiveScriptParseProcedure2_32Vtbl +#define IActiveScriptSiteDebug_Release IActiveScriptSiteDebug32_Release #endif @@ -113,7 +115,8 @@ DEFINE_EXPECT(SetScriptState_STARTED); DEFINE_EXPECT(SetScriptState_CONNECTED); DEFINE_EXPECT(SetScriptState_DISCONNECTED); DEFINE_EXPECT(AddNamedItem); -DEFINE_EXPECT(ParseScriptText); +DEFINE_EXPECT(ParseScriptText_script); +DEFINE_EXPECT(ParseScriptText_execScript); DEFINE_EXPECT(GetScriptDispatch); DEFINE_EXPECT(funcDisp); DEFINE_EXPECT(script_divid_d); @@ -123,9 +126,13 @@ DEFINE_EXPECT(script_testprop2_d); DEFINE_EXPECT(AXQueryInterface_IActiveScript); DEFINE_EXPECT(AXQueryInterface_IObjectSafety); DEFINE_EXPECT(AXGetInterfaceSafetyOptions); -DEFINE_EXPECT(AXSetInterfaceSafetyOptions_IDispatch); -DEFINE_EXPECT(AXSetInterfaceSafetyOptions_IDispatchEx); +DEFINE_EXPECT(AXSetInterfaceSafetyOptions_IDispatch_caller); +DEFINE_EXPECT(AXSetInterfaceSafetyOptions_IDispatch_data); +DEFINE_EXPECT(AXSetInterfaceSafetyOptions_IDispatchEx_caller_secmgr); +DEFINE_EXPECT(AXSetInterfaceSafetyOptions_IDispatchEx_caller); DEFINE_EXPECT(external_success); +DEFINE_EXPECT(QS_VariantConversion); +DEFINE_EXPECT(ChangeType); #define TESTSCRIPT_CLSID "{178fc163-f585-4e24-9c13-4bb7faf80746}" #define TESTACTIVEX_CLSID "{178fc163-f585-4e24-9c13-4bb7faf80646}" @@ -136,6 +143,7 @@ DEFINE_EXPECT(external_success); #define DISPID_EXTERNAL_OK 0x300000 #define DISPID_EXTERNAL_TRACE 0x300001 #define DISPID_EXTERNAL_REPORTSUCCESS 0x300002 +#define DISPID_EXTERNAL_TODO_WINE_OK 0x300003 static const GUID CLSID_TestScript = {0x178fc163,0xf585,0x4e24,{0x9c,0x13,0x4b,0xb7,0xfa,0xf8,0x07,0x46}}; @@ -149,8 +157,9 @@ static BOOL doc_complete; static IDispatch *script_disp; static BOOL ax_objsafe; static HWND container_hwnd; -static HRESULT ax_getopt_hres = S_OK, ax_setopt_dispex_hres = S_OK, ax_setopt_disp_hres = S_OK; -static DWORD ax_setopt; +static HRESULT ax_getopt_hres = S_OK, ax_setopt_dispex_hres = S_OK; +static HRESULT ax_setopt_disp_caller_hres = S_OK, ax_setopt_disp_data_hres = S_OK; +static BOOL skip_loadobject_tests; static const char *debugstr_guid(REFIID riid) { @@ -176,6 +185,9 @@ static BSTR a2bstr(const char *str) BSTR ret; int len; + if(!str) + return NULL; + len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); ret = SysAllocStringLen(NULL, len); MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); @@ -262,6 +274,88 @@ static IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = { static IPropertyNotifySink PropertyNotifySink = { &PropertyNotifySinkVtbl }; +static HRESULT WINAPI VariantChangeType_QueryInterface(IVariantChangeType *iface, REFIID riid, void **ppv) +{ + ok(0, "unexpected call %s\n", debugstr_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI VariantChangeType_AddRef(IVariantChangeType *iface) +{ + return 2; +} + +static ULONG WINAPI VariantChangeType_Release(IVariantChangeType *iface) +{ + return 1; +} + +static HRESULT WINAPI VariantChangeType_ChangeType(IVariantChangeType *iface, VARIANT *dst, VARIANT *src, LCID lcid, VARTYPE vt) +{ + CHECK_EXPECT(ChangeType); + + ok(dst != NULL, "dst = NULL\n"); + ok(V_VT(dst) == VT_EMPTY, "V_VT(dst) = %d\n", V_VT(dst)); + ok(src != NULL, "src = NULL\n"); + ok(V_VT(src) == VT_I4, "V_VT(src) = %d\n", V_VT(src)); + ok(V_I4(src) == 0xf0f0f0, "V_I4(src) = %x\n", V_I4(src)); + ok(lcid == LOCALE_NEUTRAL, "lcid = %d\n", lcid); + ok(vt == VT_BSTR, "vt = %d\n", vt); + + V_VT(dst) = VT_BSTR; + V_BSTR(dst) = a2bstr("red"); + return S_OK; +} + +static const IVariantChangeTypeVtbl VariantChangeTypeVtbl = { + VariantChangeType_QueryInterface, + VariantChangeType_AddRef, + VariantChangeType_Release, + VariantChangeType_ChangeType +}; + +static IVariantChangeType VChangeType = { &VariantChangeTypeVtbl }; + +static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) +{ + ok(0, "unexpected call\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface) +{ + return 2; +} + +static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface) +{ + return 1; +} + +static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService, + REFIID riid, void **ppv) +{ + if(IsEqualGUID(guidService, &SID_VariantConversion)) { + CHECK_EXPECT(QS_VariantConversion); + ok(IsEqualGUID(riid, &IID_IVariantChangeType), "uenxpected riid %s\n", debugstr_guid(riid)); + *ppv = &VChangeType; + return S_OK; + } + + ok(0, "unexpected service %s\n", debugstr_guid(guidService)); + return E_NOINTERFACE; +} + +static const IServiceProviderVtbl ServiceProviderVtbl = { + ServiceProvider_QueryInterface, + ServiceProvider_AddRef, + ServiceProvider_Release, + ServiceProvider_QueryService +}; + +static IServiceProvider caller_sp = { &ServiceProviderVtbl }; + static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) { *ppv = NULL; @@ -423,7 +517,7 @@ static HRESULT WINAPI scriptDisp_GetDispID(IDispatchEx *iface, BSTR bstrName, DW return E_FAIL; } - ok(0, "unexpected call\n"); + ok(0, "unexpected call %s\n", wine_dbgstr_w(bstrName)); return E_NOTIMPL; } @@ -489,6 +583,10 @@ static HRESULT WINAPI externalDisp_GetDispID(IDispatchEx *iface, BSTR bstrName, *pid = DISPID_EXTERNAL_REPORTSUCCESS; return S_OK; } + if(!strcmp_wa(bstrName, "todo_wine_ok")) { + *pid = DISPID_EXTERNAL_TODO_WINE_OK; + return S_OK; + } ok(0, "unexpected name %s\n", wine_dbgstr_w(bstrName)); return DISP_E_UNKNOWNNAME; @@ -498,7 +596,9 @@ static HRESULT WINAPI externalDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { switch(id) { - case DISPID_EXTERNAL_OK: + case DISPID_EXTERNAL_OK: { + VARIANT *b, *m; + ok(wFlags == INVOKE_FUNC || wFlags == (INVOKE_FUNC|INVOKE_PROPERTYGET), "wFlags = %x\n", wFlags); ok(pdp != NULL, "pdp == NULL\n"); ok(pdp->rgvarg != NULL, "rgvarg == NULL\n"); @@ -507,11 +607,19 @@ static HRESULT WINAPI externalDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); ok(pei != NULL, "pei == NULL\n"); - ok(V_VT(pdp->rgvarg) == VT_BSTR, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg)); - ok(V_VT(pdp->rgvarg+1) == VT_BOOL, "V_VT(psp->rgvargs+1) = %d\n", V_VT(pdp->rgvarg)); - ok(V_BOOL(pdp->rgvarg+1), "%s\n", wine_dbgstr_w(V_BSTR(pdp->rgvarg))); + m = pdp->rgvarg; + if(V_VT(m) == (VT_BYREF|VT_VARIANT)) + m = V_BYREF(m); + ok(V_VT(m) == VT_BSTR, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg)); + b = pdp->rgvarg+1; + if(V_VT(b) == (VT_BYREF|VT_VARIANT)) + b = V_BYREF(b); + ok(V_VT(b) == VT_BOOL, "V_VT(b) = %d\n", V_VT(b)); + + ok(V_BOOL(b), "%s\n", wine_dbgstr_w(V_BSTR(m))); return S_OK; + } case DISPID_EXTERNAL_TRACE: ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags); @@ -542,6 +650,22 @@ static HRESULT WINAPI externalDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID return S_OK; + case DISPID_EXTERNAL_TODO_WINE_OK: + ok(wFlags == INVOKE_FUNC || wFlags == (INVOKE_FUNC|INVOKE_PROPERTYGET), "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->rgvarg != NULL, "rgvarg == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(pdp->cArgs == 2, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pei != NULL, "pei == NULL\n"); + + ok(V_VT(pdp->rgvarg) == VT_BSTR, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg)); + ok(V_VT(pdp->rgvarg+1) == VT_BOOL, "V_VT(psp->rgvargs+1) = %d\n", V_VT(pdp->rgvarg)); + todo_wine + ok(V_BOOL(pdp->rgvarg+1), "%s\n", wine_dbgstr_w(V_BSTR(pdp->rgvarg))); + + return S_OK; + default: ok(0, "unexpected call\n"); return E_NOTIMPL; @@ -858,7 +982,7 @@ static HRESULT WINAPI InPlaceSite_GetWindowContext(IOleInPlaceSite *iface, *lprcPosRect = rect; *lprcClipRect = rect; - lpFrameInfo->cb = sizeof(*lpFrameInfo); + ok(lpFrameInfo->cb == sizeof(*lpFrameInfo), "lpFrameInfo->cb = %u, expected %u\n", lpFrameInfo->cb, (unsigned)sizeof(*lpFrameInfo)); lpFrameInfo->fMDIApp = FALSE; lpFrameInfo->hwndFrame = container_hwnd; lpFrameInfo->haccel = NULL; @@ -1248,7 +1372,7 @@ static HRESULT WINAPI AXObjectSafety_QueryInterface(IObjectSafety *iface, REFIID } if(IsEqualGUID(&IID_IObjectSafety, riid)) { - CHECK_EXPECT(AXQueryInterface_IObjectSafety); + CHECK_EXPECT2(AXQueryInterface_IObjectSafety); if(!ax_objsafe) return E_NOINTERFACE; *ppv = iface; @@ -1280,19 +1404,39 @@ static HRESULT WINAPI AXObjectSafety_SetInterfaceSafetyOptions(IObjectSafety *if DWORD dwOptionSetMask, DWORD dwEnabledOptions) { if(IsEqualGUID(&IID_IDispatchEx, riid)) { - CHECK_EXPECT(AXSetInterfaceSafetyOptions_IDispatchEx); - ok(dwOptionSetMask == ax_setopt, "dwOptionSetMask=%x, expected %x\n", dwOptionSetMask, ax_setopt); - ok(dwEnabledOptions == ax_setopt, "dwEnabledOptions=%x, expected %x\n", dwOptionSetMask, ax_setopt); + switch(dwEnabledOptions) { + case INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACE_USES_SECURITY_MANAGER: + CHECK_EXPECT(AXSetInterfaceSafetyOptions_IDispatchEx_caller_secmgr); + break; + case INTERFACESAFE_FOR_UNTRUSTED_CALLER: + CHECK_EXPECT(AXSetInterfaceSafetyOptions_IDispatchEx_caller); + break; + default: + ok(0, "unexpected dwEnabledOptions %x\n", dwEnabledOptions); + } + + ok(dwOptionSetMask == dwEnabledOptions, "dwOptionSetMask=%x, expected %x\n", dwOptionSetMask, dwEnabledOptions); return ax_setopt_dispex_hres; } if(IsEqualGUID(&IID_IDispatch, riid)) { - DWORD exopt = ax_setopt & ~INTERFACE_USES_SECURITY_MANAGER; + HRESULT hres; - CHECK_EXPECT(AXSetInterfaceSafetyOptions_IDispatch); - ok(dwOptionSetMask == exopt, "dwOptionSetMask=%x, expected %x\n", dwOptionSetMask, exopt); - ok(dwEnabledOptions == exopt, "dwEnabledOptions=%x, expected %x\n", dwOptionSetMask, exopt); - return ax_setopt_disp_hres; + switch(dwEnabledOptions) { + case INTERFACESAFE_FOR_UNTRUSTED_CALLER: + CHECK_EXPECT(AXSetInterfaceSafetyOptions_IDispatch_caller); + hres = ax_setopt_disp_caller_hres; + break; + case INTERFACESAFE_FOR_UNTRUSTED_DATA: + CHECK_EXPECT(AXSetInterfaceSafetyOptions_IDispatch_data); + hres = ax_setopt_disp_data_hres; + break; + default: + ok(0, "unexpected dwEnabledOptions %x\n", dwEnabledOptions); + hres = E_FAIL; + } + ok(dwOptionSetMask == dwEnabledOptions, "dwOptionSetMask=%x, expected %x\n", dwOptionSetMask, dwEnabledOptions); + return hres; } ok(0, "unexpected riid %s\n", debugstr_guid(riid)); @@ -1309,10 +1453,83 @@ static const IObjectSafetyVtbl AXObjectSafetyVtbl = { static IObjectSafety AXObjectSafety = { &AXObjectSafetyVtbl }; -static BOOL set_safe_reg(BOOL init) +static BOOL set_safe_reg(BOOL safe_call, BOOL safe_data) { return init_key("CLSID\\"TESTACTIVEX_CLSID"\\Implemented Categories\\{7dd95801-9882-11cf-9fa9-00aa006c42c4}", - NULL, init); + NULL, safe_call) + && init_key("CLSID\\"TESTACTIVEX_CLSID"\\Implemented Categories\\{7dd95802-9882-11cf-9fa9-00aa006c42c4}", + NULL, safe_data); +} + +#define check_custom_policy(a,b,c,d) _check_custom_policy(__LINE__,a,b,c,d) +static void _check_custom_policy(unsigned line, HRESULT hres, BYTE *ppolicy, DWORD policy_size, DWORD expolicy) +{ + ok_(__FILE__,line)(hres == S_OK, "QueryCusromPolicy failed: %08x\n", hres); + ok_(__FILE__,line)(policy_size == sizeof(DWORD), "policy_size = %d\n", policy_size); + ok_(__FILE__,line)(*(DWORD*)ppolicy == expolicy, "policy = %x, expected %x\n", *(DWORD*)ppolicy, expolicy); + CoTaskMemFree(ppolicy); +} + +static void test_security_reg(IInternetHostSecurityManager *sec_mgr, DWORD policy_caller, DWORD policy_load) +{ + struct CONFIRMSAFETY cs; + DWORD policy_size; + BYTE *ppolicy; + HRESULT hres; + + cs.clsid = CLSID_TestActiveX; + cs.pUnk = (IUnknown*)&AXObjectSafety; + + cs.dwFlags = 0; + ax_objsafe = FALSE; + SET_EXPECT(AXQueryInterface_IActiveScript); + SET_EXPECT(AXQueryInterface_IObjectSafety); + hres = IInternetHostSecurityManager_QueryCustomPolicy(sec_mgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY, + &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0); + CHECK_CALLED(AXQueryInterface_IActiveScript); + CHECK_CALLED(AXQueryInterface_IObjectSafety); + check_custom_policy(hres, ppolicy, policy_size, policy_caller); + + ax_objsafe = TRUE; + SET_EXPECT(AXQueryInterface_IActiveScript); + SET_EXPECT(AXQueryInterface_IObjectSafety); + SET_EXPECT(AXGetInterfaceSafetyOptions); + SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatchEx_caller_secmgr); + hres = IInternetHostSecurityManager_QueryCustomPolicy(sec_mgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY, + &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0); + CHECK_CALLED(AXQueryInterface_IActiveScript); + CHECK_CALLED(AXQueryInterface_IObjectSafety); + CHECK_CALLED(AXGetInterfaceSafetyOptions); + CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatchEx_caller_secmgr); + check_custom_policy(hres, ppolicy, policy_size, URLPOLICY_ALLOW); + + if(skip_loadobject_tests) + return; + + cs.dwFlags = CONFIRMSAFETYACTION_LOADOBJECT; + ax_objsafe = FALSE; + SET_EXPECT(AXQueryInterface_IActiveScript); + SET_EXPECT(AXQueryInterface_IObjectSafety); + hres = IInternetHostSecurityManager_QueryCustomPolicy(sec_mgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY, + &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0); + CHECK_CALLED(AXQueryInterface_IActiveScript); + CHECK_CALLED(AXQueryInterface_IObjectSafety); + check_custom_policy(hres, ppolicy, policy_size, policy_load); + + ax_objsafe = TRUE; + SET_EXPECT(AXQueryInterface_IActiveScript); + SET_EXPECT(AXQueryInterface_IObjectSafety); + SET_EXPECT(AXGetInterfaceSafetyOptions); + SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatchEx_caller_secmgr); + SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatch_data); + hres = IInternetHostSecurityManager_QueryCustomPolicy(sec_mgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY, + &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0); + CHECK_CALLED(AXQueryInterface_IActiveScript); + CHECK_CALLED(AXQueryInterface_IObjectSafety); + CHECK_CALLED(AXGetInterfaceSafetyOptions); + CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatchEx_caller_secmgr); + CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatch_data); + check_custom_policy(hres, ppolicy, policy_size, URLPOLICY_ALLOW); } static void test_security(void) @@ -1324,8 +1541,6 @@ static void test_security(void) BYTE *ppolicy; HRESULT hres; - ax_setopt = INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACE_USES_SECURITY_MANAGER; - hres = IActiveScriptSite_QueryInterface(site, &IID_IServiceProvider, (void**)&sp); ok(hres == S_OK, "Could not get IServiceProvider iface: %08x\n", hres); @@ -1347,19 +1562,37 @@ static void test_security(void) SET_EXPECT(AXQueryInterface_IActiveScript); SET_EXPECT(AXQueryInterface_IObjectSafety); SET_EXPECT(AXGetInterfaceSafetyOptions); - SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatchEx); + SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatchEx_caller_secmgr); hres = IInternetHostSecurityManager_QueryCustomPolicy(sec_mgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY, &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0); CHECK_CALLED(AXQueryInterface_IActiveScript); CHECK_CALLED(AXQueryInterface_IObjectSafety); CHECK_CALLED(AXGetInterfaceSafetyOptions); - CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatchEx); + CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatchEx_caller_secmgr); + check_custom_policy(hres, ppolicy, policy_size, URLPOLICY_ALLOW); - ok(hres == S_OK, "QueryCusromPolicy failed: %08x\n", hres); - ok(policy_size == sizeof(DWORD), "policy_size = %d\n", policy_size); - ok(*(DWORD*)ppolicy == URLPOLICY_ALLOW, "policy = %x\n", *(DWORD*)ppolicy); - CoTaskMemFree(ppolicy); + cs.dwFlags = CONFIRMSAFETYACTION_LOADOBJECT; + SET_EXPECT(AXQueryInterface_IActiveScript); + SET_EXPECT(AXQueryInterface_IObjectSafety); + SET_EXPECT(AXGetInterfaceSafetyOptions); + SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatchEx_caller_secmgr); + SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatch_data); + hres = IInternetHostSecurityManager_QueryCustomPolicy(sec_mgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY, + &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0); + CHECK_CALLED(AXQueryInterface_IActiveScript); + CHECK_CALLED(AXQueryInterface_IObjectSafety); + CHECK_CALLED(AXGetInterfaceSafetyOptions); + CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatchEx_caller_secmgr); + if(called_AXSetInterfaceSafetyOptions_IDispatch_data) { + CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatch_data); + }else { + win_skip("CONFIRMSAFETYACTION_LOADOBJECT flag not supported\n"); + skip_loadobject_tests = TRUE; + CLEAR_CALLED(AXSetInterfaceSafetyOptions_IDispatch_data); + } + check_custom_policy(hres, ppolicy, policy_size, URLPOLICY_ALLOW); + cs.dwFlags = 0; ax_objsafe = FALSE; SET_EXPECT(AXQueryInterface_IActiveScript); SET_EXPECT(AXQueryInterface_IObjectSafety); @@ -1367,110 +1600,127 @@ static void test_security(void) &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0); CHECK_CALLED(AXQueryInterface_IActiveScript); CHECK_CALLED(AXQueryInterface_IObjectSafety); + check_custom_policy(hres, ppolicy, policy_size, URLPOLICY_DISALLOW); - ok(hres == S_OK, "QueryCusromPolicy failed: %08x\n", hres); - ok(policy_size == sizeof(DWORD), "policy_size = %d\n", policy_size); - ok(*(DWORD*)ppolicy == URLPOLICY_DISALLOW, "policy = %x\n", *(DWORD*)ppolicy); - CoTaskMemFree(ppolicy); - - if(set_safe_reg(TRUE)) { + if(!skip_loadobject_tests) { + cs.dwFlags = CONFIRMSAFETYACTION_LOADOBJECT; ax_objsafe = FALSE; SET_EXPECT(AXQueryInterface_IActiveScript); SET_EXPECT(AXQueryInterface_IObjectSafety); - hres = IInternetHostSecurityManager_QueryCustomPolicy(sec_mgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY, - &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0); - CHECK_CALLED(AXQueryInterface_IActiveScript); - CHECK_CALLED(AXQueryInterface_IObjectSafety); - - ok(hres == S_OK, "QueryCusromPolicy failed: %08x\n", hres); - ok(policy_size == sizeof(DWORD), "policy_size = %d\n", policy_size); - ok(*(DWORD*)ppolicy == URLPOLICY_ALLOW, "policy = %x\n", *(DWORD*)ppolicy); - CoTaskMemFree(ppolicy); - - ax_objsafe = TRUE; - SET_EXPECT(AXQueryInterface_IActiveScript); - SET_EXPECT(AXQueryInterface_IObjectSafety); - SET_EXPECT(AXGetInterfaceSafetyOptions); - SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatchEx); hres = IInternetHostSecurityManager_QueryCustomPolicy(sec_mgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY, &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0); CHECK_CALLED(AXQueryInterface_IActiveScript); CHECK_CALLED(AXQueryInterface_IObjectSafety); - CHECK_CALLED(AXGetInterfaceSafetyOptions); - CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatchEx); + check_custom_policy(hres, ppolicy, policy_size, URLPOLICY_DISALLOW); + } - ok(hres == S_OK, "QueryCusromPolicy failed: %08x\n", hres); - ok(policy_size == sizeof(DWORD), "policy_size = %d\n", policy_size); - ok(*(DWORD*)ppolicy == URLPOLICY_ALLOW, "policy = %x\n", *(DWORD*)ppolicy); - CoTaskMemFree(ppolicy); + if(set_safe_reg(TRUE, FALSE)) { + test_security_reg(sec_mgr, URLPOLICY_ALLOW, URLPOLICY_DISALLOW); - set_safe_reg(FALSE); + set_safe_reg(FALSE, TRUE); + test_security_reg(sec_mgr, URLPOLICY_DISALLOW, URLPOLICY_DISALLOW); + + set_safe_reg(TRUE, TRUE); + test_security_reg(sec_mgr, URLPOLICY_ALLOW, URLPOLICY_ALLOW); + + set_safe_reg(FALSE, FALSE); }else { skip("Could not set safety registry\n"); } ax_objsafe = TRUE; + cs.dwFlags = 0; ax_setopt_dispex_hres = E_NOINTERFACE; SET_EXPECT(AXQueryInterface_IActiveScript); SET_EXPECT(AXQueryInterface_IObjectSafety); SET_EXPECT(AXGetInterfaceSafetyOptions); - SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatchEx); - SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatch); + SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatchEx_caller_secmgr); + SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatch_caller); hres = IInternetHostSecurityManager_QueryCustomPolicy(sec_mgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY, &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0); CHECK_CALLED(AXQueryInterface_IActiveScript); CHECK_CALLED(AXQueryInterface_IObjectSafety); CHECK_CALLED(AXGetInterfaceSafetyOptions); - CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatchEx); - CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatch); - - ok(hres == S_OK, "QueryCusromPolicy failed: %08x\n", hres); - ok(policy_size == sizeof(DWORD), "policy_size = %d\n", policy_size); - ok(*(DWORD*)ppolicy == URLPOLICY_ALLOW, "policy = %x\n", *(DWORD*)ppolicy); - CoTaskMemFree(ppolicy); + CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatchEx_caller_secmgr); + CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatch_caller); + check_custom_policy(hres, ppolicy, policy_size, URLPOLICY_ALLOW); ax_setopt_dispex_hres = E_FAIL; - ax_setopt_disp_hres = E_NOINTERFACE; + ax_setopt_disp_caller_hres = E_NOINTERFACE; SET_EXPECT(AXQueryInterface_IActiveScript); SET_EXPECT(AXQueryInterface_IObjectSafety); SET_EXPECT(AXGetInterfaceSafetyOptions); - SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatchEx); - SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatch); + SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatchEx_caller_secmgr); + SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatch_caller); hres = IInternetHostSecurityManager_QueryCustomPolicy(sec_mgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY, &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0); CHECK_CALLED(AXQueryInterface_IActiveScript); CHECK_CALLED(AXQueryInterface_IObjectSafety); CHECK_CALLED(AXGetInterfaceSafetyOptions); - CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatchEx); - CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatch); + CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatchEx_caller_secmgr); + CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatch_caller); + check_custom_policy(hres, ppolicy, policy_size, URLPOLICY_DISALLOW); - ok(hres == S_OK, "QueryCusromPolicy failed: %08x\n", hres); - ok(policy_size == sizeof(DWORD), "policy_size = %d\n", policy_size); - ok(*(DWORD*)ppolicy == URLPOLICY_DISALLOW, "policy = %x\n", *(DWORD*)ppolicy); - CoTaskMemFree(ppolicy); + if(!skip_loadobject_tests) { + cs.dwFlags = CONFIRMSAFETYACTION_LOADOBJECT; + ax_setopt_dispex_hres = E_FAIL; + ax_setopt_disp_caller_hres = E_NOINTERFACE; + SET_EXPECT(AXQueryInterface_IActiveScript); + SET_EXPECT(AXQueryInterface_IObjectSafety); + SET_EXPECT(AXGetInterfaceSafetyOptions); + SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatchEx_caller_secmgr); + SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatch_caller); + hres = IInternetHostSecurityManager_QueryCustomPolicy(sec_mgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY, + &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0); + CHECK_CALLED(AXQueryInterface_IActiveScript); + CHECK_CALLED(AXQueryInterface_IObjectSafety); + CHECK_CALLED(AXGetInterfaceSafetyOptions); + CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatchEx_caller_secmgr); + CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatch_caller); + check_custom_policy(hres, ppolicy, policy_size, URLPOLICY_DISALLOW); + } + cs.dwFlags = 0; ax_setopt_dispex_hres = E_FAIL; - ax_setopt_disp_hres = S_OK; + ax_setopt_disp_caller_hres = S_OK; ax_getopt_hres = E_NOINTERFACE; - ax_setopt = INTERFACESAFE_FOR_UNTRUSTED_CALLER; SET_EXPECT(AXQueryInterface_IActiveScript); SET_EXPECT(AXQueryInterface_IObjectSafety); SET_EXPECT(AXGetInterfaceSafetyOptions); - SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatchEx); - SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatch); + SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatchEx_caller); + SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatch_caller); hres = IInternetHostSecurityManager_QueryCustomPolicy(sec_mgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY, &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0); CHECK_CALLED(AXQueryInterface_IActiveScript); CHECK_CALLED(AXQueryInterface_IObjectSafety); CHECK_CALLED(AXGetInterfaceSafetyOptions); - CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatchEx); - CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatch); + CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatchEx_caller); + CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatch_caller); + check_custom_policy(hres, ppolicy, policy_size, URLPOLICY_ALLOW); - ok(hres == S_OK, "QueryCusromPolicy failed: %08x\n", hres); - ok(policy_size == sizeof(DWORD), "policy_size = %d\n", policy_size); - ok(*(DWORD*)ppolicy == URLPOLICY_ALLOW, "policy = %x\n", *(DWORD*)ppolicy); - CoTaskMemFree(ppolicy); + if(!skip_loadobject_tests) { + cs.dwFlags = CONFIRMSAFETYACTION_LOADOBJECT; + ax_setopt_dispex_hres = E_FAIL; + ax_setopt_disp_caller_hres = S_OK; + ax_setopt_disp_data_hres = E_FAIL; + ax_getopt_hres = E_NOINTERFACE; + SET_EXPECT(AXQueryInterface_IActiveScript); + SET_EXPECT(AXQueryInterface_IObjectSafety); + SET_EXPECT(AXGetInterfaceSafetyOptions); + SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatchEx_caller); + SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatch_caller); + SET_EXPECT(AXSetInterfaceSafetyOptions_IDispatch_data); + hres = IInternetHostSecurityManager_QueryCustomPolicy(sec_mgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY, + &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0); + CHECK_CALLED(AXQueryInterface_IActiveScript); + CHECK_CALLED(AXQueryInterface_IObjectSafety); + CHECK_CALLED(AXGetInterfaceSafetyOptions); + CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatchEx_caller); + CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatch_caller); + CHECK_CALLED(AXSetInterfaceSafetyOptions_IDispatch_data); + check_custom_policy(hres, ppolicy, policy_size, URLPOLICY_DISALLOW); + } IInternetHostSecurityManager_Release(sec_mgr); } @@ -1607,13 +1857,21 @@ static HRESULT WINAPI ActiveScriptParse_AddScriptlet(IActiveScriptParse *iface, return E_NOTIMPL; } -static HRESULT dispex_propput(IDispatchEx *obj, DISPID id, DWORD flags, VARIANT *var) +static HRESULT dispex_propput(IDispatchEx *obj, DISPID id, DWORD flags, VARIANT *var, IServiceProvider *caller_sp) { DISPID propput_arg = DISPID_PROPERTYPUT; DISPPARAMS dp = {var, &propput_arg, 1, 1}; EXCEPINFO ei = {0}; - return IDispatchEx_InvokeEx(obj, id, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT|flags, &dp, NULL, &ei, NULL); + return IDispatchEx_InvokeEx(obj, id, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT|flags, &dp, NULL, &ei, caller_sp); +} + +static HRESULT dispex_propget(IDispatchEx *obj, DISPID id, VARIANT *res, IServiceProvider *caller_sp) +{ + DISPPARAMS dp = {NULL}; + EXCEPINFO ei = {0}; + + return IDispatchEx_InvokeEx(obj, id, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dp, res, &ei, caller_sp); } static void test_func(IDispatchEx *obj) @@ -1661,7 +1919,7 @@ static void test_func(IDispatchEx *obj) V_VT(&var) = VT_I4; V_I4(&var) = 100; - hres = dispex_propput(obj, id, 0, &var); + hres = dispex_propput(obj, id, 0, &var, NULL); ok(hres == E_NOTIMPL, "InvokeEx failed: %08x\n", hres); IDispatchEx_Release(dispex); @@ -1680,7 +1938,8 @@ static void test_nextdispid(IDispatchEx *dispex) SysFreeString(name); V_VT(&var) = VT_EMPTY; - hres = dispex_propput(dispex, dyn_id, 0, &var); + hres = dispex_propput(dispex, dyn_id, 0, &var, NULL); + ok(hres == S_OK, "dispex_propput failed: %08x\n", hres); while(last_id != dyn_id) { hres = IDispatchEx_GetNextDispID(dispex, fdexEnumAll, last_id, &id); @@ -1732,10 +1991,136 @@ static void test_global_id(void) VariantClear(&var); } -static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *iface, - LPCOLESTR pstrCode, LPCOLESTR pstrItemName, IUnknown *punkContext, - LPCOLESTR pstrDelimiter, CTXARG_T dwSourceContextCookie, ULONG ulStartingLine, - DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo) +static void test_arg_conv(IHTMLWindow2 *window) +{ + IHTMLDocument2 *doc; + IDispatchEx *dispex; + IHTMLElement *elem; + VARIANT v; + HRESULT hres; + + hres = IHTMLWindow2_get_document(window, &doc); + ok(hres == S_OK, "get_document failed: %08x\n", hres); + + hres = IHTMLDocument2_get_body(doc, &elem); + IHTMLDocument2_Release(doc); + ok(hres == S_OK, "get_body failed: %08x\n", hres); + + hres = IHTMLElement_QueryInterface(elem, &IID_IDispatchEx, (void**)&dispex); + IHTMLElement_Release(elem); + ok(hres == S_OK, "Could not get IDispatchEx iface: %08x\n", hres); + + SET_EXPECT(QS_VariantConversion); + SET_EXPECT(ChangeType); + V_VT(&v) = VT_I4; + V_I4(&v) = 0xf0f0f0; + hres = dispex_propput(dispex, DISPID_IHTMLBODYELEMENT_BACKGROUND, 0, &v, &caller_sp); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + CHECK_CALLED(QS_VariantConversion); + CHECK_CALLED(ChangeType); + + V_VT(&v) = VT_EMPTY; + hres = dispex_propget(dispex, DISPID_IHTMLBODYELEMENT_BGCOLOR, &v, &caller_sp); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(var)=%d\n", V_VT(&v)); + ok(!V_BSTR(&v), "V_BSTR(&var) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + + IDispatchEx_Release(dispex); +} + +#define test_elem_disabled(a,b) _test_elem_disabled(__LINE__,a,b) +static void _test_elem_disabled(unsigned line, IHTMLElement *elem, VARIANT_BOOL exb) +{ + IHTMLElement3 *elem3; + VARIANT_BOOL b = 100; + HRESULT hres; + + hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLElement3, (void**)&elem3); + ok_(__FILE__,line)(hres == S_OK, "Could not get IHTMLElement3 iface: %08x\n", hres); + + hres = IHTMLElement3_get_disabled(elem3, &b); + ok_(__FILE__,line)(hres == S_OK, "get_disabled failed: %08x\n", hres); + ok_(__FILE__,line)(b == exb, "disabled = %x, expected %x\n", b, exb); + + IHTMLElement3_Release(elem3); +} + +static void test_default_arg_conv(IHTMLWindow2 *window) +{ + IHTMLDocument2 *doc; + IDispatchEx *dispex; + IHTMLElement *elem; + VARIANT v; + HRESULT hres; + + hres = IHTMLWindow2_get_document(window, &doc); + ok(hres == S_OK, "get_document failed: %08x\n", hres); + + hres = IHTMLDocument2_get_body(doc, &elem); + IHTMLDocument2_Release(doc); + ok(hres == S_OK, "get_body failed: %08x\n", hres); + + hres = IHTMLElement_QueryInterface(elem, &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "Could not get IDispatchEx iface: %08x\n", hres); + + test_elem_disabled(elem, VARIANT_FALSE); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("test"); + hres = dispex_propput(dispex, DISPID_IHTMLELEMENT3_DISABLED, 0, &v, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + SysFreeString(V_BSTR(&v)); + + test_elem_disabled(elem, VARIANT_TRUE); + + V_VT(&v) = VT_I4; + V_BSTR(&v) = 0; + hres = dispex_propput(dispex, DISPID_IHTMLELEMENT3_DISABLED, 0, &v, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + + test_elem_disabled(elem, VARIANT_FALSE); + + IHTMLElement_Release(elem); + IDispatchEx_Release(dispex); +} + +static void test_ui(void) +{ + IActiveScriptSiteUIControl *ui_control; + SCRIPTUICHANDLING uic_handling = 10; + HRESULT hres; + + hres = IActiveScriptSite_QueryInterface(site, &IID_IActiveScriptSiteUIControl, (void**)&ui_control); + if(hres == E_NOINTERFACE) { + win_skip("IActiveScriptSiteUIControl not supported\n"); + return; + } + ok(hres == S_OK, "Could not get IActiveScriptSiteUIControl: %08x\n", hres); + + hres = IActiveScriptSiteUIControl_GetUIBehavior(ui_control, SCRIPTUICITEM_MSGBOX, &uic_handling); + ok(hres == S_OK, "GetUIBehavior failed: %08x\n", hres); + ok(uic_handling == SCRIPTUICHANDLING_ALLOW, "uic_handling = %d\n", uic_handling); + + IActiveScriptSiteUIControl_Release(ui_control); +} + +static void test_sp(void) +{ + IServiceProvider *sp; + IUnknown *unk; + HRESULT hres; + + hres = IActiveScriptSite_QueryInterface(site, &IID_IServiceProvider, (void**)&sp); + ok(hres == S_OK, "Could not get IServiceProvider iface: %08x\n", hres); + + hres = IServiceProvider_QueryService(sp, &SID_SContainerDispatch, &IID_IHTMLDocument, (void**)&unk); + ok(hres == S_OK, "Could not get SID_SContainerDispatch service: %08x\n", hres); + IUnknown_Release(unk); + + IServiceProvider_Release(sp); +} + +static void test_script_run(void) { IDispatchEx *document, *dispex; IHTMLWindow2 *window; @@ -1752,8 +2137,6 @@ static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *ifac static const WCHAR testW[] = {'t','e','s','t',0}; static const WCHAR funcW[] = {'f','u','n','c',0}; - CHECK_EXPECT(ParseScriptText); - SET_EXPECT(GetScriptDispatch); tmp = SysAllocString(documentW); @@ -1793,7 +2176,7 @@ static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *ifac V_VT(&var) = VT_I4; V_I4(&var) = 100; - hres = dispex_propput(document, id, 0, &var); + hres = dispex_propput(document, id, 0, &var, NULL); ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); tmp = SysAllocString(testW); @@ -1801,6 +2184,9 @@ static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *ifac SysFreeString(tmp); ok(hres == S_OK, "GetDispID(document) failed: %08x\n", hres); + hres = IDispatchEx_DeleteMemberByDispID(document, id); + ok(hres == E_NOTIMPL, "DeleteMemberByDispID failed = %08x\n", hres); + VariantInit(&var); memset(&dp, 0, sizeof(dp)); memset(&ei, 0, sizeof(ei)); @@ -1811,7 +2197,7 @@ static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *ifac V_VT(&var) = VT_I4; V_I4(&var) = 200; - hres = dispex_propput(document, id, DISPATCH_PROPERTYPUTREF, &var); + hres = dispex_propput(document, id, DISPATCH_PROPERTYPUTREF, &var, NULL); ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); VariantInit(&var); @@ -1839,6 +2225,18 @@ 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) == 300, "V_I4(&var) = %d\n", V_I4(&var)); + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = NULL; + dispex_propput(document, id, 0, &var, NULL); + + VariantInit(&var); + memset(&dp, 0, sizeof(dp)); + memset(&ei, 0, sizeof(ei)); + hres = IDispatchEx_InvokeEx(document, id, LOCALE_NEUTRAL, INVOKE_PROPERTYGET, &dp, &var, &ei, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&var) == VT_BSTR, "V_VT(var)=%d\n", V_VT(&var)); + ok(!V_BSTR(&var), "V_BSTR(&var) = %s\n", wine_dbgstr_w(V_BSTR(&var))); + unk = (void*)0xdeadbeef; hres = IDispatchEx_GetNameSpaceParent(window_dispex, &unk); ok(hres == S_OK, "GetNameSpaceParent failed: %08x\n", hres); @@ -1882,7 +2280,6 @@ static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *ifac ok(hres == S_OK, "Could not get IHTMLWindow2 iface: %08x\n", hres); hres = IHTMLWindow2_get_navigator(window, &navigator); - IHTMLWindow2_Release(window); ok(hres == S_OK, "get_navigator failed: %08x\n", hres); hres = IOmNavigator_QueryInterface(navigator, &IID_IDispatchEx, (void**)&dispex); @@ -1892,6 +2289,10 @@ static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *ifac test_func(dispex); test_nextdispid(dispex); + test_arg_conv(window); + test_default_arg_conv(window); + IHTMLWindow2_Release(window); + tmp = a2bstr("test"); hres = IDispatchEx_DeleteMemberByName(dispex, tmp, fdexNameCaseSensitive); ok(hres == E_NOTIMPL, "DeleteMemberByName failed: %08x\n", hres); @@ -1943,8 +2344,39 @@ static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *ifac test_global_id(); test_security(); + test_ui(); + test_sp(); +} - return S_OK; +static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *iface, + LPCOLESTR pstrCode, LPCOLESTR pstrItemName, IUnknown *punkContext, + LPCOLESTR pstrDelimiter, CTXARG_T dwSourceContextCookie, ULONG ulStartingLine, + DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo) +{ + ok(pvarResult != NULL, "pvarResult == NULL\n"); + ok(pexcepinfo != NULL, "pexcepinfo == NULL\n"); + + if(!strcmp_wa(pstrCode, "execScript call")) { + CHECK_EXPECT(ParseScriptText_execScript); + ok(!pstrItemName, "pstrItemName = %s\n", wine_dbgstr_w(pstrItemName)); + ok(!strcmp_wa(pstrDelimiter, "\""), "pstrDelimiter = %s\n", wine_dbgstr_w(pstrDelimiter)); + ok(dwFlags == SCRIPTTEXT_ISVISIBLE, "dwFlags = %x\n", dwFlags); + + V_VT(pvarResult) = VT_I4; + V_I4(pvarResult) = 10; + return S_OK; + }else if(!strcmp_wa(pstrCode, "simple script")) { + CHECK_EXPECT(ParseScriptText_script); + ok(!strcmp_wa(pstrItemName, "window"), "pstrItemName = %s\n", wine_dbgstr_w(pstrItemName)); + ok(!strcmp_wa(pstrDelimiter, ""), "pstrDelimiter = %s\n", wine_dbgstr_w(pstrDelimiter)); + ok(dwFlags == (SCRIPTTEXT_ISVISIBLE|SCRIPTTEXT_HOSTMANAGESSOURCE), "dwFlags = %x\n", dwFlags); + + test_script_run(); + return S_OK; + } + + ok(0, "unexpected script %s\n", wine_dbgstr_w(pstrCode)); + return E_FAIL; } static const IActiveScriptParseVtbl ActiveScriptParseVtbl = { @@ -1990,7 +2422,7 @@ static HRESULT WINAPI ActiveScript_QueryInterface(IActiveScript *iface, REFIID r if(IsEqualGUID(&IID_IActiveScriptDebug, riid)) return E_NOINTERFACE; - ok(0, "unexpected riid %s\n", debugstr_guid(riid)); + trace("QI(%s)\n", debugstr_guid(riid)); return E_NOINTERFACE; } @@ -2031,7 +2463,7 @@ static HRESULT WINAPI ActiveScript_SetScriptSite(IActiveScript *iface, IActiveSc hres = IActiveScriptSite_QueryInterface(pass, &IID_IActiveScriptSiteDebug, (void**)&debug); ok(hres == S_OK, "Could not get IActiveScriptSiteDebug interface: %08x\n", hres); if(SUCCEEDED(hres)) - IActiveScriptSiteDebug32_Release(debug); + IActiveScriptSiteDebug_Release(debug); hres = IActiveScriptSite_QueryInterface(pass, &IID_ICanHandleException, (void**)&canexpection); ok(hres == E_NOINTERFACE, "Could not get IID_ICanHandleException interface: %08x\n", hres); @@ -2265,6 +2697,38 @@ static const char simple_script_str[] = "" ""; +static void test_exec_script(IHTMLDocument2 *doc, const char *codea, const char *langa) +{ + IHTMLWindow2 *window; + BSTR code, lang; + VARIANT v; + HRESULT hres; + + hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08x\n", hres); + + code = a2bstr(codea); + lang = a2bstr(langa); + + SET_EXPECT(ParseScriptText_execScript); + hres = IHTMLWindow2_execScript(window, code, lang, &v); + ok(hres == S_OK, "execScript failed: %08x\n", hres); + ok(V_VT(&v) == VT_I4, "V_VT(v) = %d\n", V_VT(&v)); + ok(V_I4(&v) == 10, "V_I4(v) = %d\n", V_I4(&v)); + CHECK_CALLED(ParseScriptText_execScript); + SysFreeString(lang); + + lang = a2bstr("invalid"); + V_VT(&v) = 100; + hres = IHTMLWindow2_execScript(window, code, lang, &v); + ok(hres == CO_E_CLASSSTRING, "execScript failed: %08x, expected CO_E_CLASSSTRING\n", hres); + ok(V_VT(&v) == 100, "V_VT(v) = %d\n", V_VT(&v)); + SysFreeString(lang); + SysFreeString(code); + + IHTMLWindow2_Release(window); +} + static void test_simple_script(void) { IHTMLDocument2 *doc; @@ -2284,7 +2748,7 @@ static void test_simple_script(void) SET_EXPECT(SetScriptState_STARTED); SET_EXPECT(AddNamedItem); SET_EXPECT(SetProperty_ABBREVIATE_GLOBALNAME_RESOLUTION); /* IE8 */ - SET_EXPECT(ParseScriptText); + SET_EXPECT(ParseScriptText_script); SET_EXPECT(SetScriptState_CONNECTED); load_doc(doc, simple_script_str); @@ -2300,9 +2764,11 @@ static void test_simple_script(void) CHECK_CALLED(SetScriptState_STARTED); CHECK_CALLED(AddNamedItem); CHECK_CALLED_BROKEN(SetProperty_ABBREVIATE_GLOBALNAME_RESOLUTION); /* IE8 */ - CHECK_CALLED(ParseScriptText); + CHECK_CALLED(ParseScriptText_script); CHECK_CALLED(SetScriptState_CONNECTED); + test_exec_script(doc, "execScript call", "TestScript"); + if(site) IActiveScriptSite_Release(site); if(window_dispex) @@ -2372,6 +2838,9 @@ static void run_js_script(const char *test_name) static void run_js_tests(void) { run_js_script("jstest.html"); + run_js_script("exectest.html"); + run_js_script("vbtest.html"); + run_js_script("events.html"); } static BOOL init_registry(BOOL init) @@ -2395,7 +2864,7 @@ static BOOL register_script_engine(void) hres = CoRegisterClassObject(&CLSID_TestScript, (IUnknown *)&script_cf, CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, ®id); - ok(hres == S_OK, "Could not register screipt engine: %08x\n", hres); + ok(hres == S_OK, "Could not register script engine: %08x\n", hres); return TRUE; } @@ -2431,11 +2900,11 @@ START_TEST(script) if(winetest_interactive || ! is_ie_hardened()) { if(register_script_engine()) { test_simple_script(); - run_js_tests(); init_registry(FALSE); }else { skip("Could not register TestScript engine\n"); } + run_js_tests(); }else { skip("IE running in Enhanced Security Configuration\n"); } diff --git a/rostests/winetests/mshtml/style.c b/rostests/winetests/mshtml/style.c new file mode 100644 index 00000000000..7bfc766d13b --- /dev/null +++ b/rostests/winetests/mshtml/style.c @@ -0,0 +1,2635 @@ +/* + * Copyright 2007-2011 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 "ole2.h" +#include +//#include "mshtmhst.h" +//#include "docobj.h" + +static int strcmp_wa(LPCWSTR strw, const char *stra) +{ + CHAR buf[512]; + WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL); + return lstrcmpA(stra, buf); +} + +static BSTR a2bstr(const char *str) +{ + BSTR ret; + int len; + + if(!str) + return NULL; + + len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + ret = SysAllocStringLen(NULL, len); + MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); + + return ret; +} + +#define test_var_bstr(a,b) _test_var_bstr(__LINE__,a,b) +static void _test_var_bstr(unsigned line, const VARIANT *v, const char *expect) +{ + ok_(__FILE__,line)(V_VT(v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(v)); + if(expect) + ok_(__FILE__,line)(!strcmp_wa(V_BSTR(v), expect), "V_BSTR(v) = %s, expected %s\n", wine_dbgstr_w(V_BSTR(v)), expect); + else + ok_(__FILE__,line)(!V_BSTR(v), "V_BSTR(v) = %s, expected NULL\n", wine_dbgstr_w(V_BSTR(v))); +} + +#define get_elem2_iface(u) _get_elem2_iface(__LINE__,u) +static IHTMLElement2 *_get_elem2_iface(unsigned line, IUnknown *unk) +{ + IHTMLElement2 *elem; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IHTMLElement2, (void**)&elem); + ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLElement2: %08x\n", hres); + return elem; +} + +static IHTMLElement *get_element_by_id(IHTMLDocument2 *doc, const char *id) +{ + HRESULT hres; + IHTMLDocument3 *doc3; + IHTMLElement *result; + BSTR idW = a2bstr(id); + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3); + ok(hres == S_OK, "QueryInterface(IID_IHTMLDocument3) failed: %08x\n", hres); + + hres = IHTMLDocument3_getElementById(doc3, idW, &result); + ok(hres == S_OK, "getElementById failed: %08x\n", hres); + ok(result != NULL, "result == NULL\n"); + SysFreeString(idW); + + IHTMLDocument3_Release(doc3); + return result; +} + +#define get_current_style(e) _get_current_style(__LINE__,e) +static IHTMLCurrentStyle *_get_current_style(unsigned line, IHTMLElement *elem) +{ + IHTMLCurrentStyle *cstyle; + IHTMLElement2 *elem2; + HRESULT hres; + + hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLElement2, (void**)&elem2); + ok(hres == S_OK, "Could not get IHTMLElement2 iface: %08x\n", hres); + + cstyle = NULL; + hres = IHTMLElement2_get_currentStyle(elem2, &cstyle); + ok(hres == S_OK, "get_currentStyle failed: %08x\n", hres); + ok(cstyle != NULL, "cstyle = %p\n", cstyle); + + IHTMLElement2_Release(elem2); + return cstyle; +} + +#define test_border_styles(p, n) _test_border_styles(__LINE__, p, n) +static void _test_border_styles(unsigned line, IHTMLStyle *pStyle, BSTR Name) +{ + HRESULT hres; + DISPID dispid; + + hres = IHTMLStyle_GetIDsOfNames(pStyle, &IID_NULL, &Name, 1, + LOCALE_USER_DEFAULT, &dispid); + ok_(__FILE__,line) (hres == S_OK, "GetIDsOfNames: %08x\n", hres); + if(hres == S_OK) + { + DISPPARAMS params = {NULL,NULL,0,0}; + DISPID dispidNamed = DISPID_PROPERTYPUT; + VARIANT ret; + VARIANT vDefault; + VARIANTARG arg; + + hres = IHTMLStyle_Invoke(pStyle, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT, + DISPATCH_PROPERTYGET, ¶ms, &vDefault, NULL, NULL); + ok_(__FILE__,line) (hres == S_OK, "get_default. ret: %08x\n", hres); + + params.cArgs = 1; + params.cNamedArgs = 1; + params.rgdispidNamedArgs = &dispidNamed; + V_VT(&arg) = VT_BSTR; + V_BSTR(&arg) = a2bstr("none"); + params.rgvarg = &arg; + hres = IHTMLStyle_Invoke(pStyle, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT, + DISPATCH_PROPERTYPUT, ¶ms, &ret, NULL, NULL); + ok_(__FILE__,line) (hres == S_OK, "none. ret: %08x\n", hres); + VariantClear(&arg); + + V_VT(&arg) = VT_BSTR; + V_BSTR(&arg) = a2bstr("dotted"); + hres = IHTMLStyle_Invoke(pStyle, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT, + DISPATCH_PROPERTYPUT, ¶ms, &ret, NULL, NULL); + ok_(__FILE__,line) (hres == S_OK, "dotted. ret: %08x\n", hres); + VariantClear(&arg); + + V_VT(&arg) = VT_BSTR; + V_BSTR(&arg) = a2bstr("dashed"); + hres = IHTMLStyle_Invoke(pStyle, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT, + DISPATCH_PROPERTYPUT, ¶ms, &ret, NULL, NULL); + ok_(__FILE__,line) (hres == S_OK, "dashed. ret: %08x\n", hres); + VariantClear(&arg); + + V_VT(&arg) = VT_BSTR; + V_BSTR(&arg) = a2bstr("solid"); + hres = IHTMLStyle_Invoke(pStyle, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT, + DISPATCH_PROPERTYPUT, ¶ms, &ret, NULL, NULL); + ok_(__FILE__,line) (hres == S_OK, "solid. ret: %08x\n", hres); + VariantClear(&arg); + + V_VT(&arg) = VT_BSTR; + V_BSTR(&arg) = a2bstr("double"); + hres = IHTMLStyle_Invoke(pStyle, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT, + DISPATCH_PROPERTYPUT, ¶ms, &ret, NULL, NULL); + ok_(__FILE__,line) (hres == S_OK, "double. ret: %08x\n", hres); + VariantClear(&arg); + + V_VT(&arg) = VT_BSTR; + V_BSTR(&arg) = a2bstr("groove"); + hres = IHTMLStyle_Invoke(pStyle, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT, + DISPATCH_PROPERTYPUT, ¶ms, &ret, NULL, NULL); + ok_(__FILE__,line) (hres == S_OK, "groove. ret: %08x\n", hres); + VariantClear(&arg); + + V_VT(&arg) = VT_BSTR; + V_BSTR(&arg) = a2bstr("ridge"); + hres = IHTMLStyle_Invoke(pStyle, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT, + DISPATCH_PROPERTYPUT, ¶ms, &ret, NULL, NULL); + ok_(__FILE__,line) (hres == S_OK, "ridge. ret: %08x\n", hres); + VariantClear(&arg); + + V_VT(&arg) = VT_BSTR; + V_BSTR(&arg) = a2bstr("inset"); + hres = IHTMLStyle_Invoke(pStyle, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT, + DISPATCH_PROPERTYPUT, ¶ms, &ret, NULL, NULL); + ok_(__FILE__,line) (hres == S_OK, "inset. ret: %08x\n", hres); + VariantClear(&arg); + + V_VT(&arg) = VT_BSTR; + V_BSTR(&arg) = a2bstr("outset"); + hres = IHTMLStyle_Invoke(pStyle, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT, + DISPATCH_PROPERTYPUT, ¶ms, &ret, NULL, NULL); + ok_(__FILE__,line) (hres == S_OK, "outset. ret: %08x\n", hres); + VariantClear(&arg); + + V_VT(&arg) = VT_BSTR; + V_BSTR(&arg) = a2bstr("invalid"); + hres = IHTMLStyle_Invoke(pStyle, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT, + DISPATCH_PROPERTYPUT, ¶ms, &ret, NULL, NULL); + ok_(__FILE__,line) (FAILED(hres), "invalid value passed.\n"); + VariantClear(&arg); + + params.rgvarg = &vDefault; + hres = IHTMLStyle_Invoke(pStyle, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT, + DISPATCH_PROPERTYPUT, ¶ms, &ret, NULL, NULL); + ok_(__FILE__,line) (hres == S_OK, "default. ret: %08x\n", hres); + VariantClear(&vDefault); + } +} + +#define test_style_csstext(s,t) _test_style_csstext(__LINE__,s,t) +static void _test_style_csstext(unsigned line, IHTMLStyle *style, const char *extext) +{ + BSTR text = (void*)0xdeadbeef; + HRESULT hres; + + hres = IHTMLStyle_get_cssText(style, &text); + ok_(__FILE__,line)(hres == S_OK, "get_cssText failed: %08x\n", hres); + if(extext) + ok_(__FILE__,line)(!strcmp_wa(text, extext), "cssText = %s\n", wine_dbgstr_w(text)); + else + ok_(__FILE__,line)(!text, "cssText = %s\n", wine_dbgstr_w(text)); + + SysFreeString(text); +} + +#define test_style_set_csstext(s,t) _test_style_set_csstext(__LINE__,s,t) +static void _test_style_set_csstext(unsigned line, IHTMLStyle *style, const char *text) +{ + BSTR tmp; + HRESULT hres; + + tmp = a2bstr(text); + hres = IHTMLStyle_put_cssText(style, tmp); + ok_(__FILE__,line)(hres == S_OK, "put_cssText failed: %08x\n", hres); + SysFreeString(tmp); +} + +#define test_style_remove_attribute(a,b,c) _test_style_remove_attribute(__LINE__,a,b,c) +static void _test_style_remove_attribute(unsigned line, IHTMLStyle *style, const char *attr, VARIANT_BOOL exb) +{ + BSTR str = a2bstr(attr); + VARIANT_BOOL b = 100; + HRESULT hres; + + hres = IHTMLStyle_removeAttribute(style, str, 1, &b); + SysFreeString(str); + ok_(__FILE__,line)(hres == S_OK, "removeAttribute failed: %08x\n", hres); + ok_(__FILE__,line)(b == exb, "removeAttribute returned %x, expected %x\n", b, exb); +} + +#define set_text_decoration(a,b) _set_text_decoration(__LINE__,a,b) +static void _set_text_decoration(unsigned line, IHTMLStyle *style, const char *v) +{ + BSTR str; + HRESULT hres; + + str = a2bstr(v); + hres = IHTMLStyle_put_textDecoration(style, str); + ok_(__FILE__,line)(hres == S_OK, "put_textDecoration failed: %08x\n", hres); + SysFreeString(str); +} + +#define test_text_decoration(a,b) _test_text_decoration(__LINE__,a,b) +static void _test_text_decoration(unsigned line, IHTMLStyle *style, const char *exdec) +{ + BSTR str; + HRESULT hres; + + hres = IHTMLStyle_get_textDecoration(style, &str); + ok_(__FILE__,line)(hres == S_OK, "get_textDecoration failed: %08x\n", hres); + if(exdec) + ok_(__FILE__,line)(!strcmp_wa(str, exdec), "textDecoration = %s, expected %s\n", wine_dbgstr_w(str), exdec); + else + ok_(__FILE__,line)(!str, "textDecoration = %s, expected NULL\n", wine_dbgstr_w(str)); + SysFreeString(str); +} + +static void test_set_csstext(IHTMLStyle *style) +{ + VARIANT v; + HRESULT hres; + + test_style_set_csstext(style, "background-color: black;"); + + hres = IHTMLStyle_get_backgroundColor(style, &v); + ok(hres == S_OK, "get_backgroundColor: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "type failed: %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "black"), "str=%s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); +} + +static void test_style2(IHTMLStyle2 *style2) +{ + VARIANT v; + BSTR str; + HRESULT hres; + + str = (void*)0xdeadbeef; + hres = IHTMLStyle2_get_position(style2, &str); + ok(hres == S_OK, "get_position failed: %08x\n", hres); + ok(!str, "str != NULL\n"); + + str = a2bstr("absolute"); + hres = IHTMLStyle2_put_position(style2, str); + ok(hres == S_OK, "put_position failed: %08x\n", hres); + SysFreeString(str); + + str = NULL; + hres = IHTMLStyle2_get_position(style2, &str); + ok(hres == S_OK, "get_position failed: %08x\n", hres); + ok(!strcmp_wa(str, "absolute"), "get_position returned %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + /* Test right */ + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle2_get_right(style2, &v); + ok(hres == S_OK, "get_top failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(right)=%d\n", V_VT(&v)); + ok(!V_BSTR(&v), "V_BSTR(right) != NULL\n"); + VariantClear(&v); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("3px"); + hres = IHTMLStyle2_put_right(style2, v); + ok(hres == S_OK, "put_right failed: %08x\n", hres); + VariantClear(&v); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle2_get_right(style2, &v); + ok(hres == S_OK, "get_right failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "3px"), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + /* direction */ + str = (void*)0xdeadbeef; + hres = IHTMLStyle2_get_direction(style2, &str); + ok(hres == S_OK, "get_direction failed: %08x\n", hres); + ok(!str, "str = %s\n", wine_dbgstr_w(str)); + + str = a2bstr("ltr"); + hres = IHTMLStyle2_put_direction(style2, str); + ok(hres == S_OK, "put_direction failed: %08x\n", hres); + SysFreeString(str); + + str = NULL; + hres = IHTMLStyle2_get_direction(style2, &str); + ok(hres == S_OK, "get_direction failed: %08x\n", hres); + ok(!strcmp_wa(str, "ltr"), "str = %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + /* bottom */ + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle2_get_bottom(style2, &v); + ok(hres == S_OK, "get_bottom failed: %08x\n", hres); + test_var_bstr(&v, NULL); + + V_VT(&v) = VT_I4; + V_I4(&v) = 4; + hres = IHTMLStyle2_put_bottom(style2, v); + ok(hres == S_OK, "put_bottom failed: %08x\n", hres); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle2_get_bottom(style2, &v); + ok(hres == S_OK, "get_bottom failed: %08x\n", hres); + test_var_bstr(&v, "4px"); + + /* overflowX */ + str = (void*)0xdeadbeef; + hres = IHTMLStyle2_get_overflowX(style2, &str); + ok(hres == S_OK, "get_overflowX failed: %08x\n", hres); + ok(!str, "overflowX = %s\n", wine_dbgstr_w(str)); + + str = a2bstr("hidden"); + hres = IHTMLStyle2_put_overflowX(style2, str); + ok(hres == S_OK, "put_overflowX failed: %08x\n", hres); + SysFreeString(str); + + str = NULL; + hres = IHTMLStyle2_get_overflowX(style2, &str); + ok(hres == S_OK, "get_overflowX failed: %08x\n", hres); + ok(!strcmp_wa(str, "hidden"), "overflowX = %s\n", wine_dbgstr_w(str)); + + /* overflowY */ + str = (void*)0xdeadbeef; + hres = IHTMLStyle2_get_overflowY(style2, &str); + ok(hres == S_OK, "get_overflowY failed: %08x\n", hres); + ok(!str, "overflowY = %s\n", wine_dbgstr_w(str)); + + str = a2bstr("hidden"); + hres = IHTMLStyle2_put_overflowY(style2, str); + ok(hres == S_OK, "put_overflowY failed: %08x\n", hres); + SysFreeString(str); + + str = NULL; + hres = IHTMLStyle2_get_overflowY(style2, &str); + ok(hres == S_OK, "get_overflowY failed: %08x\n", hres); + ok(!strcmp_wa(str, "hidden"), "overflowX = %s\n", wine_dbgstr_w(str)); +} + +static void test_style3(IHTMLStyle3 *style3) +{ + BSTR str; + HRESULT hres; + + str = (void*)0xdeadbeef; + hres = IHTMLStyle3_get_wordWrap(style3, &str); + ok(hres == S_OK, "get_wordWrap failed: %08x\n", hres); + ok(!str, "str != NULL\n"); + + str = a2bstr("break-word"); + hres = IHTMLStyle3_put_wordWrap(style3, str); + ok(hres == S_OK, "put_wordWrap failed: %08x\n", hres); + SysFreeString(str); + + str = NULL; + hres = IHTMLStyle3_get_wordWrap(style3, &str); + ok(hres == S_OK, "get_wordWrap failed: %08x\n", hres); + ok(!strcmp_wa(str, "break-word"), "get_wordWrap returned %s\n", wine_dbgstr_w(str)); + SysFreeString(str); +} + +static void test_style4(IHTMLStyle4 *style4) +{ + HRESULT hres; + VARIANT v; + VARIANT vdefault; + + hres = IHTMLStyle4_get_minHeight(style4, &vdefault); + ok(hres == S_OK, "get_minHeight failed: %08x\n", hres); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("10px"); + hres = IHTMLStyle4_put_minHeight(style4, v); + ok(hres == S_OK, "put_minHeight failed: %08x\n", hres); + VariantClear(&v); + + hres = IHTMLStyle4_get_minHeight(style4, &v); + ok(hres == S_OK, "get_minHeight failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + ok( !strcmp_wa(V_BSTR(&v), "10px"), "expect 10px got (%s)\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle4_put_minHeight(style4, vdefault); + ok(hres == S_OK, "put_minHeight failed: %08x\n", hres); + VariantClear(&vdefault); +} + +static void test_body_style(IHTMLStyle *style) +{ + IHTMLStyle2 *style2; + IHTMLStyle3 *style3; + IHTMLStyle4 *style4; + VARIANT_BOOL b; + VARIANT v; + BSTR str; + HRESULT hres; + float f; + BSTR sOverflowDefault; + BSTR sDefault; + LONG l; + VARIANT vDefault; + + test_style_csstext(style, NULL); + + hres = IHTMLStyle_get_position(style, &str); + ok(hres == S_OK, "get_position failed: %08x\n", hres); + ok(!str, "str=%s\n", wine_dbgstr_w(str)); + + V_VT(&v) = VT_NULL; + hres = IHTMLStyle_get_marginRight(style, &v); + ok(hres == S_OK, "get_marginRight failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(marginRight) = %d\n", V_VT(&v)); + ok(!V_BSTR(&v), "V_BSTR(marginRight) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + + V_VT(&v) = VT_I4; + V_I4(&v) = 6; + hres = IHTMLStyle_put_marginRight(style, v); + ok(hres == S_OK, "put_marginRight failed: %08x\n", hres); + + V_VT(&v) = VT_NULL; + hres = IHTMLStyle_get_marginRight(style, &v); + ok(hres == S_OK, "get_marginRight failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(marginRight) = %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "6px"), "V_BSTR(marginRight) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + + V_VT(&v) = VT_NULL; + hres = IHTMLStyle_get_marginBottom(style, &v); + ok(hres == S_OK, "get_marginBottom failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(marginBottom) = %d\n", V_VT(&v)); + ok(!V_BSTR(&v), "V_BSTR(marginBottom) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + + V_VT(&v) = VT_I4; + V_I4(&v) = 6; + hres = IHTMLStyle_put_marginBottom(style, v); + ok(hres == S_OK, "put_marginBottom failed: %08x\n", hres); + + V_VT(&v) = VT_NULL; + hres = IHTMLStyle_get_marginBottom(style, &v); + ok(hres == S_OK, "get_marginBottom failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(marginBottom) = %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "6px"), "V_BSTR(marginBottom) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + + V_VT(&v) = VT_NULL; + hres = IHTMLStyle_get_marginLeft(style, &v); + ok(hres == S_OK, "get_marginLeft failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(marginLeft) = %d\n", V_VT(&v)); + ok(!V_BSTR(&v), "V_BSTR(marginLeft) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + + V_VT(&v) = VT_I4; + V_I4(&v) = 6; + hres = IHTMLStyle_put_marginLeft(style, v); + ok(hres == S_OK, "put_marginLeft failed: %08x\n", hres); + + V_VT(&v) = VT_NULL; + hres = IHTMLStyle_get_marginLeft(style, &v); + ok(hres == S_OK, "get_marginLeft failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(marginLeft) = %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "6px"), "V_BSTR(marginLeft) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + + str = (void*)0xdeadbeef; + hres = IHTMLStyle_get_fontFamily(style, &str); + ok(hres == S_OK, "get_fontFamily failed: %08x\n", hres); + ok(!str, "fontFamily = %s\n", wine_dbgstr_w(str)); + + str = (void*)0xdeadbeef; + hres = IHTMLStyle_get_fontWeight(style, &str); + ok(hres == S_OK, "get_fontWeight failed: %08x\n", hres); + ok(!str, "fontWeight = %s\n", wine_dbgstr_w(str)); + + hres = IHTMLStyle_get_fontWeight(style, &sDefault); + ok(hres == S_OK, "get_fontWeight failed: %08x\n", hres); + + str = a2bstr("test"); + hres = IHTMLStyle_put_fontWeight(style, str); + ok(hres == E_INVALIDARG, "put_fontWeight failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("bold"); + hres = IHTMLStyle_put_fontWeight(style, str); + ok(hres == S_OK, "put_fontWeight failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("bolder"); + hres = IHTMLStyle_put_fontWeight(style, str); + ok(hres == S_OK, "put_fontWeight failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("lighter"); + hres = IHTMLStyle_put_fontWeight(style, str); + ok(hres == S_OK, "put_fontWeight failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("100"); + hres = IHTMLStyle_put_fontWeight(style, str); + ok(hres == S_OK, "put_fontWeight failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("200"); + hres = IHTMLStyle_put_fontWeight(style, str); + ok(hres == S_OK, "put_fontWeight failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("300"); + hres = IHTMLStyle_put_fontWeight(style, str); + ok(hres == S_OK, "put_fontWeight failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("400"); + hres = IHTMLStyle_put_fontWeight(style, str); + ok(hres == S_OK, "put_fontWeight failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("500"); + hres = IHTMLStyle_put_fontWeight(style, str); + ok(hres == S_OK, "put_fontWeight failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("600"); + hres = IHTMLStyle_put_fontWeight(style, str); + ok(hres == S_OK, "put_fontWeight failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("700"); + hres = IHTMLStyle_put_fontWeight(style, str); + ok(hres == S_OK, "put_fontWeight failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("800"); + hres = IHTMLStyle_put_fontWeight(style, str); + ok(hres == S_OK, "put_fontWeight failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("900"); + hres = IHTMLStyle_put_fontWeight(style, str); + ok(hres == S_OK, "put_fontWeight failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLStyle_get_fontWeight(style, &str); + ok(hres == S_OK, "get_fontWeight failed: %08x\n", hres); + ok(!strcmp_wa(str, "900"), "str != style900\n"); + SysFreeString(str); + + hres = IHTMLStyle_put_fontWeight(style, sDefault); + ok(hres == S_OK, "put_fontWeight failed: %08x\n", hres); + SysFreeString(sDefault); + + /* font Variant */ + hres = IHTMLStyle_get_fontVariant(style, NULL); + ok(hres == E_INVALIDARG, "get_fontVariant failed: %08x\n", hres); + + hres = IHTMLStyle_get_fontVariant(style, &sDefault); + ok(hres == S_OK, "get_fontVariant failed: %08x\n", hres); + + str = a2bstr("test"); + hres = IHTMLStyle_put_fontVariant(style, str); + ok(hres == E_INVALIDARG, "fontVariant failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("small-caps"); + hres = IHTMLStyle_put_fontVariant(style, str); + ok(hres == S_OK, "fontVariant failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("normal"); + hres = IHTMLStyle_put_fontVariant(style, str); + ok(hres == S_OK, "fontVariant failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLStyle_put_fontVariant(style, sDefault); + ok(hres == S_OK, "fontVariant failed: %08x\n", hres); + SysFreeString(sDefault); + + str = (void*)0xdeadbeef; + hres = IHTMLStyle_get_display(style, &str); + ok(hres == S_OK, "get_display failed: %08x\n", hres); + ok(!str, "display = %s\n", wine_dbgstr_w(str)); + + str = (void*)0xdeadbeef; + hres = IHTMLStyle_get_visibility(style, &str); + ok(hres == S_OK, "get_visibility failed: %08x\n", hres); + ok(!str, "visibility = %s\n", wine_dbgstr_w(str)); + + V_VT(&v) = VT_NULL; + hres = IHTMLStyle_get_fontSize(style, &v); + ok(hres == S_OK, "get_fontSize failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(fontSize) = %d\n", V_VT(&v)); + ok(!V_BSTR(&v), "V_BSTR(fontSize) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + + V_VT(&v) = VT_I4; + V_I4(&v) = 12; + hres = IHTMLStyle_put_fontSize(style, v); + ok(hres == S_OK, "put_fontSize failed: %08x\n", hres); + + V_VT(&v) = VT_NULL; + hres = IHTMLStyle_get_fontSize(style, &v); + ok(hres == S_OK, "get_fontSize failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(fontSize) = %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "12px"), "V_BSTR(fontSize) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + + V_VT(&v) = VT_NULL; + hres = IHTMLStyle_get_color(style, &v); + ok(hres == S_OK, "get_color failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(color) = %d\n", V_VT(&v)); + ok(!V_BSTR(&v), "V_BSTR(color) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + + V_VT(&v) = VT_I4; + V_I4(&v) = 0xfdfd; + hres = IHTMLStyle_put_color(style, v); + ok(hres == S_OK, "put_color failed: %08x\n", hres); + + V_VT(&v) = VT_NULL; + hres = IHTMLStyle_get_color(style, &v); + ok(hres == S_OK, "get_color failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(color) = %d\n", V_VT(&v)); + todo_wine + ok(!strcmp_wa(V_BSTR(&v), "#00fdfd"), "V_BSTR(color) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + + b = 0xfefe; + hres = IHTMLStyle_get_textDecorationUnderline(style, &b); + ok(hres == S_OK, "get_textDecorationUnderline failed: %08x\n", hres); + ok(b == VARIANT_FALSE, "textDecorationUnderline = %x\n", b); + + hres = IHTMLStyle_put_textDecorationUnderline(style, VARIANT_TRUE); + ok(hres == S_OK, "put_textDecorationUnderline failed: %08x\n", hres); + + hres = IHTMLStyle_get_textDecorationUnderline(style, &b); + ok(hres == S_OK, "get_textDecorationUnderline failed: %08x\n", hres); + ok(b == VARIANT_TRUE, "textDecorationUnderline = %x\n", b); + + hres = IHTMLStyle_put_textDecorationUnderline(style, VARIANT_FALSE); + ok(hres == S_OK, "put_textDecorationUnderline failed: %08x\n", hres); + + b = 0xfefe; + hres = IHTMLStyle_get_textDecorationLineThrough(style, &b); + ok(hres == S_OK, "get_textDecorationLineThrough failed: %08x\n", hres); + ok(b == VARIANT_FALSE, "textDecorationLineThrough = %x\n", b); + + hres = IHTMLStyle_put_textDecorationLineThrough(style, VARIANT_TRUE); + ok(hres == S_OK, "put_textDecorationLineThrough failed: %08x\n", hres); + + hres = IHTMLStyle_get_textDecorationLineThrough(style, &b); + ok(hres == S_OK, "get_textDecorationLineThrough failed: %08x\n", hres); + ok(b == VARIANT_TRUE, "textDecorationLineThrough = %x\n", b); + + hres = IHTMLStyle_put_textDecorationLineThrough(style, VARIANT_FALSE); + ok(hres == S_OK, "put_textDecorationLineThrough failed: %08x\n", hres); + + b = 0xfefe; + hres = IHTMLStyle_get_textDecorationNone(style, &b); + ok(hres == S_OK, "get_textDecorationNone failed: %08x\n", hres); + ok(b == VARIANT_FALSE, "textDecorationNone = %x\n", b); + + hres = IHTMLStyle_put_textDecorationNone(style, VARIANT_TRUE); + ok(hres == S_OK, "put_textDecorationNone failed: %08x\n", hres); + + hres = IHTMLStyle_get_textDecorationNone(style, &b); + ok(hres == S_OK, "get_textDecorationNone failed: %08x\n", hres); + ok(b == VARIANT_TRUE, "textDecorationNone = %x\n", b); + + hres = IHTMLStyle_put_textDecorationNone(style, VARIANT_FALSE); + ok(hres == S_OK, "put_textDecorationNone failed: %08x\n", hres); + + b = 0xfefe; + hres = IHTMLStyle_get_textDecorationOverline(style, &b); + ok(hres == S_OK, "get_textDecorationOverline failed: %08x\n", hres); + ok(b == VARIANT_FALSE, "textDecorationOverline = %x\n", b); + + hres = IHTMLStyle_put_textDecorationOverline(style, VARIANT_TRUE); + ok(hres == S_OK, "put_textDecorationOverline failed: %08x\n", hres); + + hres = IHTMLStyle_get_textDecorationOverline(style, &b); + ok(hres == S_OK, "get_textDecorationOverline failed: %08x\n", hres); + ok(b == VARIANT_TRUE, "textDecorationOverline = %x\n", b); + + hres = IHTMLStyle_put_textDecorationOverline(style, VARIANT_FALSE); + ok(hres == S_OK, "put_textDecorationOverline failed: %08x\n", hres); + + b = 0xfefe; + hres = IHTMLStyle_get_textDecorationBlink(style, &b); + ok(hres == S_OK, "get_textDecorationBlink failed: %08x\n", hres); + ok(b == VARIANT_FALSE, "textDecorationBlink = %x\n", b); + + hres = IHTMLStyle_put_textDecorationBlink(style, VARIANT_TRUE); + ok(hres == S_OK, "put_textDecorationBlink failed: %08x\n", hres); + + hres = IHTMLStyle_get_textDecorationBlink(style, &b); + ok(hres == S_OK, "get_textDecorationBlink failed: %08x\n", hres); + ok(b == VARIANT_TRUE, "textDecorationBlink = %x\n", b); + + hres = IHTMLStyle_put_textDecorationBlink(style, VARIANT_FALSE); + ok(hres == S_OK, "textDecorationBlink failed: %08x\n", hres); + + hres = IHTMLStyle_get_textDecoration(style, &sDefault); + ok(hres == S_OK, "get_textDecoration failed: %08x\n", hres); + + str = a2bstr("invalid"); + hres = IHTMLStyle_put_textDecoration(style, str); + ok(hres == E_INVALIDARG, "put_textDecoration failed: %08x\n", hres); + SysFreeString(str); + + set_text_decoration(style, "none"); + test_text_decoration(style, "none"); + set_text_decoration(style, "underline"); + set_text_decoration(style, "overline"); + set_text_decoration(style, "line-through"); + set_text_decoration(style, "blink"); + set_text_decoration(style, "overline"); + set_text_decoration(style, "blink"); + test_text_decoration(style, "blink"); + + hres = IHTMLStyle_put_textDecoration(style, sDefault); + ok(hres == S_OK, "put_textDecoration failed: %08x\n", hres); + SysFreeString(sDefault); + + hres = IHTMLStyle_get_posWidth(style, NULL); + ok(hres == E_POINTER, "get_posWidth failed: %08x\n", hres); + + hres = IHTMLStyle_get_posWidth(style, &f); + ok(hres == S_OK, "get_posWidth failed: %08x\n", hres); + ok(f == 0.0f, "f = %f\n", f); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle_get_width(style, &v); + ok(hres == S_OK, "get_width failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!V_BSTR(&v), "V_BSTR(v)=%p\n", V_BSTR(&v)); + + hres = IHTMLStyle_put_posWidth(style, 2.2); + ok(hres == S_OK, "put_posWidth failed: %08x\n", hres); + + hres = IHTMLStyle_get_posWidth(style, &f); + ok(hres == S_OK, "get_posWidth failed: %08x\n", hres); + ok(f == 2.0f || + f == 2.2f, /* IE8 */ + "f = %f\n", f); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("auto"); + hres = IHTMLStyle_put_width(style, v); + ok(hres == S_OK, "put_width failed: %08x\n", hres); + VariantClear(&v); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle_get_width(style, &v); + ok(hres == S_OK, "get_width failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "auto"), "V_BSTR(v)=%s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + V_VT(&v) = VT_I4; + V_I4(&v) = 100; + hres = IHTMLStyle_put_width(style, v); + ok(hres == S_OK, "put_width failed: %08x\n", hres); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle_get_width(style, &v); + ok(hres == S_OK, "get_width failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "100px"), "V_BSTR(v)=%s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_put_pixelWidth(style, 50); + ok(hres == S_OK, "put_pixelWidth failed: %08x\n", hres); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle_get_width(style, &v); + ok(hres == S_OK, "get_width failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "50px"), "V_BSTR(v)=%s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + /* margin tests */ + str = (void*)0xdeadbeef; + hres = IHTMLStyle_get_margin(style, &str); + ok(hres == S_OK, "get_margin failed: %08x\n", hres); + ok(!str, "margin = %s\n", wine_dbgstr_w(str)); + + str = a2bstr("1"); + hres = IHTMLStyle_put_margin(style, str); + ok(hres == S_OK, "put_margin failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLStyle_get_margin(style, &str); + ok(hres == S_OK, "get_margin failed: %08x\n", hres); + ok(!strcmp_wa(str, "1px"), "margin = %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLStyle_put_margin(style, NULL); + ok(hres == S_OK, "put_margin failed: %08x\n", hres); + + str = (void*)0xdeadbeef; + hres = IHTMLStyle_get_marginTop(style, &v); + ok(hres == S_OK, "get_marginTop failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(marginTop) = %d\n", V_VT(&v)); + ok(!V_BSTR(&v), "V_BSTR(marginTop) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("6px"); + hres = IHTMLStyle_put_marginTop(style, v); + SysFreeString(V_BSTR(&v)); + ok(hres == S_OK, "put_marginTop failed: %08x\n", hres); + + str = (void*)0xdeadbeef; + hres = IHTMLStyle_get_marginTop(style, &v); + ok(hres == S_OK, "get_marginTop failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(marginTop) = %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "6px"), "V_BSTR(marginTop) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + V_VT(&v) = VT_I4; + V_I4(&v) = 5; + hres = IHTMLStyle_put_marginTop(style, v); + ok(hres == S_OK, "put_marginTop failed: %08x\n", hres); + + str = (void*)0xdeadbeef; + hres = IHTMLStyle_get_marginTop(style, &v); + ok(hres == S_OK, "get_marginTop failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(marginTop) = %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "5px"), "V_BSTR(marginTop) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + str = NULL; + hres = IHTMLStyle_get_border(style, &str); + ok(hres == S_OK, "get_border failed: %08x\n", hres); + ok(!str || !*str, "str is not empty\n"); + SysFreeString(str); + + str = a2bstr("1px"); + hres = IHTMLStyle_put_border(style, str); + ok(hres == S_OK, "put_border failed: %08x\n", hres); + SysFreeString(str); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle_get_left(style, &v); + ok(hres == S_OK, "get_left failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!V_BSTR(&v), "V_BSTR(v) != NULL\n"); + VariantClear(&v); + + l = 0xdeadbeef; + hres = IHTMLStyle_get_pixelLeft(style, &l); + ok(hres == S_OK, "get_pixelLeft failed: %08x\n", hres); + ok(!l, "pixelLeft = %d\n", l); + + /* Test posLeft */ + hres = IHTMLStyle_get_posLeft(style, NULL); + ok(hres == E_POINTER, "get_posLeft failed: %08x\n", hres); + + f = 1.0f; + hres = IHTMLStyle_get_posLeft(style, &f); + ok(hres == S_OK, "get_posLeft failed: %08x\n", hres); + ok(f == 0.0, "expected 0.0 got %f\n", f); + + hres = IHTMLStyle_put_posLeft(style, 4.9f); + ok(hres == S_OK, "put_posLeft failed: %08x\n", hres); + + hres = IHTMLStyle_get_posLeft(style, &f); + ok(hres == S_OK, "get_posLeft failed: %08x\n", hres); + ok(f == 4.0 || + f == 4.9f, /* IE8 */ + "expected 4.0 or 4.9 (IE8) got %f\n", f); + + /* Ensure left is updated correctly. */ + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle_get_left(style, &v); + ok(hres == S_OK, "get_left failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "4px") || + !strcmp_wa(V_BSTR(&v), "4.9px"), /* IE8 */ + "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + /* Test left */ + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("3px"); + hres = IHTMLStyle_put_left(style, v); + ok(hres == S_OK, "put_left failed: %08x\n", hres); + VariantClear(&v); + + hres = IHTMLStyle_get_posLeft(style, &f); + ok(hres == S_OK, "get_posLeft failed: %08x\n", hres); + ok(f == 3.0, "expected 3.0 got %f\n", f); + + l = 0xdeadbeef; + hres = IHTMLStyle_get_pixelLeft(style, &l); + ok(hres == S_OK, "get_pixelLeft failed: %08x\n", hres); + ok(l == 3, "pixelLeft = %d\n", l); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle_get_left(style, &v); + ok(hres == S_OK, "get_left failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "3px"), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("4.99"); + hres = IHTMLStyle_put_left(style, v); + ok(hres == S_OK, "put_left failed: %08x\n", hres); + VariantClear(&v); + + l = 0xdeadbeef; + hres = IHTMLStyle_get_pixelLeft(style, &l); + ok(hres == S_OK, "get_pixelLeft failed: %08x\n", hres); + ok(l == 4, "pixelLeft = %d\n", l); + + V_VT(&v) = VT_NULL; + hres = IHTMLStyle_put_left(style, v); + ok(hres == S_OK, "put_left failed: %08x\n", hres); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle_get_left(style, &v); + ok(hres == S_OK, "get_left failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!V_BSTR(&v), "V_BSTR(v) != NULL\n"); + VariantClear(&v); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle_get_top(style, &v); + ok(hres == S_OK, "get_top failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!V_BSTR(&v), "V_BSTR(v) != NULL\n"); + VariantClear(&v); + + l = 0xdeadbeef; + hres = IHTMLStyle_get_pixelLeft(style, &l); + ok(hres == S_OK, "get_pixelLeft failed: %08x\n", hres); + ok(!l, "pixelLeft = %d\n", l); + + hres = IHTMLStyle_put_pixelLeft(style, 6); + ok(hres == S_OK, "put_pixelLeft failed: %08x\n", hres); + + l = 0xdeadbeef; + hres = IHTMLStyle_get_pixelLeft(style, &l); + ok(hres == S_OK, "get_pixelLeft failed: %08x\n", hres); + ok(l == 6, "pixelLeft = %d\n", l); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle_get_left(style, &v); + ok(hres == S_OK, "get_left failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "6px"), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + /* Test posTop */ + hres = IHTMLStyle_get_posTop(style, NULL); + ok(hres == E_POINTER, "get_posTop failed: %08x\n", hres); + + f = 1.0f; + hres = IHTMLStyle_get_posTop(style, &f); + ok(hres == S_OK, "get_posTop failed: %08x\n", hres); + ok(f == 0.0, "expected 0.0 got %f\n", f); + + hres = IHTMLStyle_put_posTop(style, 4.9f); + ok(hres == S_OK, "put_posTop failed: %08x\n", hres); + + hres = IHTMLStyle_get_posTop(style, &f); + ok(hres == S_OK, "get_posTop failed: %08x\n", hres); + ok(f == 4.0 || + f == 4.9f, /* IE8 */ + "expected 4.0 or 4.9 (IE8) got %f\n", f); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("3px"); + hres = IHTMLStyle_put_top(style, v); + ok(hres == S_OK, "put_top failed: %08x\n", hres); + VariantClear(&v); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle_get_top(style, &v); + ok(hres == S_OK, "get_top failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "3px"), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_get_posTop(style, &f); + ok(hres == S_OK, "get_posTop failed: %08x\n", hres); + ok(f == 3.0, "expected 3.0 got %f\n", f); + + V_VT(&v) = VT_NULL; + hres = IHTMLStyle_put_top(style, v); + ok(hres == S_OK, "put_top failed: %08x\n", hres); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle_get_top(style, &v); + ok(hres == S_OK, "get_top failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!V_BSTR(&v), "V_BSTR(v) != NULL\n"); + VariantClear(&v); + + /* Test posHeight */ + hres = IHTMLStyle_get_posHeight(style, NULL); + ok(hres == E_POINTER, "get_posHeight failed: %08x\n", hres); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle_get_height(style, &v); + ok(hres == S_OK, "get_height failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!V_BSTR(&v), "V_BSTR(v) != NULL\n"); + VariantClear(&v); + + f = 1.0f; + hres = IHTMLStyle_get_posHeight(style, &f); + ok(hres == S_OK, "get_posHeight failed: %08x\n", hres); + ok(f == 0.0, "expected 0.0 got %f\n", f); + + hres = IHTMLStyle_put_posHeight(style, 4.9f); + ok(hres == S_OK, "put_posHeight failed: %08x\n", hres); + + hres = IHTMLStyle_get_posHeight(style, &f); + ok(hres == S_OK, "get_posHeight failed: %08x\n", hres); + ok(f == 4.0 || + f == 4.9f, /* IE8 */ + "expected 4.0 or 4.9 (IE8) got %f\n", f); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("70px"); + hres = IHTMLStyle_put_height(style, v); + ok(hres == S_OK, "put_height failed: %08x\n", hres); + VariantClear(&v); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle_get_height(style, &v); + ok(hres == S_OK, "get_height failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "70px"), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = NULL; + hres = IHTMLStyle_put_height(style, v); + ok(hres == S_OK, "put_height failed: %08x\n", hres); + VariantClear(&v); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle_get_height(style, &v); + ok(hres == S_OK, "get_height failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!V_BSTR(&v), "V_BSTR(v) = %s, expected NULL\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + V_VT(&v) = VT_I4; + V_I4(&v) = 64; + hres = IHTMLStyle_put_height(style, v); + ok(hres == S_OK, "put_height failed: %08x\n", hres); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle_get_height(style, &v); + ok(hres == S_OK, "get_height failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "64px"), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_get_posHeight(style, &f); + ok(hres == S_OK, "get_posHeight failed: %08x\n", hres); + ok(f == 64.0, "expected 64.0 got %f\n", f); + + str = (void*)0xdeadbeef; + hres = IHTMLStyle_get_cursor(style, &str); + ok(hres == S_OK, "get_cursor failed: %08x\n", hres); + ok(!str, "get_cursor != NULL\n"); + SysFreeString(str); + + str = a2bstr("default"); + hres = IHTMLStyle_put_cursor(style, str); + ok(hres == S_OK, "put_cursor failed: %08x\n", hres); + SysFreeString(str); + + str = NULL; + hres = IHTMLStyle_get_cursor(style, &str); + ok(hres == S_OK, "get_cursor failed: %08x\n", hres); + ok(!strcmp_wa(str, "default"), "get_cursor returned %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle_get_verticalAlign(style, &v); + ok(hres == S_OK, "get_vertivalAlign failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!V_BSTR(&v), "V_BSTR(v) != NULL\n"); + VariantClear(&v); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("middle"); + hres = IHTMLStyle_put_verticalAlign(style, v); + ok(hres == S_OK, "put_vertivalAlign failed: %08x\n", hres); + VariantClear(&v); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle_get_verticalAlign(style, &v); + ok(hres == S_OK, "get_verticalAlign failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "middle"), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + V_VT(&v) = VT_I4; + V_I4(&v) = 100; + hres = IHTMLStyle_put_verticalAlign(style, v); + ok(hres == S_OK, "put_vertivalAlign failed: %08x\n", hres); + VariantClear(&v); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle_get_verticalAlign(style, &v); + ok(hres == S_OK, "get_verticalAlign failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "100px"), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + str = (void*)0xdeadbeef; + hres = IHTMLStyle_get_textAlign(style, &str); + ok(hres == S_OK, "get_textAlign failed: %08x\n", hres); + ok(!str, "textAlign != NULL\n"); + + str = a2bstr("center"); + hres = IHTMLStyle_put_textAlign(style, str); + ok(hres == S_OK, "put_textAlign failed: %08x\n", hres); + SysFreeString(str); + + str = NULL; + hres = IHTMLStyle_get_textAlign(style, &str); + ok(hres == S_OK, "get_textAlign failed: %08x\n", hres); + ok(!strcmp_wa(str, "center"), "textAlign = %s\n", wine_dbgstr_w(V_BSTR(&v))); + SysFreeString(str); + + str = (void*)0xdeadbeef; + hres = IHTMLStyle_get_filter(style, &str); + ok(hres == S_OK, "get_filter failed: %08x\n", hres); + ok(!str, "filter != NULL\n"); + + str = a2bstr("alpha(opacity=100)"); + hres = IHTMLStyle_put_filter(style, str); + ok(hres == S_OK, "put_filter failed: %08x\n", hres); + SysFreeString(str); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle_get_zIndex(style, &v); + ok(hres == S_OK, "get_zIndex failed: %08x\n", hres); + ok(V_VT(&v) == VT_I4, "V_VT(v)=%d\n", V_VT(&v)); + ok(!V_I4(&v), "V_I4(v) != 0\n"); + VariantClear(&v); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("1"); + hres = IHTMLStyle_put_zIndex(style, v); + ok(hres == S_OK, "put_zIndex failed: %08x\n", hres); + VariantClear(&v); + + V_VT(&v) = VT_EMPTY; + hres = IHTMLStyle_get_zIndex(style, &v); + ok(hres == S_OK, "get_zIndex failed: %08x\n", hres); + ok(V_VT(&v) == VT_I4, "V_VT(v)=%d\n", V_VT(&v)); + ok(V_I4(&v) == 1, "V_I4(v) = %d\n", V_I4(&v)); + VariantClear(&v); + + /* fontStyle */ + hres = IHTMLStyle_get_fontStyle(style, &sDefault); + ok(hres == S_OK, "get_fontStyle failed: %08x\n", hres); + + str = a2bstr("test"); + hres = IHTMLStyle_put_fontStyle(style, str); + ok(hres == E_INVALIDARG, "put_fontStyle failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("italic"); + hres = IHTMLStyle_put_fontStyle(style, str); + ok(hres == S_OK, "put_fontStyle failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("oblique"); + hres = IHTMLStyle_put_fontStyle(style, str); + ok(hres == S_OK, "put_fontStyle failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("normal"); + hres = IHTMLStyle_put_fontStyle(style, str); + ok(hres == S_OK, "put_fontStyle failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLStyle_put_fontStyle(style, sDefault); + ok(hres == S_OK, "put_fontStyle failed: %08x\n", hres); + SysFreeString(sDefault); + + /* overflow */ + hres = IHTMLStyle_get_overflow(style, NULL); + ok(hres == E_INVALIDARG, "get_overflow failed: %08x\n", hres); + + hres = IHTMLStyle_get_overflow(style, &sOverflowDefault); + ok(hres == S_OK, "get_overflow failed: %08x\n", hres); + + str = a2bstr("test"); + hres = IHTMLStyle_put_overflow(style, str); + ok(hres == E_INVALIDARG, "put_overflow failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("visible"); + hres = IHTMLStyle_put_overflow(style, str); + ok(hres == S_OK, "put_overflow failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("scroll"); + hres = IHTMLStyle_put_overflow(style, str); + ok(hres == S_OK, "put_overflow failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("hidden"); + hres = IHTMLStyle_put_overflow(style, str); + ok(hres == S_OK, "put_overflow failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("auto"); + hres = IHTMLStyle_put_overflow(style, str); + ok(hres == S_OK, "put_overflow failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLStyle_get_overflow(style, &str); + ok(hres == S_OK, "get_overflow failed: %08x\n", hres); + ok(!strcmp_wa(str, "auto"), "str=%s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + str = a2bstr(""); + hres = IHTMLStyle_put_overflow(style, str); + ok(hres == S_OK, "put_overflow failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLStyle_get_overflow(style, &str); + ok(hres == S_OK, "get_overflow failed: %08x\n", hres); + ok(!str, "str=%s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + /* restore overflow default */ + hres = IHTMLStyle_put_overflow(style, sOverflowDefault); + ok(hres == S_OK, "put_overflow failed: %08x\n", hres); + SysFreeString(sOverflowDefault); + + /* Attribute Tests*/ + hres = IHTMLStyle_getAttribute(style, NULL, 1, &v); + ok(hres == E_INVALIDARG, "getAttribute failed: %08x\n", hres); + + str = a2bstr("position"); + hres = IHTMLStyle_getAttribute(style, str, 1, NULL); + ok(hres == E_INVALIDARG, "getAttribute failed: %08x\n", hres); + + hres = IHTMLStyle_getAttribute(style, str, 1, &v); + ok(hres == S_OK, "getAttribute failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "type failed: %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLStyle_setAttribute(style, NULL, v, 1); + ok(hres == E_INVALIDARG, "setAttribute failed: %08x\n", hres); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("absolute"); + hres = IHTMLStyle_setAttribute(style, str, v, 1); + ok(hres == S_OK, "setAttribute failed: %08x\n", hres); + VariantClear(&v); + + hres = IHTMLStyle_getAttribute(style, str, 1, &v); + ok(hres == S_OK, "getAttribute failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "type failed: %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "absolute"), "str=%s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = NULL; + hres = IHTMLStyle_setAttribute(style, str, v, 1); + ok(hres == S_OK, "setAttribute failed: %08x\n", hres); + VariantClear(&v); + + SysFreeString(str); + + str = a2bstr("borderLeftStyle"); + test_border_styles(style, str); + SysFreeString(str); + + str = a2bstr("borderbottomstyle"); + test_border_styles(style, str); + SysFreeString(str); + + str = a2bstr("borderrightstyle"); + test_border_styles(style, str); + SysFreeString(str); + + str = a2bstr("bordertopstyle"); + test_border_styles(style, str); + SysFreeString(str); + + hres = IHTMLStyle_get_borderStyle(style, &sDefault); + ok(hres == S_OK, "get_borderStyle failed: %08x\n", hres); + + str = a2bstr("none dotted dashed solid"); + hres = IHTMLStyle_put_borderStyle(style, str); + ok(hres == S_OK, "put_borderStyle failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("none dotted dashed solid"); + hres = IHTMLStyle_get_borderStyle(style, &str); + ok(hres == S_OK, "get_borderStyle failed: %08x\n", hres); + ok(!strcmp_wa(str, "none dotted dashed solid"), + "expected (none dotted dashed solid) = (%s)\n", wine_dbgstr_w(V_BSTR(&v))); + SysFreeString(str); + + str = a2bstr("double groove ridge inset"); + hres = IHTMLStyle_put_borderStyle(style, str); + ok(hres == S_OK, "put_borderStyle failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("window-inset outset ridge inset"); + hres = IHTMLStyle_put_borderStyle(style, str); + ok(hres == S_OK, "put_borderStyle failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("window-inset"); + hres = IHTMLStyle_put_borderStyle(style, str); + ok(hres == S_OK, "put_borderStyle failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("none none none none none"); + hres = IHTMLStyle_put_borderStyle(style, str); + ok(hres == S_OK, "put_borderStyle failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("invalid none none none"); + hres = IHTMLStyle_put_borderStyle(style, str); + ok(hres == E_INVALIDARG, "put_borderStyle failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("none invalid none none"); + hres = IHTMLStyle_put_borderStyle(style, str); + ok(hres == E_INVALIDARG, "put_borderStyle failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLStyle_put_borderStyle(style, sDefault); + ok(hres == S_OK, "put_borderStyle failed: %08x\n", hres); + SysFreeString(sDefault); + + /* backgoundColor */ + hres = IHTMLStyle_get_backgroundColor(style, &v); + ok(hres == S_OK, "get_backgroundColor: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "type failed: %d\n", V_VT(&v)); + ok(!V_BSTR(&v), "str=%s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("red"); + hres = IHTMLStyle_put_backgroundColor(style, v); + ok(hres == S_OK, "put_backgroundColor failed: %08x\n", hres); + VariantClear(&v); + + hres = IHTMLStyle_get_backgroundColor(style, &v); + ok(hres == S_OK, "get_backgroundColor: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "type failed: %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "red"), "str=%s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + /* padding */ + hres = IHTMLStyle_get_padding(style, &str); + ok(hres == S_OK, "get_padding failed: %08x\n", hres); + ok(!str, "padding = %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLStyle_get_paddingTop(style, &v); + ok(hres == S_OK, "get_paddingTop: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + ok(!V_BSTR(&v), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + + V_VT(&v) = VT_I4; + V_I4(&v) = 6; + hres = IHTMLStyle_put_paddingTop(style, v); + ok(hres == S_OK, "put_paddingTop failed: %08x\n", hres); + + hres = IHTMLStyle_get_paddingTop(style, &v); + ok(hres == S_OK, "get_paddingTop: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "6px"), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_get_paddingRight(style, &v); + ok(hres == S_OK, "get_paddingRight: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + ok(!V_BSTR(&v), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + + V_VT(&v) = VT_I4; + V_I4(&v) = 6; + hres = IHTMLStyle_put_paddingRight(style, v); + ok(hres == S_OK, "put_paddingRight failed: %08x\n", hres); + + hres = IHTMLStyle_get_paddingRight(style, &v); + ok(hres == S_OK, "get_paddingRight: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "6px"), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_get_paddingBottom(style, &v); + ok(hres == S_OK, "get_paddingBottom: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + ok(!V_BSTR(&v), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + + V_VT(&v) = VT_I4; + V_I4(&v) = 6; + hres = IHTMLStyle_put_paddingBottom(style, v); + ok(hres == S_OK, "put_paddingBottom failed: %08x\n", hres); + + hres = IHTMLStyle_get_paddingBottom(style, &v); + ok(hres == S_OK, "get_paddingBottom: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "6px"), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + str = a2bstr("1"); + hres = IHTMLStyle_put_padding(style, str); + ok(hres == S_OK, "put_padding failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLStyle_get_padding(style, &str); + ok(hres == S_OK, "get_padding failed: %08x\n", hres); + ok(!strcmp_wa(str, "1px"), "padding = %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + /* PaddingLeft */ + hres = IHTMLStyle_get_paddingLeft(style, &vDefault); + ok(hres == S_OK, "get_paddingLeft: %08x\n", hres); + ok(V_VT(&vDefault) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&vDefault)); + ok(!strcmp_wa(V_BSTR(&vDefault), "1px"), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&vDefault))); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("10"); + hres = IHTMLStyle_put_paddingLeft(style, v); + ok(hres == S_OK, "put_paddingLeft: %08x\n", hres); + VariantClear(&v); + + hres = IHTMLStyle_get_paddingLeft(style, &v); + ok(hres == S_OK, "get_paddingLeft: %08x\n", hres); + ok(!strcmp_wa(V_BSTR(&v), "10px"), "expecte 10 = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_put_paddingLeft(style, vDefault); + ok(hres == S_OK, "put_paddingLeft: %08x\n", hres); + + /* BackgroundRepeat */ + hres = IHTMLStyle_get_backgroundRepeat(style, &sDefault); + ok(hres == S_OK, "get_backgroundRepeat failed: %08x\n", hres); + + str = a2bstr("invalid"); + hres = IHTMLStyle_put_backgroundRepeat(style, str); + ok(hres == E_INVALIDARG, "put_backgroundRepeat failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("repeat"); + hres = IHTMLStyle_put_backgroundRepeat(style, str); + ok(hres == S_OK, "put_backgroundRepeat failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("no-repeat"); + hres = IHTMLStyle_put_backgroundRepeat(style, str); + ok(hres == S_OK, "put_backgroundRepeat failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("repeat-x"); + hres = IHTMLStyle_put_backgroundRepeat(style, str); + ok(hres == S_OK, "put_backgroundRepeat failed: %08x\n", hres); + SysFreeString(str); + + str = a2bstr("repeat-y"); + hres = IHTMLStyle_put_backgroundRepeat(style, str); + ok(hres == S_OK, "put_backgroundRepeat failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLStyle_get_backgroundRepeat(style, &str); + ok(hres == S_OK, "get_backgroundRepeat failed: %08x\n", hres); + ok(!strcmp_wa(str, "repeat-y"), "str=%s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLStyle_put_backgroundRepeat(style, sDefault); + ok(hres == S_OK, "put_backgroundRepeat failed: %08x\n", hres); + SysFreeString(sDefault); + + /* BorderColor */ + hres = IHTMLStyle_get_borderColor(style, &sDefault); + ok(hres == S_OK, "get_borderColor failed: %08x\n", hres); + + str = a2bstr("red green red blue"); + hres = IHTMLStyle_put_borderColor(style, str); + ok(hres == S_OK, "put_borderColor failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLStyle_get_borderColor(style, &str); + ok(hres == S_OK, "get_borderColor failed: %08x\n", hres); + ok(!strcmp_wa(str, "red green red blue"), "str=%s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLStyle_put_borderColor(style, sDefault); + ok(hres == S_OK, "put_borderColor failed: %08x\n", hres); + SysFreeString(sDefault); + + /* BorderRight */ + hres = IHTMLStyle_get_borderRight(style, &sDefault); + ok(hres == S_OK, "get_borderRight failed: %08x\n", hres); + + str = a2bstr("thick dotted red"); + hres = IHTMLStyle_put_borderRight(style, str); + ok(hres == S_OK, "put_borderRight failed: %08x\n", hres); + SysFreeString(str); + + /* IHTMLStyle_get_borderRight appears to have a bug where + it returns the first letter of the color. So we check + each style individually. + */ + V_BSTR(&v) = NULL; + hres = IHTMLStyle_get_borderRightColor(style, &v); + ok(hres == S_OK, "get_borderRightColor failed: %08x\n", hres); + ok(!strcmp_wa(V_BSTR(&v), "red"), "str=%s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + V_BSTR(&v) = NULL; + hres = IHTMLStyle_get_borderRightWidth(style, &v); + ok(hres == S_OK, "get_borderRightWidth failed: %08x\n", hres); + ok(!strcmp_wa(V_BSTR(&v), "thick"), "str=%s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_get_borderRightStyle(style, &str); + ok(hres == S_OK, "get_borderRightStyle failed: %08x\n", hres); + ok(!strcmp_wa(str, "dotted"), "str=%s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLStyle_put_borderRight(style, sDefault); + ok(hres == S_OK, "put_borderRight failed: %08x\n", hres); + SysFreeString(sDefault); + + /* BorderTop */ + hres = IHTMLStyle_get_borderTop(style, &sDefault); + ok(hres == S_OK, "get_borderTop failed: %08x\n", hres); + + str = a2bstr("thick dotted red"); + hres = IHTMLStyle_put_borderTop(style, str); + ok(hres == S_OK, "put_borderTop failed: %08x\n", hres); + SysFreeString(str); + + /* IHTMLStyle_get_borderTop appears to have a bug where + it returns the first letter of the color. So we check + each style individually. + */ + V_BSTR(&v) = NULL; + hres = IHTMLStyle_get_borderTopColor(style, &v); + ok(hres == S_OK, "get_borderTopColor failed: %08x\n", hres); + ok(!strcmp_wa(V_BSTR(&v), "red"), "str=%s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + V_BSTR(&v) = NULL; + hres = IHTMLStyle_get_borderTopWidth(style, &v); + ok(hres == S_OK, "get_borderTopWidth failed: %08x\n", hres); + ok(!strcmp_wa(V_BSTR(&v), "thick"), "str=%s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_get_borderTopStyle(style, &str); + ok(hres == S_OK, "get_borderTopStyle failed: %08x\n", hres); + ok(!strcmp_wa(str, "dotted"), "str=%s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLStyle_put_borderTop(style, sDefault); + ok(hres == S_OK, "put_borderTop failed: %08x\n", hres); + SysFreeString(sDefault); + + /* BorderBottom */ + hres = IHTMLStyle_get_borderBottom(style, &sDefault); + ok(hres == S_OK, "get_borderBottom failed: %08x\n", hres); + + str = a2bstr("thick dotted red"); + hres = IHTMLStyle_put_borderBottom(style, str); + ok(hres == S_OK, "put_borderBottom failed: %08x\n", hres); + SysFreeString(str); + + /* IHTMLStyle_get_borderBottom appears to have a bug where + it returns the first letter of the color. So we check + each style individually. + */ + V_BSTR(&v) = NULL; + hres = IHTMLStyle_get_borderBottomColor(style, &v); + ok(hres == S_OK, "get_borderBottomColor failed: %08x\n", hres); + ok(!strcmp_wa(V_BSTR(&v), "red"), "str=%s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + V_BSTR(&v) = NULL; + hres = IHTMLStyle_get_borderBottomWidth(style, &v); + ok(hres == S_OK, "get_borderBottomWidth failed: %08x\n", hres); + ok(!strcmp_wa(V_BSTR(&v), "thick"), "str=%s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_get_borderBottomStyle(style, &str); + ok(hres == S_OK, "get_borderBottomStyle failed: %08x\n", hres); + ok(!strcmp_wa(str, "dotted"), "str=%s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLStyle_put_borderBottom(style, sDefault); + ok(hres == S_OK, "put_borderBottom failed: %08x\n", hres); + SysFreeString(sDefault); + + /* BorderLeft */ + hres = IHTMLStyle_get_borderLeft(style, &sDefault); + ok(hres == S_OK, "get_borderLeft failed: %08x\n", hres); + + str = a2bstr("thick dotted red"); + hres = IHTMLStyle_put_borderLeft(style, str); + ok(hres == S_OK, "put_borderLeft failed: %08x\n", hres); + SysFreeString(str); + + /* IHTMLStyle_get_borderLeft appears to have a bug where + it returns the first letter of the color. So we check + each style individually. + */ + V_BSTR(&v) = NULL; + hres = IHTMLStyle_get_borderLeftColor(style, &v); + ok(hres == S_OK, "get_borderLeftColor failed: %08x\n", hres); + ok(!strcmp_wa(V_BSTR(&v), "red"), "str=%s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + V_BSTR(&v) = NULL; + hres = IHTMLStyle_get_borderLeftWidth(style, &v); + ok(hres == S_OK, "get_borderLeftWidth failed: %08x\n", hres); + ok(!strcmp_wa(V_BSTR(&v), "thick"), "str=%s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_get_borderLeftStyle(style, &str); + ok(hres == S_OK, "get_borderLeftStyle failed: %08x\n", hres); + ok(!strcmp_wa(str, "dotted"), "str=%s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLStyle_put_borderLeft(style, sDefault); + ok(hres == S_OK, "put_borderLeft failed: %08x\n", hres); + SysFreeString(sDefault); + + /* backgroundPositionX */ + hres = IHTMLStyle_get_backgroundPositionX(style, &v); + ok(hres == S_OK, "get_backgroundPositionX failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!V_BSTR(&v), "backgroundPositionX = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("10px"); + hres = IHTMLStyle_put_backgroundPositionX(style, v); + ok(hres == S_OK, "put_backgroundPositionX failed: %08x\n", hres); + VariantClear(&v); + + hres = IHTMLStyle_get_backgroundPositionX(style, &v); + ok(hres == S_OK, "get_backgroundPositionX failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "10px"), "backgroundPositionX = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + /* backgroundPositionY */ + hres = IHTMLStyle_get_backgroundPositionY(style, &v); + ok(hres == S_OK, "get_backgroundPositionY failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + VariantClear(&v); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("15px"); + hres = IHTMLStyle_put_backgroundPositionY(style, v); + ok(hres == S_OK, "put_backgroundPositionY failed: %08x\n", hres); + VariantClear(&v); + + hres = IHTMLStyle_get_backgroundPositionY(style, &v); + ok(hres == S_OK, "get_backgroundPositionY failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "15px"), "backgroundPositionY = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + /* backgroundPosition */ + str = NULL; + hres = IHTMLStyle_get_backgroundPosition(style, &str); + ok(hres == S_OK, "get_backgroundPosition failed: %08x\n", hres); + ok(!strcmp_wa(str, "10px 15px"), "backgroundPosition = %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + str = a2bstr("center 20%"); + hres = IHTMLStyle_put_backgroundPosition(style, str); + ok(hres == S_OK, "put_backgroundPosition failed: %08x\n", hres); + SysFreeString(str); + + str = NULL; + hres = IHTMLStyle_get_backgroundPosition(style, &str); + ok(hres == S_OK, "get_backgroundPosition failed: %08x\n", hres); + ok(!strcmp_wa(str, "center 20%"), "backgroundPosition = %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLStyle_get_backgroundPositionX(style, &v); + ok(hres == S_OK, "get_backgroundPositionX failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "center"), "backgroundPositionX = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_get_backgroundPositionY(style, &v); + ok(hres == S_OK, "get_backgroundPositionY failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "20%"), "backgroundPositionY = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + /* borderTopWidth */ + hres = IHTMLStyle_get_borderTopWidth(style, &vDefault); + ok(hres == S_OK, "get_borderTopWidth: %08x\n", hres); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("10px"); + hres = IHTMLStyle_put_borderTopWidth(style, v); + ok(hres == S_OK, "put_borderTopWidth: %08x\n", hres); + VariantClear(&v); + + hres = IHTMLStyle_get_borderTopWidth(style, &v); + ok(hres == S_OK, "get_borderTopWidth: %08x\n", hres); + ok(!strcmp_wa(V_BSTR(&v), "10px"), "expected 10px = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_put_borderTopWidth(style, vDefault); + ok(hres == S_OK, "put_borderTopWidth: %08x\n", hres); + VariantClear(&vDefault); + + /* borderRightWidth */ + hres = IHTMLStyle_get_borderRightWidth(style, &vDefault); + ok(hres == S_OK, "get_borderRightWidth: %08x\n", hres); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("10"); + hres = IHTMLStyle_put_borderRightWidth(style, v); + ok(hres == S_OK, "put_borderRightWidth: %08x\n", hres); + VariantClear(&v); + + hres = IHTMLStyle_get_borderRightWidth(style, &v); + ok(hres == S_OK, "get_borderRightWidth: %08x\n", hres); + ok(!strcmp_wa(V_BSTR(&v), "10px"), "expected 10px = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_put_borderRightWidth(style, vDefault); + ok(hres == S_OK, "put_borderRightWidth: %08x\n", hres); + VariantClear(&vDefault); + + /* borderBottomWidth */ + hres = IHTMLStyle_get_borderBottomWidth(style, &vDefault); + ok(hres == S_OK, "get_borderBottomWidth: %08x\n", hres); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("10"); + hres = IHTMLStyle_put_borderBottomWidth(style, v); + ok(hres == S_OK, "put_borderBottomWidth: %08x\n", hres); + VariantClear(&v); + + hres = IHTMLStyle_get_borderBottomWidth(style, &v); + ok(hres == S_OK, "get_borderBottomWidth: %08x\n", hres); + ok(!strcmp_wa(V_BSTR(&v), "10px"), "expected 10px = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_put_borderBottomWidth(style, vDefault); + ok(hres == S_OK, "put_borderBottomWidth: %08x\n", hres); + VariantClear(&vDefault); + + /* borderLeftWidth */ + hres = IHTMLStyle_get_borderLeftWidth(style, &vDefault); + ok(hres == S_OK, "get_borderLeftWidth: %08x\n", hres); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("10"); + hres = IHTMLStyle_put_borderLeftWidth(style, v); + ok(hres == S_OK, "put_borderLeftWidth: %08x\n", hres); + VariantClear(&v); + + hres = IHTMLStyle_get_borderLeftWidth(style, &v); + ok(hres == S_OK, "get_borderLeftWidth: %08x\n", hres); + ok(!strcmp_wa(V_BSTR(&v), "10px"), "expected 10px = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_put_borderLeftWidth(style, vDefault); + ok(hres == S_OK, "put_borderLeftWidth: %08x\n", hres); + VariantClear(&vDefault); + + /* wordSpacing */ + hres = IHTMLStyle_get_wordSpacing(style, &vDefault); + ok(hres == S_OK, "get_wordSpacing: %08x\n", hres); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("10"); + hres = IHTMLStyle_put_wordSpacing(style, v); + ok(hres == S_OK, "put_wordSpacing: %08x\n", hres); + VariantClear(&v); + + hres = IHTMLStyle_get_wordSpacing(style, &v); + ok(hres == S_OK, "get_wordSpacing: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "10px"), "expected 10px = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_put_wordSpacing(style, vDefault); + ok(hres == S_OK, "put_wordSpacing: %08x\n", hres); + VariantClear(&vDefault); + + /* letterSpacing */ + hres = IHTMLStyle_get_letterSpacing(style, &vDefault); + ok(hres == S_OK, "get_letterSpacing: %08x\n", hres); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("11"); + hres = IHTMLStyle_put_letterSpacing(style, v); + ok(hres == S_OK, "put_letterSpacing: %08x\n", hres); + VariantClear(&v); + + hres = IHTMLStyle_get_letterSpacing(style, &v); + ok(hres == S_OK, "get_letterSpacing: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v)=%d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "11px"), "expected 10px = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_put_letterSpacing(style, vDefault); + ok(hres == S_OK, "put_letterSpacing: %08x\n", hres); + VariantClear(&vDefault); + + /* borderTopColor */ + hres = IHTMLStyle_get_borderTopColor(style, &vDefault); + ok(hres == S_OK, "get_borderTopColor: %08x\n", hres); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("red"); + hres = IHTMLStyle_put_borderTopColor(style, v); + ok(hres == S_OK, "put_borderTopColor: %08x\n", hres); + VariantClear(&v); + + hres = IHTMLStyle_get_borderTopColor(style, &v); + ok(hres == S_OK, "get_borderTopColor: %08x\n", hres); + ok(!strcmp_wa(V_BSTR(&v), "red"), "expecte red = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_put_borderTopColor(style, vDefault); + ok(hres == S_OK, "put_borderTopColor: %08x\n", hres); + + /* borderRightColor */ + hres = IHTMLStyle_get_borderRightColor(style, &vDefault); + ok(hres == S_OK, "get_borderRightColor: %08x\n", hres); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("blue"); + hres = IHTMLStyle_put_borderRightColor(style, v); + ok(hres == S_OK, "put_borderRightColor: %08x\n", hres); + VariantClear(&v); + + hres = IHTMLStyle_get_borderRightColor(style, &v); + ok(hres == S_OK, "get_borderRightColor: %08x\n", hres); + ok(!strcmp_wa(V_BSTR(&v), "blue"), "expected blue = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_put_borderRightColor(style, vDefault); + ok(hres == S_OK, "putborderRightColorr: %08x\n", hres); + + /* borderBottomColor */ + hres = IHTMLStyle_get_borderBottomColor(style, &vDefault); + ok(hres == S_OK, "get_borderBottomColor: %08x\n", hres); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("cyan"); + hres = IHTMLStyle_put_borderBottomColor(style, v); + ok(hres == S_OK, "put_borderBottomColor: %08x\n", hres); + VariantClear(&v); + + hres = IHTMLStyle_get_borderBottomColor(style, &v); + ok(hres == S_OK, "get_borderBottomColor: %08x\n", hres); + ok(!strcmp_wa(V_BSTR(&v), "cyan"), "expected cyan = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_put_borderBottomColor(style, vDefault); + ok(hres == S_OK, "put_borderBottomColor: %08x\n", hres); + + /* borderLeftColor */ + hres = IHTMLStyle_get_borderLeftColor(style, &vDefault); + ok(hres == S_OK, "get_borderLeftColor: %08x\n", hres); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = a2bstr("cyan"); + hres = IHTMLStyle_put_borderLeftColor(style, v); + ok(hres == S_OK, "put_borderLeftColor: %08x\n", hres); + VariantClear(&v); + + hres = IHTMLStyle_get_borderLeftColor(style, &v); + ok(hres == S_OK, "get_borderLeftColor: %08x\n", hres); + ok(!strcmp_wa(V_BSTR(&v), "cyan"), "expected cyan = %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLStyle_put_borderLeftColor(style, vDefault); + ok(hres == S_OK, "put_borderLeftColor: %08x\n", hres); + + /* clip */ + hres = IHTMLStyle_get_clip(style, &str); + ok(hres == S_OK, "get_clip failed: %08x\n", hres); + ok(!str, "clip = %s\n", wine_dbgstr_w(str)); + + str = a2bstr("rect(0px 1px 500px 505px)"); + hres = IHTMLStyle_put_clip(style, str); + ok(hres == S_OK, "put_clip failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLStyle_get_clip(style, &str); + ok(hres == S_OK, "get_clip failed: %08x\n", hres); + ok(!strcmp_wa(str, "rect(0px 1px 500px 505px)"), "clip = %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + /* clear */ + hres = IHTMLStyle_get_clear(style, &str); + ok(hres == S_OK, "get_clear failed: %08x\n", hres); + ok(!str, "clear = %s\n", wine_dbgstr_w(str)); + + str = a2bstr("both"); + hres = IHTMLStyle_put_clear(style, str); + ok(hres == S_OK, "put_clear failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLStyle_get_clear(style, &str); + ok(hres == S_OK, "get_clear failed: %08x\n", hres); + ok(!strcmp_wa(str, "both"), "clear = %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + /* pageBreakAfter */ + hres = IHTMLStyle_get_pageBreakAfter(style, &str); + ok(hres == S_OK, "get_pageBreakAfter failed: %08x\n", hres); + ok(!str, "pageBreakAfter = %s\n", wine_dbgstr_w(str)); + + str = a2bstr("always"); + hres = IHTMLStyle_put_pageBreakAfter(style, str); + ok(hres == S_OK, "put_pageBreakAfter failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLStyle_get_pageBreakAfter(style, &str); + ok(hres == S_OK, "get_pageBreakAfter failed: %08x\n", hres); + ok(!strcmp_wa(str, "always"), "pageBreakAfter = %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + /* pageBreakBefore */ + hres = IHTMLStyle_get_pageBreakBefore(style, &str); + ok(hres == S_OK, "get_pageBreakBefore failed: %08x\n", hres); + ok(!str, "pageBreakBefore = %s\n", wine_dbgstr_w(str)); + + str = a2bstr("always"); + hres = IHTMLStyle_put_pageBreakBefore(style, str); + ok(hres == S_OK, "put_pageBreakBefore failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLStyle_get_pageBreakBefore(style, &str); + ok(hres == S_OK, "get_pageBreakBefore failed: %08x\n", hres); + ok(!strcmp_wa(str, "always"), "pageBreakBefore = %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + test_style_remove_attribute(style, "pageBreakBefore", VARIANT_TRUE); + test_style_remove_attribute(style, "pageBreakBefore", VARIANT_FALSE); + + hres = IHTMLStyle_get_pageBreakBefore(style, &str); + ok(hres == S_OK, "get_pageBreakBefore failed: %08x\n", hres); + ok(!str, "pageBreakBefore = %s\n", wine_dbgstr_w(str)); + + hres = IHTMLStyle_QueryInterface(style, &IID_IHTMLStyle2, (void**)&style2); + ok(hres == S_OK, "Could not get IHTMLStyle2 iface: %08x\n", hres); + if(SUCCEEDED(hres)) { + test_style2(style2); + IHTMLStyle2_Release(style2); + } + + hres = IHTMLStyle_QueryInterface(style, &IID_IHTMLStyle3, (void**)&style3); + ok(hres == S_OK, "Could not get IHTMLStyle3 iface: %08x\n", hres); + if(SUCCEEDED(hres)) { + test_style3(style3); + IHTMLStyle3_Release(style3); + } + + hres = IHTMLStyle_QueryInterface(style, &IID_IHTMLStyle4, (void**)&style4); + ok(hres == S_OK, "Could not get IHTMLStyle4 iface: %08x\n", hres); + if(SUCCEEDED(hres)) { + test_style4(style4); + IHTMLStyle4_Release(style4); + } +} + +#define test_style_filter(a,b) _test_style_filter(__LINE__,a,b) +static void _test_style_filter(unsigned line, IHTMLStyle *style, const char *exval) +{ + BSTR str; + HRESULT hres; + + str = (void*)0xdeadbeef; + hres = IHTMLStyle_get_filter(style, &str); + ok_(__FILE__,line)(hres == S_OK, "get_filter failed: %08x\n", hres); + if(exval) + ok_(__FILE__,line)(str && !strcmp_wa(str, exval), "filter = %s, expected %s\n", wine_dbgstr_w(str), exval); + else + ok_(__FILE__,line)(!str, "str = %s, expected NULL\n", wine_dbgstr_w(str)); + + SysFreeString(str); +} + +#define test_current_style_filter(a,b) _test_current_style_filter(__LINE__,a,b) +static void _test_current_style_filter(unsigned line, IHTMLCurrentStyle2 *style, const char *exval) +{ + BSTR str; + HRESULT hres; + + str = (void*)0xdeadbeef; + hres = IHTMLCurrentStyle2_get_filter(style, &str); + ok_(__FILE__,line)(hres == S_OK, "get_filter failed: %08x\n", hres); + if(exval) + ok_(__FILE__,line)(str && !strcmp_wa(str, exval), "filter = %s, expected %s\n", wine_dbgstr_w(str), exval); + else + ok_(__FILE__,line)(!str, "str = %s, expected NULL\n", wine_dbgstr_w(str)); + + SysFreeString(str); +} + +#define set_style_filter(a,b) _set_style_filter(__LINE__,a,b) +static void _set_style_filter(unsigned line, IHTMLStyle *style, const char *val) +{ + BSTR str = a2bstr(val); + HRESULT hres; + + hres = IHTMLStyle_put_filter(style, str); + ok_(__FILE__,line)(hres == S_OK, "put_filter failed: %08x\n", hres); + SysFreeString(str); + + _test_style_filter(line, style, val); +} + +static void test_style_filters(IHTMLElement *elem) +{ + IHTMLElement2 *elem2 = get_elem2_iface((IUnknown*)elem); + IHTMLCurrentStyle2 *current_style2; + IHTMLCurrentStyle *current_style; + IHTMLStyle *style; + HRESULT hres; + + hres = IHTMLElement_get_style(elem, &style); + ok(hres == S_OK, "get_style failed: %08x\n", hres); + + hres = IHTMLElement2_get_currentStyle(elem2, ¤t_style); + ok(hres == S_OK, "get_style failed: %08x\n", hres); + + hres = IHTMLCurrentStyle_QueryInterface(current_style, &IID_IHTMLCurrentStyle2, (void**)¤t_style2); + IHTMLCurrentStyle_Release(current_style); + ok(hres == S_OK, "Could not get IHTMLCurrentStyle2 iface: %08x\n", hres); + + test_style_filter(style, NULL); + test_current_style_filter(current_style2, NULL); + set_style_filter(style, "alpha(opacity=50.0040)"); + test_current_style_filter(current_style2, "alpha(opacity=50.0040)"); + set_style_filter(style, "alpha(opacity=100)"); + + IHTMLStyle_Release(style); + + hres = IHTMLElement_get_style(elem, &style); + ok(hres == S_OK, "get_style failed: %08x\n", hres); + + test_style_filter(style, "alpha(opacity=100)"); + set_style_filter(style, "xxx(a,b,c) alpha(opacity=100)"); + set_style_filter(style, NULL); + set_style_filter(style, "alpha(opacity=100)"); + test_style_remove_attribute(style, "filter", VARIANT_TRUE); + test_style_remove_attribute(style, "filter", VARIANT_FALSE); + test_style_filter(style, NULL); + + + IHTMLCurrentStyle2_Release(current_style2); + IHTMLStyle_Release(style); + IHTMLElement2_Release(elem2); +} + +static void test_current_style(IHTMLCurrentStyle *current_style) +{ + BSTR str; + HRESULT hres; + VARIANT v; + + hres = IHTMLCurrentStyle_get_display(current_style, &str); + ok(hres == S_OK, "get_display failed: %08x\n", hres); + ok(!strcmp_wa(str, "block"), "get_display returned %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLCurrentStyle_get_position(current_style, &str); + ok(hres == S_OK, "get_position failed: %08x\n", hres); + ok(!strcmp_wa(str, "absolute"), "get_position returned %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLCurrentStyle_get_fontFamily(current_style, &str); + ok(hres == S_OK, "get_fontFamily failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLCurrentStyle_get_fontStyle(current_style, &str); + ok(hres == S_OK, "get_fontStyle failed: %08x\n", hres); + ok(!strcmp_wa(str, "normal"), "get_fontStyle returned %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLCurrentStyle_get_backgroundImage(current_style, &str); + ok(hres == S_OK, "get_backgroundImage failed: %08x\n", hres); + ok(!strcmp_wa(str, "none"), "get_backgroundImage returned %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLCurrentStyle_get_fontVariant(current_style, &str); + ok(hres == S_OK, "get_fontVariant failed: %08x\n", hres); + ok(!strcmp_wa(str, "normal"), "get_fontVariant returned %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLCurrentStyle_get_borderTopStyle(current_style, &str); + ok(hres == S_OK, "get_borderTopStyle failed: %08x\n", hres); + ok(!strcmp_wa(str, "none"), "get_borderTopStyle returned %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLCurrentStyle_get_borderRightStyle(current_style, &str); + ok(hres == S_OK, "get_borderRightStyle failed: %08x\n", hres); + ok(!strcmp_wa(str, "none"), "get_borderRightStyle returned %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLCurrentStyle_get_borderBottomStyle(current_style, &str); + ok(hres == S_OK, "get_borderBottomStyle failed: %08x\n", hres); + ok(!strcmp_wa(str, "none"), "get_borderBottomStyle returned %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLCurrentStyle_get_borderLeftStyle(current_style, &str); + ok(hres == S_OK, "get_borderLeftStyle failed: %08x\n", hres); + ok(!strcmp_wa(str, "none"), "get_borderLeftStyle returned %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLCurrentStyle_get_textAlign(current_style, &str); + ok(hres == S_OK, "get_textAlign failed: %08x\n", hres); + ok(!strcmp_wa(str, "center"), "get_textAlign returned %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLCurrentStyle_get_textDecoration(current_style, &str); + ok(hres == S_OK, "get_textDecoration failed: %08x\n", hres); + ok(!strcmp_wa(str, "none"), "get_textDecoration returned %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLCurrentStyle_get_cursor(current_style, &str); + ok(hres == S_OK, "get_cursor failed: %08x\n", hres); + ok(!strcmp_wa(str, "default"), "get_cursor returned %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLCurrentStyle_get_backgroundRepeat(current_style, &str); + ok(hres == S_OK, "get_backgroundRepeat failed: %08x\n", hres); + ok(!strcmp_wa(str, "repeat"), "get_backgroundRepeat returned %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hres = IHTMLCurrentStyle_get_borderColor(current_style, &str); + ok(hres == S_OK, "get_borderColor failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLCurrentStyle_get_borderStyle(current_style, &str); + ok(hres == S_OK, "get_borderStyle failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLCurrentStyle_get_visibility(current_style, &str); + ok(hres == S_OK, "get_visibility failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLCurrentStyle_get_overflow(current_style, &str); + ok(hres == S_OK, "get_overflow failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLCurrentStyle_get_borderWidth(current_style, &str); + ok(hres == S_OK, "get_borderWidth failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLCurrentStyle_get_margin(current_style, &str); + ok(hres == S_OK, "get_margin failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLCurrentStyle_get_padding(current_style, &str); + ok(hres == S_OK, "get_padding failed: %08x\n", hres); + SysFreeString(str); + + hres = IHTMLCurrentStyle_get_fontWeight(current_style, &v); + ok(hres == S_OK, "get_fontWeight failed: %08x\n", hres); + ok(V_VT(&v) == VT_I4, "V_VT(v) = %d\n", V_VT(&v)); + ok( V_I4(&v) == 400, "expect 400 got (%d)\n", V_I4(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_fontSize(current_style, &v); + ok(hres == S_OK, "get_fontSize failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_left(current_style, &v); + ok(hres == S_OK, "get_left failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_top(current_style, &v); + ok(hres == S_OK, "get_top failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_width(current_style, &v); + ok(hres == S_OK, "get_width failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_height(current_style, &v); + ok(hres == S_OK, "get_height failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_paddingLeft(current_style, &v); + ok(hres == S_OK, "get_paddingLeft failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_zIndex(current_style, &v); + ok(hres == S_OK, "get_zIndex failed: %08x\n", hres); + ok(V_VT(&v) == VT_I4, "V_VT(v) = %d\n", V_VT(&v)); + ok( V_I4(&v) == 1, "expect 1 got (%d)\n", V_I4(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_verticalAlign(current_style, &v); + ok(hres == S_OK, "get_verticalAlign failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + ok(!strcmp_wa(V_BSTR(&v), "100px"), "get_verticalAlign returned %s\n", wine_dbgstr_w(V_BSTR(&v))); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_marginRight(current_style, &v); + ok(hres == S_OK, "get_marginRight failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_marginLeft(current_style, &v); + ok(hres == S_OK, "get_marginLeft failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_borderLeftWidth(current_style, &v); + ok(hres == S_OK, "get_borderLeftWidth failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + V_BSTR(&v) = NULL; + hres = IHTMLCurrentStyle_get_borderRightWidth(current_style, &v); + ok(hres == S_OK, "get_borderRightWidth failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_borderBottomWidth(current_style, &v); + ok(hres == S_OK, "get_borderBottomWidth failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_borderTopWidth(current_style, &v); + ok(hres == S_OK, "get_borderTopWidth failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_color(current_style, &v); + ok(hres == S_OK, "get_color failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_backgroundColor(current_style, &v); + ok(hres == S_OK, "get_backgroundColor failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_borderLeftColor(current_style, &v); + ok(hres == S_OK, "get_borderLeftColor failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_borderTopColor(current_style, &v); + ok(hres == S_OK, "get_borderTopColor failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_borderRightColor(current_style, &v); + ok(hres == S_OK, "get_borderRightColor failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_borderBottomColor(current_style, &v); + ok(hres == S_OK, "get_borderBottomColor failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_paddingTop(current_style, &v); + ok(hres == S_OK, "get_paddingTop failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_paddingRight(current_style, &v); + ok(hres == S_OK, "get_paddingRight failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_paddingBottom(current_style, &v); + ok(hres == S_OK, "get_paddingRight failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_letterSpacing(current_style, &v); + ok(hres == S_OK, "get_letterSpacing failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_marginTop(current_style, &v); + ok(hres == S_OK, "get_marginTop failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_marginBottom(current_style, &v); + ok(hres == S_OK, "get_marginBottom failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_right(current_style, &v); + ok(hres == S_OK, "get_Right failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_bottom(current_style, &v); + ok(hres == S_OK, "get_bottom failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_lineHeight(current_style, &v); + ok(hres == S_OK, "get_lineHeight failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); + + hres = IHTMLCurrentStyle_get_textIndent(current_style, &v); + ok(hres == S_OK, "get_textIndent failed: %08x\n", hres); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + VariantClear(&v); +} + +static const char basic_test_str[] = "
"; + +static void basic_style_test(IHTMLDocument2 *doc) +{ + IHTMLCurrentStyle *cstyle; + IHTMLElement *elem; + IHTMLStyle *style; + HRESULT hres; + + hres = IHTMLDocument2_get_body(doc, &elem); + ok(hres == S_OK, "get_body failed: %08x\n", hres); + + hres = IHTMLElement_get_style(elem, &style); + ok(hres == S_OK, "get_style failed: %08x\n", hres); + + test_body_style(style); + + cstyle = get_current_style(elem); + test_current_style(cstyle); + IHTMLCurrentStyle_Release(cstyle); + IHTMLElement_Release(elem); + + elem = get_element_by_id(doc, "divid"); + test_style_filters(elem); + + test_set_csstext(style); + IHTMLStyle_Release(style); + IHTMLElement_Release(elem); +} + +static const char runtimestyle_test_str[] = + ""; + +static void runtimestyle_test(IHTMLDocument2 *doc) +{ + IHTMLStyle *style, *runtime_style; + IHTMLElement2 *elem2; + IHTMLElement *elem; + BSTR str; + HRESULT hres; + + hres = IHTMLDocument2_get_body(doc, &elem); + ok(hres == S_OK, "get_body failed: %08x\n", hres); + + elem2 = get_elem2_iface((IUnknown*)elem); + + hres = IHTMLElement2_get_runtimeStyle(elem2, &runtime_style); + ok(hres == S_OK, "get_runtimeStyle failed: %08x\n", hres); + + hres = IHTMLElement_get_style(elem, &style); + ok(hres == S_OK, "get_style failed: %08x\n", hres); + + test_text_decoration(style, NULL); + test_text_decoration(runtime_style, NULL); + set_text_decoration(style, "underline"); + test_text_decoration(style, "underline"); + + hres = IHTMLStyle_get_textDecoration(style, &str); + ok(hres == S_OK, "get_textDecoration failed: %08x\n", hres); + ok(broken(!str) || !strcmp_wa(str, "underline"), "textDecoration = %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + set_text_decoration(runtime_style, "blink"); + test_text_decoration(runtime_style, "blink"); + + hres = IHTMLStyle_get_textDecoration(style, &str); + ok(hres == S_OK, "get_textDecoration failed: %08x\n", hres); + todo_wine + ok(!strcmp_wa(str, "underline"), "textDecoration = %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + IHTMLStyle_Release(runtime_style); + IHTMLStyle_Release(style); + IHTMLElement2_Release(elem2); + IHTMLElement_Release(elem); +} + +static IHTMLDocument2 *notif_doc; +static BOOL doc_complete; + +static IHTMLDocument2 *create_document(void) +{ + IHTMLDocument2 *doc; + IHTMLDocument5 *doc5; + HRESULT hres; + + hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, + &IID_IHTMLDocument2, (void**)&doc); + ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres); + if(FAILED(hres)) + return NULL; + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument5, (void**)&doc5); + if(FAILED(hres)) { + win_skip("Could not get IHTMLDocument5, probably too old IE\n"); + IHTMLDocument2_Release(doc); + return NULL; + } + + IHTMLDocument5_Release(doc5); + return doc; +} + +static HRESULT WINAPI PropertyNotifySink_QueryInterface(IPropertyNotifySink *iface, + REFIID riid, void**ppv) +{ + if(IsEqualGUID(&IID_IPropertyNotifySink, riid)) { + *ppv = iface; + return S_OK; + } + + ok(0, "unexpected call\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI PropertyNotifySink_AddRef(IPropertyNotifySink *iface) +{ + return 2; +} + +static ULONG WINAPI PropertyNotifySink_Release(IPropertyNotifySink *iface) +{ + return 1; +} + +static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, DISPID dispID) +{ + if(dispID == DISPID_READYSTATE){ + BSTR state; + HRESULT hres; + + hres = IHTMLDocument2_get_readyState(notif_doc, &state); + ok(hres == S_OK, "get_readyState failed: %08x\n", hres); + + if(!strcmp_wa(state, "complete")) + doc_complete = TRUE; + + SysFreeString(state); + } + + return S_OK; +} + +static HRESULT WINAPI PropertyNotifySink_OnRequestEdit(IPropertyNotifySink *iface, DISPID dispID) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = { + PropertyNotifySink_QueryInterface, + PropertyNotifySink_AddRef, + PropertyNotifySink_Release, + PropertyNotifySink_OnChanged, + PropertyNotifySink_OnRequestEdit +}; + +static IPropertyNotifySink PropertyNotifySink = { &PropertyNotifySinkVtbl }; + +static IHTMLDocument2 *create_doc_with_string(const char *str) +{ + IPersistStreamInit *init; + IStream *stream; + IHTMLDocument2 *doc; + HGLOBAL mem; + SIZE_T len; + + notif_doc = doc = create_document(); + if(!doc) + return NULL; + + doc_complete = FALSE; + len = strlen(str); + mem = GlobalAlloc(0, len); + memcpy(mem, str, len); + CreateStreamOnHGlobal(mem, TRUE, &stream); + + IHTMLDocument2_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&init); + + IPersistStreamInit_Load(init, stream); + IPersistStreamInit_Release(init); + IStream_Release(stream); + + return doc; +} + +static void do_advise(IUnknown *unk, REFIID riid, IUnknown *unk_advise) +{ + IConnectionPointContainer *container; + IConnectionPoint *cp; + DWORD cookie; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IConnectionPointContainer, (void**)&container); + ok(hres == S_OK, "QueryInterface(IID_IConnectionPointContainer) failed: %08x\n", hres); + + hres = IConnectionPointContainer_FindConnectionPoint(container, riid, &cp); + IConnectionPointContainer_Release(container); + ok(hres == S_OK, "FindConnectionPoint failed: %08x\n", hres); + + hres = IConnectionPoint_Advise(cp, unk_advise, &cookie); + IConnectionPoint_Release(cp); + ok(hres == S_OK, "Advise failed: %08x\n", hres); +} + +typedef void (*style_test_t)(IHTMLDocument2*); + +static void run_test(const char *str, style_test_t test) +{ + IHTMLDocument2 *doc; + ULONG ref; + MSG msg; + + 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)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + test(doc); + + ref = IHTMLDocument2_Release(doc); + ok(!ref || broken(ref == 1), /* Vista */ + "ref = %d\n", ref); +} + + +START_TEST(style) +{ + CoInitialize(NULL); + + run_test(basic_test_str, basic_style_test); + run_test(runtimestyle_test_str, runtimestyle_test); + + CoUninitialize(); +} diff --git a/rostests/winetests/mshtml/test_tlb.idl b/rostests/winetests/mshtml/test_tlb.idl new file mode 100644 index 00000000000..362b7b401cd --- /dev/null +++ b/rostests/winetests/mshtml/test_tlb.idl @@ -0,0 +1,55 @@ +/* + * Copyright 2012 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 + */ + +import "oaidl.idl"; + +[ + version(1.0), + uuid(fb137422-de47-4630-848d-a20ccae34725) +] +library MSHTMLTest { + importlib("stdole2.tlb"); + + [ + oleautomation, + odl, + uuid(e0d1ce9d-e916-4723-ace5-888c3537de78), + dual + ] + interface IActiveXTest : IDispatch { + HRESULT nothinginteresting(); + } + + [ + uuid(0d853edb-cb70-447e-9d8a-b9661c5da56f) + ] + dispinterface DispActiveXTest { + properties: + methods: + [id(1)] long testfunc(); + [id(2)] long testfunc2(long a, long b); + } + + [ + uuid(ba9d587b-1aad-4192-a29a-99bd5f7482c3) + ] + coclass ActiveXTest { + [default] interface IActiveXTest; + [source, default] interface DispActiveXTest; + } +} diff --git a/rostests/winetests/mshtml/testlist.c b/rostests/winetests/mshtml/testlist.c index 55823446f28..af66fba4797 100644 --- a/rostests/winetests/mshtml/testlist.c +++ b/rostests/winetests/mshtml/testlist.c @@ -1,11 +1,9 @@ /* Automatically generated file; DO NOT EDIT!! */ -#define WIN32_LEAN_AND_MEAN -#include - #define STANDALONE #include "wine/test.h" +extern void func_activex(void); extern void func_dom(void); extern void func_events(void); extern void func_htmldoc(void); @@ -13,15 +11,18 @@ extern void func_htmllocation(void); extern void func_misc(void); extern void func_protocol(void); extern void func_script(void); +extern void func_style(void); const struct test winetest_testlist[] = { + { "activex", func_activex }, { "dom", func_dom }, { "events", func_events }, - { "htmldoc", func_htmldoc }, - { "htmllocation", func_htmllocation }, + { "htmldoc", func_htmldoc }, + { "htmllocation", func_htmllocation }, { "misc", func_misc }, { "protocol", func_protocol }, { "script", func_script }, + { "style", func_style }, { 0, 0 } }; diff --git a/rostests/winetests/mshtml/vbtest.html b/rostests/winetests/mshtml/vbtest.html new file mode 100644 index 00000000000..c965f424261 --- /dev/null +++ b/rostests/winetests/mshtml/vbtest.html @@ -0,0 +1,48 @@ + + + + + + + + +
+ +