From 71cbb6e17cd0aa3f44ddff97f2dca03687547b2a Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Mon, 5 Sep 2011 11:14:14 +0200 Subject: [PATCH] vbscript: Added GetScriptDispatch implementation. --- dlls/vbscript/Makefile.in | 1 + dlls/vbscript/tests/vbscript.c | 12 ++ dlls/vbscript/vbdisp.c | 205 +++++++++++++++++++++++++++++++++ dlls/vbscript/vbscript.c | 24 +++- dlls/vbscript/vbscript.h | 11 ++ 5 files changed, 251 insertions(+), 2 deletions(-) create mode 100644 dlls/vbscript/vbdisp.c diff --git a/dlls/vbscript/Makefile.in b/dlls/vbscript/Makefile.in index 2a90e4666b0..40e489ad567 100644 --- a/dlls/vbscript/Makefile.in +++ b/dlls/vbscript/Makefile.in @@ -1,6 +1,7 @@ MODULE = vbscript.dll C_SRCS = \ + vbdisp.c \ vbscript.c \ vbscript_main.c diff --git a/dlls/vbscript/tests/vbscript.c b/dlls/vbscript/tests/vbscript.c index 76d90a9759a..9dd3f0f8aa1 100644 --- a/dlls/vbscript/tests/vbscript.c +++ b/dlls/vbscript/tests/vbscript.c @@ -282,6 +282,17 @@ static void test_safety(IActiveScript *script) IObjectSafety_Release(safety); } +static void test_no_script_dispatch(IActiveScript *script) +{ + IDispatch *disp; + HRESULT hres; + + disp = (void*)0xdeadbeef; + hres = IActiveScript_GetScriptDispatch(script, NULL, &disp); + ok(hres == E_UNEXPECTED, "hres = %08x, expected E_UNEXPECTED\n", hres); + ok(!disp, "disp != NULL\n"); +} + static IActiveScript *create_vbscript(void) { IActiveScript *ret; @@ -345,6 +356,7 @@ static void test_vbscript(void) CHECK_CALLED(OnStateChange_CLOSED); test_state(vbscript, SCRIPTSTATE_CLOSED); + test_no_script_dispatch(vbscript); IActiveScriptParse64_Release(parser); diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c new file mode 100644 index 00000000000..3c817890164 --- /dev/null +++ b/dlls/vbscript/vbdisp.c @@ -0,0 +1,205 @@ +/* + * Copyright 2011 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 "vbscript.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(vbscript); + +static inline vbdisp_t *impl_from_IDispatchEx(IDispatchEx *iface) +{ + return CONTAINING_RECORD(iface, vbdisp_t, IDispatchEx_iface); +} + +static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) +{ + vbdisp_t *This = impl_from_IDispatchEx(iface); + + if(IsEqualGUID(&IID_IUnknown, riid)) { + TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); + *ppv = &This->IDispatchEx_iface; + }else if(IsEqualGUID(&IID_IDispatch, riid)) { + TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv); + *ppv = &This->IDispatchEx_iface; + }else if(IsEqualGUID(&IID_IDispatchEx, riid)) { + TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv); + *ppv = &This->IDispatchEx_iface; + }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) +{ + vbdisp_t *This = impl_from_IDispatchEx(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + return ref; +} + +static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface) +{ + vbdisp_t *This = impl_from_IDispatchEx(iface); + LONG ref = InterlockedIncrement(&This->ref); + + if(!ref) + heap_free(This); + + return ref; +} + +static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo) +{ + vbdisp_t *This = impl_from_IDispatchEx(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) +{ + vbdisp_t *This = impl_from_IDispatchEx(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) +{ + vbdisp_t *This = impl_from_IDispatchEx(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) +{ + vbdisp_t *This = impl_from_IDispatchEx(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) +{ + vbdisp_t *This = impl_from_IDispatchEx(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) +{ + vbdisp_t *This = impl_from_IDispatchEx(iface); + FIXME("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); + return DISP_E_MEMBERNOTFOUND; +} + +static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) +{ + vbdisp_t *This = impl_from_IDispatchEx(iface); + FIXME("(%p)->(%s %x)\n", This, debugstr_w(bstrName), grfdex); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id) +{ + vbdisp_t *This = impl_from_IDispatchEx(iface); + FIXME("(%p)->(%x)\n", This, id); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex) +{ + vbdisp_t *This = impl_from_IDispatchEx(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) +{ + vbdisp_t *This = impl_from_IDispatchEx(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) +{ + vbdisp_t *This = impl_from_IDispatchEx(iface); + FIXME("(%p)->(%x %x %p)\n", This, grfdex, id, pid); + return E_NOTIMPL; +} + +static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk) +{ + vbdisp_t *This = impl_from_IDispatchEx(iface); + FIXME("(%p)->(%p)\n", This, ppunk); + return E_NOTIMPL; +} + +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 create_vbdisp(vbdisp_t **ret) +{ + vbdisp_t *vbdisp; + + vbdisp = heap_alloc_zero(sizeof(*vbdisp)); + if(!vbdisp) + return E_OUTOFMEMORY; + + vbdisp->IDispatchEx_iface.lpVtbl = &DispatchExVtbl; + vbdisp->ref = 1; + + *ret = vbdisp; + return S_OK; +} + +HRESULT init_global(script_ctx_t *ctx) +{ + return create_vbdisp(&ctx->script_obj); +} diff --git a/dlls/vbscript/vbscript.c b/dlls/vbscript/vbscript.c index 08e715a3927..9d23499d561 100644 --- a/dlls/vbscript/vbscript.c +++ b/dlls/vbscript/vbscript.c @@ -70,8 +70,14 @@ static void exec_queued_code(VBScript *This) static HRESULT set_ctx_site(VBScript *This) { + HRESULT hres; + This->ctx->lcid = This->lcid; + hres = init_global(This->ctx); + if(FAILED(hres)) + return hres; + IActiveScriptSite_AddRef(This->site); This->ctx->site = This->site; @@ -83,6 +89,8 @@ static void destroy_script(script_ctx_t *ctx) { if(ctx->site) IActiveScriptSite_Release(ctx->site); + if(ctx->script_obj) + IDispatchEx_Release(&ctx->script_obj->IDispatchEx_iface); heap_free(ctx); } @@ -296,8 +304,20 @@ static HRESULT WINAPI VBScript_AddTypeLib(IActiveScript *iface, REFGUID rguidTyp static HRESULT WINAPI VBScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName, IDispatch **ppdisp) { VBScript *This = impl_from_IActiveScript(iface); - FIXME("(%p)->(%p)\n", This, ppdisp); - return E_NOTIMPL; + + TRACE("(%p)->(%p)\n", This, ppdisp); + + if(!ppdisp) + return E_POINTER; + + if(This->thread_id != GetCurrentThreadId() || !This->ctx->script_obj) { + *ppdisp = NULL; + return E_UNEXPECTED; + } + + *ppdisp = (IDispatch*)&This->ctx->script_obj->IDispatchEx_iface; + IDispatch_AddRef(*ppdisp); + return S_OK; } static HRESULT WINAPI VBScript_GetCurrentScriptThreadID(IActiveScript *iface, diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index 29909f24cd4..1f6276f98d0 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -23,15 +23,26 @@ #include "windef.h" #include "winbase.h" #include "ole2.h" +#include "dispex.h" #include "activscp.h" #include "vbscript_classes.h" +typedef struct { + IDispatchEx IDispatchEx_iface; + + LONG ref; +} vbdisp_t; + typedef struct { IActiveScriptSite *site; LCID lcid; + + vbdisp_t *script_obj; } script_ctx_t; +HRESULT init_global(script_ctx_t*); + HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**); static inline void *heap_alloc(size_t len)