Skip to content

Commit

Permalink
Add SAFEARRAY [in] support for single-dimensional SAFEARRAYs
Browse files Browse the repository at this point in the history
  • Loading branch information
enebo committed Aug 21, 2011
1 parent 5b15329 commit 22db584
Show file tree
Hide file tree
Showing 10 changed files with 339 additions and 362 deletions.
26 changes: 13 additions & 13 deletions jni/Dispatch.cpp
Expand Up @@ -161,7 +161,7 @@ JNIEXPORT jint JNICALL Java_org_racob_com_Dispatch_getActiveInstanceNative
return 0;
}
// standard connection
//printf("trying to connect to running %ls\n",bsProgId);
DLOG("trying to connect to running %ls\n",bsProgId);
hr = GetActiveObject(clsid,NULL, &punk);
if (!SUCCEEDED(hr)) {
ThrowComFail(env, "Can't get active object", hr);
Expand Down Expand Up @@ -474,20 +474,18 @@ JNIEXPORT jobject JNICALL Java_org_racob_com_Dispatch_invokev0
return result;
}

#define DISPATCH_DEBUG 0

JNIEXPORT jobject JNICALL Java_org_racob_com_Dispatch_invokev
(JNIEnv *env, jclass clazz,
jint dispPointer, jstring name, jint dispid,
jint lcid, jint wFlags, jobjectArray vArg, jintArray uArgErr) {
DISPPARAMS dispparams;
EXCEPINFO excepInfo;

if (DISPATCH_DEBUG) { printf("Before dispatch\n"); fflush(stdout); }
DLOG("Before dispatch\n");
IDispatch *pIDispatch = (IDispatch *) dispPointer;
if (!pIDispatch) return NULL;

if (DISPATCH_DEBUG) { printf("Before name\n"); fflush(stdout); }
DLOG("Before name\n");
int dispID = dispid;
if (name != NULL) {
const char *nm = env->GetStringUTFChars(name, NULL);
Expand All @@ -498,11 +496,11 @@ JNIEXPORT jobject JNICALL Java_org_racob_com_Dispatch_invokev
ThrowComFail(env, buf, -1);
return NULL;
}
if (DISPATCH_DEBUG) { printf("name setup: %s\n", nm); }
DLOG("name setup: %s\n", nm);
env->ReleaseStringUTFChars(name, nm);
}

if (DISPATCH_DEBUG) { printf("Before args handling\n"); fflush(stdout); }
DLOG("Before args handling\n");
int num_args = env->GetArrayLength(vArg);
int i, j;
VARIANT *varr = NULL;
Expand All @@ -519,12 +517,12 @@ JNIEXPORT jobject JNICALL Java_org_racob_com_Dispatch_invokev
}
}

if (DISPATCH_DEBUG) { printf("Before return setup\n"); fflush(stdout); }
DLOG("Before return setup\n");
VARIANT returnValue;
DISPID dispidPropertyPut = DISPID_PROPERTYPUT;
VariantInit(&returnValue);

if (DISPATCH_DEBUG) { printf("Before dispatch type logic\n"); fflush(stdout); }
DLOG("Before dispatch type logic\n");
// determine how to dispatch
switch (wFlags) {
case DISPATCH_PROPERTYGET: // GET
Expand All @@ -540,7 +538,7 @@ JNIEXPORT jobject JNICALL Java_org_racob_com_Dispatch_invokev
}
}

if (DISPATCH_DEBUG) { printf("Before invoke\n"); fflush(stdout); }
DLOG("Before invoke\n");
HRESULT hr = 0;
jint count = env->GetArrayLength(uArgErr);
if ( count != 0 ) {
Expand All @@ -553,7 +551,7 @@ JNIEXPORT jobject JNICALL Java_org_racob_com_Dispatch_invokev
lcid, (WORD) wFlags, &dispparams, &returnValue, &excepInfo, NULL); // SF 1689061
}

if (DISPATCH_DEBUG) { printf("Before error check\n"); fflush(stdout); }
DLOG("Before error check\n");
// check for error and display a somewhat verbose error message
if (!SUCCEEDED(hr)) {
// two buffers that may have to be freed later
Expand Down Expand Up @@ -593,7 +591,7 @@ JNIEXPORT jobject JNICALL Java_org_racob_com_Dispatch_invokev
return NULL;
}

if (DISPATCH_DEBUG) { printf("Before in/outs\n"); fflush(stdout); }
DLOG("Before in/outs\n");
if (num_args) {
// to account for inouts, I need to copy the inputs back to
// the java array after the method returns
Expand All @@ -605,9 +603,11 @@ JNIEXPORT jobject JNICALL Java_org_racob_com_Dispatch_invokev
}
if (varr) CoTaskMemFree(varr);

if (DISPATCH_DEBUG) { printf("Before return to variant\n"); fflush(stdout); }
DLOG("Before return to variant\n");
jobject result = createVariant(env, &returnValue);
DLOG("Got result. Clear variant\n");
VariantClear(&returnValue);
DLOG("Variant cleared\n");
return result;
}

Expand Down
20 changes: 10 additions & 10 deletions jni/DispatchEvents.cpp
Expand Up @@ -60,7 +60,7 @@ JNIEXPORT jint JNICALL Java_org_racob_com_DispatchEvents_init3
typeLib = A2W(typelib);
// should we call env->ReleaseStringUTFChars(,) to free the memory like we do everywhere lese?

//printf("we have a type lib %ls\n",typeLib);
DLOG("we have a type lib %ls\n",typeLib);
}

// find progid if any
Expand All @@ -70,7 +70,7 @@ JNIEXPORT jint JNICALL Java_org_racob_com_DispatchEvents_init3
const char *progid = env->GetStringUTFChars(_progid, NULL);
bsProgId = A2W(progid);
// should we call env->ReleaseStringUTFChars(,) to free the memory like we do everywhere lese?
//printf("we have an applicaton %ls\n",bsProgId);
DLOG("we have an applicaton %ls\n",bsProgId);
}

// get the IDispatch for the source object
Expand Down Expand Up @@ -136,7 +136,7 @@ LoadNameCache(LPTYPEINFO pTypeInfo, LPTYPEATTR pta,
ids[i] = pfd->memid;
/*
USES_CONVERSION;
printf("map:%d -> %s\n", ids[i], W2A((OLECHAR *)names[i]));
DLOG("map:%d -> %s\n", ids[i], W2A((OLECHAR *)names[i]));
*/
}
pTypeInfo->ReleaseFuncDesc(pfd);
Expand All @@ -163,7 +163,7 @@ BOOL GetEventIID(IUnknown *m_pObject, IID* piid,
LPTYPEINFO pClassInfo = NULL;
if (SUCCEEDED(m_pObject->QueryInterface(IID_IProvideClassInfo, (LPVOID*)&pPCI)))
{
//printf("got IProvideClassInfo\n");
DLOG("got IProvideClassInfo\n");
ATLASSERT(pPCI != NULL);
HRESULT hr = pPCI->GetClassInfo(&pClassInfo);
pPCI->Release();
Expand All @@ -172,7 +172,7 @@ BOOL GetEventIID(IUnknown *m_pObject, IID* piid,
else if (getClassInfoFromProgId(bsProgId,&pClassInfo)) {
}
else {
printf("GetEventIID: couldn't get IProvideClassInfo\n");
DLOG("GetEventIID: couldn't get IProvideClassInfo\n");
return false;
}

Expand All @@ -183,19 +183,19 @@ BOOL MapEventIIDs(IID* piid,
CComBSTR **mNames, DISPID **mIDs, int *nmeth, LPOLESTR bsProgId, LPTYPEINFO pClassInfo)
{
ATLASSERT(pClassInfo != NULL);
//printf("MapEventIIDs: got past ClassInfo assert\n");
DLOG("MapEventIIDs: got past ClassInfo assert\n");
LPTYPEATTR pClassAttr;
if (SUCCEEDED(pClassInfo->GetTypeAttr(&pClassAttr)))
{
//printf("MapEventIIDs: got TypeAttr\n");
DLOG("MapEventIIDs: got TypeAttr\n");
ATLASSERT(pClassAttr != NULL);
ATLASSERT(pClassAttr->typekind == TKIND_COCLASS);

// Search for typeinfo of the default events interface.
int nFlags;
HREFTYPE hRefType;

//printf("MapEventIIDs: looking at %d class attribute impl types \n");
DLOG("MapEventIIDs: looking at %d class attribute impl types \n");
for (unsigned int i = 0; i < pClassAttr->cImplTypes; i++)
{
if (SUCCEEDED(pClassInfo->GetImplTypeFlags(i, &nFlags)) &&
Expand Down Expand Up @@ -305,13 +305,13 @@ BOOL GetEventIIDForTypeLib(BSTR typeLib, IID* piid,
if(getClassInfoFromProgIdTypeLib(typeLib, bsProgId,&pClassInfo))
{
if (pClassInfo == NULL){
printf("we had a successful return but pClassInfo is null\n");
DLOG("we had a successful return but pClassInfo is null\n");
}
return MapEventIIDs(piid, mNames, mIDs, nmeth, bsProgId, pClassInfo);
}
else
{
printf("GetEventIIDForTypeLib: couldn't get IProvideClassInfo\n");
DLOG("GetEventIIDForTypeLib: couldn't get IProvideClassInfo\n");
return false;
}
}
Expand Down
39 changes: 16 additions & 23 deletions jni/EventProxy.cpp
Expand Up @@ -20,8 +20,6 @@
#include "EventProxy.h"
#include "Variant.h"

#define EVENT_PROXY_DEBUG 0

#define HANDLE_EXCEPTION if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}

// hook myself up as a listener for delegate
Expand Down Expand Up @@ -58,7 +56,7 @@ EventProxy::~EventProxy() {
if (env != NULL) { HANDLE_EXCEPTION; }

if (vmConnectionStatus == JNI_EDETACHED){
//printf("Unhook: Attaching to current thread using JNI Version 1.2 (%d)\n",vmConnectionStatus);
DLOG("Unhook: Attaching to current thread using JNI Version 1.2 (%d)\n",vmConnectionStatus);
JavaVMAttachArgs attachmentArgs;
attachmentArgs.version = JNI_VERSION_1_2;
attachmentArgs.name = NULL;
Expand All @@ -68,7 +66,7 @@ EventProxy::~EventProxy() {
} else {
// should really look for JNI_OK versus an error because it could have been JNI_EVERSION
// started method with thread hooked to VM so no need to attach again
//printf("Unhook: No need to attach because already attached %d\n",vmConnectionStatus);
DLOG("Unhook: No need to attach because already attached %d\n",vmConnectionStatus);
}

// we should always have an env by this point but lets be paranoid and check
Expand All @@ -83,9 +81,9 @@ EventProxy::~EventProxy() {
// detach from thread only if we attached to it in this function
if (attachReturnStatus == 0) {
jvm->DetachCurrentThread();
//printf("Unhook: Detached\n");
DLOG("Unhook: Detached\n");
} else {
//printf("Unhook: No need to detatch because attached prior to method\n");
DLOG("Unhook: No need to detatch because attached prior to method\n");
}
//fflush(stdout);
}
Expand Down Expand Up @@ -120,7 +118,7 @@ STDMETHODIMP EventProxy::Invoke(DISPID dispID, REFIID riid,
const char *eventMethodName = NULL; //Sourceforge report 1394001
JNIEnv *env = NULL;

if (EVENT_PROXY_DEBUG) { printf("In Invoke\n"); fflush(stdout); }
DLOG("In Invoke\n");
// map dispID to jmethodID
for (int i = 0; i < MethNum; i++) {
if (MethID[i] == dispID) {
Expand All @@ -131,10 +129,7 @@ STDMETHODIMP EventProxy::Invoke(DISPID dispID, REFIID riid,

// added 1.12 - Just bail if can't find signature. no need to attach
if (!eventMethodName) return S_OK;
if (EVENT_PROXY_DEBUG) {
printf("In invoke of %s\n", eventMethodName);
fflush(stdout);
}
DLOG("In invoke of %s\n", eventMethodName);

if (DISPATCH_METHOD & wFlags) {
// attach to the current running thread
Expand All @@ -153,41 +148,39 @@ STDMETHODIMP EventProxy::Invoke(DISPID dispID, REFIID riid,
// create the variant parameter array
// how many params
int numVariantParams = pDispParams->cArgs;
if (EVENT_PROXY_DEBUG) {
printf("Setup parm list for event %s(%d)\n", eventMethodName, numVariantParams);
fflush(stdout);
}
DLOG("Setup parm list for event %s(%d)\n", eventMethodName, numVariantParams);

// make an array of them
jobjectArray varr = env->NewObjectArray(numVariantParams, VARIANT_CLASS, 0); HANDLE_EXCEPTION;

int i,j;
for (i=numVariantParams-1,j=0; i>=0; i--,j++) {
if (EVENT_PROXY_DEBUG) { printf("In invoke of %s (parm %d) start\n", eventMethodName, i); fflush(stdout); }
DLOG("In invoke of %s (parm %d) start\n", eventMethodName, i);
env->SetObjectArrayElement(varr, j, createVariant(env, &pDispParams->rgvarg[i])); HANDLE_EXCEPTION;
VariantClear(&pDispParams->rgvarg[i]);
if (EVENT_PROXY_DEBUG) { printf("In invoke of %s (parm %d) end\n", eventMethodName, i); fflush(stdout); }
DLOG("In invoke of %s (parm %d) end\n", eventMethodName, i);
}

if (EVENT_PROXY_DEBUG) { printf("Right before sink invoke of %s\n", eventMethodName); fflush(stdout); }
DLOG("Right before sink invoke of %s\n", eventMethodName);
// Set up the return value
jobject ret = env->CallObjectMethod(javaSinkObj, invokeMethod, eventMethodNameAsString, varr); HANDLE_EXCEPTION;
if (EVENT_PROXY_DEBUG) { printf("Right after sink invoke of %s\n", eventMethodName); fflush(stdout); }
DLOG("Right after sink invoke of %s\n", eventMethodName);
if (ret != NULL) { populateVariant(env, ret, pVarResult); }
if (EVENT_PROXY_DEBUG) { printf("Right after return variant populate of %s\n", eventMethodName); fflush(stdout); }
DLOG("Right after return variant populate of %s\n", eventMethodName);

/*
// Begin code from Jiffie team that copies parameters back from java to COM
for(i=numVariantParams-1,j=0;i>=0;i--,j++) {
if (EVENT_PROXY_DEBUG) { printf("In invoke of %s (parm swapback %d) start\n", eventMethodName, i); fflush(stdout); }
DLOG("In invoke of %s (parm swapback %d) start\n", eventMethodName, i);
jobject arg = env->GetObjectArrayElement(varr, j);
populateVariant(env, arg, &pDispParams->rgvarg[i]);
env->DeleteLocalRef(arg);
if (EVENT_PROXY_DEBUG) { printf("In invoke of %s (parm swapback %d) end\n", eventMethodName, i); fflush(stdout); }
DLOG("In invoke of %s (parm swapback %d) end\n", eventMethodName, i);
}
// End code from Jiffie team that copies parameters back from java to COM
* */

if (EVENT_PROXY_DEBUG) { printf("Done with invoke of %s\n", eventMethodName); fflush(stdout); }
DLOG("Done with invoke of %s\n", eventMethodName);
jvm->DetachCurrentThread(); // detach from thread

return S_OK;
Expand Down
52 changes: 52 additions & 0 deletions jni/SafeArray.cpp
@@ -0,0 +1,52 @@
#include "jni.h"
#include <wchar.h>
#include <string.h>
#include <atlbase.h>
#include <objbase.h>
#include <oleauto.h>
#include <olectl.h>
#include "util.h"

extern "C" {
SAFEARRAY *makeSingleArray(int vt, long lowerBounds, long size) {
SAFEARRAYBOUND safeArrayBounds;

safeArrayBounds.lLbound = lowerBounds;
safeArrayBounds.cElements = size;

return SafeArrayCreate(vt, 1, &safeArrayBounds);
}

SAFEARRAY *makeArray(int vt, int dimensions, long *lowerBounds, long *elementSizes) {
if (dimensions == 1) return makeSingleArray(vt, lowerBounds[0], elementSizes[0]);

SAFEARRAYBOUND* safeArrayBounds = new SAFEARRAYBOUND[dimensions];

for (int i = 0; i < dimensions; i++) {
safeArrayBounds[i].lLbound = lowerBounds[i];
safeArrayBounds[i].cElements = elementSizes[i];
}

SAFEARRAY *sa = SafeArrayCreate(vt, dimensions, safeArrayBounds);
delete[] safeArrayBounds;
return sa;
}

SAFEARRAY *newSingleArray(JNIEnv* env, int vt, jobjectArray data) {
long size = env->GetArrayLength(data);
SAFEARRAY *newArray = makeSingleArray(vt, 0, size);

DLOG("newSingleArray of length %d\n", size);
for (long i = 0; i < size; i++) {
DLOG("newSingleArray iter %d\n", i);
VARIANT variant;
VariantInit(&variant);
jobject object = env->GetObjectArrayElement(data, i);
populateVariant(env, object, &variant);
SafeArrayPutElement(newArray, &i, &variant);
VariantClear(&variant);
}
DLOG("newSingleArray of length %d (done)\n", size);
return newArray;
}
}

0 comments on commit 22db584

Please sign in to comment.