From 6c32d10c0186a1aebe212f0f61c940204d7f1e73 Mon Sep 17 00:00:00 2001 From: suke Date: Tue, 8 Jul 2008 11:13:09 +0000 Subject: * ext/win32ole/win32ole.c (find_default_source): try to find COCLASS when WIN32OLE object is not COCLASS. * test/win32ole/test_win32ole_event.rb: ditto git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17956 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 7 ++++ ext/win32ole/win32ole.c | 81 ++++++++++++++++++++++++++++++++++-- test/win32ole/test_win32ole_event.rb | 14 +++++++ 3 files changed, 99 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index ccc431ee3d..3b276c7679 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Tue Jul 8 19:55:40 2008 Masaki Suketa + + * ext/win32ole/win32ole.c (find_default_source): try to + find COCLASS when WIN32OLE object is not COCLASS. + + * test/win32ole/test_win32ole_event.rb: ditto + Tue Jul 8 13:44:01 2008 Koichi Sasada * lib/debug.rb, lib/profile.rb: fix to use RubyVM. diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c index dd7d7b13a9..2de548a4cb 100644 --- a/ext/win32ole/win32ole.c +++ b/ext/win32ole/win32ole.c @@ -118,7 +118,7 @@ #define WC2VSTR(x) ole_wc2vstr((x), TRUE) -#define WIN32OLE_VERSION "1.2.1" +#define WIN32OLE_VERSION "1.2.2" typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX) (REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*); @@ -7606,10 +7606,18 @@ find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo) IDispatch *pDispatch; ITypeInfo *pTypeInfo; + ITypeInfo *pTypeInfo2; + ITypeInfo *pRefTypeInfo; + ITypeLib *pTypeLib; TYPEATTR *pTypeAttr; - int i; + TYPEATTR *pTypeAttr2; + TYPEATTR *pRefTypeAttr; + int i, j; int iFlags; - HREFTYPE hRefType; + int flags; + HREFTYPE hRefType, href; + int count; + BOOL found = FALSE; struct oledata *pole; @@ -7649,6 +7657,73 @@ find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo) OLE_RELEASE(pTypeInfo); return hr; } + + /* + * if the ole is not COCLASS, then try to find COCLASS which + * has ole as [default] interface. + */ + if (pTypeAttr->typekind != TKIND_COCLASS) { + /* + * search coclass + */ + hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, NULL); + if (FAILED(hr)) { + OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); + OLE_RELEASE(pTypeInfo); + return hr; + } + count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); + + for (i = 0; i < count && !found; i++) { + hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo2); + if (FAILED(hr)) + continue; + hr = OLE_GET_TYPEATTR(pTypeInfo2, &pTypeAttr2); + if (FAILED(hr)) { + OLE_RELEASE(pTypeInfo2); + continue; + } + if (pTypeAttr2->typekind != TKIND_COCLASS) { + OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2); + OLE_RELEASE(pTypeInfo2); + continue; + } + for (j = 0; j < pTypeAttr2->cImplTypes && !found; j++) { + hr = pTypeInfo2->lpVtbl->GetImplTypeFlags(pTypeInfo2, j, &flags); + if (FAILED(hr)) + continue; + if (!(flags & IMPLTYPEFLAG_FDEFAULT)) + continue; + hr = pTypeInfo2->lpVtbl->GetRefTypeOfImplType(pTypeInfo2, j, &href); + if (FAILED(hr)) + continue; + hr = pTypeInfo2->lpVtbl->GetRefTypeInfo(pTypeInfo2, href, &pRefTypeInfo); + if (FAILED(hr)) + continue; + hr = OLE_GET_TYPEATTR(pRefTypeInfo, &pRefTypeAttr); + if (FAILED(hr)) { + OLE_RELEASE(pRefTypeInfo); + continue; + } + if (IsEqualGUID(&(pTypeAttr->guid), &(pRefTypeAttr->guid))) { + found = TRUE; + } + OLE_RELEASE_TYPEATTR(pRefTypeInfo, pRefTypeAttr); + OLE_RELEASE(pRefTypeInfo); + } + if (!found) { + OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2); + OLE_RELEASE(pTypeInfo2); + } + } + if (found) { + OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); + OLE_RELEASE(pTypeInfo); + pTypeInfo = pTypeInfo2; + pTypeAttr = pTypeAttr2; + } + } + /* Enumerate all implemented types of the COCLASS */ for (i = 0; i < pTypeAttr->cImplTypes; i++) { hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &iFlags); diff --git a/test/win32ole/test_win32ole_event.rb b/test/win32ole/test_win32ole_event.rb index 744021dfd2..79e5b06080 100644 --- a/test/win32ole/test_win32ole_event.rb +++ b/test/win32ole/test_win32ole_event.rb @@ -30,6 +30,20 @@ if defined?(WIN32OLE_EVENT) @event += event end + def test_s_new_without_itf + ev = WIN32OLE_EVENT.new(@ie) + ev.on_event {|*args| default_handler(*args)} + @ie.navigate("file:///#{@f}") + while @ie.busy + WIN32OLE_EVENT.new(@ie) + GC.start + WIN32OLE_EVENT.message_loop + sleep 0.1 + end + assert_match(/BeforeNavigate/, @event) + assert_match(/NavigateComplete/, @event) + end + def test_on_event ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents') ev.on_event {|*args| default_handler(*args)} -- cgit v1.2.3