-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Bind more functions from OleAut32.dll - Fix bug in function bindings from OleAut32.dll (long vs. LONG) - Ensure SAFEARRAY.rgsabound is completely accessible - Modify Variant#getValue and Variant#setValue to allow flexible access to data - Add object oriented helper methods to SAFEARRAY and move functionality from limited methods in OleAutoUtil to SAFEARRAY - Add unittests based on windows search provider that excercise SAFEARRAY functions - Added a helper for optimized conversion from SAFEARRAY to Object[] Closes #522
- Loading branch information
1 parent
6b0d9ba
commit 56b1f33
Showing
10 changed files
with
1,870 additions
and
215 deletions.
There are no files selected for viewing
477 changes: 477 additions & 0 deletions
477
contrib/platform/src/com/sun/jna/platform/win32/OaIdl.java
Large diffs are not rendered by default.
Oops, something went wrong.
266 changes: 266 additions & 0 deletions
266
contrib/platform/src/com/sun/jna/platform/win32/OaIdlUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,266 @@ | ||
package com.sun.jna.platform.win32; | ||
|
||
import com.sun.jna.Pointer; | ||
import com.sun.jna.platform.win32.OaIdl.DATE; | ||
import com.sun.jna.platform.win32.OaIdl.SAFEARRAY; | ||
import com.sun.jna.platform.win32.Variant.VARIANT; | ||
import static com.sun.jna.platform.win32.Variant.VT_BOOL; | ||
import static com.sun.jna.platform.win32.Variant.VT_BSTR; | ||
import static com.sun.jna.platform.win32.Variant.VT_CY; | ||
import static com.sun.jna.platform.win32.Variant.VT_DATE; | ||
import static com.sun.jna.platform.win32.Variant.VT_DECIMAL; | ||
import static com.sun.jna.platform.win32.Variant.VT_DISPATCH; | ||
import static com.sun.jna.platform.win32.Variant.VT_EMPTY; | ||
import static com.sun.jna.platform.win32.Variant.VT_ERROR; | ||
import static com.sun.jna.platform.win32.Variant.VT_I1; | ||
import static com.sun.jna.platform.win32.Variant.VT_I2; | ||
import static com.sun.jna.platform.win32.Variant.VT_I4; | ||
import static com.sun.jna.platform.win32.Variant.VT_INT; | ||
import static com.sun.jna.platform.win32.Variant.VT_NULL; | ||
import static com.sun.jna.platform.win32.Variant.VT_R4; | ||
import static com.sun.jna.platform.win32.Variant.VT_R8; | ||
import static com.sun.jna.platform.win32.Variant.VT_RECORD; | ||
import static com.sun.jna.platform.win32.Variant.VT_UI1; | ||
import static com.sun.jna.platform.win32.Variant.VT_UI2; | ||
import static com.sun.jna.platform.win32.Variant.VT_UI4; | ||
import static com.sun.jna.platform.win32.Variant.VT_UINT; | ||
import static com.sun.jna.platform.win32.Variant.VT_UNKNOWN; | ||
import static com.sun.jna.platform.win32.Variant.VT_VARIANT; | ||
import com.sun.jna.platform.win32.WTypes.BSTR; | ||
import com.sun.jna.platform.win32.WinDef.SCODE; | ||
import java.lang.reflect.Array; | ||
|
||
public abstract class OaIdlUtil { | ||
|
||
/** | ||
* Read SAFEARRAY into a java array. Not all VARTYPEs are supported! | ||
* | ||
* <p> | ||
* Supported types:</p> | ||
* <ul> | ||
* <li>VT_BOOL</li> | ||
* <li>VT_UI1</li> | ||
* <li>VT_I1</li> | ||
* <li>VT_UI2</li> | ||
* <li>VT_I2</li> | ||
* <li>VT_UI4</li> | ||
* <li>VT_UINT</li> | ||
* <li>VT_I4</li> | ||
* <li>VT_INT</li> | ||
* <li>VT_ERROR</li> | ||
* <li>VT_R4</li> | ||
* <li>VT_R8</li> | ||
* <li>VT_DATE</li> | ||
* <li>VT_BSTR</li> | ||
* <li>VT_VARIANT (Onle the following VARTYPES): | ||
* <ul> | ||
* <li>VT_EMPTY (converted to NULL)</li> | ||
* <li>VT_NULL</li> | ||
* <li>VT_BOOL</li> | ||
* <li>VT_UI1</li> | ||
* <li>VT_I1</li> | ||
* <li>VT_UI2</li> | ||
* <li>VT_I2</li> | ||
* <li>VT_UI4</li> | ||
* <li>VT_UINT</li> | ||
* <li>VT_I4</li> | ||
* <li>VT_INT</li> | ||
* <li>VT_ERROR</li> | ||
* <li>VT_R4</li> | ||
* <li>VT_R8</li> | ||
* <li>VT_DATE</li> | ||
* <li>VT_BSTR</li> | ||
* </ul> | ||
* </li> | ||
* </ul> | ||
* | ||
* @param sa SAFEARRAY to convert | ||
* @param destruct if true the supplied SAFEARRAY is destroyed, there must | ||
* not be additional locks on the array! | ||
* @return | ||
*/ | ||
public static Object toPrimitiveArray(SAFEARRAY sa, boolean destruct) { | ||
Pointer dataPointer = sa.accessData(); | ||
try { | ||
int dimensions = sa.getDimensionCount(); | ||
int[] minIdx = new int[dimensions]; | ||
int[] maxIdx = new int[dimensions]; | ||
int[] elements = new int[dimensions]; | ||
int[] cumElements = new int[dimensions]; | ||
int varType = sa.getVarType().intValue(); | ||
|
||
for (int i = 0; i < dimensions; i++) { | ||
minIdx[i] = sa.getLBound(i); | ||
maxIdx[i] = sa.getUBound(i); | ||
elements[i] = maxIdx[i] - minIdx[i] + 1; | ||
} | ||
|
||
for (int i = dimensions - 1; i >= 0; i--) { | ||
if (i == (dimensions - 1)) { | ||
cumElements[i] = 1; | ||
} else { | ||
cumElements[i] = cumElements[i + 1] * elements[i + 1]; | ||
} | ||
} | ||
|
||
if (dimensions == 0) { | ||
throw new IllegalArgumentException("Supplied Array has no dimensions."); | ||
} | ||
|
||
int elementCount = cumElements[0] * elements[0]; | ||
|
||
Object sourceArray; | ||
switch (varType) { | ||
case VT_UI1: | ||
case VT_I1: | ||
sourceArray = dataPointer.getByteArray(0, elementCount); | ||
break; | ||
case VT_BOOL: | ||
case VT_UI2: | ||
case VT_I2: | ||
sourceArray = dataPointer.getShortArray(0, elementCount); | ||
break; | ||
case VT_UI4: | ||
case VT_UINT: | ||
case VT_I4: | ||
case VT_INT: | ||
case VT_ERROR: | ||
sourceArray = dataPointer.getIntArray(0, elementCount); | ||
break; | ||
case VT_R4: | ||
sourceArray = dataPointer.getFloatArray(0, elementCount); | ||
break; | ||
case VT_R8: | ||
case VT_DATE: | ||
sourceArray = dataPointer.getDoubleArray(0, elementCount); | ||
break; | ||
case VT_BSTR: | ||
sourceArray = dataPointer.getPointerArray(0, elementCount); | ||
break; | ||
case VT_VARIANT: | ||
VARIANT variant = new VARIANT(dataPointer); | ||
sourceArray = variant.toArray(elementCount); | ||
break; | ||
case VT_UNKNOWN: | ||
case VT_DISPATCH: | ||
case VT_CY: | ||
case VT_DECIMAL: | ||
case VT_RECORD: | ||
default: | ||
throw new IllegalStateException("Type not supported: " + varType); | ||
} | ||
|
||
Object targetArray = Array.newInstance(Object.class, elements); | ||
toPrimitiveArray(sourceArray, targetArray, minIdx, maxIdx, elements, cumElements, varType, new int[0]); | ||
return targetArray; | ||
} finally { | ||
sa.unaccessData(); | ||
if (destruct) { | ||
sa.destroy(); | ||
} | ||
} | ||
} | ||
|
||
private static void toPrimitiveArray(Object dataArray, Object targetArray, int[] minIdx, int[] maxIdx, int[] elements, int[] cumElements, int varType, int[] currentIdx) { | ||
int dimIdx = currentIdx.length; | ||
int[] subIdx = new int[currentIdx.length + 1]; | ||
System.arraycopy(currentIdx, 0, subIdx, 0, dimIdx); | ||
for (int i = minIdx[dimIdx]; i <= maxIdx[dimIdx]; i++) { | ||
subIdx[dimIdx] = i; | ||
if (dimIdx == (minIdx.length - 1)) { | ||
int offset = 0; | ||
for (int j = 0; j < dimIdx; j++) { | ||
offset += cumElements[j] * currentIdx[j]; | ||
} | ||
offset += subIdx[dimIdx] - minIdx[dimIdx]; | ||
int targetPos = subIdx[dimIdx] - minIdx[dimIdx]; | ||
switch (varType) { | ||
case VT_BOOL: | ||
Array.set(targetArray, targetPos, Array.getShort(dataArray, offset) != 0); | ||
break; | ||
case VT_UI1: | ||
case VT_I1: | ||
Array.set(targetArray, targetPos, Array.getByte(dataArray, offset)); | ||
break; | ||
case VT_UI2: | ||
case VT_I2: | ||
Array.set(targetArray, targetPos, Array.getShort(dataArray, offset)); | ||
break; | ||
case VT_UI4: | ||
case VT_UINT: | ||
case VT_I4: | ||
case VT_INT: | ||
Array.set(targetArray, targetPos, Array.getInt(dataArray, offset)); | ||
break; | ||
case VT_ERROR: | ||
Array.set(targetArray, targetPos, new SCODE(Array.getInt(dataArray, offset))); | ||
break; | ||
case VT_R4: | ||
Array.set(targetArray, targetPos, Array.getFloat(dataArray, offset)); | ||
break; | ||
case VT_R8: | ||
Array.set(targetArray, targetPos, Array.getDouble(dataArray, offset)); | ||
break; | ||
case VT_DATE: | ||
Array.set(targetArray, targetPos, new DATE(Array.getDouble(dataArray, offset)).getAsJavaDate()); | ||
break; | ||
case VT_BSTR: | ||
Array.set(targetArray, targetPos, new BSTR((Pointer) Array.get(dataArray, offset)).getValue()); | ||
break; | ||
case VT_VARIANT: | ||
VARIANT holder = (VARIANT) Array.get(dataArray, offset); | ||
switch (holder.getVarType().intValue()) { | ||
case VT_NULL: | ||
case VT_EMPTY: | ||
Array.set(targetArray, targetPos, null); | ||
break; | ||
case VT_BOOL: | ||
Array.set(targetArray, targetPos, holder.booleanValue()); | ||
break; | ||
case VT_UI1: | ||
case VT_I1: | ||
Array.set(targetArray, targetPos, holder.byteValue()); | ||
break; | ||
case VT_UI2: | ||
case VT_I2: | ||
Array.set(targetArray, targetPos, holder.shortValue()); | ||
break; | ||
case VT_UI4: | ||
case VT_UINT: | ||
case VT_I4: | ||
case VT_INT: | ||
Array.set(targetArray, targetPos, holder.intValue()); | ||
break; | ||
case VT_ERROR: | ||
Array.set(targetArray, targetPos, new SCODE(holder.intValue())); | ||
break; | ||
case VT_R4: | ||
Array.set(targetArray, targetPos, holder.floatValue()); | ||
break; | ||
case VT_R8: | ||
Array.set(targetArray, targetPos, holder.doubleValue()); | ||
break; | ||
case VT_DATE: | ||
Array.set(targetArray, targetPos, holder.dateValue()); | ||
break; | ||
case VT_BSTR: | ||
Array.set(targetArray, targetPos, holder.stringValue()); | ||
break; | ||
default: | ||
throw new IllegalStateException("Type not supported: " + holder.getVarType().intValue()); | ||
} | ||
break; | ||
case VT_UNKNOWN: | ||
case VT_DISPATCH: | ||
case VT_CY: | ||
case VT_DECIMAL: | ||
case VT_RECORD: | ||
default: | ||
throw new IllegalStateException("Type not supported: " + varType); | ||
} | ||
} else { | ||
toPrimitiveArray(dataArray, Array.get(targetArray, i), minIdx, maxIdx, elements, cumElements, varType, subIdx); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.