1146 lines
30 KiB
C++
1146 lines
30 KiB
C++
/*
|
|
* Copyright (c) 1999-2004 Sourceforge JACOB Project.
|
|
* All rights reserved. Originator: Dan Adler (http://danadler.com).
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
* 3. Redistributions in any form must be accompanied by information on
|
|
* how to obtain complete source code for the JACOB software.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
#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);
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_Save
|
|
(JNIEnv *env, jobject _this, jobject outStream)
|
|
{
|
|
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;
|
|
|
|
//java code: DataOutputStream dos = new DataOutputStream(outStream);
|
|
jclass dosCls = env->FindClass("java/io/DataOutputStream");
|
|
jmethodID dosCons =
|
|
env->GetMethodID(dosCls, "<init>", "(Ljava/io/OutputStream;)V");
|
|
jmethodID dosWriteInt =
|
|
env->GetMethodID(dosCls, "writeInt", "(I)V");
|
|
jmethodID dosWriteBytes =
|
|
env->GetMethodID(dosCls, "write", "([B)V");
|
|
jobject dos = env->NewObject(dosCls, dosCons, outStream);
|
|
// write the size into the stream
|
|
env->CallVoidMethod(dos, dosWriteInt, size);
|
|
// write the buffer into the stream
|
|
env->CallVoidMethod(dos, dosWriteBytes, ba);
|
|
}
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_Load
|
|
(JNIEnv *env, jobject _this, jobject inStream)
|
|
{
|
|
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (!v)
|
|
{
|
|
// since the default constructor is not called when serializing in
|
|
// I need to init the underlying VARIANT
|
|
jclass clazz = env->GetObjectClass(_this);
|
|
jfieldID jf = env->GetFieldID( clazz, VARIANT_FLD, "I");
|
|
v = new VARIANT();
|
|
VariantInit(v);
|
|
env->SetIntField(_this, jf, (unsigned int)v);
|
|
}
|
|
if (v)
|
|
{
|
|
//java code: DataInputStream dis = new DataInputStream(outStream);
|
|
jclass disCls = env->FindClass("java/io/DataInputStream");
|
|
jmethodID disCons =
|
|
env->GetMethodID(disCls, "<init>", "(Ljava/io/InputStream;)V");
|
|
jmethodID disReadInt =
|
|
env->GetMethodID(disCls, "readInt", "()I");
|
|
jmethodID disReadBytes =
|
|
env->GetMethodID(disCls, "readFully", "([B)V");
|
|
jobject dis = env->NewObject(disCls, disCons, inStream);
|
|
|
|
// read in the size from the input stream
|
|
jint size = env->CallIntMethod(dis, disReadInt);
|
|
// allocate a byte array of this size
|
|
jbyteArray ba = env->NewByteArray(size);
|
|
// read it in from the input stream
|
|
env->CallVoidMethod(dis, disReadBytes, ba);
|
|
if ( size > 0 )
|
|
{
|
|
// get a buffer from it
|
|
jbyte *pBuf = env->GetByteArrayElements(ba, 0);
|
|
// unmarshall the Variant from the buffer
|
|
DWORD flags = MSHCTX_LOCAL;
|
|
VARIANT_UserUnmarshal(&flags, (unsigned char *)pBuf, v);
|
|
// release the byte array
|
|
env->ReleaseByteArrayElements(ba, pBuf, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_toInt
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
HRESULT hr;
|
|
if (FAILED(hr = VariantChangeType(v, v, 0, VT_I4))) {
|
|
ThrowComFail(env, "VariantChangeType failed", hr);
|
|
return NULL;
|
|
}
|
|
return (jint)V_I4(v);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_toDate
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
HRESULT hr;
|
|
if (FAILED(hr = VariantChangeType(v, v, 0, VT_DATE))) {
|
|
ThrowComFail(env, "VariantChangeType failed", hr);
|
|
return NULL;
|
|
}
|
|
return (jdouble)V_DATE(v);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
JNIEXPORT jboolean JNICALL Java_com_jacob_com_Variant_toBoolean
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
HRESULT hr;
|
|
if (FAILED(hr = VariantChangeType(v, v, 0, VT_BOOL))) {
|
|
ThrowComFail(env, "VariantChangeType failed", hr);
|
|
return NULL;
|
|
}
|
|
return (jboolean)V_BOOL(v);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
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_getNull
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putNull
|
|
(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 jdouble JNICALL Java_com_jacob_com_Variant_toDouble
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
HRESULT hr;
|
|
if (FAILED(hr = VariantChangeType(v, v, 0, VT_R8))) {
|
|
ThrowComFail(env, "VariantChangeType failed", hr);
|
|
return NULL;
|
|
}
|
|
return (jdouble)V_R8(v);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_toCurrency
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
HRESULT hr;
|
|
if (FAILED(hr = VariantChangeType(v, v, 0, VT_CY))) {
|
|
ThrowComFail(env, "VariantChangeType failed", hr);
|
|
return NULL;
|
|
}
|
|
CY cy = V_CY(v);
|
|
return (jlong)cy.int64;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putShortRef
|
|
(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_putIntRef
|
|
(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_putDoubleRef
|
|
(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_putDateRef
|
|
(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;
|
|
}
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putStringRef
|
|
(JNIEnv *env, jobject _this, jstring s)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
VariantClear(v); // whatever was there before
|
|
|
|
// need to convert to C-style char buffer
|
|
jclass strcls = env->FindClass("java/lang/String");
|
|
jmethodID getBytes = env->GetMethodID(strcls, "getBytes", "()[B");
|
|
jbyteArray ba = (jbyteArray)env->CallObjectMethod(s, getBytes);
|
|
int len = env->GetArrayLength(ba);
|
|
jbyte* buf = (jbyte*)alloca(len + 1);
|
|
env->GetByteArrayRegion(ba, 0, len, buf);
|
|
buf[len] = '\0';
|
|
CComBSTR bs((char*)buf);
|
|
|
|
BSTR *pbs = (BSTR *)CoTaskMemAlloc(sizeof(BSTR));
|
|
bs.CopyTo(pbs);
|
|
V_VT(v) = VT_BSTR|VT_BYREF;
|
|
V_BSTRREF(v) = pbs;
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jshort JNICALL Java_com_jacob_com_Variant_getShortRef
|
|
(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_getIntRef
|
|
(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_putShort
|
|
(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_getShort
|
|
(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_getDoubleRef
|
|
(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_getDateRef
|
|
(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_getStringRef
|
|
(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;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_VariantClear
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
VariantClear(v);
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_toDispatch
|
|
(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;
|
|
}
|
|
|
|
JNIEXPORT jstring JNICALL Java_com_jacob_com_Variant_toString
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
switch (V_VT(v))
|
|
{
|
|
case VT_EMPTY:
|
|
case VT_NULL:
|
|
case VT_ERROR:
|
|
// causes VariantChangeType to bomb
|
|
return env->NewStringUTF("null");
|
|
}
|
|
HRESULT hr;
|
|
if (FAILED(hr = VariantChangeType(v, v, 0, VT_BSTR))) {
|
|
// cannot change type to a string
|
|
return env->NewStringUTF("???");
|
|
}
|
|
BSTR bs = V_BSTR(v);
|
|
jstring js = env->NewString(bs, SysStringLen(bs));
|
|
return js;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getInt
|
|
(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;
|
|
}
|
|
|
|
JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getDate
|
|
(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_putInt
|
|
(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_putDate
|
|
(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;
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jbyte JNICALL Java_com_jacob_com_Variant_toByte
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
HRESULT hr;
|
|
if (FAILED(hr = VariantChangeType(v, v, 0, VT_UI1))) {
|
|
ThrowComFail(env, "VariantChangeType failed", hr);
|
|
return NULL;
|
|
}
|
|
return (jbyte)V_UI1(v);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
JNIEXPORT jboolean JNICALL Java_com_jacob_com_Variant_getBoolean
|
|
(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;
|
|
}
|
|
|
|
JNIEXPORT jbyte JNICALL Java_com_jacob_com_Variant_getByte
|
|
(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_putBoolean
|
|
(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, "putBoolean failed", -1);
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putByte
|
|
(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, "putByte failed", -1);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_toError
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
HRESULT hr;
|
|
if (FAILED(hr = VariantChangeType(v, v, 0, VT_ERROR))) {
|
|
ThrowComFail(env, "VariantChangeType failed", hr);
|
|
return NULL;
|
|
}
|
|
return (jint)V_ERROR(v);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_toObject
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
// not supported
|
|
return NULL;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_getEmpty
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putEmpty
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
VariantClear(v); // whatever was there before
|
|
V_VT(v) = VT_EMPTY;
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getError
|
|
(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_putError
|
|
(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;
|
|
}
|
|
}
|
|
|
|
|
|
JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getDouble
|
|
(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 jobject JNICALL Java_com_jacob_com_Variant_getObject
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
// not supported
|
|
return NULL;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putCurrency
|
|
(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, "putCurrency failed", -1);
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putObject
|
|
(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_putDouble
|
|
(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;
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getCurrency
|
|
(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_putFloatRef
|
|
(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_putCurrencyRef
|
|
(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_putErrorRef
|
|
(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_putBooleanRef
|
|
(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_putByteRef
|
|
(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;
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jstring JNICALL Java_com_jacob_com_Variant_getString
|
|
(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;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putString
|
|
(JNIEnv *env, jobject _this, jstring s)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
VariantClear(v); // whatever was there before
|
|
V_VT(v) = VT_BSTR;
|
|
|
|
// get C-style byte array
|
|
jclass strcls = env->FindClass("java/lang/String");
|
|
jmethodID getBytes = env->GetMethodID(strcls, "getBytes", "()[B");
|
|
jbyteArray ba = (jbyteArray)env->CallObjectMethod(s, getBytes);
|
|
int len = env->GetArrayLength(ba);
|
|
jbyte* buf = (jbyte*)alloca(len + 1);
|
|
env->GetByteArrayRegion(ba, 0, len, buf);
|
|
buf[len] = '\0';
|
|
|
|
CComBSTR bs((char*)buf);
|
|
V_VT(v) = VT_BSTR;
|
|
V_BSTR(v) = bs.Copy();
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jfloat JNICALL Java_com_jacob_com_Variant_getFloatRef
|
|
(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_getCurrencyRef
|
|
(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_getErrorRef
|
|
(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_getBooleanRef
|
|
(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 jobject JNICALL Java_com_jacob_com_Variant_getObjectRef
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
|
|
JNIEXPORT jbyte JNICALL Java_com_jacob_com_Variant_getByteRef
|
|
(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;
|
|
}
|
|
|
|
JNIEXPORT jfloat JNICALL Java_com_jacob_com_Variant_toFloat
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
HRESULT hr;
|
|
if (FAILED(hr = VariantChangeType(v, v, 0, VT_R4))) {
|
|
ThrowComFail(env, "VariantChangeType failed", hr);
|
|
return NULL;
|
|
}
|
|
return (jfloat)V_R4(v);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_toSafeArray
|
|
(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_putSafeArrayRef
|
|
(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_putSafeArray
|
|
(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) = psa;
|
|
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_noParam
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
V_VT(v) = VT_ERROR;
|
|
V_ERROR(v) = DISP_E_PARAMNOTFOUND;
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jfloat JNICALL Java_com_jacob_com_Variant_getFloat
|
|
(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_putFloat
|
|
(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;
|
|
}
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_changeType
|
|
(JNIEnv *env, jobject _this, jshort t)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
VariantChangeType(v, v, 0, t);
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jshort JNICALL Java_com_jacob_com_Variant_getvt
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
return (jshort)V_VT(v);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
JNIEXPORT jshort JNICALL Java_com_jacob_com_Variant_toShort
|
|
(JNIEnv *env, jobject _this)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
HRESULT hr;
|
|
if (FAILED(hr = VariantChangeType(v, v, 0, VT_I2))) {
|
|
ThrowComFail(env, "VariantChangeType failed", hr);
|
|
return NULL;
|
|
}
|
|
return (jshort)V_I2(v);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putSafeArrayRefHelper
|
|
(JNIEnv *env, jobject _this, jint pSA)
|
|
{
|
|
VARIANT *v = extractVariant(env, _this);
|
|
if (v) {
|
|
VariantClear(v); // whatever was there before
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jboolean JNICALL Java_com_jacob_com_Variant_isNull
|
|
(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
|
|
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;
|
|
}
|
|
|
|
}
|