| /******************************************************************************* | |
| * Copyright (c) 2000, 2006 IBM Corporation and others. | |
| * All rights reserved. This program and the accompanying materials | |
| * are made available under the terms of the Eclipse Public License v1.0 | |
| * which accompanies this distribution, and is available at | |
| * http://www.eclipse.org/legal/epl-v10.html | |
| * | |
| * Contributors: | |
| * IBM Corporation - initial API and implementation | |
| *******************************************************************************/ | |
| // Modified by Google | |
| package org.eclipse.swt.ole.win32; | |
| import org.eclipse.swt.*; | |
| import org.eclipse.swt.internal.ole.win32.*; | |
| import org.eclipse.swt.internal.win32.*; | |
| /** | |
| * | |
| * A Variant is a generic OLE mechanism for passing data of different types via a common interface. | |
| * | |
| * <p>It is used within the OleAutomation object for getting a property, setting a property or invoking | |
| * a method on an OLE Control or OLE Document. | |
| * | |
| */ | |
| public final class Variant | |
| { | |
| /** | |
| * A variant always takes up 16 bytes, no matter what you | |
| * store in it. Objects, strings, and arrays are not physically | |
| * stored in the Variant; in these cases, four bytes of the | |
| * Variant are used to hold either an object reference, or a | |
| * pointer to the string or array. The actual data are stored elsewhere. | |
| */ | |
| public static final int sizeof = 16; | |
| private short type; // OLE.VT_* type | |
| private boolean booleanData; | |
| private byte byteData; | |
| private char charData; | |
| private double doubleData; | |
| private int intData; | |
| private float floatData; | |
| private long longData; | |
| private short shortData; | |
| private String stringData; | |
| private int byRefPtr; | |
| private IDispatch dispatchData; | |
| private IUnknown unknownData; | |
| /** | |
| * Invokes platform specific functionality to wrap a variant. | |
| * <p> | |
| * <b>IMPORTANT:</b> This method is <em>not</em> part of the public | |
| * API for <code>GC</code>. It is marked public only so that it | |
| * can be shared within the packages provided by SWT. It is not | |
| * available on all platforms, and should never be called from | |
| * application code. | |
| * </p> | |
| * | |
| * @param pVariant pointer to a variant | |
| * | |
| * @return a new <code>GC</code> | |
| * | |
| * @since 3.3 | |
| */ | |
| public static Variant win32_new (int pVariant) { | |
| Variant variant = new Variant (); | |
| variant.setData (pVariant); | |
| return variant; | |
| } | |
| /** | |
| * Invokes platform specific functionality to copy a variant | |
| * into operating system memory. | |
| * <p> | |
| * <b>IMPORTANT:</b> This method is <em>not</em> part of the public | |
| * API for <code>Variant</code>. It is marked public only so that it | |
| * can be shared within the packages provided by SWT. It is not | |
| * available on all platforms, and should never be called from | |
| * application code. | |
| * </p> | |
| * | |
| * @param pVarDest destination pointer to a variant | |
| * @param varSrc source <code>Variant</code> | |
| * | |
| * @since 3.3 | |
| */ | |
| public static void win32_copy (int pVarDest, Variant varSrc) { | |
| varSrc.getData (pVarDest); | |
| } | |
| /** | |
| * Create an empty Variant object with type VT_EMPTY. | |
| * | |
| * @since 2.0 | |
| */ | |
| public Variant(){ | |
| type = COM.VT_EMPTY; | |
| } | |
| /** | |
| * Create a Variant object which represents a Java float as a VT_R4. | |
| * | |
| * @param val the Java float value that this Variant represents | |
| * | |
| */ | |
| public Variant(float val) { | |
| type = COM.VT_R4; | |
| floatData = val; | |
| } | |
| /** | |
| * Create a Variant object which represents a Java double as a VT_R8. | |
| * | |
| * @param val the Java double value that this Variant represents | |
| * | |
| * @since 3.2 | |
| */ | |
| public Variant(double val) { | |
| type = COM.VT_R8; | |
| doubleData = val; | |
| } | |
| /** | |
| * Create a Variant object which represents a Java int as a VT_I4. | |
| * | |
| * @param val the Java int value that this Variant represents | |
| * | |
| */ | |
| public Variant(int val) { | |
| type = COM.VT_I4; | |
| intData = val; | |
| } | |
| /** | |
| * Create a Variant object which contains a reference to the data being transferred. | |
| * | |
| * <p>When creating a VT_BYREF Variant, you must give the full Variant type | |
| * including VT_BYREF such as | |
| * | |
| * <pre><code>short byRefType = OLE.VT_BSTR | OLE.VT_BYREF</code></pre>. | |
| * | |
| * @param ptr a pointer to the data being transferred. | |
| * @param byRefType the type of the data being transferred such as OLE.VT_BSTR | OLE.VT_BYREF | |
| * | |
| */ | |
| public Variant(int ptr, short byRefType) { | |
| type = byRefType; | |
| byRefPtr = ptr; | |
| } | |
| /** | |
| * Create a Variant object which represents an IDispatch interface as a VT_Dispatch. | |
| * | |
| * @param automation the OleAutomation object that this Variant represents | |
| * | |
| */ | |
| public Variant(OleAutomation automation) { | |
| type = COM.VT_DISPATCH; | |
| dispatchData = new IDispatch(automation.getAddress()); | |
| } | |
| /** | |
| * Create a Variant object which represents an IDispatch interface as a VT_Dispatch. | |
| * <p>The caller is expected to have appropriately invoked unknown.AddRef() before creating | |
| * this Variant. | |
| * | |
| * @since 2.0 | |
| * | |
| * @param idispatch the IDispatch object that this Variant represents | |
| * | |
| */ | |
| public Variant(IDispatch idispatch) { | |
| type = COM.VT_DISPATCH; | |
| dispatchData = idispatch; | |
| } | |
| /** | |
| * Create a Variant object which represents an IUnknown interface as a VT_UNKNOWN. | |
| * | |
| * <p>The caller is expected to have appropriately invoked unknown.AddRef() before creating | |
| * this Variant. | |
| * | |
| * @param unknown the IUnknown object that this Variant represents | |
| * | |
| */ | |
| public Variant(IUnknown unknown) { | |
| type = COM.VT_UNKNOWN; | |
| unknownData = unknown; | |
| } | |
| /** | |
| * Create a Variant object which represents a Java long as a VT_I8. | |
| * | |
| * @param val the Java long value that this Variant represents | |
| * | |
| *@since 3.2 | |
| */ | |
| public Variant(long val) { | |
| type = COM.VT_I8; | |
| longData = val; | |
| } | |
| /** | |
| * Create a Variant object which represents a Java String as a VT_BSTR. | |
| * | |
| * @param string the Java String value that this Variant represents | |
| * | |
| */ | |
| public Variant(String string) { | |
| type = COM.VT_BSTR; | |
| stringData = string; | |
| } | |
| /** | |
| * Create a Variant object which represents a Java short as a VT_I2. | |
| * | |
| * @param val the Java short value that this Variant represents | |
| * | |
| */ | |
| public Variant(short val) { | |
| type = COM.VT_I2; | |
| shortData = val; | |
| } | |
| /** | |
| * Create a Variant object which represents a Java boolean as a VT_BOOL. | |
| * | |
| * @param val the Java boolean value that this Variant represents | |
| * | |
| */ | |
| public Variant(boolean val) { | |
| type = COM.VT_BOOL; | |
| booleanData = val; | |
| } | |
| /** | |
| * Calling dispose will release resources associated with this Variant. | |
| * If the resource is an IDispatch or IUnknown interface, Release will be called. | |
| * If the resource is a ByRef pointer, nothing is released. | |
| * | |
| * @since 2.1 | |
| */ | |
| public void dispose() { | |
| if ((type & COM.VT_BYREF) == COM.VT_BYREF) { | |
| return; | |
| } | |
| switch (type) { | |
| case COM.VT_DISPATCH : | |
| dispatchData.Release(); | |
| break; | |
| case COM.VT_UNKNOWN : | |
| unknownData.Release(); | |
| break; | |
| } | |
| } | |
| /** | |
| * Returns the OleAutomation object represented by this Variant. | |
| * | |
| * <p>If this Variant does not contain an OleAutomation object, an attempt is made to | |
| * coerce the Variant type into an OleAutomation object. If this fails, an error is | |
| * thrown. Note that OleAutomation objects must be disposed when no longer | |
| * needed. | |
| * | |
| * @return the OleAutomation object represented by this Variant | |
| * | |
| * @exception SWTException <ul> | |
| * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into an OleAutomation object</li> | |
| * </ul> | |
| */ | |
| public OleAutomation getAutomation() { | |
| if (type == COM.VT_EMPTY) { | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); | |
| } | |
| if (type == COM.VT_DISPATCH) { | |
| return new OleAutomation(dispatchData); | |
| } | |
| // try to coerce the value to the desired type | |
| int oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| int newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| Variant autoVar = null; // GOOGLE: prevent memory leaks | |
| try { | |
| getData(oldPtr); | |
| int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_DISPATCH); | |
| if (result != COM.S_OK) | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); | |
| autoVar = new Variant(); | |
| autoVar.setData(newPtr); | |
| return autoVar.getAutomation(); | |
| } finally { | |
| COM.VariantClear(oldPtr); | |
| OS.GlobalFree(oldPtr); | |
| COM.VariantClear(newPtr); // Note: This must absolutely be done AFTER the | |
| // OleAutomation object is created as Variant Clear | |
| // will result in a Release being performed on the | |
| // Dispatch object | |
| OS.GlobalFree(newPtr); | |
| // GOOGLE: prevent memory leaks | |
| if (autoVar != null) | |
| autoVar.dispose(); | |
| } | |
| } | |
| /** | |
| * Returns the IDispatch object represented by this Variant. | |
| * | |
| * <p>If this Variant does not contain an IDispatch object, an attempt is made to | |
| * coerce the Variant type into an IDIspatch object. If this fails, an error is | |
| * thrown. | |
| * | |
| * @since 2.0 | |
| * | |
| * @return the IDispatch object represented by this Variant | |
| * | |
| * @exception SWTException <ul> | |
| * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into an IDispatch object</li> | |
| * </ul> | |
| */ | |
| public IDispatch getDispatch() { | |
| if (type == COM.VT_EMPTY) { | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); | |
| } | |
| if (type == COM.VT_DISPATCH) { | |
| return dispatchData; | |
| } | |
| // try to coerce the value to the desired type | |
| int oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| int newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| Variant autoVar = null; // GOOGLE: prevent memory leaks | |
| try { | |
| getData(oldPtr); | |
| int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_DISPATCH); | |
| if (result != COM.S_OK) | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); | |
| autoVar = new Variant(); | |
| autoVar.setData(newPtr); | |
| return autoVar.getDispatch(); | |
| } finally { | |
| COM.VariantClear(oldPtr); | |
| OS.GlobalFree(oldPtr); | |
| COM.VariantClear(newPtr); // Note: This must absolutely be done AFTER the | |
| // OleAutomation object is created as Variant Clear | |
| // will result in a Release being performed on the | |
| // Dispatch object | |
| OS.GlobalFree(newPtr); | |
| // GOOGLE: prevent memory leaks | |
| if (autoVar != null) | |
| autoVar.dispose(); | |
| } | |
| } | |
| /** | |
| * Returns the Java boolean represented by this Variant. | |
| * | |
| * <p>If this Variant does not contain a Java boolean, an attempt is made to | |
| * coerce the Variant type into a Java boolean. If this fails, an error is thrown. | |
| * | |
| * @return the Java boolean represented by this Variant | |
| * | |
| * @exception SWTException <ul> | |
| * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a boolean</li> | |
| * </ul> | |
| * | |
| */ | |
| public boolean getBoolean() { | |
| if (type == COM.VT_EMPTY) { | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); | |
| } | |
| if (type == COM.VT_BOOL) { | |
| return booleanData; | |
| } | |
| // try to coerce the value to the desired type | |
| int oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| int newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| try { | |
| getData(oldPtr); | |
| int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_BOOL); | |
| if (result != COM.S_OK) | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); | |
| Variant boolVar = new Variant(); | |
| boolVar.setData(newPtr); | |
| return boolVar.getBoolean(); | |
| } finally { | |
| COM.VariantClear(oldPtr); | |
| OS.GlobalFree(oldPtr); | |
| COM.VariantClear(newPtr); | |
| OS.GlobalFree(newPtr); | |
| } | |
| } | |
| /** | |
| * Returns a pointer to the referenced data represented by this Variant. | |
| * | |
| * <p>If this Variant does not contain a reference to data, zero is returned. | |
| * | |
| * @return a pointer to the referenced data represented by this Variant or 0 | |
| * | |
| */ | |
| public int getByRef() { | |
| if (type == COM.VT_EMPTY) { | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); | |
| } | |
| if ((type & COM.VT_BYREF)== COM.VT_BYREF) { | |
| return byRefPtr; | |
| } | |
| return 0; | |
| } | |
| /** | |
| * Returns the Java byte represented by this Variant. | |
| * | |
| * <p>If this Variant does not contain a Java byte, an attempt is made to | |
| * coerce the Variant type into a Java byte. If this fails, an error is thrown. | |
| * | |
| * @return the Java byte represented by this Variant | |
| * | |
| * @exception SWTException <ul> | |
| * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a byte</li> | |
| * </ul> | |
| * | |
| * @since 3.3 | |
| */ | |
| public byte getByte() { | |
| if (type == COM.VT_EMPTY) { | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); | |
| } | |
| if (type == COM.VT_I1) { | |
| return byteData; | |
| } | |
| // try to coerce the value to the desired type | |
| int oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| int newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| try { | |
| getData(oldPtr); | |
| int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_I1); | |
| if (result != COM.S_OK) | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); | |
| Variant byteVar = new Variant(); | |
| byteVar.setData(newPtr); | |
| return byteVar.getByte(); | |
| } finally { | |
| COM.VariantClear(oldPtr); | |
| OS.GlobalFree(oldPtr); | |
| COM.VariantClear(newPtr); | |
| OS.GlobalFree(newPtr); | |
| } | |
| } | |
| /** | |
| * Returns the Java char represented by this Variant. | |
| * | |
| * <p>If this Variant does not contain a Java char, an attempt is made to | |
| * coerce the Variant type into a Java char. If this fails, an error is thrown. | |
| * | |
| * @return the Java char represented by this Variant | |
| * | |
| * @exception SWTException <ul> | |
| * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a char</li> | |
| * </ul> | |
| * | |
| * @since 3.3 | |
| */ | |
| public char getChar() { | |
| if (type == COM.VT_EMPTY) { | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); | |
| } | |
| if (type == COM.VT_UI2) { | |
| return charData; | |
| } | |
| // try to coerce the value to the desired type | |
| int oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| int newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| try { | |
| getData(oldPtr); | |
| int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_UI2); | |
| if (result != COM.S_OK) | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); | |
| Variant charVar = new Variant(); | |
| charVar.setData(newPtr); | |
| return charVar.getChar(); | |
| } finally { | |
| COM.VariantClear(oldPtr); | |
| OS.GlobalFree(oldPtr); | |
| COM.VariantClear(newPtr); | |
| OS.GlobalFree(newPtr); | |
| } | |
| } | |
| void getData(int pData){ | |
| if (pData == 0) OLE.error(OLE.ERROR_OUT_OF_MEMORY); | |
| COM.VariantInit(pData); | |
| if ((type & COM.VT_BYREF) == COM.VT_BYREF) { | |
| COM.MoveMemory(pData, new short[] {type}, 2); | |
| COM.MoveMemory(pData + 8, new int[]{byRefPtr}, 4); | |
| return; | |
| } | |
| switch (type) { | |
| case COM.VT_EMPTY : | |
| case COM.VT_NULL : | |
| COM.MoveMemory(pData, new short[] {type}, 2); | |
| break; | |
| case COM.VT_BOOL : | |
| COM.MoveMemory(pData, new short[] {type}, 2); | |
| COM.MoveMemory(pData + 8, new int[]{(booleanData) ? COM.VARIANT_TRUE : COM.VARIANT_FALSE}, 2); | |
| break; | |
| case COM.VT_I1 : | |
| COM.MoveMemory(pData, new short[] {type}, 2); | |
| COM.MoveMemory(pData + 8, new byte[]{byteData}, 1); | |
| break; | |
| case COM.VT_I2 : | |
| COM.MoveMemory(pData, new short[] {type}, 2); | |
| COM.MoveMemory(pData + 8, new short[]{shortData}, 2); | |
| break; | |
| case COM.VT_I4 : | |
| COM.MoveMemory(pData, new short[] {type}, 2); | |
| COM.MoveMemory(pData + 8, new int[]{intData}, 4); | |
| break; | |
| case COM.VT_I8 : | |
| COM.MoveMemory(pData, new short[] {type}, 2); | |
| COM.MoveMemory(pData + 8, new long[]{longData}, 8); | |
| case COM.VT_UI2 : | |
| COM.MoveMemory(pData, new short[] {type}, 2); | |
| COM.MoveMemory(pData + 8, new char[]{charData}, 2); | |
| break; | |
| case COM.VT_R4 : | |
| COM.MoveMemory(pData, new short[] {type}, 2); | |
| COM.MoveMemory(pData + 8, new float[]{floatData}, 4); | |
| break; | |
| case COM.VT_R8 : | |
| COM.MoveMemory(pData, new short[] {type}, 2); | |
| COM.MoveMemory(pData + 8, new double[]{doubleData}, 8); | |
| break; | |
| case COM.VT_DISPATCH : | |
| dispatchData.AddRef(); | |
| COM.MoveMemory(pData, new short[] {type}, 2); | |
| COM.MoveMemory(pData + 8, new int[]{dispatchData.getAddress()}, 4); | |
| break; | |
| case COM.VT_UNKNOWN : | |
| unknownData.AddRef(); | |
| COM.MoveMemory(pData, new short[] {type}, 2); | |
| COM.MoveMemory(pData + 8, new int[]{unknownData.getAddress()}, 4); | |
| break; | |
| case COM.VT_BSTR : | |
| COM.MoveMemory(pData, new short[] {type}, 2); | |
| int ptr = COM.SysAllocStringLen(stringData.toCharArray(), | |
| stringData.length()); // GOOGLE | |
| COM.MoveMemory(pData + 8, new int[] {ptr}, 4); | |
| break; | |
| default : | |
| OLE.error(SWT.ERROR_NOT_IMPLEMENTED); | |
| } | |
| } | |
| /** | |
| * Returns the Java double represented by this Variant. | |
| * | |
| * <p>If this Variant does not contain a Java double, an attempt is made to | |
| * coerce the Variant type into a Java double. If this fails, an error is thrown. | |
| * | |
| * @return the Java double represented by this Variant | |
| * | |
| * @exception SWTException <ul> | |
| * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a double</li> | |
| * </ul> | |
| * | |
| * @since 3.2 | |
| */ | |
| public double getDouble() { | |
| if (type == COM.VT_EMPTY) { | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); | |
| } | |
| if (type == COM.VT_R8) { | |
| return doubleData; | |
| } | |
| // try to coerce the value to the desired type | |
| int oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| int newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| try { | |
| getData(oldPtr); | |
| int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_R8); | |
| if (result != COM.S_OK) | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); | |
| Variant doubleVar = new Variant(); | |
| doubleVar.setData(newPtr); | |
| return doubleVar.getDouble(); | |
| } finally { | |
| COM.VariantClear(oldPtr); | |
| OS.GlobalFree(oldPtr); | |
| COM.VariantClear(newPtr); | |
| OS.GlobalFree(newPtr); | |
| } | |
| } | |
| /** | |
| * Returns the Java float represented by this Variant. | |
| * | |
| * <p>If this Variant does not contain a Java float, an attempt is made to | |
| * coerce the Variant type into a Java float. If this fails, an error is thrown. | |
| * | |
| * @return the Java float represented by this Variant | |
| * | |
| * @exception SWTException <ul> | |
| * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a float</li> | |
| * </ul> | |
| */ | |
| public float getFloat() { | |
| if (type == COM.VT_EMPTY) { | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); | |
| } | |
| if (type == COM.VT_R4) { | |
| return floatData; | |
| } | |
| // try to coerce the value to the desired type | |
| int oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| int newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| try { | |
| getData(oldPtr); | |
| int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_R4); | |
| if (result != COM.S_OK) | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); | |
| Variant floatVar = new Variant(); | |
| floatVar.setData(newPtr); | |
| return floatVar.getFloat(); | |
| } finally { | |
| COM.VariantClear(oldPtr); | |
| OS.GlobalFree(oldPtr); | |
| COM.VariantClear(newPtr); | |
| OS.GlobalFree(newPtr); | |
| } | |
| } | |
| /** | |
| * Returns the Java int represented by this Variant. | |
| * | |
| * <p>If this Variant does not contain a Java int, an attempt is made to | |
| * coerce the Variant type into a Java int. If this fails, an error is thrown. | |
| * | |
| * @return the Java int represented by this Variant | |
| * | |
| * @exception SWTException <ul> | |
| * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a int</li> | |
| * </ul> | |
| */ | |
| public int getInt() { | |
| if (type == COM.VT_EMPTY) { | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); | |
| } | |
| if (type == COM.VT_I4) { | |
| return intData; | |
| } | |
| // try to coerce the value to the desired type | |
| int oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| int newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| try { | |
| getData(oldPtr); | |
| int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_I4); | |
| if (result != COM.S_OK) | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); | |
| Variant intVar = new Variant(); | |
| intVar.setData(newPtr); | |
| return intVar.getInt(); | |
| } finally { | |
| COM.VariantClear(oldPtr); | |
| OS.GlobalFree(oldPtr); | |
| COM.VariantClear(newPtr); | |
| OS.GlobalFree(newPtr); | |
| } | |
| } | |
| /** | |
| * Returns the Java long represented by this Variant. | |
| * | |
| * <p>If this Variant does not contain a Java long, an attempt is made to | |
| * coerce the Variant type into a Java long. If this fails, an error is thrown. | |
| * | |
| * @return the Java long represented by this Variant | |
| * | |
| * @exception SWTException <ul> | |
| * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a long</li> | |
| * </ul> | |
| * | |
| * @since 3.2 | |
| */ | |
| public long getLong() { | |
| if (type == COM.VT_EMPTY) { | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); | |
| } | |
| if (type == COM.VT_I8) { | |
| return longData; | |
| } | |
| // try to coerce the value to the desired type | |
| int oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| int newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| try { | |
| getData(oldPtr); | |
| int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_I8); | |
| if (result != COM.S_OK) | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); | |
| Variant longVar = new Variant(); | |
| longVar.setData(newPtr); | |
| return longVar.getLong(); | |
| } finally { | |
| COM.VariantClear(oldPtr); | |
| OS.GlobalFree(oldPtr); | |
| COM.VariantClear(newPtr); | |
| OS.GlobalFree(newPtr); | |
| } | |
| } | |
| /** | |
| * Returns the Java short represented by this Variant. | |
| * | |
| * <p>If this Variant does not contain a Java short, an attempt is made to | |
| * coerce the Variant type into a Java short. If this fails, an error is thrown. | |
| * | |
| * @return the Java short represented by this Variant | |
| * | |
| * @exception SWTException <ul> | |
| * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a short</li> | |
| * </ul> | |
| */ | |
| public short getShort() { | |
| if (type == COM.VT_EMPTY) { | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); | |
| } | |
| if (type == COM.VT_I2) { | |
| return shortData; | |
| } | |
| // try to coerce the value to the desired type | |
| int oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| int newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| try { | |
| getData(oldPtr); | |
| int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_I2); | |
| if (result != COM.S_OK) | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); | |
| Variant shortVar = new Variant(); | |
| shortVar.setData(newPtr); | |
| return shortVar.getShort(); | |
| } finally { | |
| COM.VariantClear(oldPtr); | |
| OS.GlobalFree(oldPtr); | |
| COM.VariantClear(newPtr); | |
| OS.GlobalFree(newPtr); | |
| } | |
| } | |
| /** | |
| * Returns the Java String represented by this Variant. | |
| * | |
| * <p>If this Variant does not contain a Java String, an attempt is made to | |
| * coerce the Variant type into a Java String. If this fails, an error is thrown. | |
| * | |
| * @return the Java String represented by this Variant | |
| * | |
| * @exception SWTException <ul> | |
| * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a String</li> | |
| * </ul> | |
| */ | |
| public String getString() { | |
| if (type == COM.VT_EMPTY) { | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); | |
| } | |
| if (type == COM.VT_BSTR) { | |
| return stringData; | |
| } | |
| // try to coerce the value to the desired type | |
| int oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| int newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| try { | |
| getData(oldPtr); | |
| int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_BSTR); | |
| if (result != COM.S_OK) | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); | |
| Variant stringVar = new Variant(); | |
| stringVar.setData(newPtr); | |
| return stringVar.getString(); | |
| } finally { | |
| COM.VariantClear(oldPtr); | |
| OS.GlobalFree(oldPtr); | |
| COM.VariantClear(newPtr); | |
| OS.GlobalFree(newPtr); | |
| } | |
| } | |
| /** | |
| * Returns the type of the variant type. This will be an OLE.VT_* value or | |
| * a bitwise combination of OLE.VT_* values as in the case of | |
| * OLE.VT_BSTR | OLE.VT_BYREF. | |
| * | |
| * @return the type of the variant data | |
| * | |
| * @since 2.0 | |
| */ | |
| public short getType() { | |
| return type; | |
| } | |
| /** | |
| * Returns the IUnknown object represented by this Variant. | |
| * | |
| * <p>If this Variant does not contain an IUnknown object, an attempt is made to | |
| * coerce the Variant type into an IUnknown object. If this fails, an error is | |
| * thrown. | |
| * | |
| * @return the IUnknown object represented by this Variant | |
| * | |
| * @exception SWTException <ul> | |
| * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into | |
| * an IUnknown object</li> | |
| * </ul> | |
| */ | |
| public IUnknown getUnknown() { | |
| if (type == COM.VT_EMPTY) { | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); | |
| } | |
| if (type == COM.VT_UNKNOWN) { | |
| return unknownData; | |
| } | |
| // try to coerce the value to the desired type | |
| int oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| int newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof); | |
| Variant unknownVar = null; // GOOGLE: prevent memory leaks | |
| try { | |
| getData(oldPtr); | |
| int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_UNKNOWN); | |
| if (result != COM.S_OK) | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); | |
| unknownVar = new Variant(); | |
| unknownVar.setData(newPtr); | |
| return unknownVar.getUnknown(); | |
| } finally { | |
| COM.VariantClear(oldPtr); | |
| OS.GlobalFree(oldPtr); | |
| COM.VariantClear(newPtr); // Note: This must absolutely be done AFTER the | |
| // IUnknown object is created as Variant Clear | |
| // will result in a Release being performed on the | |
| // Dispatch object | |
| OS.GlobalFree(newPtr); | |
| // GOOGLE: prevent memory leaks | |
| if (unknownVar != null) | |
| unknownVar.dispose(); | |
| } | |
| } | |
| /** | |
| * Update the by reference value of this variant with a new boolean value. | |
| * | |
| * @param val the new boolean value | |
| * | |
| * @exception SWTException <ul> | |
| * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not | |
| * a (VT_BYREF | VT_BOOL) object</li> | |
| * </ul> | |
| * | |
| * @since 2.1 | |
| */ | |
| public void setByRef(boolean val) { | |
| if ((type & COM.VT_BYREF) == 0 || (type & COM.VT_BOOL) == 0) { | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE); | |
| } | |
| COM.MoveMemory(byRefPtr, new short[]{val ? COM.VARIANT_TRUE : COM.VARIANT_FALSE}, 2); | |
| } | |
| /** | |
| * Update the by reference value of this variant with a new float value. | |
| * | |
| * @param val the new float value | |
| * | |
| * @exception SWTException <ul> | |
| * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not | |
| * a (VT_BYREF | VT_R4) object</li> | |
| * </ul> | |
| * | |
| * @since 2.1 | |
| */ | |
| public void setByRef(float val) { | |
| if ((type & COM.VT_BYREF) == 0 || (type & COM.VT_R4) == 0) { | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE); | |
| } | |
| COM.MoveMemory(byRefPtr, new float[]{val}, 4); | |
| } | |
| /** | |
| * Update the by reference value of this variant with a new integer value. | |
| * | |
| * @param val the new integer value | |
| * | |
| * @exception SWTException <ul> | |
| * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not a (VT_BYREF | VT_I4) object</li> | |
| * </ul> | |
| * | |
| * @since 2.1 | |
| */ | |
| public void setByRef(int val) { | |
| if ((type & COM.VT_BYREF) == 0 || (type & COM.VT_I4) == 0) { | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE); | |
| } | |
| COM.MoveMemory(byRefPtr, new int[]{val}, 4); | |
| } | |
| /** | |
| * Update the by reference value of this variant with a new short value. | |
| * | |
| * @param val the new short value | |
| * | |
| * @exception SWTException <ul> | |
| * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not a (VT_BYREF | VT_I2) object | |
| * </ul> | |
| * | |
| * @since 2.1 | |
| */ | |
| public void setByRef(short val) { | |
| if ((type & COM.VT_BYREF) == 0 || (type & COM.VT_I2) == 0) { | |
| OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE); | |
| } | |
| COM.MoveMemory(byRefPtr, new short[]{val}, 2); | |
| } | |
| void setData(int pData){ | |
| if (pData == 0) OLE.error(OLE.ERROR_INVALID_ARGUMENT); | |
| short[] dataType = new short[1]; | |
| COM.MoveMemory(dataType, pData, 2); | |
| type = dataType[0]; | |
| if ((type & COM.VT_BYREF) == COM.VT_BYREF) { | |
| int[] newByRefPtr = new int[1]; | |
| OS.MoveMemory(newByRefPtr, pData + 8, 4); | |
| byRefPtr = newByRefPtr[0]; | |
| return; | |
| } | |
| switch (type) { | |
| case COM.VT_EMPTY : | |
| case COM.VT_NULL : | |
| break; | |
| case COM.VT_BOOL : | |
| short[] newBooleanData = new short[1]; | |
| COM.MoveMemory(newBooleanData, pData + 8, 2); | |
| booleanData = (newBooleanData[0] != COM.VARIANT_FALSE); | |
| break; | |
| case COM.VT_I1 : | |
| byte[] newByteData = new byte[1]; | |
| COM.MoveMemory(newByteData, pData + 8, 1); | |
| byteData = newByteData[0]; | |
| break; | |
| case COM.VT_I2 : | |
| short[] newShortData = new short[1]; | |
| COM.MoveMemory(newShortData, pData + 8, 2); | |
| shortData = newShortData[0]; | |
| break; | |
| case COM.VT_I4 : | |
| int[] newIntData = new int[1]; | |
| OS.MoveMemory(newIntData, pData + 8, 4); | |
| intData = newIntData[0]; | |
| break; | |
| case COM.VT_I8 : | |
| long[] newLongData = new long[1]; | |
| OS.MoveMemory(newLongData, pData + 8, 8); | |
| longData = newLongData[0]; | |
| break; | |
| case COM.VT_UI2 : | |
| char[] newCharData = new char[1]; | |
| COM.MoveMemory(newCharData, pData + 8, 2); | |
| charData = newCharData[0]; | |
| break; | |
| case COM.VT_R4 : | |
| float[] newFloatData = new float[1]; | |
| COM.MoveMemory(newFloatData, pData + 8, 4); | |
| floatData = newFloatData[0]; | |
| break; | |
| case COM.VT_R8 : | |
| double[] newDoubleData = new double[1]; | |
| COM.MoveMemory(newDoubleData, pData + 8, 8); | |
| doubleData = newDoubleData[0]; | |
| break; | |
| case COM.VT_DISPATCH : { | |
| int[] ppvObject = new int[1]; | |
| OS.MoveMemory(ppvObject, pData + 8, 4); | |
| if (ppvObject[0] == 0) { | |
| type = COM.VT_EMPTY; | |
| break; | |
| } | |
| dispatchData = new IDispatch(ppvObject[0]); | |
| dispatchData.AddRef(); | |
| break; | |
| } | |
| case COM.VT_UNKNOWN : { | |
| int[] ppvObject = new int[1]; | |
| OS.MoveMemory(ppvObject, pData + 8, 4); | |
| if (ppvObject[0] == 0) { | |
| type = COM.VT_EMPTY; | |
| break; | |
| } | |
| unknownData = new IUnknown(ppvObject[0]); | |
| unknownData.AddRef(); | |
| break; | |
| } | |
| // GOOGLE: map exception name in IE7 to BSTR | |
| case COM.VT_WEIRD_IE7_BSTR : | |
| type = COM.VT_BSTR; | |
| // intentional fall-through to VT_BSTR case | |
| case COM.VT_BSTR : | |
| // get the address of the memory in which the string resides | |
| int[] hMem = new int[1]; | |
| OS.MoveMemory(hMem, pData + 8, 4); | |
| if (hMem[0] == 0) { | |
| // A VT_BSTR with a null pointer is equivalent to an empty string | |
| stringData = ""; //$NON-NLS-1$ | |
| break; | |
| } | |
| // Get the size of the string from the OS - the size is expressed in number | |
| // of bytes - each unicode character is 2 bytes. | |
| int size = COM.SysStringByteLen(hMem[0]); | |
| if (size > 0){ | |
| // get the unicode character array from the global memory and create a String | |
| char[] buffer = new char[(size + 1) /2]; // add one to avoid rounding errors | |
| COM.MoveMemory(buffer, hMem[0], size); | |
| stringData = new String(buffer); | |
| } else { | |
| stringData = ""; //$NON-NLS-1$ | |
| } | |
| break; | |
| default : | |
| // try coercing it into one of the known forms | |
| int newPData = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, Variant.sizeof); | |
| if (COM.VariantChangeType(newPData, pData, (short) 0, COM.VT_R4) == COM.S_OK) { | |
| setData(newPData); | |
| } else if (COM.VariantChangeType(newPData, pData, (short) 0, COM.VT_I4) == COM.S_OK) { | |
| setData(newPData); | |
| } else if (COM.VariantChangeType(newPData, pData, (short) 0, COM.VT_BSTR) == COM.S_OK) { | |
| setData(newPData); | |
| } | |
| COM.VariantClear(newPData); | |
| OS.GlobalFree(newPData); | |
| break; | |
| } | |
| } | |
| /** | |
| * Returns a string containing a concise, human-readable | |
| * description of the receiver. | |
| * | |
| * @return a string representation of the Variant | |
| */ | |
| public String toString () { | |
| switch (type) { | |
| case COM.VT_BOOL : | |
| return "VT_BOOL{"+booleanData+"}"; | |
| case COM.VT_I1 : | |
| return "VT_I1{"+byteData+"}"; | |
| case COM.VT_I2 : | |
| return "VT_I2{"+shortData+"}"; | |
| case COM.VT_I4 : | |
| return "VT_I4{"+intData+"}"; | |
| case COM.VT_I8 : | |
| return "VT_I8{"+longData+"}"; | |
| case COM.VT_UI2 : | |
| return "VT_UI2{"+charData+"}"; | |
| case COM.VT_R4 : | |
| return "VT_R4{"+floatData+"}"; | |
| case COM.VT_R8 : | |
| return "VT_R8{"+doubleData+"}"; | |
| case COM.VT_BSTR : | |
| return "VT_BSTR{"+stringData+"}"; | |
| case COM.VT_DISPATCH : | |
| return "VT_DISPATCH{"+(dispatchData == null ? 0 : dispatchData.getAddress())+"}"; | |
| case COM.VT_UNKNOWN : | |
| return "VT_UNKNOWN{"+(unknownData == null ? 0 : unknownData.getAddress())+"}"; | |
| case COM.VT_EMPTY : | |
| return "VT_EMPTY"; | |
| case COM.VT_NULL : | |
| return "VT_NULL"; | |
| } | |
| if ((type & COM.VT_BYREF) != 0) { | |
| return "VT_BYREF|"+(type & ~COM.VT_BYREF)+"{"+byRefPtr+"}"; | |
| } | |
| return "Unsupported Type "+type; | |
| } | |
| } |