* ext/win32ole/win32ole.c: avoid creating Ruby object during
GC. thanks to arton <artonx AT yahoo.co.jp>. [ruby-dev:35313] * test/win32ole/test_win32ole_event.rb: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17821 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
d2926df775
commit
b892e3dd1b
@ -1,3 +1,10 @@
|
|||||||
|
Thu Jul 3 00:18:00 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
|
||||||
|
|
||||||
|
* ext/win32ole/win32ole.c: avoid creating Ruby object during
|
||||||
|
GC. thanks to arton <artonx AT yahoo.co.jp>. [ruby-dev:35313]
|
||||||
|
|
||||||
|
* test/win32ole/test_win32ole_event.rb: ditto.
|
||||||
|
|
||||||
Thu Jul 3 00:09:31 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
|
Thu Jul 3 00:09:31 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
|
||||||
|
|
||||||
* gc.c: add rb_during_gc(). based on a patch from arton <artonx AT
|
* gc.c: add rb_during_gc(). based on a patch from arton <artonx AT
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include <varargs.h>
|
#include <varargs.h>
|
||||||
#define va_init_list(a,b) va_start(a)
|
#define va_init_list(a,b) va_start(a)
|
||||||
#endif
|
#endif
|
||||||
|
#include <objidl.h>
|
||||||
|
|
||||||
#define DOUT fprintf(stderr,"[%d]\n",__LINE__)
|
#define DOUT fprintf(stderr,"[%d]\n",__LINE__)
|
||||||
#define DOUTS(x) fprintf(stderr,"[%d]:" #x "=%s\n",__LINE__,x)
|
#define DOUTS(x) fprintf(stderr,"[%d]:" #x "=%s\n",__LINE__,x)
|
||||||
@ -116,7 +117,7 @@
|
|||||||
|
|
||||||
#define WC2VSTR(x) ole_wc2vstr((x), TRUE)
|
#define WC2VSTR(x) ole_wc2vstr((x), TRUE)
|
||||||
|
|
||||||
#define WIN32OLE_VERSION "1.1.7"
|
#define WIN32OLE_VERSION "1.1.8"
|
||||||
|
|
||||||
typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX)
|
typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX)
|
||||||
(REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*);
|
(REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*);
|
||||||
@ -202,6 +203,9 @@ static UINT g_cp_to_check = CP_ACP;
|
|||||||
static char g_lcid_to_check[8 + 1];
|
static char g_lcid_to_check[8 + 1];
|
||||||
static VARTYPE g_nil_to = VT_ERROR;
|
static VARTYPE g_nil_to = VT_ERROR;
|
||||||
static st_table *enc2cp_table;
|
static st_table *enc2cp_table;
|
||||||
|
static IMessageFilterVtbl message_filter;
|
||||||
|
static IMessageFilter imessage_filter = { &message_filter };
|
||||||
|
static IMessageFilter* previous_filter;
|
||||||
|
|
||||||
struct oledata {
|
struct oledata {
|
||||||
IDispatch *pDispatch;
|
IDispatch *pDispatch;
|
||||||
@ -523,6 +527,101 @@ static VALUE folevariant_set_value(VALUE self, VALUE val);
|
|||||||
static void init_enc2cp();
|
static void init_enc2cp();
|
||||||
static void free_enc2cp();
|
static void free_enc2cp();
|
||||||
|
|
||||||
|
static HRESULT (STDMETHODCALLTYPE mf_QueryInterface)(
|
||||||
|
IMessageFilter __RPC_FAR * This,
|
||||||
|
/* [in] */ REFIID riid,
|
||||||
|
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
|
||||||
|
{
|
||||||
|
if (MEMCMP(riid, &IID_IUnknown, GUID, 1) == 0
|
||||||
|
|| MEMCMP(riid, &IID_IMessageFilter, GUID, 1) == 0)
|
||||||
|
{
|
||||||
|
*ppvObject = &message_filter;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG (STDMETHODCALLTYPE mf_AddRef)(
|
||||||
|
IMessageFilter __RPC_FAR * This)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG (STDMETHODCALLTYPE mf_Release)(
|
||||||
|
IMessageFilter __RPC_FAR * This)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD (STDMETHODCALLTYPE mf_HandleInComingCall)(
|
||||||
|
IMessageFilter __RPC_FAR * pThis,
|
||||||
|
DWORD dwCallType, //Type of incoming call
|
||||||
|
HTASK threadIDCaller, //Task handle calling this task
|
||||||
|
DWORD dwTickCount, //Elapsed tick count
|
||||||
|
LPINTERFACEINFO lpInterfaceInfo //Pointer to INTERFACEINFO structure
|
||||||
|
)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_MESSAGEFILTER
|
||||||
|
printf("incoming %08X, %08X, %d\n", dwCallType, threadIDCaller, dwTickCount);
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
switch (dwCallType)
|
||||||
|
{
|
||||||
|
case CALLTYPE_ASYNC:
|
||||||
|
case CALLTYPE_TOPLEVEL_CALLPENDING:
|
||||||
|
case CALLTYPE_ASYNC_CALLPENDING:
|
||||||
|
if (rb_during_gc()) {
|
||||||
|
return SERVERCALL_RETRYLATER;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (previous_filter) {
|
||||||
|
return previous_filter->lpVtbl->HandleInComingCall(previous_filter,
|
||||||
|
dwCallType,
|
||||||
|
threadIDCaller,
|
||||||
|
dwTickCount,
|
||||||
|
lpInterfaceInfo);
|
||||||
|
}
|
||||||
|
return SERVERCALL_ISHANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD (STDMETHODCALLTYPE mf_RetryRejectedCall)(
|
||||||
|
IMessageFilter* pThis,
|
||||||
|
HTASK threadIDCallee, //Server task handle
|
||||||
|
DWORD dwTickCount, //Elapsed tick count
|
||||||
|
DWORD dwRejectType //Returned rejection message
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (previous_filter) {
|
||||||
|
return previous_filter->lpVtbl->RetryRejectedCall(previous_filter,
|
||||||
|
threadIDCallee,
|
||||||
|
dwTickCount,
|
||||||
|
dwRejectType);
|
||||||
|
}
|
||||||
|
return 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD (STDMETHODCALLTYPE mf_MessagePending)(
|
||||||
|
IMessageFilter* pThis,
|
||||||
|
HTASK threadIDCallee, //Called applications task handle
|
||||||
|
DWORD dwTickCount, //Elapsed tick count
|
||||||
|
DWORD dwPendingType //Call type
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (rb_during_gc()) {
|
||||||
|
return PENDINGMSG_WAITNOPROCESS;
|
||||||
|
}
|
||||||
|
if (previous_filter) {
|
||||||
|
return previous_filter->lpVtbl->MessagePending(previous_filter,
|
||||||
|
threadIDCallee,
|
||||||
|
dwTickCount,
|
||||||
|
dwPendingType);
|
||||||
|
}
|
||||||
|
return PENDINGMSG_WAITNOPROCESS;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct _Win32OLEIDispatch
|
typedef struct _Win32OLEIDispatch
|
||||||
{
|
{
|
||||||
IDispatch dispatch;
|
IDispatch dispatch;
|
||||||
@ -1059,6 +1158,11 @@ ole_initialize()
|
|||||||
/*
|
/*
|
||||||
atexit((void (*)(void))ole_uninitialize);
|
atexit((void (*)(void))ole_uninitialize);
|
||||||
*/
|
*/
|
||||||
|
hr = CoRegisterMessageFilter(&imessage_filter, &previous_filter);
|
||||||
|
if(FAILED(hr)) {
|
||||||
|
previous_filter = NULL;
|
||||||
|
ole_raise(hr, rb_eRuntimeError, "fail: install OLE MessageFilter");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8168,6 +8272,15 @@ Init_win32ole()
|
|||||||
com_vtbl.GetTypeInfo = GetTypeInfo;
|
com_vtbl.GetTypeInfo = GetTypeInfo;
|
||||||
com_vtbl.GetIDsOfNames = GetIDsOfNames;
|
com_vtbl.GetIDsOfNames = GetIDsOfNames;
|
||||||
com_vtbl.Invoke = Invoke;
|
com_vtbl.Invoke = Invoke;
|
||||||
|
|
||||||
|
message_filter.QueryInterface = mf_QueryInterface;
|
||||||
|
message_filter.AddRef = mf_AddRef;
|
||||||
|
message_filter.Release = mf_Release;
|
||||||
|
message_filter.HandleInComingCall = mf_HandleInComingCall;
|
||||||
|
message_filter.RetryRejectedCall = mf_RetryRejectedCall;
|
||||||
|
message_filter.MessagePending = mf_MessagePending;
|
||||||
|
|
||||||
|
com_hash = Data_Wrap_Struct(rb_cData, rb_mark_hash, st_free_table, st_init_numtable());
|
||||||
com_hash = Data_Wrap_Struct(rb_cData, rb_mark_hash, st_free_table, st_init_numtable());
|
com_hash = Data_Wrap_Struct(rb_cData, rb_mark_hash, st_free_table, st_init_numtable());
|
||||||
rb_register_mark_object(com_hash);
|
rb_register_mark_object(com_hash);
|
||||||
|
|
||||||
|
@ -35,6 +35,8 @@ if defined?(WIN32OLE_EVENT)
|
|||||||
ev.on_event {|*args| default_handler(*args)}
|
ev.on_event {|*args| default_handler(*args)}
|
||||||
@ie.navigate("file:///#{@f}")
|
@ie.navigate("file:///#{@f}")
|
||||||
while @ie.busy
|
while @ie.busy
|
||||||
|
WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
|
||||||
|
GC.start
|
||||||
sleep 0.1
|
sleep 0.1
|
||||||
end
|
end
|
||||||
assert_match(/BeforeNavigate/, @event)
|
assert_match(/BeforeNavigate/, @event)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user