VALUE ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask) { HRESULT hr; TYPEATTR *pTypeAttr; WORD i; HREFTYPE href; ITypeInfo *pRefTypeInfo; VALUE methods = rb_ary_new(); hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) { ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); } ole_methods_sub(0, pTypeInfo, methods, mask); for(i=0; i < pTypeAttr->cImplTypes; i++){ hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href); if(FAILED(hr)) continue; hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo); if (FAILED(hr)) continue; ole_methods_sub(pTypeInfo, pRefTypeInfo, methods, mask); OLE_RELEASE(pRefTypeInfo); } OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return methods; }
static VALUE ole_variables(ITypeInfo *pTypeInfo) { HRESULT hr; TYPEATTR *pTypeAttr; WORD i; UINT len; BSTR bstr; VARDESC *pVarDesc; VALUE var; VALUE variables = rb_ary_new(); hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) { ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); } for(i = 0; i < pTypeAttr->cVars; i++) { hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, i, &pVarDesc); if(FAILED(hr)) continue; len = 0; hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pVarDesc->memid, &bstr, 1, &len); if(FAILED(hr) || len == 0 || !bstr) continue; var = create_win32ole_variable(pTypeInfo, i, WC2VSTR(bstr)); rb_ary_push(variables, var); pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); pVarDesc = NULL; } OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return variables; }
static VALUE olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name) { HRESULT hr; TYPEATTR *pTypeAttr; WORD i; HREFTYPE href; ITypeInfo *pRefTypeInfo; VALUE method = Qnil; hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) { ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); } method = ole_method_sub(self, 0, pTypeInfo, name); if (method != Qnil) { return method; } for(i=0; i < pTypeAttr->cImplTypes && method == Qnil; i++){ hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href); if(FAILED(hr)) continue; hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo); if (FAILED(hr)) continue; method = ole_method_sub(self, pTypeInfo, pRefTypeInfo, name); OLE_RELEASE(pRefTypeInfo); } OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return method; }
static VALUE ole_type_typekind(ITypeInfo *pTypeInfo) { VALUE typekind; TYPEATTR *pTypeAttr; HRESULT hr; hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); typekind = INT2FIX(pTypeAttr->typekind); OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return typekind; }
static VALUE ole_type_minor_version(ITypeInfo *pTypeInfo) { VALUE ver; TYPEATTR *pTypeAttr; HRESULT hr; hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); ver = INT2FIX(pTypeAttr->wMinorVerNum); OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return ver; }
static VALUE ole_type_src_type(ITypeInfo *pTypeInfo) { HRESULT hr; TYPEATTR *pTypeAttr; VALUE alias = Qnil; hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) return alias; if(pTypeAttr->typekind != TKIND_ALIAS) { OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return alias; } alias = ole_typedesc2val(pTypeInfo, &(pTypeAttr->tdescAlias), Qnil); OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return alias; }
static VALUE ole_type_visible(ITypeInfo *pTypeInfo) { HRESULT hr; TYPEATTR *pTypeAttr; VALUE visible; hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) return Qtrue; if (pTypeAttr->wTypeFlags & (TYPEFLAG_FHIDDEN | TYPEFLAG_FRESTRICTED)) { visible = Qfalse; } else { visible = Qtrue; } OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return visible; }
static VALUE ole_ole_type(ITypeInfo *pTypeInfo) { HRESULT hr; TYPEATTR *pTypeAttr; VALUE type = Qnil; hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if(FAILED(hr)){ return type; } switch(pTypeAttr->typekind) { case TKIND_ENUM: type = rb_str_new2("Enum"); break; case TKIND_RECORD: type = rb_str_new2("Record"); break; case TKIND_MODULE: type = rb_str_new2("Module"); break; case TKIND_INTERFACE: type = rb_str_new2("Interface"); break; case TKIND_DISPATCH: type = rb_str_new2("Dispatch"); break; case TKIND_COCLASS: type = rb_str_new2("Class"); break; case TKIND_ALIAS: type = rb_str_new2("Alias"); break; case TKIND_UNION: type = rb_str_new2("Union"); break; case TKIND_MAX: type = rb_str_new2("Max"); break; default: type = Qnil; break; } OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return type; }
static VALUE ole_type_guid(ITypeInfo *pTypeInfo) { HRESULT hr; TYPEATTR *pTypeAttr; int len; OLECHAR bstr[80]; VALUE guid = Qnil; hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) return guid; len = StringFromGUID2(&pTypeAttr->guid, bstr, sizeof(bstr)/sizeof(OLECHAR)); if (len > 3) { guid = ole_wc2vstr(bstr, FALSE); } OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return guid; }
static VALUE ole_type_progid(ITypeInfo *pTypeInfo) { HRESULT hr; TYPEATTR *pTypeAttr; OLECHAR *pbuf; VALUE progid = Qnil; hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) return progid; hr = ProgIDFromCLSID(&pTypeAttr->guid, &pbuf); if (SUCCEEDED(hr)) { progid = ole_wc2vstr(pbuf, FALSE); CoTaskMemFree(pbuf); } OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return progid; }
static VALUE ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags) { HRESULT hr; ITypeInfo *pRefTypeInfo; HREFTYPE href; WORD i; VALUE type; TYPEATTR *pTypeAttr; int flags; VALUE types = rb_ary_new(); hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) { return types; } for (i = 0; i < pTypeAttr->cImplTypes; i++) { hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags); if (FAILED(hr)) continue; hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href); if (FAILED(hr)) continue; hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo); if (FAILED(hr)) continue; if ((flags & implflags) == implflags) { type = ole_type_from_itypeinfo(pRefTypeInfo); if (type != Qnil) { rb_ary_push(types, type); } } OLE_RELEASE(pRefTypeInfo); } OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return types; }
static VALUE ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask) { HRESULT hr; TYPEATTR *pTypeAttr; BSTR bstr; FUNCDESC *pFuncDesc; VALUE method; WORD i; hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) { ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); } for(i = 0; i < pTypeAttr->cFuncs; i++) { hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, i, &pFuncDesc); if (FAILED(hr)) continue; hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid, &bstr, NULL, NULL, NULL); if (FAILED(hr)) { pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); continue; } if(pFuncDesc->invkind & mask) { method = folemethod_s_allocate(cWIN32OLE_METHOD); olemethod_set_member(method, pTypeInfo, pOwnerTypeInfo, i, WC2VSTR(bstr)); rb_ary_push(methods, method); } pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); pFuncDesc=NULL; } OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return methods; }
static VALUE ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name) { HRESULT hr; TYPEATTR *pTypeAttr; BSTR bstr; FUNCDESC *pFuncDesc; WORD i; VALUE fname; VALUE method = Qnil; hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) { ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); } for(i = 0; i < pTypeAttr->cFuncs && method == Qnil; i++) { hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, i, &pFuncDesc); if (FAILED(hr)) continue; hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid, &bstr, NULL, NULL, NULL); if (FAILED(hr)) { pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); continue; } fname = WC2VSTR(bstr); if (strcasecmp(StringValuePtr(name), StringValuePtr(fname)) == 0) { olemethod_set_member(self, pTypeInfo, pOwnerTypeInfo, i, fname); method = self; } pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); pFuncDesc=NULL; } OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return method; }
static HRESULT find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo) { HRESULT hr; IProvideClassInfo2 *pProvideClassInfo2; IProvideClassInfo *pProvideClassInfo; void *p; IDispatch *pDispatch; ITypeInfo *pTypeInfo; ITypeInfo *pTypeInfo2 = NULL; TYPEATTR *pTypeAttr; TYPEATTR *pTypeAttr2 = NULL; struct oledata *pole; OLEData_Get_Struct(ole, pole); pDispatch = pole->pDispatch; hr = pDispatch->lpVtbl->QueryInterface(pDispatch, &IID_IProvideClassInfo2, &p); if (SUCCEEDED(hr)) { pProvideClassInfo2 = p; hr = pProvideClassInfo2->lpVtbl->GetGUID(pProvideClassInfo2, GUIDKIND_DEFAULT_SOURCE_DISP_IID, piid); OLE_RELEASE(pProvideClassInfo2); if (SUCCEEDED(hr)) { hr = find_iid(ole, NULL, piid, ppTypeInfo); } } if (SUCCEEDED(hr)) { return hr; } hr = pDispatch->lpVtbl->QueryInterface(pDispatch, &IID_IProvideClassInfo, &p); if (SUCCEEDED(hr)) { pProvideClassInfo = p; hr = pProvideClassInfo->lpVtbl->GetClassInfo(pProvideClassInfo, &pTypeInfo); OLE_RELEASE(pProvideClassInfo); } if (FAILED(hr)) { hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, cWIN32OLE_lcid, &pTypeInfo ); } if (FAILED(hr)) return hr; hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) { OLE_RELEASE(pTypeInfo); return hr; } *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); } } 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)) hr = E_UNEXPECTED; return hr; } /* Determine IID of default source interface */ hr = (*ppTypeInfo)->lpVtbl->GetTypeAttr(*ppTypeInfo, &pTypeAttr); if (SUCCEEDED(hr)) { *piid = pTypeAttr->guid; (*ppTypeInfo)->lpVtbl->ReleaseTypeAttr(*ppTypeInfo, pTypeAttr); } else OLE_RELEASE(*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_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo) { HRESULT hr; IDispatch *pDispatch; ITypeInfo *pTypeInfo; ITypeLib *pTypeLib; TYPEATTR *pTypeAttr; HREFTYPE RefType; ITypeInfo *pImplTypeInfo; TYPEATTR *pImplTypeAttr; struct oledata *pole; unsigned int index; unsigned int count; int type; BSTR bstr; char *pstr; BOOL is_found = FALSE; LCID lcid = cWIN32OLE_lcid; OLEData_Get_Struct(ole, pole); pDispatch = pole->pDispatch; hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, lcid, &pTypeInfo); if (FAILED(hr)) return hr; hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &index); OLE_RELEASE(pTypeInfo); if (FAILED(hr)) return hr; if (!pitf) { hr = pTypeLib->lpVtbl->GetTypeInfoOfGuid(pTypeLib, piid, ppTypeInfo); OLE_RELEASE(pTypeLib); return hr; } count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); for (index = 0; index < count; index++) { hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, index, &pTypeInfo); if (FAILED(hr)) break; hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if(FAILED(hr)) { OLE_RELEASE(pTypeInfo); break; } if(pTypeAttr->typekind == TKIND_COCLASS) { for (type = 0; type < pTypeAttr->cImplTypes; type++) { hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, type, &RefType); if (FAILED(hr)) break; hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, RefType, &pImplTypeInfo); if (FAILED(hr)) break; hr = pImplTypeInfo->lpVtbl->GetDocumentation(pImplTypeInfo, -1, &bstr, NULL, NULL, NULL); if (FAILED(hr)) { OLE_RELEASE(pImplTypeInfo); break; } pstr = ole_wc2mb(bstr); if (strcmp(pitf, pstr) == 0) { hr = pImplTypeInfo->lpVtbl->GetTypeAttr(pImplTypeInfo, &pImplTypeAttr); if (SUCCEEDED(hr)) { is_found = TRUE; *piid = pImplTypeAttr->guid; if (ppTypeInfo) { *ppTypeInfo = pImplTypeInfo; (*ppTypeInfo)->lpVtbl->AddRef((*ppTypeInfo)); } pImplTypeInfo->lpVtbl->ReleaseTypeAttr(pImplTypeInfo, pImplTypeAttr); } } free(pstr); OLE_RELEASE(pImplTypeInfo); if (is_found || FAILED(hr)) break; } } OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); OLE_RELEASE(pTypeInfo); if (is_found || FAILED(hr)) break; } OLE_RELEASE(pTypeLib); if(!is_found) return E_NOINTERFACE; return hr; }
static VALUE ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name) { TYPEATTR *pTypeAttr; HRESULT hr; WORD i; int flags; HREFTYPE href; ITypeInfo *pRefTypeInfo; FUNCDESC *pFuncDesc; BSTR bstr; VALUE name; VALUE event = Qfalse; hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) return event; if(pTypeAttr->typekind != TKIND_COCLASS) { pTypeInfo->lpVtbl->ReleaseTypeAttr(pTypeInfo, pTypeAttr); return event; } for (i = 0; i < pTypeAttr->cImplTypes; i++) { hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags); if (FAILED(hr)) continue; if (flags & IMPLTYPEFLAG_FSOURCE) { hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href); if (FAILED(hr)) continue; hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo); if (FAILED(hr)) continue; hr = pRefTypeInfo->lpVtbl->GetFuncDesc(pRefTypeInfo, method_index, &pFuncDesc); if (FAILED(hr)) { OLE_RELEASE(pRefTypeInfo); continue; } hr = pRefTypeInfo->lpVtbl->GetDocumentation(pRefTypeInfo, pFuncDesc->memid, &bstr, NULL, NULL, NULL); if (FAILED(hr)) { pRefTypeInfo->lpVtbl->ReleaseFuncDesc(pRefTypeInfo, pFuncDesc); OLE_RELEASE(pRefTypeInfo); continue; } name = WC2VSTR(bstr); pRefTypeInfo->lpVtbl->ReleaseFuncDesc(pRefTypeInfo, pFuncDesc); OLE_RELEASE(pRefTypeInfo); if (rb_str_cmp(method_name, name) == 0) { event = Qtrue; break; } } } OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return event; }