summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--ext/win32ole/tests/testOLEEVENT.rb91
-rw-r--r--ext/win32ole/tests/testWIN32OLE.rb3
-rw-r--r--ext/win32ole/tests/testall.rb1
-rw-r--r--ext/win32ole/win32ole.c115
5 files changed, 127 insertions, 94 deletions
diff --git a/ChangeLog b/ChangeLog
index 7b6bc81e0a..a7992b4f21 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Thu Jul 3 19:23:20 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]
+
+ * ext/win32ole/tests: add test_win32ole_event.rb, remove
+ testOLEEVENT.rb
+
+ * ext/win32ole/tests/testWIN32OLE.rb(test_convert_bignum):
+ fix test.
+
Thu Jul 3 16:46:56 2008 Tanaka Akira <akr@fsij.org>
* include/ruby/ruby.h (POSFIXABLE): use FIXNUM_MAX+1 instead of
diff --git a/ext/win32ole/tests/testOLEEVENT.rb b/ext/win32ole/tests/testOLEEVENT.rb
deleted file mode 100644
index 0901158642..0000000000
--- a/ext/win32ole/tests/testOLEEVENT.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-require 'rubyunit'
-require 'win32ole'
-
-class TestWIN32OLE_EVENT < RUNIT::TestCase
- def setup
- @excel = WIN32OLE.new("Excel.Application")
- @excel.visible = true
- @event = ""
- @event2 = ""
- end
- def test_on_event
- book = @excel.workbooks.Add
- value = ""
- begin
- ev = WIN32OLE_EVENT.new(book, 'WorkbookEvents')
- ev.on_event('SheetChange'){|arg1, arg2|
- begin
- value = arg1.value
- rescue
- value = $!.message
- end
- }
- book.Worksheets(1).Range("A1").value = "OK"
- ensure
- book.saved = true
- end
- assert_equal("OK", value)
- end
-
- def handler1
- @event += "handler1"
- end
- def handler2
- @event += "handler2"
- end
-
- def handler3
- @event += "handler3"
- end
-
- def test_on_event2
- book = @excel.workbooks.Add
- begin
- ev = WIN32OLE_EVENT.new(book, 'WorkbookEvents')
- ev.on_event('SheetChange'){|arg1, arg2|
- handler1
- }
- ev.on_event('SheetChange'){|arg1, arg2|
- handler2
- }
- book.Worksheets(1).Range("A1").value = "OK"
- ensure
- book.saved = true
- end
- assert_equal("handler2", @event)
- end
-
- def test_on_event3
- book = @excel.workbooks.Add
- begin
- ev = WIN32OLE_EVENT.new(book, 'WorkbookEvents')
- ev.on_event{ handler1 }
- ev.on_event{ handler2 }
- book.Worksheets(1).Range("A1").value = "OK"
- ensure
- book.saved = true
- end
- assert_equal("handler2", @event)
- end
-
- def test_on_event4
- book = @excel.workbooks.Add
- begin
- ev = WIN32OLE_EVENT.new(book, 'WorkbookEvents')
- ev.on_event{ handler1 }
- ev.on_event{ handler2 }
- ev.on_event('SheetChange'){|arg1, arg2| handler3 }
- book.Worksheets(1).Range("A1").value = "OK"
- ensure
- book.saved = true
- end
- assert_equal("handler3", @event)
- end
-
- def teardown
- @excel.quit
- @excel = nil
- GC.start
- end
-end
-
diff --git a/ext/win32ole/tests/testWIN32OLE.rb b/ext/win32ole/tests/testWIN32OLE.rb
index 5c01507377..d7f9dd2543 100644
--- a/ext/win32ole/tests/testWIN32OLE.rb
+++ b/ext/win32ole/tests/testWIN32OLE.rb
@@ -156,7 +156,8 @@ class TestWin32OLE < RUNIT::TestCase
sheet.range("A3").value = "=A1*10 + 9"
assert_equal(9999999999, sheet.range("A2").value)
assert_equal(9999999999, sheet.range("A3").value)
-
+ sheet.range("A4").value = "2008/03/04"
+ assert_equal("2008/03/04 00:00:00", sheet.range("A4").value)
ensure
book.saved = true
end
diff --git a/ext/win32ole/tests/testall.rb b/ext/win32ole/tests/testall.rb
index d45541f571..553ce88509 100644
--- a/ext/win32ole/tests/testall.rb
+++ b/ext/win32ole/tests/testall.rb
@@ -12,4 +12,5 @@ require "testNIL2VTEMPTY"
require "test_ole_methods.rb"
require "test_propertyputref.rb"
require "test_word.rb"
+require "test_win32ole_event.rb"
# require "testOLEEVENT"
diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c
index 94eff3aa51..ae0066ffc9 100644
--- a/ext/win32ole/win32ole.c
+++ b/ext/win32ole/win32ole.c
@@ -29,7 +29,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)
@@ -79,7 +79,7 @@
#define WC2VSTR(x) ole_wc2vstr((x), TRUE)
-#define WIN32OLE_VERSION "0.7.5"
+#define WIN32OLE_VERSION "0.7.6"
typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX)
(REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*);
@@ -157,6 +157,9 @@ static VALUE com_hash;
static IDispatchVtbl com_vtbl;
static UINT cWIN32OLE_cp = CP_ACP;
static VARTYPE g_nil_to = VT_ERROR;
+static IMessageFilterVtbl message_filter;
+static IMessageFilter imessage_filter = { &message_filter };
+static IMessageFilter* previous_filter;
struct oledata {
IDispatch *pDispatch;
@@ -203,6 +206,101 @@ static char *ole_wc2mb(LPWSTR);
static VALUE ole_variant2val(VARIANT*);
static void ole_val2variant(VALUE, VARIANT*);
+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;
@@ -625,6 +723,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");
+ }
}
}
@@ -6183,6 +6286,14 @@ 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());
cWIN32OLE = rb_define_class("WIN32OLE", rb_cObject);