[MSHTML_WINETEST]
[reactos.git] / rostests / winetests / mshtml / script.c
index 5f59ea4..fae49c8 100644 (file)
 #include "windef.h"
 #include "winbase.h"
 #include "ole2.h"
+#include "wininet.h"
+#include "docobj.h"
 #include "dispex.h"
+#include "hlink.h"
 #include "mshtml.h"
+#include "mshtmhst.h"
 #include "initguid.h"
 #include "activscp.h"
 #include "activdbg.h"
@@ -112,16 +116,25 @@ DEFINE_EXPECT(AddNamedItem);
 DEFINE_EXPECT(ParseScriptText);
 DEFINE_EXPECT(GetScriptDispatch);
 DEFINE_EXPECT(funcDisp);
+DEFINE_EXPECT(script_divid_d);
 DEFINE_EXPECT(script_testprop_d);
 DEFINE_EXPECT(script_testprop_i);
+DEFINE_EXPECT(script_testprop2_d);
 DEFINE_EXPECT(AXQueryInterface_IActiveScript);
 DEFINE_EXPECT(AXQueryInterface_IObjectSafety);
 DEFINE_EXPECT(AXGetInterfaceSafetyOptions);
 DEFINE_EXPECT(AXSetInterfaceSafetyOptions);
+DEFINE_EXPECT(external_success);
 
 #define TESTSCRIPT_CLSID "{178fc163-f585-4e24-9c13-4bb7faf80746}"
+#define TESTACTIVEX_CLSID "{178fc163-f585-4e24-9c13-4bb7faf80646}"
 
 #define DISPID_SCRIPT_TESTPROP   0x100000
+#define DISPID_SCRIPT_TESTPROP2  0x100001
+
+#define DISPID_EXTERNAL_OK             0x300000
+#define DISPID_EXTERNAL_TRACE          0x300001
+#define DISPID_EXTERNAL_REPORTSUCCESS  0x300002
 
 static const GUID CLSID_TestScript =
     {0x178fc163,0xf585,0x4e24,{0x9c,0x13,0x4b,0xb7,0xfa,0xf8,0x07,0x46}};
@@ -129,9 +142,12 @@ static const GUID CLSID_TestActiveX =
     {0x178fc163,0xf585,0x4e24,{0x9c,0x13,0x4b,0xb7,0xfa,0xf8,0x06,0x46}};
 
 static IHTMLDocument2 *notif_doc;
+static IOleDocumentView *view;
 static IDispatchEx *window_dispex;
 static BOOL doc_complete;
 static IDispatch *script_disp;
+static BOOL ax_objsafe;
+static HWND container_hwnd;
 
 static const char *debugstr_guid(REFIID riid)
 {
@@ -164,6 +180,28 @@ static BSTR a2bstr(const char *str)
     return ret;
 }
 
+static BOOL init_key(const char *key_name, const char *def_value, BOOL init)
+{
+    HKEY hkey;
+    DWORD res;
+
+    if(!init) {
+        RegDeleteKey(HKEY_CLASSES_ROOT, key_name);
+        return TRUE;
+    }
+
+    res = RegCreateKeyA(HKEY_CLASSES_ROOT, key_name, &hkey);
+    if(res != ERROR_SUCCESS)
+        return FALSE;
+
+    if(def_value)
+        res = RegSetValueA(hkey, NULL, REG_SZ, def_value, strlen(def_value));
+
+    RegCloseKey(hkey);
+
+    return res == ERROR_SUCCESS;
+}
+
 static HRESULT WINAPI PropertyNotifySink_QueryInterface(IPropertyNotifySink *iface,
         REFIID riid, void**ppv)
 {
@@ -298,128 +336,716 @@ static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BS
     return E_NOTIMPL;
 }
 
-static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
+static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI funcDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
+        VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
+{
+    CHECK_EXPECT(funcDisp);
+
+    ok(id == DISPID_VALUE, "id = %d\n", id);
+    ok(lcid == 0, "lcid = %x\n", lcid);
+    ok(wFlags == DISPATCH_METHOD, "wFlags = %x\n", wFlags);
+    ok(pdp != NULL, "pdp == NULL\n");
+    ok(pdp->cArgs == 2, "pdp->cArgs = %d\n", pdp->cArgs);
+    ok(pdp->cNamedArgs == 1, "pdp->cNamedArgs = %d\n", pdp->cNamedArgs);
+    ok(pdp->rgdispidNamedArgs[0] == DISPID_THIS, "pdp->rgdispidNamedArgs[0] = %d\n", pdp->rgdispidNamedArgs[0]);
+    ok(V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(rgvarg) = %d\n", V_VT(pdp->rgvarg));
+    ok(V_VT(pdp->rgvarg+1) == VT_BOOL, "V_VT(rgvarg[1]) = %d\n", V_VT(pdp->rgvarg));
+    ok(V_BOOL(pdp->rgvarg+1) == VARIANT_TRUE, "V_BOOL(rgvarg[1]) = %x\n", V_BOOL(pdp->rgvarg));
+    ok(pvarRes != NULL, "pvarRes == NULL\n");
+    ok(pei != NULL, "pei == NULL\n");
+    ok(!pspCaller, "pspCaller != NULL\n");
+
+    V_VT(pvarRes) = VT_I4;
+    V_I4(pvarRes) = 100;
+    return S_OK;
+}
+
+static IDispatchExVtbl testObjVtbl = {
+    DispatchEx_QueryInterface,
+    DispatchEx_AddRef,
+    DispatchEx_Release,
+    DispatchEx_GetTypeInfoCount,
+    DispatchEx_GetTypeInfo,
+    DispatchEx_GetIDsOfNames,
+    DispatchEx_Invoke,
+    DispatchEx_GetDispID,
+    funcDisp_InvokeEx,
+    DispatchEx_DeleteMemberByName,
+    DispatchEx_DeleteMemberByDispID,
+    DispatchEx_GetMemberProperties,
+    DispatchEx_GetMemberName,
+    DispatchEx_GetNextDispID,
+    DispatchEx_GetNameSpaceParent
+};
+
+static IDispatchEx funcDisp = { &testObjVtbl };
+
+static HRESULT WINAPI scriptDisp_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
+{
+    if(!strcmp_wa(bstrName, "testProp")) {
+        CHECK_EXPECT(script_testprop_d);
+        ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex);
+        *pid = DISPID_SCRIPT_TESTPROP;
+        return S_OK;
+    }
+
+    if(!strcmp_wa(bstrName, "testProp2")) {
+        CHECK_EXPECT(script_testprop2_d);
+        ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex);
+        *pid = DISPID_SCRIPT_TESTPROP2;
+        return S_OK;
+    }
+
+    if(!strcmp_wa(bstrName, "divid")) {
+        CHECK_EXPECT(script_divid_d);
+        ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex);
+        return E_FAIL;
+    }
+
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI scriptDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
+        VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
+{
+    switch(id) {
+    case DISPID_SCRIPT_TESTPROP:
+        CHECK_EXPECT(script_testprop_i);
+
+        ok(lcid == 0, "lcid = %x\n", lcid);
+        ok(wFlags == DISPATCH_PROPERTYGET, "wFlags = %x\n", wFlags);
+        ok(pdp != NULL, "pdp == NULL\n");
+        ok(pdp->cArgs == 0, "pdp->cArgs = %d\n", pdp->cArgs);
+        ok(pdp->cNamedArgs == 0, "pdp->cNamedArgs = %d\n", pdp->cNamedArgs);
+        ok(!pdp->rgdispidNamedArgs, "pdp->rgdispidNamedArgs != NULL\n");
+        ok(!pdp->rgvarg, "rgvarg != NULL\n");
+        ok(pvarRes != NULL, "pvarRes == NULL\n");
+        ok(pei != NULL, "pei == NULL\n");
+        ok(!pspCaller, "pspCaller != NULL\n");
+
+        V_VT(pvarRes) = VT_NULL;
+        break;
+    default:
+        ok(0, "unexpected call\n");
+        return E_NOTIMPL;
+    }
+
+    return S_OK;
+}
+
+static IDispatchExVtbl scriptDispVtbl = {
+    DispatchEx_QueryInterface,
+    DispatchEx_AddRef,
+    DispatchEx_Release,
+    DispatchEx_GetTypeInfoCount,
+    DispatchEx_GetTypeInfo,
+    DispatchEx_GetIDsOfNames,
+    DispatchEx_Invoke,
+    scriptDisp_GetDispID,
+    scriptDisp_InvokeEx,
+    DispatchEx_DeleteMemberByName,
+    DispatchEx_DeleteMemberByDispID,
+    DispatchEx_GetMemberProperties,
+    DispatchEx_GetMemberName,
+    DispatchEx_GetNextDispID,
+    DispatchEx_GetNameSpaceParent
+};
+
+static IDispatchEx scriptDisp = { &scriptDispVtbl };
+
+static HRESULT WINAPI externalDisp_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
+{
+    if(!strcmp_wa(bstrName, "ok")) {
+        *pid = DISPID_EXTERNAL_OK;
+        return S_OK;
+    }
+    if(!strcmp_wa(bstrName, "trace")) {
+        *pid = DISPID_EXTERNAL_TRACE;
+        return S_OK;
+    }
+    if(!strcmp_wa(bstrName, "reportSuccess")) {
+        *pid = DISPID_EXTERNAL_REPORTSUCCESS;
+        return S_OK;
+    }
+
+    ok(0, "unexpected name %s\n", wine_dbgstr_w(bstrName));
+    return DISP_E_UNKNOWNNAME;
+}
+
+static HRESULT WINAPI externalDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
+        VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
+{
+    switch(id) {
+    case DISPID_EXTERNAL_OK:
+        ok(wFlags == INVOKE_FUNC || wFlags == (INVOKE_FUNC|INVOKE_PROPERTYGET), "wFlags = %x\n", wFlags);
+        ok(pdp != NULL, "pdp == NULL\n");
+        ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
+        ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
+        ok(pdp->cArgs == 2, "cArgs = %d\n", pdp->cArgs);
+        ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
+        ok(pei != NULL, "pei == NULL\n");
+
+        ok(V_VT(pdp->rgvarg) == VT_BSTR, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg));
+        ok(V_VT(pdp->rgvarg+1) == VT_BOOL, "V_VT(psp->rgvargs+1) = %d\n", V_VT(pdp->rgvarg));
+        ok(V_BOOL(pdp->rgvarg+1), "%s\n", wine_dbgstr_w(V_BSTR(pdp->rgvarg)));
+
+        return S_OK;
+
+     case DISPID_EXTERNAL_TRACE:
+        ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags);
+        ok(pdp != NULL, "pdp == NULL\n");
+        ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
+        ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
+        ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
+        ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
+        ok(!pvarRes, "pvarRes != NULL\n");
+        ok(pei != NULL, "pei == NULL\n");
+
+        ok(V_VT(pdp->rgvarg) == VT_BSTR, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg));
+        if(V_VT(pdp->rgvarg) == VT_BSTR)
+            trace("%s\n", wine_dbgstr_w(V_BSTR(pdp->rgvarg)));
+
+        return S_OK;
+
+    case DISPID_EXTERNAL_REPORTSUCCESS:
+        CHECK_EXPECT(external_success);
+
+        ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags);
+        ok(pdp != NULL, "pdp == NULL\n");
+        ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
+        ok(pdp->cArgs == 0, "cArgs = %d\n", pdp->cArgs);
+        ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
+        ok(!pvarRes, "pvarRes != NULL\n");
+        ok(pei != NULL, "pei == NULL\n");
+
+        return S_OK;
+
+    default:
+        ok(0, "unexpected call\n");
+        return E_NOTIMPL;
+    }
+
+    return S_OK;
+}
+
+static IDispatchExVtbl externalDispVtbl = {
+    DispatchEx_QueryInterface,
+    DispatchEx_AddRef,
+    DispatchEx_Release,
+    DispatchEx_GetTypeInfoCount,
+    DispatchEx_GetTypeInfo,
+    DispatchEx_GetIDsOfNames,
+    DispatchEx_Invoke,
+    externalDisp_GetDispID,
+    externalDisp_InvokeEx,
+    DispatchEx_DeleteMemberByName,
+    DispatchEx_DeleteMemberByDispID,
+    DispatchEx_GetMemberProperties,
+    DispatchEx_GetMemberName,
+    DispatchEx_GetNextDispID,
+    DispatchEx_GetNameSpaceParent
+};
+
+static IDispatchEx externalDisp = { &externalDispVtbl };
+
+static HRESULT QueryInterface(REFIID,void**);
+
+static HRESULT WINAPI DocHostUIHandler_QueryInterface(IDocHostUIHandler2 *iface, REFIID riid, void **ppv)
+{
+    return QueryInterface(riid, ppv);
+}
+
+static ULONG WINAPI DocHostUIHandler_AddRef(IDocHostUIHandler2 *iface)
+{
+    return 2;
+}
+
+static ULONG WINAPI DocHostUIHandler_Release(IDocHostUIHandler2 *iface)
+{
+    return 1;
+}
+
+static HRESULT WINAPI DocHostUIHandler_ShowContextMenu(IDocHostUIHandler2 *iface, DWORD dwID, POINT *ppt,
+        IUnknown *pcmdtReserved, IDispatch *pdicpReserved)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_GetHostInfo(IDocHostUIHandler2 *iface, DOCHOSTUIINFO *pInfo)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_ShowUI(IDocHostUIHandler2 *iface, DWORD dwID,
+        IOleInPlaceActiveObject *pActiveObject, IOleCommandTarget *pCommandTarget,
+        IOleInPlaceFrame *pFrame, IOleInPlaceUIWindow *pDoc)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI DocHostUIHandler_HideUI(IDocHostUIHandler2 *iface)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI DocHostUIHandler_UpdateUI(IDocHostUIHandler2 *iface)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI DocHostUIHandler_EnableModeless(IDocHostUIHandler2 *iface, BOOL fEnable)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_OnDocWindowActivate(IDocHostUIHandler2 *iface, BOOL fActivate)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_OnFrameWindowActivate(IDocHostUIHandler2 *iface, BOOL fActivate)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI DocHostUIHandler_ResizeBorder(IDocHostUIHandler2 *iface, LPCRECT prcBorder,
+        IOleInPlaceUIWindow *pUIWindow, BOOL fRameWindow)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_TranslateAccelerator(IDocHostUIHandler2 *iface, LPMSG lpMsg,
+        const GUID *pguidCmdGroup, DWORD nCmdID)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_GetOptionKeyPath(IDocHostUIHandler2 *iface,
+        LPOLESTR *pchKey, DWORD dw)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI DocHostUIHandler_GetDropTarget(IDocHostUIHandler2 *iface,
+        IDropTarget *pDropTarget, IDropTarget **ppDropTarget)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_GetExternal(IDocHostUIHandler2 *iface, IDispatch **ppDispatch)
+{
+    *ppDispatch = (IDispatch*)&externalDisp;
+    return S_OK;
+}
+
+static HRESULT WINAPI DocHostUIHandler_TranslateUrl(IDocHostUIHandler2 *iface, DWORD dwTranslate,
+        OLECHAR *pchURLIn, OLECHAR **ppchURLOut)
+{
+    return S_FALSE;
+}
+
+static HRESULT WINAPI DocHostUIHandler_FilterDataObject(IDocHostUIHandler2 *iface, IDataObject *pDO,
+        IDataObject **ppPORet)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DocHostUIHandler_GetOverrideKeyPath(IDocHostUIHandler2 *iface,
+        LPOLESTR *pchKey, DWORD dw)
+{
+    return E_NOTIMPL;
+}
+
+static const IDocHostUIHandler2Vtbl DocHostUIHandlerVtbl = {
+    DocHostUIHandler_QueryInterface,
+    DocHostUIHandler_AddRef,
+    DocHostUIHandler_Release,
+    DocHostUIHandler_ShowContextMenu,
+    DocHostUIHandler_GetHostInfo,
+    DocHostUIHandler_ShowUI,
+    DocHostUIHandler_HideUI,
+    DocHostUIHandler_UpdateUI,
+    DocHostUIHandler_EnableModeless,
+    DocHostUIHandler_OnDocWindowActivate,
+    DocHostUIHandler_OnFrameWindowActivate,
+    DocHostUIHandler_ResizeBorder,
+    DocHostUIHandler_TranslateAccelerator,
+    DocHostUIHandler_GetOptionKeyPath,
+    DocHostUIHandler_GetDropTarget,
+    DocHostUIHandler_GetExternal,
+    DocHostUIHandler_TranslateUrl,
+    DocHostUIHandler_FilterDataObject,
+    DocHostUIHandler_GetOverrideKeyPath
+};
+
+static IDocHostUIHandler2 DocHostUIHandler = { &DocHostUIHandlerVtbl };
+
+static HRESULT WINAPI InPlaceFrame_QueryInterface(IOleInPlaceFrame *iface, REFIID riid, void **ppv)
+{
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI InPlaceFrame_AddRef(IOleInPlaceFrame *iface)
+{
+    return 2;
+}
+
+static ULONG WINAPI InPlaceFrame_Release(IOleInPlaceFrame *iface)
+{
+    return 1;
+}
+
+static HRESULT WINAPI InPlaceFrame_GetWindow(IOleInPlaceFrame *iface, HWND *phwnd)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceFrame_ContextSensitiveHelp(IOleInPlaceFrame *iface, BOOL fEnterMode)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceFrame_GetBorder(IOleInPlaceFrame *iface, LPRECT lprectBorder)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceFrame_RequestBorderSpace(IOleInPlaceFrame *iface,
+        LPCBORDERWIDTHS pborderwidths)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceFrame_SetBorderSpace(IOleInPlaceFrame *iface,
+        LPCBORDERWIDTHS pborderwidths)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI InPlaceFrame_SetActiveObject(IOleInPlaceFrame *iface,
+        IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI InPlaceFrame_InsertMenus(IOleInPlaceFrame *iface, HMENU hmenuShared,
+        LPOLEMENUGROUPWIDTHS lpMenuWidths)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceFrame_SetMenu(IOleInPlaceFrame *iface, HMENU hmenuShared,
+        HOLEMENU holemenu, HWND hwndActiveObject)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceFrame_RemoveMenus(IOleInPlaceFrame *iface, HMENU hmenuShared)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceFrame_SetStatusText(IOleInPlaceFrame *iface, LPCOLESTR pszStatusText)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI InPlaceFrame_EnableModeless(IOleInPlaceFrame *iface, BOOL fEnable)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceFrame_TranslateAccelerator(IOleInPlaceFrame *iface, LPMSG lpmsg, WORD wID)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static const IOleInPlaceFrameVtbl InPlaceFrameVtbl = {
+    InPlaceFrame_QueryInterface,
+    InPlaceFrame_AddRef,
+    InPlaceFrame_Release,
+    InPlaceFrame_GetWindow,
+    InPlaceFrame_ContextSensitiveHelp,
+    InPlaceFrame_GetBorder,
+    InPlaceFrame_RequestBorderSpace,
+    InPlaceFrame_SetBorderSpace,
+    InPlaceFrame_SetActiveObject,
+    InPlaceFrame_InsertMenus,
+    InPlaceFrame_SetMenu,
+    InPlaceFrame_RemoveMenus,
+    InPlaceFrame_SetStatusText,
+    InPlaceFrame_EnableModeless,
+    InPlaceFrame_TranslateAccelerator
+};
+
+static IOleInPlaceFrame InPlaceFrame = { &InPlaceFrameVtbl };
+
+static HRESULT WINAPI InPlaceSite_QueryInterface(IOleInPlaceSite *iface, REFIID riid, void **ppv)
+{
+    return QueryInterface(riid, ppv);
+}
+
+static ULONG WINAPI InPlaceSite_AddRef(IOleInPlaceSite *iface)
+{
+    return 2;
+}
+
+static ULONG WINAPI InPlaceSite_Release(IOleInPlaceSite *iface)
+{
+    return 1;
+}
+
+static HRESULT WINAPI InPlaceSite_GetWindow(IOleInPlaceSite *iface, HWND *phwnd)
+{
+    *phwnd = container_hwnd;
+    return S_OK;
+}
+
+static HRESULT WINAPI InPlaceSite_ContextSensitiveHelp(IOleInPlaceSite *iface, BOOL fEnterMode)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceSite_CanInPlaceActivate(IOleInPlaceSite *iface)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI InPlaceSite_OnInPlaceActivate(IOleInPlaceSite *iface)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI InPlaceSite_OnUIActivate(IOleInPlaceSite *iface)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI InPlaceSite_GetWindowContext(IOleInPlaceSite *iface,
+        IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect,
+        LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
+{
+    static const RECT rect = {0,0,300,300};
+
+    *ppFrame = &InPlaceFrame;
+    *ppDoc = (IOleInPlaceUIWindow*)&InPlaceFrame;
+    *lprcPosRect = rect;
+    *lprcClipRect = rect;
+
+    lpFrameInfo->cb = sizeof(*lpFrameInfo);
+    lpFrameInfo->fMDIApp = FALSE;
+    lpFrameInfo->hwndFrame = container_hwnd;
+    lpFrameInfo->haccel = NULL;
+    lpFrameInfo->cAccelEntries = 0;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI InPlaceSite_Scroll(IOleInPlaceSite *iface, SIZE scrollExtant)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceSite_OnUIDeactivate(IOleInPlaceSite *iface, BOOL fUndoable)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI InPlaceSite_OnInPlaceDeactivate(IOleInPlaceSite *iface)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI InPlaceSite_DiscardUndoState(IOleInPlaceSite *iface)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceSite_DeactivateAndUndo(IOleInPlaceSite *iface)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InPlaceSite_OnPosRectChange(IOleInPlaceSite *iface, LPCRECT lprcPosRect)
+{
+    return E_NOTIMPL;
+}
+
+static const IOleInPlaceSiteVtbl InPlaceSiteVtbl = {
+    InPlaceSite_QueryInterface,
+    InPlaceSite_AddRef,
+    InPlaceSite_Release,
+    InPlaceSite_GetWindow,
+    InPlaceSite_ContextSensitiveHelp,
+    InPlaceSite_CanInPlaceActivate,
+    InPlaceSite_OnInPlaceActivate,
+    InPlaceSite_OnUIActivate,
+    InPlaceSite_GetWindowContext,
+    InPlaceSite_Scroll,
+    InPlaceSite_OnUIDeactivate,
+    InPlaceSite_OnInPlaceDeactivate,
+    InPlaceSite_DiscardUndoState,
+    InPlaceSite_DeactivateAndUndo,
+    InPlaceSite_OnPosRectChange,
+};
+
+static IOleInPlaceSite InPlaceSite = { &InPlaceSiteVtbl };
+
+static HRESULT WINAPI ClientSite_QueryInterface(IOleClientSite *iface, REFIID riid, void **ppv)
+{
+    return QueryInterface(riid, ppv);
+}
+
+static ULONG WINAPI ClientSite_AddRef(IOleClientSite *iface)
+{
+    return 2;
+}
+
+static ULONG WINAPI ClientSite_Release(IOleClientSite *iface)
+{
+    return 1;
+}
+
+static HRESULT WINAPI ClientSite_SaveObject(IOleClientSite *iface)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ClientSite_GetMoniker(IOleClientSite *iface, DWORD dwAssign, DWORD dwWhichMoniker,
+        IMoniker **ppmon)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ClientSite_GetContainer(IOleClientSite *iface, IOleContainer **ppContainer)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ClientSite_ShowObject(IOleClientSite *iface)
 {
     ok(0, "unexpected call\n");
     return E_NOTIMPL;
 }
 
-static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
+static HRESULT WINAPI ClientSite_OnShowWindow(IOleClientSite *iface, BOOL fShow)
 {
     ok(0, "unexpected call\n");
     return E_NOTIMPL;
 }
 
-static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
+static HRESULT WINAPI ClientSite_RequestNewObjectLayout(IOleClientSite *iface)
 {
     ok(0, "unexpected call\n");
     return E_NOTIMPL;
 }
 
-static HRESULT WINAPI funcDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
-        VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
-{
-    CHECK_EXPECT(funcDisp);
+static const IOleClientSiteVtbl ClientSiteVtbl = {
+    ClientSite_QueryInterface,
+    ClientSite_AddRef,
+    ClientSite_Release,
+    ClientSite_SaveObject,
+    ClientSite_GetMoniker,
+    ClientSite_GetContainer,
+    ClientSite_ShowObject,
+    ClientSite_OnShowWindow,
+    ClientSite_RequestNewObjectLayout
+};
 
-    ok(id == DISPID_VALUE, "id = %d\n", id);
-    ok(lcid == 0, "lcid = %x\n", lcid);
-    ok(wFlags == DISPATCH_METHOD, "wFlags = %x\n", wFlags);
-    ok(pdp != NULL, "pdp == NULL\n");
-    ok(pdp->cArgs == 2, "pdp->cArgs = %d\n", pdp->cArgs);
-    ok(pdp->cNamedArgs == 1, "pdp->cNamedArgs = %d\n", pdp->cNamedArgs);
-    ok(pdp->rgdispidNamedArgs[0] == DISPID_THIS, "pdp->rgdispidNamedArgs[0] = %d\n", pdp->rgdispidNamedArgs[0]);
-    ok(V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(rgvarg) = %d\n", V_VT(pdp->rgvarg));
-    ok(V_VT(pdp->rgvarg+1) == VT_BOOL, "V_VT(rgvarg[1]) = %d\n", V_VT(pdp->rgvarg));
-    ok(V_BOOL(pdp->rgvarg+1) == VARIANT_TRUE, "V_BOOL(rgvarg[1]) = %x\n", V_BOOL(pdp->rgvarg));
-    ok(pvarRes != NULL, "pvarRes == NULL\n");
-    ok(pei != NULL, "pei == NULL\n");
-    ok(!pspCaller, "pspCaller != NULL\n");
+static IOleClientSite ClientSite = { &ClientSiteVtbl };
 
-    V_VT(pvarRes) = VT_I4;
-    V_I4(pvarRes) = 100;
-    return S_OK;
+static HRESULT WINAPI DocumentSite_QueryInterface(IOleDocumentSite *iface, REFIID riid, void **ppv)
+{
+    return QueryInterface(riid, ppv);
 }
 
-static IDispatchExVtbl testObjVtbl = {
-    DispatchEx_QueryInterface,
-    DispatchEx_AddRef,
-    DispatchEx_Release,
-    DispatchEx_GetTypeInfoCount,
-    DispatchEx_GetTypeInfo,
-    DispatchEx_GetIDsOfNames,
-    DispatchEx_Invoke,
-    DispatchEx_GetDispID,
-    funcDisp_InvokeEx,
-    DispatchEx_DeleteMemberByName,
-    DispatchEx_DeleteMemberByDispID,
-    DispatchEx_GetMemberProperties,
-    DispatchEx_GetMemberName,
-    DispatchEx_GetNextDispID,
-    DispatchEx_GetNameSpaceParent
-};
-
-static IDispatchEx funcDisp = { &testObjVtbl };
-
-static HRESULT WINAPI scriptDisp_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
+static ULONG WINAPI DocumentSite_AddRef(IOleDocumentSite *iface)
 {
-    if(!strcmp_wa(bstrName, "testProp")) {
-        CHECK_EXPECT(script_testprop_d);
-        ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex);
-        *pid = DISPID_SCRIPT_TESTPROP;
-        return S_OK;
-    }
+    return 2;
+}
 
-    ok(0, "unexpected call\n");
-    return E_NOTIMPL;
+static ULONG WINAPI DocumentSite_Release(IOleDocumentSite *iface)
+{
+    return 1;
 }
 
-static HRESULT WINAPI scriptDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
-        VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
+static HRESULT WINAPI DocumentSite_ActivateMe(IOleDocumentSite *iface, IOleDocumentView *pViewToActivate)
 {
-    switch(id) {
-    case DISPID_SCRIPT_TESTPROP:
-        CHECK_EXPECT(script_testprop_i);
+    RECT rect = {0,0,300,300};
+    IOleDocument *document;
+    HRESULT hres;
 
-        ok(lcid == 0, "lcid = %x\n", lcid);
-        ok(wFlags == DISPATCH_PROPERTYGET, "wFlags = %x\n", wFlags);
-        ok(pdp != NULL, "pdp == NULL\n");
-        ok(pdp->cArgs == 0, "pdp->cArgs = %d\n", pdp->cArgs);
-        ok(pdp->cNamedArgs == 0, "pdp->cNamedArgs = %d\n", pdp->cNamedArgs);
-        ok(!pdp->rgdispidNamedArgs, "pdp->rgdispidNamedArgs != NULL\n");
-        ok(!pdp->rgvarg, "rgvarg != NULL\n");
-        ok(pvarRes != NULL, "pvarRes == NULL\n");
-        ok(pei != NULL, "pei == NULL\n");
-        ok(!pspCaller, "pspCaller != NULL\n");
+    hres = IOleDocumentView_QueryInterface(pViewToActivate, &IID_IOleDocument, (void**)&document);
+    ok(hres == S_OK, "could not get IOleDocument: %08x\n", hres);
 
-        V_VT(pvarRes) = VT_NULL;
-        break;
-    default:
-        ok(0, "unexpected call\n");
-        return E_NOTIMPL;
-    }
+    hres = IOleDocument_CreateView(document, &InPlaceSite, NULL, 0, &view);
+    IOleDocument_Release(document);
+    ok(hres == S_OK, "CreateView failed: %08x\n", hres);
+
+    hres = IOleDocumentView_SetInPlaceSite(view, &InPlaceSite);
+    ok(hres == S_OK, "SetInPlaceSite failed: %08x\n", hres);
+
+    hres = IOleDocumentView_UIActivate(view, TRUE);
+    ok(hres == S_OK, "UIActivate failed: %08x\n", hres);
+
+    hres = IOleDocumentView_SetRect(view, &rect);
+    ok(hres == S_OK, "SetRect failed: %08x\n", hres);
+
+    hres = IOleDocumentView_Show(view, TRUE);
+    ok(hres == S_OK, "Show failed: %08x\n", hres);
 
     return S_OK;
 }
 
-static IDispatchExVtbl scriptDispVtbl = {
-    DispatchEx_QueryInterface,
-    DispatchEx_AddRef,
-    DispatchEx_Release,
-    DispatchEx_GetTypeInfoCount,
-    DispatchEx_GetTypeInfo,
-    DispatchEx_GetIDsOfNames,
-    DispatchEx_Invoke,
-    scriptDisp_GetDispID,
-    scriptDisp_InvokeEx,
-    DispatchEx_DeleteMemberByName,
-    DispatchEx_DeleteMemberByDispID,
-    DispatchEx_GetMemberProperties,
-    DispatchEx_GetMemberName,
-    DispatchEx_GetNextDispID,
-    DispatchEx_GetNameSpaceParent
+static const IOleDocumentSiteVtbl DocumentSiteVtbl = {
+    DocumentSite_QueryInterface,
+    DocumentSite_AddRef,
+    DocumentSite_Release,
+    DocumentSite_ActivateMe
 };
 
-static IDispatchEx scriptDisp = { &scriptDispVtbl };
+static IOleDocumentSite DocumentSite = { &DocumentSiteVtbl };
+
+static HRESULT QueryInterface(REFIID riid, void **ppv)
+{
+    *ppv = NULL;
+
+    if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IOleClientSite, riid))
+        *ppv = &ClientSite;
+    else if(IsEqualGUID(&IID_IOleDocumentSite, riid))
+        *ppv = &DocumentSite;
+    else if(IsEqualGUID(&IID_IOleWindow, riid) || IsEqualGUID(&IID_IOleInPlaceSite, riid))
+        *ppv = &InPlaceSite;
+    else if(IsEqualGUID(&IID_IDocHostUIHandler, riid) || IsEqualGUID(&IID_IDocHostUIHandler2, riid))
+        *ppv = &DocHostUIHandler;
+
+    return *ppv ? S_OK : E_NOINTERFACE;
+}
 
 static IHTMLDocument2 *create_document(void)
 {
@@ -433,18 +1059,13 @@ static IHTMLDocument2 *create_document(void)
     return doc;
 }
 
-static IHTMLDocument2 *create_doc_with_string(const char *str)
+static void load_string(IHTMLDocument2 *doc, const char *str)
 {
     IPersistStreamInit *init;
     IStream *stream;
-    IHTMLDocument2 *doc;
     HGLOBAL mem;
     SIZE_T len;
 
-    notif_doc = doc = create_document();
-    if(!doc)
-        return NULL;
-
     doc_complete = FALSE;
     len = strlen(str);
     mem = GlobalAlloc(0, len);
@@ -456,45 +1077,76 @@ static IHTMLDocument2 *create_doc_with_string(const char *str)
     IPersistStreamInit_Load(init, stream);
     IPersistStreamInit_Release(init);
     IStream_Release(stream);
-
-    return doc;
 }
 
-static void do_advise(IUnknown *unk, REFIID riid, IUnknown *unk_advise)
+static void do_advise(IHTMLDocument2 *doc, REFIID riid, IUnknown *unk_advise)
 {
     IConnectionPointContainer *container;
     IConnectionPoint *cp;
     DWORD cookie;
     HRESULT hres;
 
-    hres = IUnknown_QueryInterface(unk, &IID_IConnectionPointContainer, (void**)&container);
+    hres = IHTMLDocument2_QueryInterface(doc, &IID_IConnectionPointContainer, (void**)&container);
     ok(hres == S_OK, "QueryInterface(IID_IConnectionPointContainer) failed: %08x\n", hres);
 
     hres = IConnectionPointContainer_FindConnectionPoint(container, riid, &cp);
     IConnectionPointContainer_Release(container);
     ok(hres == S_OK, "FindConnectionPoint failed: %08x\n", hres);
 
+    notif_doc = doc;
+
     hres = IConnectionPoint_Advise(cp, unk_advise, &cookie);
     IConnectionPoint_Release(cp);
     ok(hres == S_OK, "Advise failed: %08x\n", hres);
 }
 
+static void set_client_site(IHTMLDocument2 *doc, BOOL set)
+{
+    IOleObject *oleobj;
+    HRESULT hres;
+
+    if(!set && view) {
+        IOleDocumentView_Show(view, FALSE);
+        IOleDocumentView_CloseView(view, 0);
+        IOleDocumentView_SetInPlaceSite(view, NULL);
+        IOleDocumentView_Release(view);
+        view = NULL;
+    }
+
+    hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj);
+    ok(hres == S_OK, "Could not et IOleObject: %08x\n", hres);
+
+    hres = IOleObject_SetClientSite(oleobj, set ? &ClientSite : NULL);
+    ok(hres == S_OK, "SetClientSite failed: %08x\n", hres);
+
+    if(set) {
+        IHlinkTarget *hlink;
+
+        hres = IOleObject_QueryInterface(oleobj, &IID_IHlinkTarget, (void**)&hlink);
+        ok(hres == S_OK, "Could not get IHlinkTarget iface: %08x\n", hres);
+
+        hres = IHlinkTarget_Navigate(hlink, 0, NULL);
+        ok(hres == S_OK, "Navgate failed: %08x\n", hres);
+
+        IHlinkTarget_Release(hlink);
+    }
+
+    IOleObject_Release(oleobj);
+}
+
 typedef void (*domtest_t)(IHTMLDocument2*);
 
-static IHTMLDocument2 *create_and_load_doc(const char *str)
+static void load_doc(IHTMLDocument2 *doc, const char *str)
 {
-    IHTMLDocument2 *doc;
     IHTMLElement *body = NULL;
-    ULONG ref;
     MSG msg;
     HRESULT hres;
     static const WCHAR ucPtr[] = {'b','a','c','k','g','r','o','u','n','d',0};
     DISPID dispID = -1;
     OLECHAR *name;
 
-
-    doc = create_doc_with_string(str);
-    do_advise((IUnknown*)doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink);
+    load_string(doc, str);
+    do_advise(doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink);
 
     while(!doc_complete && GetMessage(&msg, NULL, 0, 0)) {
         TranslateMessage(&msg);
@@ -504,13 +1156,6 @@ static IHTMLDocument2 *create_and_load_doc(const char *str)
     hres = IHTMLDocument2_get_body(doc, &body);
     ok(hres == S_OK, "get_body failed: %08x\n", hres);
 
-    if(!body) {
-        skip("Could not get document body. Assuming no Gecko installed.\n");
-        ref = IHTMLDocument2_Release(doc);
-        ok(!ref, "ref = %d\n", ref);
-        return NULL;
-    }
-
     /* Check we can query for function on the IHTMLElementBody interface */
     name = (WCHAR*)ucPtr;
     hres = IHTMLElement_GetIDsOfNames(body, &IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &dispID);
@@ -518,7 +1163,6 @@ static IHTMLDocument2 *create_and_load_doc(const char *str)
     ok(dispID == DISPID_IHTMLBODYELEMENT_BACKGROUND, "Incorrect dispID got (%d)\n", dispID);
 
     IHTMLElement_Release(body);
-    return doc;
 }
 
 static IActiveScriptSite *site;
@@ -592,6 +1236,8 @@ static HRESULT WINAPI AXObjectSafety_QueryInterface(IObjectSafety *iface, REFIID
 
     if(IsEqualGUID(&IID_IObjectSafety, riid)) {
         CHECK_EXPECT(AXQueryInterface_IObjectSafety);
+        if(!ax_objsafe)
+            return E_NOINTERFACE;
         *ppv = iface;
         return S_OK;
     }
@@ -640,6 +1286,12 @@ static const IObjectSafetyVtbl AXObjectSafetyVtbl = {
 
 static IObjectSafety AXObjectSafety = { &AXObjectSafetyVtbl };
 
+static BOOL set_safe_reg(BOOL init)
+{
+    return init_key("CLSID\\"TESTACTIVEX_CLSID"\\Implemented Categories\\{7dd95801-9882-11cf-9fa9-00aa006c42c4}",
+                    NULL, init);
+}
+
 static void test_security(void)
 {
     IInternetHostSecurityManager *sec_mgr;
@@ -666,6 +1318,7 @@ static void test_security(void)
     cs.pUnk = (IUnknown*)&AXObjectSafety;
     cs.dwFlags = 0;
 
+    ax_objsafe = TRUE;
     SET_EXPECT(AXQueryInterface_IActiveScript);
     SET_EXPECT(AXQueryInterface_IObjectSafety);
     SET_EXPECT(AXGetInterfaceSafetyOptions);
@@ -682,6 +1335,55 @@ static void test_security(void)
     ok(*(DWORD*)ppolicy == URLPOLICY_ALLOW, "policy = %x\n", *(DWORD*)ppolicy);
     CoTaskMemFree(ppolicy);
 
+    ax_objsafe = FALSE;
+    SET_EXPECT(AXQueryInterface_IActiveScript);
+    SET_EXPECT(AXQueryInterface_IObjectSafety);
+    hres = IInternetHostSecurityManager_QueryCustomPolicy(sec_mgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY,
+            &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
+    CHECK_CALLED(AXQueryInterface_IActiveScript);
+    CHECK_CALLED(AXQueryInterface_IObjectSafety);
+
+    ok(hres == S_OK, "QueryCusromPolicy failed: %08x\n", hres);
+    ok(policy_size == sizeof(DWORD), "policy_size = %d\n", policy_size);
+    ok(*(DWORD*)ppolicy == URLPOLICY_DISALLOW, "policy = %x\n", *(DWORD*)ppolicy);
+    CoTaskMemFree(ppolicy);
+
+    if(set_safe_reg(TRUE)) {
+        ax_objsafe = FALSE;
+        SET_EXPECT(AXQueryInterface_IActiveScript);
+        SET_EXPECT(AXQueryInterface_IObjectSafety);
+        hres = IInternetHostSecurityManager_QueryCustomPolicy(sec_mgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY,
+                 &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
+        CHECK_CALLED(AXQueryInterface_IActiveScript);
+        CHECK_CALLED(AXQueryInterface_IObjectSafety);
+
+        ok(hres == S_OK, "QueryCusromPolicy failed: %08x\n", hres);
+        ok(policy_size == sizeof(DWORD), "policy_size = %d\n", policy_size);
+        ok(*(DWORD*)ppolicy == URLPOLICY_ALLOW, "policy = %x\n", *(DWORD*)ppolicy);
+        CoTaskMemFree(ppolicy);
+
+        ax_objsafe = TRUE;
+        SET_EXPECT(AXQueryInterface_IActiveScript);
+        SET_EXPECT(AXQueryInterface_IObjectSafety);
+        SET_EXPECT(AXGetInterfaceSafetyOptions);
+        SET_EXPECT(AXSetInterfaceSafetyOptions);
+        hres = IInternetHostSecurityManager_QueryCustomPolicy(sec_mgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY,
+                &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
+        CHECK_CALLED(AXQueryInterface_IActiveScript);
+        CHECK_CALLED(AXQueryInterface_IObjectSafety);
+        CHECK_CALLED(AXGetInterfaceSafetyOptions);
+        CHECK_CALLED(AXSetInterfaceSafetyOptions);
+
+        ok(hres == S_OK, "QueryCusromPolicy failed: %08x\n", hres);
+        ok(policy_size == sizeof(DWORD), "policy_size = %d\n", policy_size);
+        ok(*(DWORD*)ppolicy == URLPOLICY_ALLOW, "policy = %x\n", *(DWORD*)ppolicy);
+        CoTaskMemFree(ppolicy);
+
+        set_safe_reg(FALSE);
+    }else {
+        skip("Could not set safety registry\n");
+    }
+
     IInternetHostSecurityManager_Release(sec_mgr);
 }
 
@@ -817,13 +1519,13 @@ static HRESULT WINAPI ActiveScriptParse_AddScriptlet(IActiveScriptParse *iface,
     return E_NOTIMPL;
 }
 
-static HRESULT dispex_propput(IDispatchEx *obj, DISPID id, VARIANT *var)
+static HRESULT dispex_propput(IDispatchEx *obj, DISPID id, DWORD flags, VARIANT *var)
 {
     DISPID propput_arg = DISPID_PROPERTYPUT;
     DISPPARAMS dp = {var, &propput_arg, 1, 1};
     EXCEPINFO ei = {0};
 
-    return IDispatchEx_InvokeEx(obj, id, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dp, NULL, &ei, NULL);
+    return IDispatchEx_InvokeEx(obj, id, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT|flags, &dp, NULL, &ei, NULL);
 }
 
 static void test_func(IDispatchEx *obj)
@@ -871,7 +1573,7 @@ static void test_func(IDispatchEx *obj)
 
     V_VT(&var) = VT_I4;
     V_I4(&var) = 100;
-    hres = dispex_propput(obj, id, &var);
+    hres = dispex_propput(obj, id, 0, &var);
     ok(hres == E_NOTIMPL, "InvokeEx failed: %08x\n", hres);
 
     IDispatchEx_Release(dispex);
@@ -890,7 +1592,7 @@ static void test_nextdispid(IDispatchEx *dispex)
     SysFreeString(name);
 
     V_VT(&var) = VT_EMPTY;
-    hres = dispex_propput(dispex, dyn_id, &var);
+    hres = dispex_propput(dispex, dyn_id, 0, &var);
 
     while(last_id != dyn_id) {
         hres = IDispatchEx_GetNextDispID(dispex, fdexEnumAll, last_id, &id);
@@ -915,6 +1617,33 @@ static void test_nextdispid(IDispatchEx *dispex)
     ok(id == DISPID_STARTENUM, "id != DISPID_STARTENUM\n");
 }
 
+static void test_global_id(void)
+{
+    VARIANT var;
+    DISPPARAMS dp;
+    EXCEPINFO ei;
+    BSTR tmp;
+    DISPID id;
+    HRESULT hres;
+
+    SET_EXPECT(GetScriptDispatch);
+    SET_EXPECT(script_divid_d);
+    tmp = a2bstr("divid");
+    hres = IDispatchEx_GetDispID(window_dispex, tmp, fdexNameCaseSensitive, &id);
+    ok(hres == S_OK, "GetDispID failed: %08x\n", hres);
+    SysFreeString(tmp);
+    CHECK_CALLED(GetScriptDispatch);
+    CHECK_CALLED(script_divid_d);
+
+    VariantInit(&var);
+    memset(&ei, 0, sizeof(ei));
+    memset(&dp, 0, sizeof(dp));
+    hres = IDispatchEx_InvokeEx(window_dispex, id, 0, DISPATCH_PROPERTYGET, &dp, &var, &ei, NULL);
+    ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
+    ok(V_VT(&var) == VT_DISPATCH, "V_VT(var) = %d\n", V_VT(&var));
+    VariantClear(&var);
+}
+
 static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *iface,
         LPCOLESTR pstrCode, LPCOLESTR pstrItemName, IUnknown *punkContext,
         LPCOLESTR pstrDelimiter, CTXARG_T dwSourceContextCookie, ULONG ulStartingLine,
@@ -976,7 +1705,7 @@ static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *ifac
 
     V_VT(&var) = VT_I4;
     V_I4(&var) = 100;
-    hres = dispex_propput(document, id, &var);
+    hres = dispex_propput(document, id, 0, &var);
     ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
 
     tmp = SysAllocString(testW);
@@ -990,7 +1719,37 @@ static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *ifac
     hres = IDispatchEx_InvokeEx(document, id, LOCALE_NEUTRAL, INVOKE_PROPERTYGET, &dp, &var, &ei, NULL);
     ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
     ok(V_VT(&var) == VT_I4, "V_VT(var)=%d\n", V_VT(&var));
-    ok(V_I4(&var) == 100, "V_I4(&var) == NULL\n");
+    ok(V_I4(&var) == 100, "V_I4(&var) = %d\n", V_I4(&var));
+
+    V_VT(&var) = VT_I4;
+    V_I4(&var) = 200;
+    hres = dispex_propput(document, id, DISPATCH_PROPERTYPUTREF, &var);
+    ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
+
+    VariantInit(&var);
+    memset(&dp, 0, sizeof(dp));
+    memset(&ei, 0, sizeof(ei));
+    hres = IDispatchEx_InvokeEx(document, id, LOCALE_NEUTRAL, INVOKE_PROPERTYGET, &dp, &var, &ei, NULL);
+    ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
+    ok(V_VT(&var) == VT_I4, "V_VT(var)=%d\n", V_VT(&var));
+    ok(V_I4(&var) == 200, "V_I4(&var) = %d\n", V_I4(&var));
+
+    memset(&dp, 0, sizeof(dp));
+    memset(&ei, 0, sizeof(ei));
+    V_VT(&var) = VT_I4;
+    V_I4(&var) = 300;
+    dp.cArgs = 1;
+    dp.rgvarg = &var;
+    hres = IDispatchEx_InvokeEx(document, id, LOCALE_NEUTRAL, INVOKE_PROPERTYPUT, &dp, NULL, &ei, NULL);
+    ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
+
+    VariantInit(&var);
+    memset(&dp, 0, sizeof(dp));
+    memset(&ei, 0, sizeof(ei));
+    hres = IDispatchEx_InvokeEx(document, id, LOCALE_NEUTRAL, INVOKE_PROPERTYGET, &dp, &var, &ei, NULL);
+    ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
+    ok(V_VT(&var) == VT_I4, "V_VT(var)=%d\n", V_VT(&var));
+    ok(V_I4(&var) == 300, "V_I4(&var) = %d\n", V_I4(&var));
 
     unk = (void*)0xdeadbeef;
     hres = IDispatchEx_GetNameSpaceParent(window_dispex, &unk);
@@ -1074,6 +1833,18 @@ static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *ifac
     CHECK_CALLED(GetScriptDispatch);
     CHECK_CALLED(script_testprop_i);
 
+    SET_EXPECT(GetScriptDispatch);
+    SET_EXPECT(script_testprop2_d);
+    tmp = a2bstr("testProp2");
+    hres = IDispatchEx_GetDispID(window_dispex, tmp, fdexNameCaseSensitive|fdexNameEnsure, &id);
+    ok(hres == S_OK, "GetDispID failed: %08x\n", hres);
+    ok(id != DISPID_SCRIPT_TESTPROP2, "id == DISPID_SCRIPT_TESTPROP2\n");
+    CHECK_CALLED(GetScriptDispatch);
+    CHECK_CALLED(script_testprop2_d);
+    SysFreeString(tmp);
+
+    test_global_id();
+
     test_security();
 
     return S_OK;
@@ -1391,6 +2162,7 @@ static IClassFactory script_cf = { &ClassFactoryVtbl };
 
 static const char simple_script_str[] =
     "<html><head></head><body>"
+    "<div id=\"divid\"></div>"
     "<script language=\"TestScript\">simple script</script>"
     "</body></html>";
 
@@ -1398,6 +2170,10 @@ static void test_simple_script(void)
 {
     IHTMLDocument2 *doc;
 
+    doc = create_document();
+    if(!doc)
+        return;
+
     SET_EXPECT(CreateInstance);
     SET_EXPECT(GetInterfaceSafetyOptions);
     SET_EXPECT(SetInterfaceSafetyOptions);
@@ -1412,8 +2188,7 @@ static void test_simple_script(void)
     SET_EXPECT(ParseScriptText);
     SET_EXPECT(SetScriptState_CONNECTED);
 
-    doc = create_and_load_doc(simple_script_str);
-    if(!doc) return;
+    load_doc(doc, simple_script_str);
 
     CHECK_CALLED(CreateInstance);
     CHECK_CALLED(GetInterfaceSafetyOptions);
@@ -1443,26 +2218,61 @@ static void test_simple_script(void)
     CHECK_CALLED(Close);
 }
 
-static BOOL init_key(const char *key_name, const char *def_value, BOOL init)
+static void run_js_script(const char *test_name)
 {
-    HKEY hkey;
-    DWORD res;
+    WCHAR url[INTERNET_MAX_URL_LENGTH];
+    char urlA[INTERNET_MAX_URL_LENGTH];
+    IPersistMoniker *persist;
+    IHTMLDocument2 *doc;
+    IMoniker *mon;
+    MSG msg;
+    HRESULT hres;
 
-    if(!init) {
-        RegDeleteKey(HKEY_CLASSES_ROOT, key_name);
-        return TRUE;
-    }
+    static const char res[] = "res://";
 
-    res = RegCreateKeyA(HKEY_CLASSES_ROOT, key_name, &hkey);
-    if(res != ERROR_SUCCESS)
-        return FALSE;
+    trace("running %s...\n", test_name);
 
-    if(def_value)
-        res = RegSetValueA(hkey, NULL, REG_SZ, def_value, strlen(def_value));
+    doc = create_document();
+    if(!doc)
+        return;
 
-    RegCloseKey(hkey);
+    set_client_site(doc, TRUE);
+    do_advise(doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink);
 
-    return res == ERROR_SUCCESS;
+    lstrcpyA(urlA, res);
+    GetModuleFileNameA(NULL, urlA + lstrlenA(res), sizeof(urlA) - lstrlenA(res));
+    lstrcatA(urlA, "/");
+    lstrcatA(urlA, test_name);
+    MultiByteToWideChar(CP_ACP, 0, urlA, -1, url, sizeof(url)/sizeof(WCHAR));
+
+    hres = CreateURLMoniker(NULL, url, &mon);
+    ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
+
+    hres = IHTMLDocument2_QueryInterface(doc, &IID_IPersistMoniker, (void**)&persist);
+    ok(hres == S_OK, "Could not get IPersistMoniker iface: %08x\n", hres);
+
+    hres = IPersistMoniker_Load(persist, FALSE, mon, NULL, 0);
+    ok(hres == S_OK, "Load failed: %08x\n", hres);
+
+    IMoniker_Release(mon);
+    IPersistMoniker_Release(persist);
+
+    SET_EXPECT(external_success);
+
+    while(!called_external_success && GetMessage(&msg, NULL, 0, 0)) {
+        TranslateMessage(&msg);
+        DispatchMessage(&msg);
+    }
+
+    CHECK_CALLED(external_success);
+
+    set_client_site(doc, FALSE);
+    IHTMLDocument2_Release(doc);
+}
+
+static void run_js_tests(void)
+{
+    run_js_script("jstest.html");
 }
 
 static BOOL init_registry(BOOL init)
@@ -1491,44 +2301,38 @@ static BOOL register_script_engine(void)
     return TRUE;
 }
 
-static void gecko_installer_workaround(BOOL disable)
+static LRESULT WINAPI wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
-    HKEY hkey;
-    DWORD res;
-
-    static BOOL has_url = FALSE;
-    static char url[2048];
-
-    if(!disable && !has_url)
-        return;
-
-    res = RegOpenKey(HKEY_CURRENT_USER, "Software\\Wine\\MSHTML", &hkey);
-    if(res != ERROR_SUCCESS)
-        return;
-
-    if(disable) {
-        DWORD type, size = sizeof(url);
-
-        res = RegQueryValueEx(hkey, "GeckoUrl", NULL, &type, (PVOID)url, &size);
-        if(res == ERROR_SUCCESS && type == REG_SZ)
-            has_url = TRUE;
+    return DefWindowProc(hwnd, msg, wParam, lParam);
+}
 
-        RegDeleteValue(hkey, "GeckoUrl");
-    }else {
-        RegSetValueEx(hkey, "GeckoUrl", 0, REG_SZ, (PVOID)url, lstrlenA(url)+1);
-    }
+static HWND create_container_window(void)
+{
+    static const CHAR szHTMLDocumentTest[] = "HTMLDocumentTest";
+    static WNDCLASSEXA wndclass = {
+        sizeof(WNDCLASSEXA),
+        0,
+        wnd_proc,
+        0, 0, NULL, NULL, NULL, NULL, NULL,
+        szHTMLDocumentTest,
+        NULL
+    };
 
-    RegCloseKey(hkey);
+    RegisterClassExA(&wndclass);
+    return CreateWindowA(szHTMLDocumentTest, szHTMLDocumentTest,
+            WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
+            300, 300, NULL, NULL, NULL, NULL);
 }
 
 START_TEST(script)
 {
-    gecko_installer_workaround(TRUE);
     CoInitialize(NULL);
+    container_hwnd = create_container_window();
 
     if(winetest_interactive || ! is_ie_hardened()) {
         if(register_script_engine()) {
             test_simple_script();
+            run_js_tests();
             init_registry(FALSE);
         }else {
             skip("Could not register TestScript engine\n");
@@ -1537,6 +2341,6 @@ START_TEST(script)
         skip("IE running in Enhanced Security Configuration\n");
     }
 
+    DestroyWindow(container_hwnd);
     CoUninitialize();
-    gecko_installer_workaround(FALSE);
 }