From 485754369101514e6230f4cd0a68922016f29b0e Mon Sep 17 00:00:00 2001 From: suke Date: Tue, 8 Jul 2008 14:05:38 +0000 Subject: [PATCH] * ext/win32ole/win32ole.c (find_default_source): bug fix when OLE object does not have default source interface. * test/win32ole/test_win32ole_event.rb: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17960 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 7 + ext/win32ole/win32ole.c | 229 +++++++++++++++------------ test/win32ole/test_win32ole_event.rb | 10 ++ 3 files changed, 143 insertions(+), 103 deletions(-) diff --git a/ChangeLog b/ChangeLog index cd82535d53..2e412d2788 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Tue Jul 8 23:02:35 2008 Masaki Suketa + + * ext/win32ole/win32ole.c (find_default_source): bug fix when + OLE object does not have default source interface. + + * test/win32ole/test_win32ole_event.rb: ditto. + Tue Jul 8 22:56:23 2008 Yusuke Endoh * thread.c (rb_enable_coverages): hide coverage array by setting 0 to diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c index 2de548a4cb..bfefb83e2a 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.2" +#define WIN32OLE_VERSION "1.2.3" typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX) (REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*); @@ -501,6 +501,8 @@ static long ole_search_event_at(VALUE ary, VALUE ev); static VALUE ole_search_event(VALUE ary, VALUE ev, BOOL *is_default); static void ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams); static HRESULT find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo); +static HRESULT find_coclass(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **pTypeInfo2, TYPEATTR **pTypeAttr2); +static HRESULT find_default_source_from_typeinfo(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **ppTypeInfo); static HRESULT find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo); static void ole_event_free(struct oleeventdata *poleev); static VALUE fev_s_allocate(VALUE klass); @@ -7597,6 +7599,117 @@ find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo) return hr; } +static HRESULT +find_coclass( + ITypeInfo *pTypeInfo, + TYPEATTR *pTypeAttr, + ITypeInfo **pCOTypeInfo, + TYPEATTR **pCOTypeAttr) +{ + HRESULT hr = E_NOINTERFACE; + ITypeLib *pTypeLib; + int count; + BOOL found = FALSE; + ITypeInfo *pTypeInfo2; + TYPEATTR *pTypeAttr2; + int flags; + int i,j; + HREFTYPE href; + ITypeInfo *pRefTypeInfo; + TYPEATTR *pRefTypeAttr; + + hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, NULL); + if (FAILED(hr)) { + 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; + } + } + if (!found) { + OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2); + OLE_RELEASE(pTypeInfo2); + } + } + OLE_RELEASE(pTypeLib); + if (found) { + *pCOTypeInfo = pTypeInfo2; + *pCOTypeAttr = pTypeAttr2; + hr = S_OK; + } else { + hr = E_NOINTERFACE; + } + return hr; +} + +static HRESULT +find_default_source_from_typeinfo( + ITypeInfo *pTypeInfo, + TYPEATTR *pTypeAttr, + ITypeInfo **ppTypeInfo) +{ + int i = 0; + HRESULT hr = E_NOINTERFACE; + int flags; + HREFTYPE hRefType; + /* Enumerate all implemented types of the COCLASS */ + for (i = 0; i < pTypeAttr->cImplTypes; i++) { + hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags); + if (FAILED(hr)) + continue; + + /* + looking for the [default] [source] + we just hope that it is a dispinterface :-) + */ + if ((flags & IMPLTYPEFLAG_FDEFAULT) && + (flags & IMPLTYPEFLAG_FSOURCE)) { + + hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, + i, &hRefType); + if (FAILED(hr)) + continue; + hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, + hRefType, ppTypeInfo); + if (SUCCEEDED(hr)) + break; + } + } + return hr; +} + static HRESULT find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo) { @@ -7606,18 +7719,9 @@ find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo) IDispatch *pDispatch; ITypeInfo *pTypeInfo; - ITypeInfo *pTypeInfo2; - ITypeInfo *pRefTypeInfo; - ITypeLib *pTypeLib; + ITypeInfo *pTypeInfo2 = NULL; TYPEATTR *pTypeAttr; - TYPEATTR *pTypeAttr2; - TYPEATTR *pRefTypeAttr; - int i, j; - int iFlags; - int flags; - HREFTYPE hRefType, href; - int count; - BOOL found = FALSE; + TYPEATTR *pTypeAttr2 = NULL; struct oledata *pole; @@ -7658,99 +7762,18 @@ find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo) 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; - } + *ppTypeInfo = 0; + hr = find_default_source_from_typeinfo(pTypeInfo, pTypeAttr, ppTypeInfo); + if (!*ppTypeInfo) { + hr = find_coclass(pTypeInfo, pTypeAttr, &pTypeInfo2, &pTypeAttr2); + if (SUCCEEDED(hr)) { + hr = find_default_source_from_typeinfo(pTypeInfo2, pTypeAttr2, ppTypeInfo); + OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2); + OLE_RELEASE(pTypeInfo2); + } } - - /* Enumerate all implemented types of the COCLASS */ - for (i = 0; i < pTypeAttr->cImplTypes; i++) { - hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &iFlags); - if (FAILED(hr)) - continue; - - /* - looking for the [default] [source] - we just hope that it is a dispinterface :-) - */ - if ((iFlags & IMPLTYPEFLAG_FDEFAULT) && - (iFlags & IMPLTYPEFLAG_FSOURCE)) { - - hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, - i, &hRefType); - if (FAILED(hr)) - continue; - hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, - hRefType, ppTypeInfo); - if (SUCCEEDED(hr)) - break; - } - } - OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); OLE_RELEASE(pTypeInfo); - /* Now that would be a bad surprise, if we didn't find it, wouldn't it? */ if (!*ppTypeInfo) { if (SUCCEEDED(hr)) @@ -7799,7 +7822,7 @@ ev_advise(int argc, VALUE *argv, VALUE self) char *pitf; HRESULT hr; IID iid; - ITypeInfo *pTypeInfo; + ITypeInfo *pTypeInfo = 0; IDispatch *pDispatch; IConnectionPointContainer *pContainer; IConnectionPoint *pConnectionPoint; diff --git a/test/win32ole/test_win32ole_event.rb b/test/win32ole/test_win32ole_event.rb index 79e5b06080..4888539361 100644 --- a/test/win32ole/test_win32ole_event.rb +++ b/test/win32ole/test_win32ole_event.rb @@ -125,6 +125,16 @@ if defined?(WIN32OLE_EVENT) } end + def test_non_exist_event + assert_raise(RuntimeError) { + ev = WIN32OLE_EVENT.new(@ie, 'XXXX') + } + dict = WIN32OLE.new('Scripting.Dictionary') + assert_raise(RuntimeError) { + ev = WIN32OLE_EVENT.new(dict) + } + end + def handler1 @event2 = "handler1" end