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;