Files
jlibcom/jni/Variant.cpp
clay_shooter 0b16b2eeae SF1570270 Proxy unhook detatched threads.
SF1538011 toString() not compliant, large ripple into toXXX() methods
SF1478172 Variant jni methods public without protection.  Now JNI methods behind java methods
2006-10-04 03:18:59 +00:00

1015 lines
26 KiB
C++

/*
* 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 <wchar.h>
#include <string.h>
#include <atlbase.h>
#include <objbase.h>
#include <oleauto.h>
#include <olectl.h>
#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, "<init>", "(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, "<init>", "(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, "<init>", "()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;
}
}