Permalink
Browse files

Add SAFEARRAY [in] support for single-dimensional SAFEARRAYs

  • Loading branch information...
enebo committed Aug 21, 2011
1 parent 5b15329 commit 22db584a2a5163179fbfee9d4c4ca81cbe2b7b19
Showing with 339 additions and 362 deletions.
  1. +13 −13 jni/Dispatch.cpp
  2. +10 −10 jni/DispatchEvents.cpp
  3. +16 −23 jni/EventProxy.cpp
  4. +52 −0 jni/SafeArray.cpp
  5. +201 −38 jni/Variant.cpp
  6. +1 −178 jni/Variant.h
  7. +2 −3 jni/util.cpp
  8. +12 −0 jni/util.h
  9. +32 −32 src/org/racob/com/SafeArray.java
  10. +0 −65 unittest/org/racob/com/VariantUtilitiesTest.java
View
@@ -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);
@@ -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);
@@ -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;
@@ -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
@@ -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 ) {
@@ -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
@@ -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
@@ -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;
}
View
@@ -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
@@ -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
@@ -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);
@@ -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();
@@ -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;
}
@@ -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)) &&
@@ -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;
}
}
View
@@ -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
@@ -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;
@@ -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
@@ -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);
}
@@ -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) {
@@ -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
@@ -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;
View
@@ -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;
+ }
+}
Oops, something went wrong.

0 comments on commit 22db584

Please sign in to comment.