From c62c4f89281ec4433e66a419965db298f3d7124c Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Mon, 1 Sep 2008 01:23:38 +0200 Subject: [PATCH] jscript: Added IActiveScript::GetScriptDispatch implementation. --- dlls/jscript/Makefile.in | 1 + dlls/jscript/dispex.c | 217 +++++++++++++++++++++++++++++++++++ dlls/jscript/jscript.c | 28 ++++- dlls/jscript/jscript.h | 22 ++++ dlls/jscript/tests/jscript.c | 33 ++++++ 5 files changed, 298 insertions(+), 3 deletions(-) create mode 100644 dlls/jscript/dispex.c diff --git a/dlls/jscript/Makefile.in b/dlls/jscript/Makefile.in index ecf6ffedd7..cca8090c8b 100644 --- a/dlls/jscript/Makefile.in +++ b/dlls/jscript/Makefile.in @@ -8,6 +8,7 @@ IMPORTS = kernel32 RC_SRCS = rsrc.rc C_SRCS = \ + dispex.c \ jscript.c \ jscript_main.c diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c new file mode 100644 index 0000000000..7dfa0d0b7f --- /dev/null +++ b/dlls/jscript/dispex.c @@ -0,0 +1,217 @@ +/* + * Copyright 2008 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 + */ + +#include "jscript.h" + +#include "wine/unicode.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(jscript); + +#define DISPATCHEX_THIS(iface) DEFINE_THIS(DispatchEx, IDispatchEx, iface) + +static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) +{ + DispatchEx *This = DISPATCHEX_THIS(iface); + + if(IsEqualGUID(&IID_IUnknown, riid)) { + TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); + *ppv = _IDispatchEx_(This); + }else if(IsEqualGUID(&IID_IDispatch, riid)) { + TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv); + *ppv = _IDispatchEx_(This); + }else if(IsEqualGUID(&IID_IDispatchEx, riid)) { + TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv); + *ppv = _IDispatchEx_(This); + }else { + WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface) +{ + DispatchEx *This = DISPATCHEX_THIS(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + return ref; +} + +static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface) +{ + DispatchEx *This = DISPATCHEX_THIS(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + if(!ref) { + script_release(This->ctx); + heap_free(This); + } + + return ref; +} + +static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo) +{ + DispatchEx *This = DISPATCHEX_THIS(iface); + + TRACE("(%p)->(%p)\n", This, pctinfo); + + *pctinfo = 1; + return S_OK; +} + +static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, + LCID lcid, ITypeInfo **ppTInfo) +{ + DispatchEx *This = DISPATCHEX_THIS(iface); + FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid, + LPOLESTR *rgszNames, UINT cNames, + LCID lcid, DISPID *rgDispId) +{ + DispatchEx *This = DISPATCHEX_THIS(iface); + FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, + lcid, rgDispId); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember, + REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, + VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) +{ + DispatchEx *This = DISPATCHEX_THIS(iface); + FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), + lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) +{ + DispatchEx *This = DISPATCHEX_THIS(iface); + FIXME("(%p)->(%s %x %p)\n", This, debugstr_w(bstrName), grfdex, pid); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + DispatchEx *This = DISPATCHEX_THIS(iface); + FIXME("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) +{ + DispatchEx *This = DISPATCHEX_THIS(iface); + FIXME("(%p)->(%s %x)\n", This, debugstr_w(bstrName), grfdex); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id) +{ + DispatchEx *This = DISPATCHEX_THIS(iface); + FIXME("(%p)->(%x)\n", This, id); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex) +{ + DispatchEx *This = DISPATCHEX_THIS(iface); + FIXME("(%p)->(%x %x %p)\n", This, id, grfdexFetch, pgrfdex); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName) +{ + DispatchEx *This = DISPATCHEX_THIS(iface); + FIXME("(%p)->(%x %p)\n", This, id, pbstrName); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid) +{ + DispatchEx *This = DISPATCHEX_THIS(iface); + FIXME("(%p)->(%x %x %p)\n", This, grfdex, id, pid); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk) +{ + DispatchEx *This = DISPATCHEX_THIS(iface); + FIXME("(%p)->(%p)\n", This, ppunk); + return E_NOTIMPL; +} + +#undef DISPATCHEX_THIS + +static IDispatchExVtbl DispatchExVtbl = { + DispatchEx_QueryInterface, + DispatchEx_AddRef, + DispatchEx_Release, + DispatchEx_GetTypeInfoCount, + DispatchEx_GetTypeInfo, + DispatchEx_GetIDsOfNames, + DispatchEx_Invoke, + DispatchEx_GetDispID, + DispatchEx_InvokeEx, + DispatchEx_DeleteMemberByName, + DispatchEx_DeleteMemberByDispID, + DispatchEx_GetMemberProperties, + DispatchEx_GetMemberName, + DispatchEx_GetNextDispID, + DispatchEx_GetNameSpaceParent +}; + +static HRESULT init_dispex(DispatchEx *dispex, script_ctx_t *ctx) +{ + dispex->lpIDispatchExVtbl = &DispatchExVtbl; + dispex->ref = 1; + + script_addref(ctx); + dispex->ctx = ctx; + + return S_OK; +} + +HRESULT create_dispex(script_ctx_t *ctx, DispatchEx **dispex) +{ + DispatchEx *ret; + HRESULT hres; + + ret = heap_alloc_zero(sizeof(DispatchEx)); + if(!ret) + return E_OUTOFMEMORY; + + hres = init_dispex(ret, ctx); + if(FAILED(hres)) + return hres; + + *dispex = ret; + return S_OK; +} diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index ed2dd478c7..26586d1f2e 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -152,6 +152,10 @@ static HRESULT WINAPI JScript_SetScriptSite(IActiveScript *iface, return hres; } + hres = create_dispex(This->ctx, &This->ctx->script_disp); + if(FAILED(hres)) + return hres; + if(InterlockedCompareExchange(&This->thread_id, GetCurrentThreadId(), 0)) return E_UNEXPECTED; @@ -197,9 +201,15 @@ static HRESULT WINAPI JScript_Close(IActiveScript *iface) if(This->thread_id != GetCurrentThreadId()) return E_UNEXPECTED; - if(This->ctx) + if(This->ctx) { change_state(This, SCRIPTSTATE_CLOSED); + if(This->ctx->script_disp) { + IDispatchEx_Release(_IDispatchEx_(This->ctx->script_disp)); + This->ctx->script_disp = NULL; + } + } + if(This->site) { IActiveScriptSite_Release(This->site); This->site = NULL; @@ -228,8 +238,20 @@ static HRESULT WINAPI JScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR IDispatch **ppdisp) { JScript *This = ACTSCRIPT_THIS(iface); - FIXME("(%p)->()\n", This); - return E_NOTIMPL; + + TRACE("(%p)->(%p)\n", This, ppdisp); + + if(!ppdisp) + return E_POINTER; + + if(This->thread_id != GetCurrentThreadId() || !This->ctx->script_disp) { + *ppdisp = NULL; + return E_UNEXPECTED; + } + + *ppdisp = (IDispatch*)_IDispatchEx_(This->ctx->script_disp); + IDispatch_AddRef(*ppdisp); + return S_OK; } static HRESULT WINAPI JScript_GetCurrentScriptThreadID(IActiveScript *iface, diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 455dee8207..a53f599ef3 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -25,17 +25,39 @@ #include "winbase.h" #include "winuser.h" #include "ole2.h" +#include "dispex.h" #include "activscp.h" typedef struct _script_ctx_t script_ctx_t; +typedef struct DispatchEx { + const IDispatchExVtbl *lpIDispatchExVtbl; + + LONG ref; + + script_ctx_t *ctx; +} DispatchEx; + +#define _IDispatchEx_(x) ((IDispatchEx*) &(x)->lpIDispatchExVtbl) + +HRESULT create_dispex(script_ctx_t*,DispatchEx**); + struct _script_ctx_t { LONG ref; SCRIPTSTATE state; LCID lcid; + + DispatchEx *script_disp; }; +void script_release(script_ctx_t*); + +static void inline script_addref(script_ctx_t *ctx) +{ + ctx->ref++; +} + HRESULT WINAPI JScriptFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**); extern LONG module_ref; diff --git a/dlls/jscript/tests/jscript.c b/dlls/jscript/tests/jscript.c index b0c61be91d..18aef1a366 100644 --- a/dlls/jscript/tests/jscript.c +++ b/dlls/jscript/tests/jscript.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "wine/test.h" @@ -171,6 +172,32 @@ static const IActiveScriptSiteVtbl ActiveScriptSiteVtbl = { static IActiveScriptSite ActiveScriptSite = { &ActiveScriptSiteVtbl }; +static void test_script_dispatch(IActiveScript *script, BOOL initialized) +{ + IDispatchEx *dispex; + IDispatch *disp; + HRESULT hres; + + disp = (void*)0xdeadbeef; + hres = IActiveScript_GetScriptDispatch(script, NULL, &disp); + if(!initialized) { + ok(hres == E_UNEXPECTED, "hres = %08x, expected E_UNEXPECTED\n", hres); + ok(!disp, "disp != NULL\n"); + return; + } + + ok(hres == S_OK, "GetScriptDispatch failed: %08x\n", hres); + if(FAILED(hres)) + return; + + ok(disp != NULL, "disp == NULL\n"); + hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); + IDispatch_Release(disp); + ok(hres == S_OK, "Could not get IDispatchEx interface: %08x\n", hres); + + IDispatchEx_Release(dispex); +} + static void test_safety(IUnknown *unk) { IObjectSafety *safety; @@ -261,6 +288,8 @@ static void test_jscript(void) hres = IActiveScript_SetScriptSite(script, NULL); ok(hres == E_POINTER, "SetScriptSite failed: %08x, expected E_POINTER\n", hres); + test_script_dispatch(script, FALSE); + SET_EXPECT(GetLCID); SET_EXPECT(OnStateChange_INITIALIZED); hres = IActiveScript_SetScriptSite(script, &ActiveScriptSite); @@ -271,11 +300,15 @@ static void test_jscript(void) hres = IActiveScript_SetScriptSite(script, &ActiveScriptSite); ok(hres == E_UNEXPECTED, "SetScriptSite failed: %08x, expected E_UNEXPECTED\n", hres); + test_script_dispatch(script, TRUE); + SET_EXPECT(OnStateChange_CLOSED); hres = IActiveScript_Close(script); ok(hres == S_OK, "Close failed: %08x\n", hres); CHECK_CALLED(OnStateChange_CLOSED); + test_script_dispatch(script, FALSE); + IActiveScriptParse_Release(parse); IActiveScript_Release(script); -- 2.32.0.93.g670b81a890