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; }
/** * 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; }
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; }
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; }
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; }
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; }
void EventProxy::Connect(JNIEnv *env) { HRESULT hr = pCP->Advise(this, &dwEventCookie); if (SUCCEEDED(hr)) { connected = 1; } else { connected = 0; ThrowComFail(env, "Advise failed", hr); } }
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); }
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; }
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); }
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); }
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; }
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; }
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); }
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; }
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); }
/** * 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); }
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; }
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; }
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); }
/** * 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; }
/** * 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; }
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; }
// 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; }