зеркало из https://github.com/github/ruby.git
* 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:
Родитель
d2926df775
Коммит
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>
|
||||
|
||||
* gc.c: add rb_during_gc(). based on a patch from arton <artonx AT
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <varargs.h>
|
||||
#define va_init_list(a,b) va_start(a)
|
||||
#endif
|
||||
#include <objidl.h>
|
||||
|
||||
#define DOUT fprintf(stderr,"[%d]\n",__LINE__)
|
||||
#define DOUTS(x) fprintf(stderr,"[%d]:" #x "=%s\n",__LINE__,x)
|
||||
|
@ -116,7 +117,7 @@
|
|||
|
||||
#define WC2VSTR(x) ole_wc2vstr((x), TRUE)
|
||||
|
||||
#define WIN32OLE_VERSION "1.1.7"
|
||||
#define WIN32OLE_VERSION "1.1.8"
|
||||
|
||||
typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX)
|
||||
(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 VARTYPE g_nil_to = VT_ERROR;
|
||||
static st_table *enc2cp_table;
|
||||
static IMessageFilterVtbl message_filter;
|
||||
static IMessageFilter imessage_filter = { &message_filter };
|
||||
static IMessageFilter* previous_filter;
|
||||
|
||||
struct oledata {
|
||||
IDispatch *pDispatch;
|
||||
|
@ -523,6 +527,101 @@ static VALUE folevariant_set_value(VALUE self, VALUE val);
|
|||
static void init_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
|
||||
{
|
||||
IDispatch dispatch;
|
||||
|
@ -1059,6 +1158,11 @@ ole_initialize()
|
|||
/*
|
||||
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.GetIDsOfNames = GetIDsOfNames;
|
||||
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());
|
||||
rb_register_mark_object(com_hash);
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@ if defined?(WIN32OLE_EVENT)
|
|||
ev.on_event {|*args| default_handler(*args)}
|
||||
@ie.navigate("file:///#{@f}")
|
||||
while @ie.busy
|
||||
WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
|
||||
GC.start
|
||||
sleep 0.1
|
||||
end
|
||||
assert_match(/BeforeNavigate/, @event)
|
||||
|
|
Загрузка…
Ссылка в новой задаче