ruby-changes:6444
From: suke <ko1@a...>
Date: Tue, 8 Jul 2008 23:06:01 +0900 (JST)
Subject: [ruby-changes:6444] Ruby:r17960 (trunk): * ext/win32ole/win32ole.c (find_default_source): bug fix when
suke 2008-07-08 23:05:38 +0900 (Tue, 08 Jul 2008) New Revision: 17960 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=17960 Log: * 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. Modified files: trunk/ChangeLog trunk/ext/win32ole/win32ole.c trunk/test/win32ole/test_win32ole_event.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 17959) +++ ChangeLog (revision 17960) @@ -1,3 +1,10 @@ +Tue Jul 8 23:02:35 2008 Masaki Suketa <masaki.suketa@n...> + + * 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 <mame@t...> * thread.c (rb_enable_coverages): hide coverage array by setting 0 to Index: ext/win32ole/win32ole.c =================================================================== --- ext/win32ole/win32ole.c (revision 17959) +++ ext/win32ole/win32ole.c (revision 17960) @@ -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 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,7 +7599,118 @@ 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) { HRESULT hr; @@ -7606,18 +7719,9 @@ 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 @@ 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 @@ char *pitf; HRESULT hr; IID iid; - ITypeInfo *pTypeInfo; + ITypeInfo *pTypeInfo = 0; IDispatch *pDispatch; IConnectionPointContainer *pContainer; IConnectionPoint *pConnectionPoint; Index: test/win32ole/test_win32ole_event.rb =================================================================== --- test/win32ole/test_win32ole_event.rb (revision 17959) +++ test/win32ole/test_win32ole_event.rb (revision 17960) @@ -125,6 +125,16 @@ } 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 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/