Commit c62c4f89 authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

jscript: Added IActiveScript::GetScriptDispatch implementation.

parent f3eb7761
......@@ -8,6 +8,7 @@ IMPORTS = kernel32
RC_SRCS = rsrc.rc
C_SRCS = \
dispex.c \
jscript.c \
jscript_main.c
......
/*
* 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;
}
......@@ -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,
......
......@@ -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;
......
......@@ -23,6 +23,7 @@
#include <ole2.h>
#include <activscp.h>
#include <objsafe.h>
#include <dispex.h>
#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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment