/* * Copyright (c) 1999-2004 Sourceforge JACOB Project. * All rights reserved. Originator: Dan Adler (http://danadler.com). * Get more information about JACOB at http://sourceforge.net/projects/jacob-project * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "stdafx.h" #include "Variant.h" // Win32 support for Ole Automation #include #include #include #include #include #include #include "util.h" extern "C" { #define VARIANT_FLD "m_pVariant" // extract a VARIANT from a Variant object VARIANT *extractVariant(JNIEnv *env, jobject arg) { jclass argClass = env->GetObjectClass(arg); jfieldID ajf = env->GetFieldID( argClass, VARIANT_FLD, "I"); jint anum = env->GetIntField(arg, ajf); VARIANT *v = (VARIANT *)anum; return v; } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_release (JNIEnv *env, jobject _this) { jclass clazz = env->GetObjectClass(_this); jfieldID jf = env->GetFieldID(clazz, VARIANT_FLD, "I"); VARIANT *v = extractVariant(env, _this); if (v) { // fix byref leak if (V_VT(v) & VT_BYREF) // is this a reference { void *pMem = V_BSTRREF(v); // get allocated memory if (pMem) { if (V_VT(v) == (VT_BYREF|VT_BSTR)) { BSTR *pBstr = (BSTR*)pMem; if (*pBstr) SysFreeString(*pBstr);// release bstr } CoTaskMemFree(pMem); } } VariantClear(v); delete v; env->SetIntField(_this, jf, (unsigned int)0); } } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_init (JNIEnv *env, jobject _this) { jclass clazz = env->GetObjectClass(_this); jfieldID jf = env->GetFieldID( clazz, VARIANT_FLD, "I"); VARIANT *v = new VARIANT(); VariantInit(v); env->SetIntField(_this, jf, (unsigned int)v); } /* * Class: com_jacob_com_Variant * Method: zeroVariant * Signature: ()V * * This should only be used on variant objects created by teh * com layer as part of a call through EventProxy. * This zeros out the variant pointer in the Variant object * so that the calling COM program can free the memory. * instead of both the COM program and the Java GC doing it. */ void zeroVariant(JNIEnv *env, jobject _this) { jclass clazz = env->GetObjectClass(_this); jfieldID jf = env->GetFieldID(clazz, VARIANT_FLD, "I"); env->SetIntField(_this, jf, (unsigned int)0); } /** * This is the core of the old Save method. * It copies this variant to a byte stream. * The unmarshalling part of this doesn't work but it was left in * with the hope that someone will want to fix this later **/ JNIEXPORT jbyteArray JNICALL Java_com_jacob_com_Variant_SerializationWriteToBytes (JNIEnv *env, jobject _this){ VARIANT *v = extractVariant(env, _this); if (v) { DWORD flags = MSHCTX_LOCAL; jint size = VARIANT_UserSize(&flags, 0L, v); // allocate a byte array of the right length jbyte* pBuf = new jbyte[size]; // clear it out ZeroMemory(pBuf, size); // marshall the Variant into the buffer VARIANT_UserMarshal(&flags, (unsigned char *)pBuf, v); // need to convert the buffer to a java byte ba[] jbyteArray ba = env->NewByteArray(size); env->SetByteArrayRegion(ba, 0, size, pBuf); // and delete the original memory delete [] pBuf; return ba; } else { jbyteArray ba = env->NewByteArray(0); return ba; } } /** * This is the core of the old Load method. It is broken because the * unmarshalling code doesn't work under 2000/XP. * * It probably needs a custom handler. **/ JNIEXPORT void JNICALL Java_com_jacob_com_Variant_SerializationReadFromBytes (JNIEnv *env, jobject _this, jbyteArray ba){ VARIANT *v = extractVariant(env, _this); if (v){ // get a buffer from it jbyte *pBuf = env->GetByteArrayElements(ba, 0); // unmarshall the Variant from the buffer DWORD flags = MSHCTX_LOCAL; printf("about to unmarshall array elements\n"); VARIANT_UserUnmarshal(&flags, (unsigned char *)pBuf, v); // release the byte array printf("about to release array elements\n"); env->ReleaseByteArrayElements(ba, pBuf, 0); } } /** * Converts the data to a Enum Variant object and then returns it as a Dispatch */ JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_toEnumVariant (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { HRESULT hr; if (FAILED(hr = VariantChangeType(v, v, 0, VT_UNKNOWN))) { ThrowComFail(env, "VariantChangeType failed", hr); return NULL; } jclass autoClass = env->FindClass("com/jacob/com/EnumVariant"); jmethodID autoCons = env->GetMethodID(autoClass, "", "(I)V"); // construct an Unknown object to return IUnknown *unk = V_UNKNOWN(v); IEnumVARIANT *ie; hr = unk->QueryInterface(IID_IEnumVARIANT, (void **)&ie); if (FAILED(hr)) { ThrowComFail(env, "[toEnumVariant]: Object does not implement IEnumVariant", hr); return NULL; } // I am copying the pointer to java if (ie) ie->AddRef(); jobject newAuto = env->NewObject(autoClass, autoCons, ie); return newAuto; } return NULL; } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantNull (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before V_VT(v) = VT_NULL; } } JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_cloneIndirect (JNIEnv *env, jobject _this) { return NULL; } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantShortRef (JNIEnv *env, jobject _this, jshort s) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before short *ps = (short *)CoTaskMemAlloc(sizeof(short)); *ps = s; V_VT(v) = VT_I2|VT_BYREF; V_I2REF(v) = ps; } } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantIntRef (JNIEnv *env, jobject _this, jint s) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before long *ps = (long *)CoTaskMemAlloc(sizeof(long)); *ps = s; V_VT(v) = VT_I4|VT_BYREF; V_I4REF(v) = ps; } } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDoubleRef (JNIEnv *env, jobject _this, jdouble s) { VARIANT *v = extractVariant(env, _this); if (v) { double *ps = (double *)CoTaskMemAlloc(sizeof(double)); *ps = s; V_VT(v) = VT_R8|VT_BYREF; V_R8REF(v) = ps; } } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDateRef (JNIEnv *env, jobject _this, jdouble s) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before double *ps = (double *)CoTaskMemAlloc(sizeof(double)); *ps = s; V_VT(v) = VT_DATE|VT_BYREF; V_DATEREF(v) = ps; } } // SF 1065533 added unicode support JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantStringRef (JNIEnv *env, jobject _this, jstring s) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before const jchar *cStr = env->GetStringChars(s,NULL); // SF 1314116 // DBeck: 2005-09-23: changed CComBSTR c-tor to accept // Unicode string (no terminating NULL) provided by GetStringChars const jsize numChars = env->GetStringLength(s); //CComBSTR bs(cStr); CComBSTR bs( numChars, cStr ); BSTR *pbs = (BSTR *)CoTaskMemAlloc(sizeof(BSTR)); bs.CopyTo(pbs); V_VT(v) = VT_BSTR|VT_BYREF; V_BSTRREF(v) = pbs; env->ReleaseStringChars(s,cStr); } } JNIEXPORT jshort JNICALL Java_com_jacob_com_Variant_getVariantShortRef (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { if (V_VT(v) != (VT_I2|VT_BYREF)) { return NULL; } return (jshort)*V_I2REF(v); } return NULL; } JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getVariantIntRef (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { if (V_VT(v) != (VT_I4|VT_BYREF)) { return NULL; } return (jint)*V_I4REF(v); } return NULL; } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantShort (JNIEnv *env, jobject _this, jshort s) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before V_VT(v) = VT_I2; V_I2(v) = (short)s; } } JNIEXPORT jshort JNICALL Java_com_jacob_com_Variant_getVariantShort (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { if (V_VT(v) != VT_I2) { return NULL; } return (jshort)V_I2(v); } return NULL; } JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getVariantDoubleRef (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { if (V_VT(v) != (VT_R8|VT_BYREF)) { return NULL; } return (jdouble)*V_R8REF(v); } return NULL; } JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getVariantDateRef (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { if (V_VT(v) != (VT_DATE|VT_BYREF)) { return NULL; } return (jdouble)*V_DATEREF(v); } return NULL; } JNIEXPORT jstring JNICALL Java_com_jacob_com_Variant_getVariantStringRef (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { if (V_VT(v) != (VT_BSTR|VT_BYREF)) { return NULL; } BSTR *bs = V_BSTRREF(v); jstring js = env->NewString(*bs, SysStringLen(*bs)); return js; } return NULL; } /** * cover for underlying C VariantClear function */ JNIEXPORT void JNICALL Java_com_jacob_com_Variant_VariantClear (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); } } /** * Converts the data to a Dispatch object and then returns it as a Dispatch */ JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_toVariantDispatch (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { HRESULT hr; if (FAILED(hr = VariantChangeType(v, v, 0, VT_DISPATCH))) { ThrowComFail(env, "VariantChangeType failed", hr); return NULL; } jclass autoClass = env->FindClass("com/jacob/com/Dispatch"); jmethodID autoCons = env->GetMethodID(autoClass, "", "(I)V"); // construct a Dispatch object to return IDispatch *disp = V_DISPATCH(v); // I am copying the pointer to java if (disp) disp->AddRef(); jobject newAuto = env->NewObject(autoClass, autoCons, disp); return newAuto; } return NULL; } JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_clone (JNIEnv *env, jobject _this) { return NULL; } /** * Returns the value of this int as a Boolea if it is of that type. * Otherwise it will return null (no conversion done) */ JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getVariantInt (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { if (V_VT(v) != VT_I4) { return NULL; } return (jint)V_I4(v); } return NULL; } /** * Returns the value of this Date as a Boolea if it is of that type. * Otherwise it will return null (no conversion done) */ JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getVariantDate (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { if (V_VT(v) != VT_DATE) { return NULL; } return (jdouble)V_DATE(v); } return NULL; } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantInt (JNIEnv *env, jobject _this, jint i) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before V_VT(v) = VT_I4; V_I4(v) = (int)i; } } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDate (JNIEnv *env, jobject _this, jdouble date) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before V_VT(v) = VT_DATE; V_DATE(v) = date; } } /** * Returns the value of this Variant as a Boolea if it is of that type. * Otherwise it will return null (no conversion done) */ JNIEXPORT jboolean JNICALL Java_com_jacob_com_Variant_getVariantBoolean (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { if (V_VT(v) != (VT_BOOL)) { return NULL; } return (jboolean)V_BOOL(v); } return NULL; } /** * Returns the value of this Variant as a Byte if it is of that type. * Otherwise it will return null (no conversion done) */ JNIEXPORT jbyte JNICALL Java_com_jacob_com_Variant_getVariantByte (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { if (V_VT(v) != (VT_UI1)) { return NULL; } return (jbyte)V_UI1(v); } return NULL; } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantBoolean (JNIEnv *env, jobject _this, jboolean b) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before V_VT(v) = VT_BOOL; V_BOOL(v) = b == JNI_TRUE ? VARIANT_TRUE : VARIANT_FALSE; } else ThrowComFail(env, "putVariantBoolean failed", -1); } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantByte (JNIEnv *env, jobject _this, jbyte b) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before V_VT(v) = VT_UI1; V_UI1(v) = b; } else ThrowComFail(env, "putVariantByte failed", -1); } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantEmpty (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before V_VT(v) = VT_EMPTY; } } /** * Sets the variant type to dispatch with no value object **/ JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantNothing (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before V_VT(v) = VT_DISPATCH; } } JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getVariantError (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { if (V_VT(v) != VT_ERROR) { return NULL; } return (jint)V_ERROR(v); } return NULL; } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantError (JNIEnv *env, jobject _this, jint i) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before V_VT(v) = VT_ERROR; V_ERROR(v) = (int)i; } } /** * Returns the value of this Variant as a double if it is of that type. * Otherwise it will return null (no conversion done) */ JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getVariantDouble (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { if (V_VT(v) != VT_R8) { return NULL; } return (jdouble)V_R8(v); } return NULL; } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantCurrency (JNIEnv *env, jobject _this, jlong cur) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before CY pf; pf.int64 = (LONGLONG)cur; V_VT(v) = VT_CY; V_CY(v) = pf; } else ThrowComFail(env, "putVariantCurrency failed", -1); } /** * Accepts a dispatch object and sets the type to VT_DISPATCH. * There is currently no way to pass NULL into this method * to create something like "NOTHING" from VB * */ JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDispatch (JNIEnv *env, jobject _this, jobject _that) { VARIANT *v = extractVariant(env, _this); IDispatch *disp = extractDispatch(env, _that); if (disp && v) { VariantClear(v); // whatever was there before V_VT(v) = VT_DISPATCH; V_DISPATCH(v) = disp; // I am handing the pointer to COM disp->AddRef(); } else ThrowComFail(env, "putObject failed", -1); } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDouble (JNIEnv *env, jobject _this, jdouble d) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before V_VT(v) = VT_R8; V_R8(v) = (double)d; } } /** * Returns the value of this Variant as a long if it is of that type. * Otherwise it will return null (no conversion done) */ JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantCurrency (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { if (V_VT(v) != VT_CY) { return NULL; } CY cy; cy = V_CY(v); jlong jl; memcpy(&jl, &cy, 64); return jl; } return NULL; } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantFloatRef (JNIEnv *env, jobject _this, jfloat val) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before float *pf = (float *)CoTaskMemAlloc(sizeof(float)); *pf = val; V_VT(v) = VT_R4|VT_BYREF; V_R4REF(v) = pf; } } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantCurrencyRef (JNIEnv *env, jobject _this, jlong cur) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before CY *pf = (CY *)CoTaskMemAlloc(sizeof(CY)); memcpy(pf, &cur, 64); V_VT(v) = VT_BYREF|VT_CY; V_CYREF(v) = pf; } } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantErrorRef (JNIEnv *env, jobject _this, jint i) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before V_VT(v) = VT_ERROR|VT_BYREF; V_ERROR(v) = (int)i; } } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantBooleanRef (JNIEnv *env, jobject _this, jboolean b) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before VARIANT_BOOL *br = (VARIANT_BOOL *)CoTaskMemAlloc(sizeof(VARIANT_BOOL)); *br = b ? VARIANT_TRUE : VARIANT_FALSE; V_VT(v) = VT_BOOL|VT_BYREF; V_BOOLREF(v) = br; } } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantByteRef (JNIEnv *env, jobject _this, jbyte b) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before unsigned char *br = (unsigned char *)CoTaskMemAlloc(sizeof(char)); *br = b; V_VT(v) = VT_UI1|VT_BYREF; V_UI1REF(v) = br; } } /** * Returns the value of this Variant as a String if it is of that type. * Otherwise it will return null (no conversion done) */ JNIEXPORT jstring JNICALL Java_com_jacob_com_Variant_getVariantString (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { if (V_VT(v) != VT_BSTR) { return NULL; } BSTR bs = V_BSTR(v); jstring js = env->NewString(bs, SysStringLen(bs)); return js; } return NULL; } /** * SF 1065533 added unicode support * */ JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantString (JNIEnv *env, jobject _this, jstring s) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before V_VT(v) = VT_BSTR; const jchar *cStr = env->GetStringChars(s,NULL); // SF 1314116 // DBeck: 2005-09-23: changed CComBSTR c-tor to accept // Unicode string (no terminating NULL) provided by GetStringChars const jsize numChars = env->GetStringLength(s); //CComBSTR bs(cStr); CComBSTR bs( numChars, cStr ); V_VT(v) = VT_BSTR; V_BSTR(v) = bs.Copy(); env->ReleaseStringChars(s,cStr); } } JNIEXPORT jfloat JNICALL Java_com_jacob_com_Variant_getVariantFloatRef (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { if (V_VT(v) != (VT_R4|VT_BYREF)) { return NULL; } return (jfloat)*V_R4REF(v); } return NULL; } JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantCurrencyRef (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { if (V_VT(v) != (VT_CY|VT_BYREF)) { return NULL; } CY *cy; cy = V_CYREF(v); jlong jl; memcpy(&jl, cy, 64); return jl; } return NULL; } JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getVariantErrorRef (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { if (V_VT(v) != (VT_ERROR|VT_BYREF)) { return NULL; } return (jint)V_ERROR(v); } return NULL; } JNIEXPORT jboolean JNICALL Java_com_jacob_com_Variant_getVariantBooleanRef (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { if (V_VT(v) != (VT_BOOL|VT_BYREF)) { return NULL; } return (jboolean)*V_BOOLREF(v); } return NULL; } JNIEXPORT jbyte JNICALL Java_com_jacob_com_Variant_getVariantByteRef (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { if (V_VT(v) != (VT_UI1|VT_BYREF)) { return NULL; } return (jbyte)*V_UI1REF(v); } return NULL; } /** * Converts the data to a Safe Array object and then returns it as a Dispatch */ JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_toVariantSafeArray (JNIEnv *env, jobject _this, jboolean deepCopy) { VARIANT *v = extractVariant(env, _this); if (v) { if ((V_VT(v) & VT_ARRAY) == 0) { ThrowComFail(env, "Variant not array", -1); return NULL; } // prepare a new sa obj jclass saClass = env->FindClass("com/jacob/com/SafeArray"); jmethodID saCons = env->GetMethodID(saClass, "", "()V"); // construct an SA to return jobject newSA = env->NewObject(saClass, saCons); // pass in the deep copy indicator setSA(env, newSA, V_ARRAY(v), deepCopy == JNI_TRUE ? 1 : 0); return newSA; } return NULL; } JNIEXPORT void JNICALL Java_com_jacob_com_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; } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantSafeArray (JNIEnv *env, jobject _this, jobject sa) { SAFEARRAY *psa = extractSA(env, sa); if (psa) { VARIANT *v = extractVariant(env, _this); if (v) { VARTYPE vt; SafeArrayGetVartype(psa, &vt); V_VT(v) = VT_ARRAY | vt; V_ARRAY(v) = copySA(psa); return; } ThrowComFail(env, "Can't get variant pointer", -1); return; } ThrowComFail(env, "Can't get sa pointer", -1); return; } /** * sets the type to VT_ERROR and the error message to DISP_E_PARAMNOTFOIUND * */ JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantNoParam (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { V_VT(v) = VT_ERROR; V_ERROR(v) = DISP_E_PARAMNOTFOUND; } } /** * Returns the value of this Variant as a Float if it is of that type. * Otherwise it will return null (no conversion done) */ JNIEXPORT jfloat JNICALL Java_com_jacob_com_Variant_getVariantFloat (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { if (V_VT(v) != (VT_R4)) { return NULL; } return (jfloat)V_R4(v); } return NULL; } JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantFloat (JNIEnv *env, jobject _this, jfloat val) { VARIANT *v = extractVariant(env, _this); if (v) { VariantClear(v); // whatever was there before V_VT(v) = VT_R4; V_R4(v) = val; } } /** * changes the type of the underlying variant data * */ JNIEXPORT void JNICALL Java_com_jacob_com_Variant_changeVariantType (JNIEnv *env, jobject _this, jshort t) { VARIANT *v = extractVariant(env, _this); if (v) { VariantChangeType(v, v, 0, t); } } /** * returns the variant type if it is set, otherwise * returns null * */ JNIEXPORT jshort JNICALL Java_com_jacob_com_Variant_getVariantType (JNIEnv *env, jobject _this) { VARIANT *v = extractVariant(env, _this); if (v) { return (jshort)V_VT(v); } return NULL; } // removed Java_com_jacob_com_Variant_putSafeArrayRefHelper /** * 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_jacob_com_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; } }