Jacek Caban : mshtml: Added support for quering global variables from window object.

Alexandre Julliard julliard at winehq.org
Thu Sep 10 09:08:08 CDT 2009


Module: wine
Branch: master
Commit: a50c4edb930798c0fbd5d2b9c0ead1ec795fe72f
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a50c4edb930798c0fbd5d2b9c0ead1ec795fe72f

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Wed Sep  9 21:31:32 2009 +0200

mshtml: Added support for quering global variables from window object.

---

 dlls/mshtml/htmlwindow.c     |   88 +++++++++++++++++++++++++++++++++++++++++-
 dlls/mshtml/mshtml_private.h |   14 +++++++
 dlls/mshtml/script.c         |   50 +++++++++++++++++++++++-
 3 files changed, 149 insertions(+), 3 deletions(-)

diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c
index 81bcebd..f268a0a 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 f74b220..e202688 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 3046a7d..96dbb47 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;




More information about the wine-cvs mailing list