static unsigned long wire_extra_user_size(unsigned long *pFlags, unsigned long Start, VARIANT *pvar) { if (V_ISARRAY(pvar)) { if (V_ISBYREF(pvar)) return LPSAFEARRAY_UserSize(pFlags, Start, V_ARRAYREF(pvar)); else return LPSAFEARRAY_UserSize(pFlags, Start, &V_ARRAY(pvar)); } switch (V_VT(pvar)) { case VT_BSTR: return BSTR_UserSize(pFlags, Start, &V_BSTR(pvar)); case VT_BSTR | VT_BYREF: return BSTR_UserSize(pFlags, Start, V_BSTRREF(pvar)); case VT_VARIANT | VT_BYREF: return VARIANT_UserSize(pFlags, Start, V_VARIANTREF(pvar)); case VT_UNKNOWN: return Start + interface_variant_size(pFlags, &IID_IUnknown, pvar); case VT_DISPATCH: return Start + interface_variant_size(pFlags, &IID_IDispatch, pvar); case VT_RECORD: FIXME("wire-size record\n"); return Start; case VT_SAFEARRAY: case VT_SAFEARRAY | VT_BYREF: FIXME("wire-size safearray: shouldn't be marshaling this\n"); return Start; default: return Start; } }
/** * this is a big cover method that returns TRUE if * the variant type is * VT_EMPTY, VT_NULL, VT_ERROR or VT_DISPATCH with no dispatch object * */ JNIEXPORT jboolean JNICALL Java_com_tangram_Variant_isVariantConsideredNull(JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (!v) return JNI_TRUE; if ((V_VT(v) & VT_ARRAY)) { // is it a null safearray // prior to 4 Dec 2005 the squiggle brackets were missing // so this did the wrong thing for the else statement if ((V_VT(v) & VT_BYREF)) { if (!V_ARRAYREF(v)) return JNI_TRUE; } else { if (!V_ARRAY(v)) return JNI_TRUE; } } switch (V_VT(v)) { case VT_EMPTY: case VT_NULL: case VT_ERROR: return JNI_TRUE; // is it a null dispatch (Nothing in VB) case VT_DISPATCH: if (!V_DISPATCH(v)) return JNI_TRUE; } return JNI_FALSE; }
/* * call-seq: * WIN32OLE_VARIANT.value #=> Ruby object. * * Returns Ruby object value from OLE variant. * obj = WIN32OLE_VARIANT.new(1, WIN32OLE::VARIANT::VT_BSTR) * obj.value # => "1" (not Integer object, but String object "1") * */ static VALUE folevariant_value(VALUE self) { struct olevariantdata *pvar; VALUE val = Qnil; VARTYPE vt; int dim; SAFEARRAY *psa; TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar); val = ole_variant2val(&(pvar->var)); vt = V_VT(&(pvar->var)); if ((vt & ~VT_BYREF) == (VT_UI1|VT_ARRAY)) { if (vt & VT_BYREF) { psa = *V_ARRAYREF(&(pvar->var)); } else { psa = V_ARRAY(&(pvar->var)); } if (!psa) { return val; } dim = SafeArrayGetDim(psa); if (dim == 1) { val = rb_funcall(val, rb_intern("pack"), 1, rb_str_new2("C*")); } } return val; }
HRESULT create_vbdisp(const class_desc_t *desc, vbdisp_t **ret) { vbdisp_t *vbdisp; HRESULT hres = S_OK; vbdisp = heap_alloc_zero( FIELD_OFFSET( vbdisp_t, props[desc->prop_cnt] )); if(!vbdisp) return E_OUTOFMEMORY; vbdisp->IDispatchEx_iface.lpVtbl = &DispatchExVtbl; vbdisp->ref = 1; vbdisp->desc = desc; list_add_tail(&desc->ctx->objects, &vbdisp->entry); if(desc->array_cnt) { vbdisp->arrays = heap_alloc_zero(desc->array_cnt * sizeof(*vbdisp->arrays)); if(vbdisp->arrays) { unsigned i, j; for(i=0; i < desc->array_cnt; i++) { if(!desc->array_descs[i].dim_cnt) continue; vbdisp->arrays[i] = SafeArrayCreate(VT_VARIANT, desc->array_descs[i].dim_cnt, desc->array_descs[i].bounds); if(!vbdisp->arrays[i]) { hres = E_OUTOFMEMORY; break; } } if(SUCCEEDED(hres)) { for(i=0, j=0; i < desc->prop_cnt; i++) { if(desc->props[i].is_array) { V_VT(vbdisp->props+i) = VT_ARRAY|VT_BYREF|VT_VARIANT; V_ARRAYREF(vbdisp->props+i) = vbdisp->arrays + j++; } } } }else { hres = E_OUTOFMEMORY; } } if(SUCCEEDED(hres) && desc->class_initialize_id) { DISPPARAMS dp = {0}; hres = exec_script(desc->ctx, desc->funcs[desc->class_initialize_id].entries[VBDISP_CALLGET], vbdisp, &dp, NULL); } if(FAILED(hres)) { IDispatchEx_Release(&vbdisp->IDispatchEx_iface); return hres; } *ret = vbdisp; return S_OK; }
/* * call-seq: * WIN32OLE_VARIANT.array(ary, vt) * * Returns Ruby object wrapping OLE variant whose variant type is VT_ARRAY. * The first argument should be Array object which specifies dimensions * and each size of dimensions of OLE array. * The second argument specifies variant type of the element of OLE array. * * The following create 2 dimensions OLE array. The first dimensions size * is 3, and the second is 4. * * ole_ary = WIN32OLE_VARIANT.array([3,4], VT_I4) * ruby_ary = ole_ary.value # => [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] * */ static VALUE folevariant_s_array(VALUE klass, VALUE elems, VALUE vvt) { VALUE obj = Qnil; VARTYPE vt; struct olevariantdata *pvar; SAFEARRAYBOUND *psab = NULL; SAFEARRAY *psa = NULL; UINT dim = 0; UINT i = 0; ole_initialize(); vt = RB_NUM2UINT(vvt); vt = (vt | VT_ARRAY); Check_Type(elems, T_ARRAY); obj = folevariant_s_allocate(klass); TypedData_Get_Struct(obj, struct olevariantdata, &olevariant_datatype, pvar); dim = RARRAY_LEN(elems); psab = ALLOC_N(SAFEARRAYBOUND, dim); if(!psab) { rb_raise(rb_eRuntimeError, "memory allocation error"); } for (i = 0; i < dim; i++) { psab[i].cElements = RB_FIX2INT(rb_ary_entry(elems, i)); psab[i].lLbound = 0; } psa = SafeArrayCreate((VARTYPE)(vt & VT_TYPEMASK), dim, psab); if (psa == NULL) { if (psab) free(psab); rb_raise(rb_eRuntimeError, "memory allocation error(SafeArrayCreate)"); } V_VT(&(pvar->var)) = vt; if (vt & VT_BYREF) { V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF); V_ARRAY(&(pvar->realvar)) = psa; V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar))); } else { V_ARRAY(&(pvar->var)) = psa; } if (psab) free(psab); return obj; }
/* Get the number of dimensions. For each of these dimensions, get the lower and upper bound and iterate over the elements. */ static SEXP convertArrayToR(const VARIANT *var) { SAFEARRAY *arr; SEXP ans; UINT dim; if(V_ISBYREF(var)) arr = *V_ARRAYREF(var); else arr = V_ARRAY(var); dim = SafeArrayGetDim(arr); long *indices = (long*) S_alloc(dim, sizeof(long)); // new long[dim]; ans = getArray(arr, dim, dim, indices); return(ans); }
static SAFEARRAY * get_locked_safe_array(VALUE val) { struct olevariantdata *pvar; SAFEARRAY *psa = NULL; HRESULT hr; TypedData_Get_Struct(val, struct olevariantdata, &olevariant_datatype, pvar); if (!(V_VT(&(pvar->var)) & VT_ARRAY)) { rb_raise(rb_eTypeError, "variant type is not VT_ARRAY."); } psa = V_ISBYREF(&(pvar->var)) ? *V_ARRAYREF(&(pvar->var)) : V_ARRAY(&(pvar->var)); if (psa == NULL) { return psa; } hr = SafeArrayLock(psa); if (FAILED(hr)) { ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayLock"); } return psa; }
JNIEXPORT void JNICALL Java_com_tangram_Variant_putVariantSafeArrayRef(JNIEnv *env, jobject _this, jobject sa) { SAFEARRAY *psa = extractSA(env, sa); if (psa) { VARIANT *v = extractVariant(env, _this); if (v) { VARTYPE vt; SAFEARRAY **sa = (SAFEARRAY **)CoTaskMemAlloc(sizeof(SAFEARRAY*)); *sa = psa; SafeArrayGetVartype(psa, &vt); V_VT(v) = VT_ARRAY | vt | VT_BYREF; V_ARRAYREF(v) = sa; return; } ThrowComFail(env, "Can't get variant pointer", -1); return; } ThrowComFail(env, "Can't get sa pointer", -1); return; }
void WINAPI VARIANT_UserFree(unsigned long *pFlags, VARIANT *pvar) { VARTYPE vt = V_VT(pvar); PVOID ref = NULL; TRACE("(%lx,%p)\n", *pFlags, pvar); TRACE("vt=%04x\n", V_VT(pvar)); if (vt & VT_BYREF) ref = pvar->n1.n2.n3.byref; VariantClear(pvar); if (!ref) return; if(vt & VT_ARRAY) LPSAFEARRAY_UserFree(pFlags, V_ARRAYREF(pvar)); else { switch (vt) { case VT_BSTR | VT_BYREF: BSTR_UserFree(pFlags, V_BSTRREF(pvar)); break; case VT_VARIANT | VT_BYREF: VARIANT_UserFree(pFlags, V_VARIANTREF(pvar)); break; case VT_RECORD | VT_BYREF: FIXME("handle BRECORD by ref\n"); break; case VT_UNKNOWN | VT_BYREF: case VT_DISPATCH | VT_BYREF: IUnknown_Release(*V_UNKNOWNREF(pvar)); break; } } CoTaskMemFree(ref); }
unsigned char * WINAPI VARIANT_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, VARIANT *pvar) { variant_wire_t *header; unsigned long type_size; int align; unsigned char *Pos; TRACE("(%lx,%p,%p)\n", *pFlags, Buffer, pvar); ALIGN_POINTER(Buffer, 7); VariantInit(pvar); header = (variant_wire_t *)Buffer; pvar->n1.n2.vt = header->vt; pvar->n1.n2.wReserved1 = header->wReserved1; pvar->n1.n2.wReserved2 = header->wReserved2; pvar->n1.n2.wReserved3 = header->wReserved3; Pos = (unsigned char*)(header + 1); type_size = get_type_size(pFlags, pvar); align = get_type_alignment(pFlags, pvar); ALIGN_POINTER(Pos, align); if(header->vt & VT_BYREF) { Pos += 4; pvar->n1.n2.n3.byref = CoTaskMemAlloc(type_size); memcpy(pvar->n1.n2.n3.byref, Pos, type_size); if((header->vt & VT_TYPEMASK) != VT_VARIANT) Pos += type_size; else Pos += 4; } else { if((header->vt & VT_TYPEMASK) == VT_DECIMAL) memcpy(pvar, Pos, type_size); else memcpy(&pvar->n1.n2.n3, Pos, type_size); Pos += type_size; } if(header->vt & VT_ARRAY) { if(header->vt & VT_BYREF) Pos = LPSAFEARRAY_UserUnmarshal(pFlags, Pos, V_ARRAYREF(pvar)); else Pos = LPSAFEARRAY_UserUnmarshal(pFlags, Pos, &V_ARRAY(pvar)); } else { switch (header->vt) { case VT_BSTR: V_BSTR(pvar) = NULL; Pos = BSTR_UserUnmarshal(pFlags, Pos, &V_BSTR(pvar)); break; case VT_BSTR | VT_BYREF: *V_BSTRREF(pvar) = NULL; Pos = BSTR_UserUnmarshal(pFlags, Pos, V_BSTRREF(pvar)); break; case VT_VARIANT | VT_BYREF: Pos = VARIANT_UserUnmarshal(pFlags, Pos, V_VARIANTREF(pvar)); break; case VT_DISPATCH | VT_BYREF: FIXME("handle DISPATCH by ref\n"); break; case VT_UNKNOWN: /* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */ Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, pvar); break; case VT_DISPATCH: /* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */ Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, pvar); break; case VT_RECORD: FIXME("handle BRECORD by val\n"); break; case VT_RECORD | VT_BYREF: FIXME("handle BRECORD by ref\n"); break; } } return Pos; }
TclObject::TclObject (VARIANT *pSrc, const Type &type, Tcl_Interp *interp, int bytes) { if (V_ISARRAY(pSrc)) { SAFEARRAY *psa = V_ISBYREF(pSrc) ? *V_ARRAYREF(pSrc) : V_ARRAY(pSrc); VARTYPE elementType = V_VT(pSrc) & VT_TYPEMASK; unsigned numDimensions = SafeArrayGetDim(psa); std::vector<long> indices(numDimensions); m_pObj = convertFromSafeArray( psa, elementType, 1, &indices[0], type, interp, bytes); } else if (vtMissing == pSrc) { m_pObj = Extension::newNaObj(); } else { switch (V_VT(pSrc)) { case VT_BOOL: m_pObj = Tcl_NewBooleanObj(V_BOOL(pSrc)); break; case VT_ERROR: m_pObj = Tcl_NewLongObj(V_ERROR(pSrc)); break; case VT_I1: case VT_UI1: m_pObj = Tcl_NewLongObj(V_I1(pSrc)); break; case VT_I2: case VT_UI2: m_pObj = Tcl_NewLongObj(V_I2(pSrc)); break; case VT_I4: case VT_UI4: case VT_INT: case VT_UINT: m_pObj = Tcl_NewLongObj(V_I4(pSrc)); break; #ifdef V_I8 case VT_I8: case VT_UI8: m_pObj = Tcl_NewWideIntObj(V_I8(pSrc)); break; #endif case VT_R4: m_pObj = Tcl_NewDoubleObj(V_R4(pSrc)); break; case VT_DATE: case VT_R8: m_pObj = Tcl_NewDoubleObj(V_R8(pSrc)); break; case VT_DISPATCH: m_pObj = convertFromUnknown(V_DISPATCH(pSrc), type.iid(), interp); break; case VT_DISPATCH | VT_BYREF: m_pObj = convertFromUnknown( (V_DISPATCHREF(pSrc) != 0) ? *V_DISPATCHREF(pSrc) : 0, type.iid(), interp); break; case VT_UNKNOWN: m_pObj = convertFromUnknown(V_UNKNOWN(pSrc), type.iid(), interp); break; case VT_UNKNOWN | VT_BYREF: m_pObj = convertFromUnknown( (V_UNKNOWNREF(pSrc) != 0) ? *V_UNKNOWNREF(pSrc) : 0, type.iid(), interp); break; case VT_NULL: m_pObj = Extension::newNullObj(); break; case VT_LPSTR: m_pObj = Tcl_NewStringObj(V_I1REF(pSrc), -1); break; case VT_LPWSTR: { #if TCL_MINOR_VERSION >= 2 // Uses Unicode function introduced in Tcl 8.2. m_pObj = newUnicodeObj(V_UI2REF(pSrc), -1); #else const wchar_t *pWide = V_UI2REF(pSrc); _bstr_t str(pWide); m_pObj = Tcl_NewStringObj(str, -1); #endif } break; default: if (V_VT(pSrc) == VT_USERDEFINED && type.name() == "GUID") { Uuid uuid(*static_cast<UUID *>(V_BYREF(pSrc))); m_pObj = Tcl_NewStringObj( const_cast<char *>(uuid.toString().c_str()), -1); } else { if (V_VT(pSrc) == (VT_VARIANT | VT_BYREF)) { pSrc = V_VARIANTREF(pSrc); } _bstr_t str(pSrc); #if TCL_MINOR_VERSION >= 2 // Uses Unicode function introduced in Tcl 8.2. wchar_t *pWide = str; m_pObj = newUnicodeObj( reinterpret_cast<Tcl_UniChar *>(pWide), str.length()); #else m_pObj = Tcl_NewStringObj(str, -1); #endif } } } Tcl_IncrRefCount(m_pObj); }
unsigned char * WINAPI VARIANT_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, VARIANT *pvar) { variant_wire_t *header; unsigned long type_size; int align; unsigned char *Pos; TRACE("(%lx,%p,%p)\n", *pFlags, Buffer, pvar); TRACE("vt=%04x\n", V_VT(pvar)); ALIGN_POINTER(Buffer, 7); header = (variant_wire_t *)Buffer; header->clSize = 0; /* fixed up at the end */ header->rpcReserverd = 0; header->vt = pvar->n1.n2.vt; header->wReserved1 = pvar->n1.n2.wReserved1; header->wReserved2 = pvar->n1.n2.wReserved2; header->wReserved3 = pvar->n1.n2.wReserved3; header->switch_is = pvar->n1.n2.vt; if(header->switch_is & VT_ARRAY) header->switch_is &= ~VT_TYPEMASK; Pos = (unsigned char*)(header + 1); type_size = get_type_size(pFlags, pvar); align = get_type_alignment(pFlags, pvar); ALIGN_POINTER(Pos, align); if(header->vt & VT_BYREF) { *(DWORD *)Pos = max(type_size, 4); Pos += 4; if((header->vt & VT_TYPEMASK) != VT_VARIANT) { memcpy(Pos, pvar->n1.n2.n3.byref, type_size); Pos += type_size; } else { *(DWORD*)Pos = 'U' | 's' << 8 | 'e' << 16 | 'r' << 24; Pos += 4; } } else { if((header->vt & VT_TYPEMASK) == VT_DECIMAL) memcpy(Pos, pvar, type_size); else memcpy(Pos, &pvar->n1.n2.n3, type_size); Pos += type_size; } if(header->vt & VT_ARRAY) { if(header->vt & VT_BYREF) Pos = LPSAFEARRAY_UserMarshal(pFlags, Pos, V_ARRAYREF(pvar)); else Pos = LPSAFEARRAY_UserMarshal(pFlags, Pos, &V_ARRAY(pvar)); } else { switch (header->vt) { case VT_BSTR: Pos = BSTR_UserMarshal(pFlags, Pos, &V_BSTR(pvar)); break; case VT_BSTR | VT_BYREF: Pos = BSTR_UserMarshal(pFlags, Pos, V_BSTRREF(pvar)); break; case VT_VARIANT | VT_BYREF: Pos = VARIANT_UserMarshal(pFlags, Pos, V_VARIANTREF(pvar)); break; case VT_DISPATCH | VT_BYREF: FIXME("handle DISPATCH by ref\n"); break; case VT_UNKNOWN: /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */ Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, pvar); break; case VT_DISPATCH: /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */ Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, pvar); break; case VT_RECORD: FIXME("handle BRECORD by val\n"); break; case VT_RECORD | VT_BYREF: FIXME("handle BRECORD by ref\n"); break; } } header->clSize = ((Pos - Buffer) + 7) >> 3; TRACE("marshalled size=%ld\n", header->clSize); return Pos; }
HRESULT navigate_url(DocHost *This, LPCWSTR url, const VARIANT *Flags, const VARIANT *TargetFrameName, VARIANT *PostData, VARIANT *Headers) { SAFEARRAY *post_array = NULL; PBYTE post_data = NULL; ULONG post_data_len = 0; LPWSTR headers = NULL; HRESULT hres = S_OK; TRACE("navigating to %s\n", debugstr_w(url)); if((Flags && V_VT(Flags) != VT_EMPTY && V_VT(Flags) != VT_ERROR) || (TargetFrameName && V_VT(TargetFrameName) != VT_EMPTY && V_VT(TargetFrameName) != VT_ERROR)) FIXME("Unsupported args (Flags %s; TargetFrameName %s)\n", debugstr_variant(Flags), debugstr_variant(TargetFrameName)); if(PostData) { if(V_VT(PostData) & VT_ARRAY) post_array = V_ISBYREF(PostData) ? *V_ARRAYREF(PostData) : V_ARRAY(PostData); else WARN("Invalid post data %s\n", debugstr_variant(PostData)); } if(post_array) { LONG elem_max; SafeArrayAccessData(post_array, (void**)&post_data); SafeArrayGetUBound(post_array, 1, &elem_max); post_data_len = (elem_max+1) * SafeArrayGetElemsize(post_array); } if(Headers && V_VT(Headers) == VT_BSTR) { headers = V_BSTR(Headers); TRACE("Headers: %s\n", debugstr_w(headers)); } set_doc_state(This, READYSTATE_LOADING); This->ready_state = READYSTATE_LOADING; if(This->doc_navigate) { WCHAR new_url[INTERNET_MAX_URL_LENGTH]; if(PathIsURLW(url)) { new_url[0] = 0; }else { DWORD size; size = sizeof(new_url)/sizeof(WCHAR); hres = UrlApplySchemeW(url, new_url, &size, URL_APPLY_GUESSSCHEME | URL_APPLY_GUESSFILE | URL_APPLY_DEFAULT); if(FAILED(hres)) { WARN("UrlApplyScheme failed: %08x\n", hres); new_url[0] = 0; } } hres = async_doc_navigate(This, *new_url ? new_url : url, headers, post_data, post_data_len, TRUE); }else { task_navigate_bsc_t *task; task = heap_alloc(sizeof(*task)); task->bsc = create_callback(This, url, post_data, post_data_len, headers); push_dochost_task(This, &task->header, navigate_bsc_proc, navigate_bsc_task_destr, This->url == NULL); } if(post_data) SafeArrayUnaccessData(post_array); return hres; }
static void putOutVariant (Tcl_Interp *interp, VARIANT *pDest, TclObject &tclObject, const Type &type) { switch (type.vartype()) { case VT_BOOL: *V_BOOLREF(pDest) = tclObject.getBool() ? VARIANT_TRUE : VARIANT_FALSE; break; case VT_R4: *V_R4REF(pDest) = static_cast<float>(tclObject.getDouble()); break; case VT_R8: *V_R8REF(pDest) = tclObject.getDouble(); break; case VT_DISPATCH: case VT_UNKNOWN: case VT_USERDEFINED: { IUnknown *pUnknown; Tcl_Obj *pObj = tclObject; if (pObj->typePtr == &Extension::unknownPointerType) { pUnknown = static_cast<IUnknown *>(pObj->internalRep.otherValuePtr); } else { Reference *pRef = Extension::referenceHandles.find( interp, tclObject); pUnknown = (pRef == 0) ? 0 : pRef->unknown(); } *V_UNKNOWNREF(pDest) = pUnknown; // The COM rules say we must increment the reference count of // interface pointers returned from methods. if (pUnknown != 0) { pUnknown->AddRef(); } } break; case VT_BSTR: *V_BSTRREF(pDest) = tclObject.getBSTR(); break; case VT_VARIANT: { // Must increment reference count of interface pointers returned // from methods. tclObject.toVariant( V_VARIANTREF(pDest), Type::variant(), interp, true); } break; case VT_SAFEARRAY: if (*V_ARRAYREF(pDest) != 0) { SafeArrayDestroy(*V_ARRAYREF(pDest)); } *V_ARRAYREF(pDest) = tclObject.getSafeArray(type.elementType(), interp); break; default: *V_I4REF(pDest) = tclObject.getLong(); } }
PyObject *PyRecord::getattro(PyObject *self, PyObject *obname) { PyObject *res; PyRecord *pyrec = (PyRecord *)self; char *name=PYWIN_ATTR_CONVERT(obname); if (name==NULL) return NULL; if (strcmp(name, "__members__")==0) { ULONG cnames = 0; HRESULT hr = pyrec->pri->GetFieldNames(&cnames, NULL); if (FAILED(hr)) return PyCom_BuildPyException(hr, pyrec->pri, IID_IRecordInfo); BSTR *strs = (BSTR *)malloc(sizeof(BSTR) * cnames); if (strs==NULL) return PyErr_NoMemory(); hr = pyrec->pri->GetFieldNames(&cnames, strs); if (FAILED(hr)) { free(strs); return PyCom_BuildPyException(hr, pyrec->pri, IID_IRecordInfo); } res = PyList_New(cnames); for (ULONG i=0;i<cnames && res != NULL;i++) { PyObject *item = PyWinCoreString_FromString(strs[i]); SysFreeString(strs[i]); if (item==NULL) { Py_DECREF(res); res = NULL; } else PyList_SET_ITEM(res, i, item); // ref count swallowed. } free(strs); return res; } res = PyObject_GenericGetAttr(self, obname); if (res != NULL) return res; PyErr_Clear(); WCHAR *wname; if (!PyWinObject_AsWCHAR(obname, &wname)) return NULL; VARIANT vret; VariantInit(&vret); void *sub_data = NULL; PY_INTERFACE_PRECALL; HRESULT hr = pyrec->pri->GetFieldNoCopy(pyrec->pdata, wname, &vret, &sub_data); PyWinObject_FreeWCHAR(wname); PY_INTERFACE_POSTCALL; if (FAILED(hr)) { if (hr == TYPE_E_FIELDNOTFOUND){ // This is slightly suspect - throwing a unicode // object for an AttributeError in py2k - but this // is the value we asked COM for, so it makes sense... // (and PyErr_Format doesn't handle unicode in py2x) PyErr_SetObject(PyExc_AttributeError, obname); return NULL; } return PyCom_BuildPyException(hr, pyrec->pri, IID_IRecordInfo); } // Short-circuit sub-structs and arrays here, so we dont allocate a new chunk // of memory and copy it - we need sub-structs to persist. if (V_VT(&vret)==(VT_BYREF | VT_RECORD)) return new PyRecord(V_RECORDINFO(&vret), V_RECORD(&vret), pyrec->owner); else if (V_VT(&vret)==(VT_BYREF | VT_ARRAY | VT_RECORD)) { SAFEARRAY *psa = *V_ARRAYREF(&vret); int d = SafeArrayGetDim(psa); if (sub_data==NULL) return PyErr_Format(PyExc_RuntimeError, "Did not get a buffer for the array!"); if (SafeArrayGetDim(psa) != 1) return PyErr_Format(PyExc_TypeError, "Only support single dimensional arrays of records"); IRecordInfo *sub = NULL; long ubound, lbound, nelems; int i; BYTE *this_data; PyObject *ret_tuple = NULL; ULONG element_size = 0; hr = SafeArrayGetUBound(psa, 1, &ubound); if (FAILED(hr)) goto array_end; hr = SafeArrayGetLBound(psa, 1, &lbound); if (FAILED(hr)) goto array_end; hr = SafeArrayGetRecordInfo(psa, &sub); if (FAILED(hr)) goto array_end; hr = sub->GetSize(&element_size); if (FAILED(hr)) goto array_end; nelems = ubound-lbound; ret_tuple = PyTuple_New(nelems); if (ret_tuple==NULL) goto array_end; this_data = (BYTE *)sub_data; for (i=0;i<nelems;i++) { PyTuple_SET_ITEM(ret_tuple, i, new PyRecord(sub, this_data, pyrec->owner)); this_data += element_size; } array_end: if (sub) sub->Release(); if (FAILED(hr)) return PyCom_BuildPyException(hr, pyrec->pri, IID_IRecordInfo); return ret_tuple; } // This default conversion we use is a little slow (but it will do!) // For arrays, the pparray->pvData member is *not* set, since the actual data // pointer from the record is returned in sub_data, so set it here. if (V_ISARRAY(&vret) && V_ISBYREF(&vret)) (*V_ARRAYREF(&vret))->pvData = sub_data; PyObject *ret = PyCom_PyObjectFromVariant(&vret); // VariantClear(&vret); return ret; }
static void ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt) { V_VT(var) = vt; if (vt == (VT_VARIANT|VT_BYREF)) { V_VARIANTREF(var) = realvar; } else { if (V_VT(realvar) != (vt & ~VT_BYREF)) { rb_raise(eWIN32OLERuntimeError, "variant type mismatch"); } switch(vt & ~VT_BYREF) { case VT_I1: V_I1REF(var) = &V_I1(realvar); break; case VT_UI1: V_UI1REF(var) = &V_UI1(realvar); break; case VT_I2: V_I2REF(var) = &V_I2(realvar); break; case VT_UI2: V_UI2REF(var) = &V_UI2(realvar); break; case VT_I4: V_I4REF(var) = &V_I4(realvar); break; case VT_UI4: V_UI4REF(var) = &V_UI4(realvar); break; case VT_R4: V_R4REF(var) = &V_R4(realvar); break; case VT_R8: V_R8REF(var) = &V_R8(realvar); break; #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) #ifdef V_I8REF case VT_I8: V_I8REF(var) = &V_I8(realvar); break; #endif #ifdef V_UI8REF case VT_UI8: V_UI8REF(var) = &V_UI8(realvar); break; #endif #endif case VT_INT: V_INTREF(var) = &V_INT(realvar); break; case VT_UINT: V_UINTREF(var) = &V_UINT(realvar); break; case VT_CY: V_CYREF(var) = &V_CY(realvar); break; case VT_DATE: V_DATEREF(var) = &V_DATE(realvar); break; case VT_BSTR: V_BSTRREF(var) = &V_BSTR(realvar); break; case VT_DISPATCH: V_DISPATCHREF(var) = &V_DISPATCH(realvar); break; case VT_ERROR: V_ERRORREF(var) = &V_ERROR(realvar); break; case VT_BOOL: V_BOOLREF(var) = &V_BOOL(realvar); break; case VT_UNKNOWN: V_UNKNOWNREF(var) = &V_UNKNOWN(realvar); break; case VT_ARRAY: V_ARRAYREF(var) = &V_ARRAY(realvar); break; default: rb_raise(eWIN32OLERuntimeError, "unknown type specified(setting BYREF):%d", vt); break; } } }
static void ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar) { HRESULT hr = S_OK; if (((vt & ~VT_BYREF) == (VT_ARRAY | VT_UI1)) && RB_TYPE_P(val, T_STRING)) { long len = RSTRING_LEN(val); void *pdest = NULL; SAFEARRAY *p = NULL; SAFEARRAY *psa = SafeArrayCreateVector(VT_UI1, 0, len); if (!psa) { rb_raise(rb_eRuntimeError, "fail to SafeArrayCreateVector"); } hr = SafeArrayAccessData(psa, &pdest); if (SUCCEEDED(hr)) { memcpy(pdest, RSTRING_PTR(val), len); SafeArrayUnaccessData(psa); V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF); p = V_ARRAY(&(pvar->realvar)); if (p != NULL) { SafeArrayDestroy(p); } V_ARRAY(&(pvar->realvar)) = psa; if (vt & VT_BYREF) { V_VT(&(pvar->var)) = vt; V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar))); } else { hr = VariantCopy(&(pvar->var), &(pvar->realvar)); } } else { if (psa) SafeArrayDestroy(psa); } } else if (vt & VT_ARRAY) { if (val == Qnil) { V_VT(&(pvar->var)) = vt; if (vt & VT_BYREF) { V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar))); } } else { hr = ole_val_ary2variant_ary(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF)); if (SUCCEEDED(hr)) { if (vt & VT_BYREF) { V_VT(&(pvar->var)) = vt; V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar))); } else { hr = VariantCopy(&(pvar->var), &(pvar->realvar)); } } } #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) } else if ( (vt & ~VT_BYREF) == VT_I8 || (vt & ~VT_BYREF) == VT_UI8) { ole_val2variant_ex(val, &(pvar->realvar), (vt & ~VT_BYREF)); ole_val2variant_ex(val, &(pvar->var), (vt & ~VT_BYREF)); V_VT(&(pvar->var)) = vt; if (vt & VT_BYREF) { ole_set_byref(&(pvar->realvar), &(pvar->var), vt); } #endif } else if ( (vt & ~VT_BYREF) == VT_ERROR) { ole_val2variant_err(val, &(pvar->realvar)); if (vt & VT_BYREF) { ole_set_byref(&(pvar->realvar), &(pvar->var), vt); } else { hr = VariantCopy(&(pvar->var), &(pvar->realvar)); } } else { if (val == Qnil) { V_VT(&(pvar->var)) = vt; if (vt == (VT_BYREF | VT_VARIANT)) { ole_set_byref(&(pvar->realvar), &(pvar->var), vt); } else { V_VT(&(pvar->realvar)) = vt & ~VT_BYREF; if (vt & VT_BYREF) { ole_set_byref(&(pvar->realvar), &(pvar->var), vt); } } } else { ole_val2variant_ex(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF)); if (vt == (VT_BYREF | VT_VARIANT)) { ole_set_byref(&(pvar->realvar), &(pvar->var), vt); } else if (vt & VT_BYREF) { if ( (vt & ~VT_BYREF) != V_VT(&(pvar->realvar))) { hr = VariantChangeTypeEx(&(pvar->realvar), &(pvar->realvar), cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF)); } if (SUCCEEDED(hr)) { ole_set_byref(&(pvar->realvar), &(pvar->var), vt); } } else { if (vt == V_VT(&(pvar->realvar))) { hr = VariantCopy(&(pvar->var), &(pvar->realvar)); } else { hr = VariantChangeTypeEx(&(pvar->var), &(pvar->realvar), cWIN32OLE_lcid, 0, vt); } } } } if (FAILED(hr)) { ole_raise(hr, eWIN32OLERuntimeError, "failed to change type"); } }