コード例 #1
0
JNIEXPORT jobject JNICALL Java_com_jacob_com_DispatchProxy_MarshalFromStream
  (JNIEnv *env, jobject _this)
{
  IStream *ps = extractStream(env, _this);
  if (!ps) 
  {
    ThrowComFail(env, "Could not get IStream from DispatchProxy", -1);
    return NULL;
  }
  IDispatch *pD;
  HRESULT hr = CoGetInterfaceAndReleaseStream(ps, IID_IDispatch, (void **)&pD);
  // zero out the stream pointer on the object
  // since the stream can only be read once
  jclass argClass = env->GetObjectClass(_this);
  jfieldID ajf = env->GetFieldID( argClass, "m_pStream", "I");
  env->SetIntField(_this, ajf, (unsigned int)0);

  if (!SUCCEEDED(hr))
  {
    ThrowComFail(env, "Could not Marshal Dispatch from IStream", 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
  // I am copying the pointer to java
  if (pD) pD->AddRef();
  jobject newAuto = env->NewObject(autoClass, autoCons, pD);
  return newAuto;
}
コード例 #2
0
ファイル: Variant.cpp プロジェクト: jiazhy-zhiyuan/TANGRAM
	/**
	 * Converts the data to a Enum Variant object and then returns it as a Dispatch
	 */
	JNIEXPORT jobject JNICALL Java_com_tangram_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/tangram/EnumVariant");
			jmethodID autoCons =
				env->GetMethodID(autoClass, "<init>", "(J)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;
	}
コード例 #3
0
ファイル: TypeInfo.cpp プロジェクト: enebo/racob
 JNIEXPORT jobject JNICALL Java_org_racob_com_TypeInfo_getContainingTypeLib
  (JNIEnv *env, jobject obj, jint pointer) {
   ITypeInfo *typeInfo = (ITypeInfo *) pointer;
   ITypeLib* typeLib = NULL;
   unsigned int index = 0;
   HRESULT hr = typeInfo->GetContainingTypeLib(&typeLib, &index);
   if (!SUCCEEDED(hr)) {
      ThrowComFail(env, "GetContainingTypeLib failed", hr);
      return NULL;
   }

   int typeCount = typeLib->GetTypeInfoCount();
   if (typeCount == E_NOTIMPL) {
      ThrowComFail(env, "GetContainingTypeLib failed to get count", hr);
      return NULL;
   }

 TLIBATTR *libAttr = NULL;
 hr = typeLib->GetLibAttr(&libAttr);
 if (!SUCCEEDED(hr)) {
    ThrowComFail(env, "Automation.loadTypeLibEx failed", hr);
    return NULL;
 }

 jstring guid = makeGUIDString(env, libAttr->guid);
 jclass autoClass = env->FindClass("org/racob/com/TypeLib");
 jmethodID autoCons = env->GetMethodID(autoClass, "<init>", "(IILjava/lang/String;IIII)V");
 jobject newAuto = env->NewObject(autoClass, autoCons, (jint) typeLib, index,
         guid, typeCount, libAttr->wLibFlags, libAttr->wMajorVerNum,
         libAttr->wMinorVerNum);

 typeLib->ReleaseTLibAttr(libAttr);

 return newAuto;
 }
コード例 #4
0
ファイル: TypeInfo.cpp プロジェクト: enebo/racob
JNIEXPORT jobjectArray JNICALL Java_org_racob_com_TypeInfo_getNames
  (JNIEnv *env, jobject obj, jint pointer, jint memid) {
   ITypeInfo *typeInfo = (ITypeInfo *) pointer;
   BSTR names[MAX_NAMES];
   unsigned int namesCount;
   HRESULT hr = typeInfo->GetNames(memid, names, MAX_NAMES, &namesCount);
   if (!SUCCEEDED(hr)) {
      ThrowComFail(env, "getNames failed", hr);
      return NULL;
   }

   // Make primitive String array for names
   jclass autoClass = env->FindClass("java/lang/String");
   jobjectArray array = env->NewObjectArray(namesCount, autoClass, NULL);
   if (!SUCCEEDED(hr)) {
      ThrowComFail(env, "getNames failed to make return array", hr);
      return NULL;
   }

   // Fill up array
   for (unsigned int i = 0; i < namesCount; i++) {
      int len = SysStringLen(names[i]);
      jstring string = env->NewString((const jchar *) names[i], len);
      env->SetObjectArrayElement(array, i, string);
      SysFreeString(names[i]);
   }

   return array;
}
コード例 #5
0
ファイル: TypeInfo.cpp プロジェクト: enebo/racob
  JNIEXPORT jobject JNICALL Java_org_racob_com_TypeInfo_getDocumentation
  (JNIEnv *env, jobject obj, jint pointer, jint index) {
   ITypeInfo *typeInfo = (ITypeInfo *) pointer;
   BSTR name;
   BSTR docString;
   unsigned long helpContext;
   BSTR helpFile;
   HRESULT hr = typeInfo->GetDocumentation(index, &name, &docString, &helpContext,
           &helpFile);
   if (!SUCCEEDED(hr)) {
      freeDocumentationStrings(name, docString, helpFile);
      ThrowComFail(env, "getDocumentation failed", hr);
      return NULL;
   }

   jclass autoClass = env->FindClass("org/racob/com/Documentation");
   jmethodID autoCons = env->GetMethodID(autoClass, "<init>",
           "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V");
   jobject newAuto = env->NewObject(autoClass, autoCons, makeString(env, name),
           makeString(env, docString), makeString(env, helpFile), helpContext);

   freeDocumentationStrings(name, docString, helpFile);

   return newAuto;
 }
コード例 #6
0
ファイル: TypeInfo.cpp プロジェクト: enebo/racob
 JNIEXPORT jobject JNICALL Java_org_racob_com_TypeInfo_getFuncDesc
  (JNIEnv *env, jobject obj, jint pointer, jint index) {
   ITypeInfo *typeInfo = (ITypeInfo *) pointer;
   if (!typeInfo) return NULL;

   FUNCDESC *funcDesc = NULL;
   HRESULT hr = typeInfo->GetFuncDesc(index, &funcDesc);
   if (!SUCCEEDED(hr)) {
      ThrowComFail(env, "getFuncDesc failed", hr);
      return NULL;
   }


   int paramLength = funcDesc->cParams;
   unsigned int nameLength = 0;
   BSTR *names = (BSTR *) malloc(sizeof(BSTR) * paramLength + 1);
   hr = typeInfo->GetNames(funcDesc->memid, names, paramLength + 1, &nameLength);
   if (FAILED(hr)) {
      typeInfo->ReleaseFuncDesc(funcDesc);
      ThrowComFail(env, "getFuncDesc failed", hr);
      return NULL;
   }
   SysFreeString(names[0]);

   jclass paramClass = env->FindClass("org/racob/com/Parameter");
   jmethodID paramCons = env->GetMethodID(paramClass, "<init>", "(Ljava/lang/String;ZZZZIZLorg/racob/com/Variant;)V");
   jobjectArray parameters = env->NewObjectArray(nameLength - 1, paramClass, 0);
   for (int i = 0; i < nameLength - 1; i++) {
      jobject parameter = createParameter(env, paramClass, paramCons,
              funcDesc->lprgelemdescParam[i], names[i+1]);
      env->SetObjectArrayElement(parameters, i, parameter);
      env->DeleteLocalRef(parameter);
   }

   jobject returnValue = createParameter(env, paramClass, paramCons, funcDesc->elemdescFunc, NULL);
   jclass autoClass = env->FindClass("org/racob/com/FuncDesc");
   jmethodID autoCons = env->GetMethodID(autoClass, "<init>", "(IIII[Lorg/racob/com/Parameter;Lorg/racob/com/Parameter;II)V");
   jobject newAuto = env->NewObject(autoClass, autoCons, funcDesc->memid,
           index, funcDesc->invkind, funcDesc->wFuncFlags, parameters,
           returnValue, funcDesc->cParamsOpt, funcDesc->oVft);

   typeInfo->ReleaseFuncDesc(funcDesc);

   return newAuto;
 }
コード例 #7
0
ファイル: EventProxy.cpp プロジェクト: cherry-wb/jacob
void EventProxy::Connect(JNIEnv *env) {
  HRESULT hr = pCP->Advise(this, &dwEventCookie);
  if (SUCCEEDED(hr)) {
        connected = 1;
  } else {
        connected = 0;
    ThrowComFail(env, "Advise failed", hr);
  }
}
コード例 #8
0
ファイル: Variant.cpp プロジェクト: jiazhy-zhiyuan/TANGRAM
	JNIEXPORT void JNICALL Java_com_tangram_Variant_putVariantLong(JNIEnv *env, jobject _this, jlong longValue)
	{
		VARIANT *v = extractVariant(env, _this);
		if (v) {
			VariantClear(v); // whatever was there before
			V_VT(v) = VT_I8;
			V_I8(v) = (LONGLONG)longValue;
		}
		else ThrowComFail(env, "putVariantLong failed", -1);
	}
コード例 #9
0
ファイル: Variant.cpp プロジェクト: jiazhy-zhiyuan/TANGRAM
	JNIEXPORT void JNICALL Java_com_tangram_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;
	}
コード例 #10
0
ファイル: Variant.cpp プロジェクト: jiazhy-zhiyuan/TANGRAM
	JNIEXPORT void JNICALL Java_com_tangram_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);
	}
コード例 #11
0
ファイル: Variant.cpp プロジェクト: jiazhy-zhiyuan/TANGRAM
	JNIEXPORT void JNICALL Java_com_tangram_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);
	}
コード例 #12
0
ファイル: Variant.cpp プロジェクト: jiazhy-zhiyuan/TANGRAM
	JNIEXPORT void JNICALL Java_com_tangram_Variant_putVariantSafeArrayRef(JNIEnv *env, jobject _this, jobject sa)
	{
		SAFEARRAY *psa = extractSA(env, sa);
		if (psa)
		{
			VARIANT *v = extractVariant(env, _this);
			if (v) {
				VARTYPE vt;
				SAFEARRAY **sa = (SAFEARRAY **)CoTaskMemAlloc(sizeof(SAFEARRAY*));
				*sa = psa;
				SafeArrayGetVartype(psa, &vt);
				V_VT(v) = VT_ARRAY | vt | VT_BYREF;
				V_ARRAYREF(v) = sa;
				return;
			}
			ThrowComFail(env, "Can't get variant pointer", -1);
			return;
		}
		ThrowComFail(env, "Can't get sa pointer", -1);
		return;
	}
コード例 #13
0
ファイル: TypeInfo.cpp プロジェクト: enebo/racob
JNIEXPORT jint JNICALL Java_org_racob_com_TypeInfo_getRefTypeOfImplType
  (JNIEnv *env, jobject obj, jint pointer, jint index) {
  ITypeInfo *typeInfo = (ITypeInfo *) pointer;
  HREFTYPE href;
  HRESULT hr = typeInfo->GetRefTypeOfImplType(index, &href);
  if (!SUCCEEDED(hr)) {
     ThrowComFail(env, "getRefTypeOfImplType failed", hr);
     return NULL;
  }

  return (jint) href;
}
コード例 #14
0
ファイル: TypeInfo.cpp プロジェクト: enebo/racob
JNIEXPORT jobject JNICALL Java_org_racob_com_TypeInfo_getRefTypeInfo
  (JNIEnv *env, jobject obj, jint pointer, jint reftype) {
   ITypeInfo *typeInfo = (ITypeInfo *) pointer;
   ITypeInfo *newTypeInfo = NULL;
   HRESULT hr = typeInfo->GetRefTypeInfo(reftype, &newTypeInfo);
   if (!SUCCEEDED(hr)) {
      ThrowComFail(env, "getRefTypeInfo failed", hr);
      return NULL;
   }

   return makeTypeInfo(env, newTypeInfo);
}
コード例 #15
0
ファイル: TypeInfo.cpp プロジェクト: enebo/racob
JNIEXPORT jint JNICALL Java_org_racob_com_TypeInfo_getImplTypeFlags
  (JNIEnv *env, jobject obj, jint pointer, jint index) {
   ITypeInfo *typeInfo = (ITypeInfo *) pointer;
  int flags;
  HRESULT hr = typeInfo->GetImplTypeFlags(index, &flags);
  if (!SUCCEEDED(hr)) {
     ThrowComFail(env, "getImplTypeFlags failed", hr);
     return NULL;
  }

  return (jint) flags;
}
コード例 #16
0
ファイル: Variant.cpp プロジェクト: jiazhy-zhiyuan/TANGRAM
	JNIEXPORT void JNICALL Java_com_tangram_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);
	}
コード例 #17
0
ファイル: Variant.cpp プロジェクト: jiazhy-zhiyuan/TANGRAM
	/**
	 * 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_tangram_Variant_putVariantDispatch(JNIEnv *env, jobject _this, jobject _that)
	{
		VARIANT *v = extractVariant(env, _this);
		IDispatch *disp = extractDispatch(env, _that);
		if (v) {
			VariantClear(v); // whatever was there before
			V_VT(v) = VT_DISPATCH;
			V_DISPATCH(v) = disp;
			// I am handing the pointer to COM
			// SF 3435567 support null dispatch pointer
			if (disp)
				disp->AddRef();
		}
		else ThrowComFail(env, "putObject failed", -1);
	}
コード例 #18
0
ファイル: DispatchProxy.cpp プロジェクト: enebo/racob
JNIEXPORT int JNICALL Java_org_racob_com_DispatchProxy_MarshalIntoStream
  (JNIEnv *env, jobject _this, jint pointer)
{
  IDispatch *pIDispatch = (IDispatch *) pointer;
  if (!pIDispatch) return 0;
  
  IStream *ps; // this is the stream we will marshall into
  HRESULT hr = CoMarshalInterThreadInterfaceInStream(IID_IDispatch, pIDispatch, &ps);
  if (!SUCCEEDED(hr)) {
    ThrowComFail(env, "Could not Marshal Dispatch into IStream", hr);
    return 0;
  }

  return (jint) ps;
}
コード例 #19
0
ファイル: DispatchProxy.cpp プロジェクト: enebo/racob
JNIEXPORT jobject JNICALL Java_org_racob_com_DispatchProxy_MarshalFromStream
  (JNIEnv *env, jobject _this, jint pointer)
{
  IStream *ps = (IStream *) pointer;
  if (!ps) {
    ThrowComFail(env, "Could not get IStream from DispatchProxy", -1);
    return NULL;
  }
  
  IDispatch *pD;
  HRESULT hr = CoGetInterfaceAndReleaseStream(ps, IID_IDispatch, (void **)&pD);

  if (!SUCCEEDED(hr)) {
    ThrowComFail(env, "Could not Marshal Dispatch from IStream", hr);
    return NULL;
  }
  jclass autoClass = env->FindClass("org/racob/com/Dispatch");
  jmethodID autoCons = env->GetMethodID(autoClass, "<init>", "(I)V");
  // construct a Dispatch object to return
  // I am copying the pointer to java
  if (pD) pD->AddRef();
  jobject newAuto = env->NewObject(autoClass, autoCons, pD);
  return newAuto;
}
コード例 #20
0
JNIEXPORT void JNICALL Java_com_jacob_com_DispatchProxy_MarshalIntoStream
  (JNIEnv *env, jobject _this, jobject disp)
{
  IDispatch *pIDispatch = extractDispatch(env, disp);
  if (!pIDispatch) return;
  IStream *ps; // this is the stream we will marshall into
  HRESULT hr = CoMarshalInterThreadInterfaceInStream(
                 IID_IDispatch, pIDispatch, &ps);
  if (!SUCCEEDED(hr))
  {
    ThrowComFail(env, "Could not Marshal Dispatch into IStream", hr);
    return;
  }
  // store the stream pointer on the object
  jclass argClass = env->GetObjectClass(_this);
  jfieldID ajf = env->GetFieldID( argClass, "m_pStream", "I");
  env->SetIntField(_this, ajf, (jint)ps);
}
コード例 #21
0
ファイル: Variant.cpp プロジェクト: jiazhy-zhiyuan/TANGRAM
	/**
	 * Converts the data to a Safe Array object and then returns it as a Dispatch
	 */
	JNIEXPORT jobject JNICALL Java_com_tangram_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/tangram/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;
	}
コード例 #22
0
ファイル: Variant.cpp プロジェクト: jiazhy-zhiyuan/TANGRAM
	/**
	 * Converts the data to a Dispatch object and then returns it as a Dispatch
	 */
	JNIEXPORT jobject JNICALL Java_com_tangram_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/tangram/Dispatch");
			jmethodID autoCons =
				env->GetMethodID(autoClass, "<init>", "(J)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;
	}
コード例 #23
0
ファイル: TypeInfo.cpp プロジェクト: enebo/racob
 JNIEXPORT jobject JNICALL Java_org_racob_com_TypeInfo_getVarDesc
  (JNIEnv *env, jobject obj, jint pointer, jint index)
 {
   ITypeInfo *typeInfo = (ITypeInfo *) pointer;
   VARDESC *varDesc = NULL;
   HRESULT hr = typeInfo->GetVarDesc(index, &varDesc);
   if (!SUCCEEDED(hr)) {
      ThrowComFail(env, "getVarDesc failed", hr);
      return NULL;
   }

   // We have a constant so let's save the variant
   jobject cValue = varDesc->varkind == VAR_CONST ? createVariant(env, varDesc->lpvarValue) : NULL;
   jclass autoClass = env->FindClass("org/racob/com/VarDesc");
   jmethodID autoCons = env->GetMethodID(autoClass, "<init>", "(ILorg/racob/com/Variant;II)V");
   jobject newAuto = env->NewObject(autoClass, autoCons, varDesc->memid,
           cValue, varDesc->varkind, varDesc->wVarFlags);

   typeInfo->ReleaseVarDesc(varDesc);

   return newAuto;
 }
コード例 #24
0
ファイル: EventProxy.cpp プロジェクト: cherry-wb/jacob
// The actual callback from the connection point arrives here
STDMETHODIMP EventProxy::Invoke(DISPID dispID, REFIID riid,
    LCID lcid, unsigned short wFlags, DISPPARAMS *pDispParams,
    VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
  	const char 	*eventMethodName = NULL; //Sourceforge report 1394001 
  	JNIEnv      *env = NULL;

  // map dispID to jmethodID
  for(int i=0;i<MethNum;i++) 
  {
    if (MethID[i] == dispID) { 
		USES_CONVERSION;
		eventMethodName = W2A((OLECHAR *)MethName[i]);
    	}
  }
  // added 1.12
  if (!eventMethodName) {
  	// just bail if can't find signature.  no need to attach
	// printf("Invoke: didn't find method name for dispatch id %d\n",dispID);
   	return S_OK;
  }
  if (DISPATCH_METHOD & wFlags) 
  {
        
    // attach to the current running thread
	//printf("Invoke: Attaching to current thread using JNI Version 1.2\n");
		JavaVMAttachArgs attachmentArgs; 
        attachmentArgs.version = JNI_VERSION_1_2;  
        attachmentArgs.name = NULL; 
        attachmentArgs.group = NULL; 
        jvm->AttachCurrentThread((void **)&env, &attachmentArgs); 
		if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}

	if (!eventMethodName) 
  	{
	    // could not find this signature in list
  		// printf("Invoke: didn't find method name for dispatch id %d\n",dispID);
  		// this probably leaves a native thread attached to the vm when we don't want it
  		ThrowComFail(env, "Event method received was not defined as part of callback interface", -1);
  		
  		// should we detatch before returning?? We probably never get here if we ThrowComFail()
	    // jvm->DetachCurrentThread();
    	return S_OK;
	  }

	// find the class of the InvocationHandler
   	jclass javaSinkClass = env->GetObjectClass(javaSinkObj);
		if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
	//printf("Invoke: Got sink class\n");
    jmethodID invokeMethod;
    invokeMethod = env->GetMethodID(javaSinkClass, "invoke", "(Ljava/lang/String;[Lcom/jacob/com/Variant;)Lcom/jacob/com/Variant;");
		if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
    jstring eventMethodNameAsString = env->NewStringUTF(eventMethodName);
	//printf("Invoke: Got method name\n");
	// now do what we need for the variant
    jmethodID getVariantMethod = env->GetMethodID(javaSinkClass, "getVariant", "()Lcom/jacob/com/Variant;");
		if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
	//printf("Invoke: Found way too getVariant\n");
    jobject aVariantObj = env->CallObjectMethod(javaSinkObj, getVariantMethod); 
		if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
	//printf("Invoke: Made Variant\n");
   	jclass variantClass = env->GetObjectClass(aVariantObj);
		if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}

	// create the variant parameter array
    // how many params
    int numVariantParams = pDispParams->cArgs;
    // make an array of them
    jobjectArray varr = env->NewObjectArray(numVariantParams, variantClass, 0);
		if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
	//printf("Invoke: Created Array\n");
    int i,j;
    for(i=numVariantParams-1,j=0;i>=0;i--,j++) 
    {
      // construct a java variant holder
	  jobject arg = env->CallObjectMethod(javaSinkObj, getVariantMethod); 
		if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
      // get the empty variant from it
      VARIANT *va = extractVariant(env, arg);
      // copy the value
      VariantCopy(va, &pDispParams->rgvarg[i]);
      // put it in the array
      env->SetObjectArrayElement(varr, j, arg);
	  env->DeleteLocalRef(arg);
		if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
    }
	//printf("Invoke: Filled Array\n");
    // Set up the return value
    jobject ret;

    ret = env->CallObjectMethod(javaSinkObj, invokeMethod, 
		eventMethodNameAsString, varr); 
	//printf("Invoke: Invoked callback\n");
    if (!env->ExceptionOccurred() && ret != NULL) {
        VariantCopy(pVarResult, extractVariant(env,ret));
    }
		if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
	// don't need the first variant we created to get the class
	// SF 1689061 change not accepted but put in as comment for later reminder
    //Java_com_jacob_com_Variant_release(env, aVariantObj);
	env->DeleteLocalRef(aVariantObj);
		if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}

    // Begin code from Jiffie team that copies parameters back from java to COM
    for(i=numVariantParams-1,j=0;i>=0;i--,j++) 
    {
		jobject arg = env->GetObjectArrayElement(varr, j);
		VARIANT *java = extractVariant(env, arg);
		VARIANT *com = &pDispParams->rgvarg[i];
		convertJavaVariant(java, com);
		// SF 1689061 change not accepted but put in as comment for later reminder
		//Java_com_jacob_com_Variant_release(env, arg);
		zeroVariant(env, arg);
		env->DeleteLocalRef(arg);
    }
    // End code from Jiffie team that copies parameters back from java to COM
    // detach from thread
	//printf("Invoke: Detatching\n");
	jvm->DetachCurrentThread();
  	//fflush(stdout);
    return S_OK;
  }
  return E_NOINTERFACE;
}