1218 lines
32 KiB
C++
1218 lines
32 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 the
|
|
* 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
|
|
// SF-1674179 fix EnumVariants memory leak
|
|
// AJ: yes, but the QueryInterface call above already incremented the reference
|
|
//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, (LPCOLESTR)cStr ); // SR cast SF 1689061
|
|
|
|
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((jchar*)*bs, SysStringLen(*bs)); // SR cast SF 1689061
|
|
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, sizeof(jl)); // was 64. should be sizeof(x) SF 1690420
|
|
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, sizeof(*pf)); // was 64. should be sizeof(x) SF 1690420
|
|
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((jchar*)bs, SysStringLen(bs));// SR cast SF 1689061
|
|
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, (LPCOLESTR)cStr ); // SR cast SF 1689061
|
|
|
|
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, sizeof(jl)); // was 64. should be sizeof(x) SF 1690420
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* Puts a variant into a the Variant as its data and sets the type
|
|
* to VT_VARIANT|VT_BYREF.
|
|
* Added 1.12 pre 6
|
|
*
|
|
* */
|
|
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantVariant
|
|
(JNIEnv *env, jobject _this, jobject var)
|
|
{
|
|
|
|
VARIANT *vVar = extractVariant(env, var);
|
|
VARIANT *v = extractVariant(env, _this);
|
|
|
|
if (v) {
|
|
VariantClear(v); // whatever was there before
|
|
|
|
V_VT(v) = VT_VARIANT|VT_BYREF;
|
|
V_VARIANTREF(v) = vVar;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* retrieves the enclosed variant when they are of type VT_VARIANT
|
|
* Added 1.12 pre 6
|
|
*
|
|
* */
|
|
JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getVariantVariant
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
|
|
if (V_VT(v) != (VT_VARIANT|VT_BYREF)) {
|
|
return NULL;
|
|
}
|
|
|
|
VARIANT *refVar = V_VARIANTREF(v);
|
|
|
|
// we could have made a copy of refV here but we aren't every going to free
|
|
// it outside of the scope of the enclosing context so we will just used the
|
|
// enclosed. This relies on the java layer to zero out its ref to this
|
|
// enclosed variant before the gc can come along and free the memory out from
|
|
// under this enclosing variant.
|
|
return (unsigned int)refVar;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* puts a VT_DECIMAL by reference
|
|
* Added 1.13M4
|
|
* */
|
|
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDecRef
|
|
(JNIEnv *env, jobject _this, jint signum, jint scale, jint lo, jint mid, jint hi)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
VariantClear(v); // whatever was there before
|
|
DECIMAL *pd = (DECIMAL *)CoTaskMemAlloc(sizeof(DECIMAL));
|
|
pd->scale = scale;
|
|
pd->sign = signum == 1?0:0x80;
|
|
pd->Hi32 = hi;
|
|
pd->Mid32 = mid;
|
|
pd->Lo32 = lo;
|
|
V_VT(v) = VT_DECIMAL | VT_BYREF;
|
|
V_DECIMALREF(v) = pd;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* puts a VT_DECIMAL
|
|
* Added 1.13M4
|
|
* */
|
|
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDec
|
|
(JNIEnv *env, jobject _this, jint signum, jint scale, jint lo, jint mid, jint hi)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
DECIMAL *d;
|
|
if (v) {
|
|
VariantClear(v); // whatever was there before
|
|
d = (DECIMAL*)v;
|
|
d->scale = scale;
|
|
d->sign = signum == 1?0:0x80;
|
|
d->Hi32 = hi;
|
|
d->Mid32 = mid;
|
|
d->Lo32 = lo;
|
|
V_VT(v) = VT_DECIMAL;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* utility method used by the getVariantXXX() methods to convert VT_DECIMAL to BigDecimal
|
|
* */
|
|
jobject extractDecimal
|
|
(JNIEnv *env, DECIMAL* d)
|
|
{
|
|
jclass bigIntegerClass;
|
|
jclass bigDecimalClass;
|
|
jobject integer;
|
|
jmethodID bigIntegerConstructor;
|
|
jmethodID bigDecimalConstructor;
|
|
jbyteArray bArray;
|
|
jobject result = NULL;
|
|
jbyte* buffer;
|
|
|
|
bigIntegerClass = env->FindClass("java/math/BigInteger");
|
|
if (bigIntegerClass == NULL)
|
|
return NULL;
|
|
bigDecimalClass = env->FindClass("java/math/BigDecimal");
|
|
if (bigDecimalClass == NULL) {
|
|
env->DeleteLocalRef(bigIntegerClass);
|
|
return NULL;
|
|
}
|
|
|
|
bigIntegerConstructor = env->GetMethodID(bigIntegerClass, "<init>", "(I[B)V");
|
|
if (bigIntegerConstructor == NULL) {
|
|
env->DeleteLocalRef(bigIntegerClass);
|
|
env->DeleteLocalRef(bigDecimalClass);
|
|
return NULL;
|
|
}
|
|
bigDecimalConstructor = env->GetMethodID(bigDecimalClass, "<init>", "(Ljava/math/BigInteger;I)V");
|
|
if (bigIntegerConstructor == NULL) {
|
|
env->DeleteLocalRef(bigIntegerClass);
|
|
env->DeleteLocalRef(bigDecimalClass);
|
|
return NULL;
|
|
}
|
|
bArray = env->NewByteArray(12);
|
|
if (bArray == NULL) {
|
|
env->DeleteLocalRef(bigIntegerClass);
|
|
env->DeleteLocalRef(bigDecimalClass);
|
|
return NULL;
|
|
}
|
|
/* Unfortunately the byte ordering is completely wrong, so we remap it into buffer */
|
|
buffer = (jbyte*)malloc(12);
|
|
buffer[11] = d->Lo32 & 255;
|
|
buffer[10] = (d->Lo32 >> 8) & 255;
|
|
buffer[9] = (d->Lo32 >> 16) & 255;;
|
|
buffer[8] = (d->Lo32 >> 24) & 255;;
|
|
buffer[7] = (d->Mid32) & 255;;
|
|
buffer[6] = (d->Mid32 >> 8) & 255;
|
|
buffer[5] = (d->Mid32 >> 16) & 255;
|
|
buffer[4] = (d->Mid32 >> 24) & 255;
|
|
buffer[3] = (d->Hi32) & 255;
|
|
buffer[2] = (d->Hi32 >> 8) & 255;
|
|
buffer[1] = (d->Hi32 >> 16) & 255;
|
|
buffer[0] = (d->Hi32 >> 24) & 255;
|
|
/* Load buffer into the actual array */
|
|
env->SetByteArrayRegion(bArray, 0, 12, buffer);
|
|
/* then clean up the C array */
|
|
free(buffer);
|
|
|
|
/* instantiate the BigInteger */
|
|
integer = env->NewObject(bigIntegerClass, bigIntegerConstructor, d->sign == 0x80?-1:1, bArray);
|
|
|
|
result = env->NewObject(bigDecimalClass, bigDecimalConstructor, integer, (jint)(d->scale));
|
|
|
|
/* Clean up the Java global references */
|
|
env->DeleteLocalRef(bArray);
|
|
env->DeleteLocalRef(integer);
|
|
env->DeleteLocalRef(bigIntegerClass);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* gets a VT_DECIMAL by ref as a BigDecimal
|
|
* Added 1.13M4
|
|
* */
|
|
JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_getVariantDecRef
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
if (V_VT(v) != (VT_DECIMAL|VT_BYREF)) {
|
|
return NULL;
|
|
}
|
|
return extractDecimal(env, v->pdecVal);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* gets a VT_DECIMAL as a BigDecimal
|
|
* Added 1.13M4
|
|
* */
|
|
JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_getVariantDec
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
if (V_VT(v) != VT_DECIMAL) {
|
|
return NULL;
|
|
}
|
|
return extractDecimal(env, (DECIMAL*)v);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
}
|