diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c
index 81bcebdb7be..f268a0adea7 100644
--- a/dlls/mshtml/htmlwindow.c
+++ b/dlls/mshtml/htmlwindow.c
@@ -93,8 +93,13 @@ static ULONG WINAPI HTMLWindow2_Release(IHTMLWindow2 *iface)
TRACE("(%p) ref=%d\n", This, ref);
if(!ref) {
+ DWORD i;
+
if(This->event_target)
release_event_target(This->event_target);
+ for(i=0; i < This->global_prop_cnt; i++)
+ heap_free(This->global_props[i].name);
+ heap_free(This->global_props);
release_script_hosts(This);
list_remove(&This->entry);
release_dispex(&This->dispex);
@@ -840,6 +845,40 @@ static HRESULT WINAPI HTMLWindow2_get_external(IHTMLWindow2 *iface, IDispatch **
return IDocHostUIHandler_GetExternal(This->doc->hostui, p);
}
+static HRESULT HTMLWindow_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
+ VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
+{
+ HTMLWindow *This = HTMLWINDOW2_THIS(iface);
+ IDispatchEx *dispex;
+ IDispatch *disp;
+ DWORD idx;
+ HRESULT hres;
+
+ idx = id - MSHTML_DISPID_CUSTOM_MIN;
+ if(idx >= This->global_prop_cnt)
+ return DISP_E_MEMBERNOTFOUND;
+
+ disp = get_script_disp(This->global_props[idx].script_host);
+ if(!disp)
+ return E_UNEXPECTED;
+
+ hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
+ if(SUCCEEDED(hres)) {
+ TRACE("%s >>>\n", debugstr_w(This->global_props[idx].name));
+ hres = IDispatchEx_InvokeEx(dispex, This->global_props[idx].id, lcid, flags, params, res, ei, caller);
+ if(hres == S_OK)
+ TRACE("%s <<<\n", debugstr_w(This->global_props[idx].name));
+ else
+ WARN("%s <<< %08x\n", debugstr_w(This->global_props[idx].name), hres);
+ IDispatchEx_Release(dispex);
+ }else {
+ FIXME("No IDispatchEx\n");
+ }
+
+ IDispatch_Release(disp);
+ return hres;
+}
+
#undef HTMLWINDOW2_THIS
static const IHTMLWindow2Vtbl HTMLWindow2Vtbl = {
@@ -1207,9 +1246,49 @@ static HRESULT WINAPI WindowDispEx_Invoke(IDispatchEx *iface, DISPID dispIdMembe
static HRESULT WINAPI WindowDispEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
{
HTMLWindow *This = DISPEX_THIS(iface);
+ ScriptHost *script_host;
+ DISPID id;
+ DWORD i;
TRACE("(%p)->(%s %x %p)\n", This, debugstr_w(bstrName), grfdex, pid);
+ for(i=0; i < This->global_prop_cnt; i++) {
+ /* FIXME: case sensitivity */
+ if(!strcmpW(This->global_props[i].name, bstrName)) {
+ *pid = MSHTML_DISPID_CUSTOM_MIN+i;
+ return S_OK;
+ }
+ }
+
+ if(find_global_prop(This, bstrName, grfdex, &script_host, &id)) {
+ if(This->global_prop_cnt == This->global_prop_size) {
+ global_prop_t *new_props;
+ DWORD new_size;
+
+ if(This->global_props) {
+ new_size = This->global_prop_size*2;
+ new_props = heap_realloc(This->global_props, new_size*sizeof(global_prop_t));
+ }else {
+ new_size = 16;
+ new_props = heap_alloc(new_size*sizeof(global_prop_t));
+ }
+ if(!new_props)
+ return E_OUTOFMEMORY;
+ This->global_props = new_props;
+ This->global_prop_size = new_size;
+ }
+
+ This->global_props[This->global_prop_cnt].name = heap_strdupW(bstrName);
+ if(!This->global_props[This->global_prop_cnt].name)
+ return E_OUTOFMEMORY;
+
+ This->global_props[This->global_prop_cnt].script_host = script_host;
+ This->global_props[This->global_prop_cnt].id = id;
+
+ *pid = MSHTML_DISPID_CUSTOM_MIN + (This->global_prop_cnt++);
+ return S_OK;
+ }
+
return IDispatchEx_GetDispID(DISPATCHEX(&This->dispex), bstrName, grfdex, pid);
}
@@ -1303,8 +1382,15 @@ static const tid_t HTMLWindow_iface_tids[] = {
IHTMLWindow3_tid,
0
};
-static dispex_static_data_t HTMLWindow_dispex = {
+
+static const dispex_static_data_vtbl_t HTMLWindow_dispex_vtbl = {
NULL,
+ NULL,
+ HTMLWindow_invoke
+};
+
+static dispex_static_data_t HTMLWindow_dispex = {
+ &HTMLWindow_dispex_vtbl,
DispHTMLWindow2_tid,
NULL,
HTMLWindow_iface_tids
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index f74b2209aa6..e202688714f 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -158,6 +158,14 @@ typedef enum {
SCRIPTMODE_ACTIVESCRIPT
} SCRIPTMODE;
+typedef struct ScriptHost ScriptHost;
+
+typedef struct {
+ WCHAR *name;
+ ScriptHost *script_host;
+ DISPID id;
+} global_prop_t;
+
typedef struct {
DispatchEx dispex;
const IHTMLWindow2Vtbl *lpHTMLWindow2Vtbl;
@@ -175,6 +183,10 @@ typedef struct {
SCRIPTMODE scriptmode;
struct list script_hosts;
+ global_prop_t *global_props;
+ DWORD global_prop_cnt;
+ DWORD global_prop_size;
+
struct list entry;
} HTMLWindow;
@@ -628,6 +640,8 @@ void connect_scripts(HTMLWindow*);
void doc_insert_script(HTMLDocument*,nsIDOMHTMLScriptElement*);
IDispatch *script_parse_event(HTMLDocument*,LPCWSTR);
void set_script_mode(HTMLWindow*,SCRIPTMODE);
+BOOL find_global_prop(HTMLWindow*,BSTR,DWORD,ScriptHost**,DISPID*);
+IDispatch *get_script_disp(ScriptHost*);
IHTMLElementCollection *create_all_collection(HTMLDOMNode*,BOOL);
IHTMLElementCollection *create_collection_from_nodelist(HTMLDocument*,IUnknown*,nsIDOMNodeList*);
diff --git a/dlls/mshtml/script.c b/dlls/mshtml/script.c
index 3046a7d12e0..96dbb4702a1 100644
--- a/dlls/mshtml/script.c
+++ b/dlls/mshtml/script.c
@@ -42,7 +42,7 @@ static const WCHAR emptyW[] = {0};
static const CLSID CLSID_JScript =
{0xf414c260,0x6ac0,0x11cf,{0xb6,0xd1,0x00,0xaa,0x00,0xbb,0xbb,0x58}};
-typedef struct {
+struct ScriptHost {
const IActiveScriptSiteVtbl *lpIActiveScriptSiteVtbl;
const IActiveScriptSiteInterruptPollVtbl *lpIActiveScriptSiteInterruptPollVtbl;
const IActiveScriptSiteWindowVtbl *lpIActiveScriptSiteWindowVtbl;
@@ -60,7 +60,7 @@ typedef struct {
GUID guid;
struct list entry;
-} ScriptHost;
+};
#define ACTSCPSITE(x) ((IActiveScriptSite*) &(x)->lpIActiveScriptSiteVtbl)
#define ACTSCPPOLL(x) (&(x)->lpIActiveScriptSiteInterruptPollVtbl)
@@ -811,6 +811,52 @@ IDispatch *script_parse_event(HTMLDocument *doc, LPCWSTR text)
return disp;
}
+IDispatch *get_script_disp(ScriptHost *script_host)
+{
+ IDispatch *disp;
+ HRESULT hres;
+
+ if(!script_host->script)
+ return NULL;
+
+ hres = IActiveScript_GetScriptDispatch(script_host->script, windowW, &disp);
+ if(FAILED(hres))
+ return NULL;
+
+ return disp;
+}
+
+BOOL find_global_prop(HTMLWindow *window, BSTR name, DWORD flags, ScriptHost **ret_host, DISPID *ret_id)
+{
+ IDispatchEx *dispex;
+ IDispatch *disp;
+ ScriptHost *iter;
+ HRESULT hres;
+
+ LIST_FOR_EACH_ENTRY(iter, &window->script_hosts, ScriptHost, entry) {
+ disp = get_script_disp(iter);
+ if(!disp)
+ continue;
+
+ hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
+ if(SUCCEEDED(hres)) {
+ hres = IDispatchEx_GetDispID(dispex, name, flags, ret_id);
+ IDispatchEx_Release(dispex);
+ }else {
+ FIXME("No IDispatchEx\n");
+ hres = E_NOTIMPL;
+ }
+
+ IDispatch_Release(disp);
+ if(SUCCEEDED(hres)) {
+ *ret_host = iter;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
static BOOL is_jscript_available(void)
{
static BOOL available, checked;