0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2006 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.swt.ole.win32;
0011:
0012: import org.eclipse.swt.*;
0013: import org.eclipse.swt.internal.ole.win32.*;
0014: import org.eclipse.swt.internal.win32.*;
0015:
0016: /**
0017: *
0018: * A Variant is a generic OLE mechanism for passing data of different types via a common interface.
0019: *
0020: * <p>It is used within the OleAutomation object for getting a property, setting a property or invoking
0021: * a method on an OLE Control or OLE Document.
0022: *
0023: */
0024: public final class Variant {
0025: public static final int sizeof = VARIANT.sizeof;
0026: private short type; // OLE.VT_* type
0027:
0028: private boolean booleanData;
0029: private byte byteData;
0030: private short shortData;
0031: private char charData;
0032: private int intData;
0033: private long longData;
0034: private float floatData;
0035: private double doubleData;
0036: private String stringData;
0037: private int /*long*/byRefPtr;
0038: private IDispatch dispatchData;
0039: private IUnknown unknownData;
0040:
0041: /**
0042: * Invokes platform specific functionality to copy a variant
0043: * into operating system memory.
0044: * <p>
0045: * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
0046: * API for <code>Variant</code>. It is marked public only so that it
0047: * can be shared within the packages provided by SWT. It is not
0048: * available on all platforms, and should never be called from
0049: * application code.
0050: * </p>
0051: *
0052: * @param pVarDest destination pointer to a variant
0053: * @param varSrc source <code>Variant</code>
0054: *
0055: * @since 3.3
0056: */
0057: public static void win32_copy(int /*long*/pVarDest, Variant varSrc) {
0058: varSrc.getData(pVarDest);
0059: }
0060:
0061: /**
0062: * Invokes platform specific functionality to wrap a variant
0063: * that was allocated in operating system memory.
0064: * <p>
0065: * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
0066: * API for <code>Variant</code>. It is marked public only so that it
0067: * can be shared within the packages provided by SWT. It is not
0068: * available on all platforms, and should never be called from
0069: * application code.
0070: * </p>
0071: *
0072: * @param pVariant pointer to a variant
0073: *
0074: * @return a new <code>Variant</code>
0075: *
0076: * @since 3.3
0077: */
0078: public static Variant win32_new(int /*long*/pVariant) {
0079: Variant variant = new Variant();
0080: variant.setData(pVariant);
0081: return variant;
0082: }
0083:
0084: /**
0085: * Create an empty Variant object with type VT_EMPTY.
0086: *
0087: * @since 2.0
0088: */
0089: public Variant() {
0090: type = COM.VT_EMPTY;
0091: }
0092:
0093: /**
0094: * Create a Variant object which represents a Java float as a VT_R4.
0095: *
0096: * @param val the Java float value that this Variant represents
0097: *
0098: */
0099: public Variant(float val) {
0100: type = COM.VT_R4;
0101: floatData = val;
0102:
0103: }
0104:
0105: /**
0106: * Create a Variant object which represents a Java double as a VT_R8.
0107: *
0108: * @param val the Java double value that this Variant represents
0109: *
0110: * @since 3.2
0111: */
0112: public Variant(double val) {
0113: type = COM.VT_R8;
0114: doubleData = val;
0115: }
0116:
0117: /**
0118: * Create a Variant object which represents a Java int as a VT_I4.
0119: *
0120: * @param val the Java int value that this Variant represents
0121: *
0122: */
0123: public Variant(int val) {
0124: type = COM.VT_I4;
0125: intData = val;
0126: }
0127:
0128: /**
0129: * Create a Variant object which contains a reference to the data being transferred.
0130: *
0131: * <p>When creating a VT_BYREF Variant, you must give the full Variant type
0132: * including VT_BYREF such as
0133: *
0134: * <pre><code>short byRefType = OLE.VT_BSTR | OLE.VT_BYREF</code></pre>.
0135: *
0136: * @param ptr a pointer to the data being transferred.
0137: * @param byRefType the type of the data being transferred such as OLE.VT_BSTR | OLE.VT_BYREF
0138: *
0139: */
0140: public Variant(int /*long*/ptr, short byRefType) {
0141: type = byRefType;
0142: byRefPtr = ptr;
0143: }
0144:
0145: /**
0146: * Create a Variant object which represents an IDispatch interface as a VT_Dispatch.
0147: *
0148: * @param automation the OleAutomation object that this Variant represents
0149: *
0150: */
0151: public Variant(OleAutomation automation) {
0152: type = COM.VT_DISPATCH;
0153: dispatchData = new IDispatch(automation.getAddress());
0154: }
0155:
0156: /**
0157: * Create a Variant object which represents an IDispatch interface as a VT_Dispatch.
0158: * <p>The caller is expected to have appropriately invoked unknown.AddRef() before creating
0159: * this Variant.
0160: *
0161: * @since 2.0
0162: *
0163: * @param idispatch the IDispatch object that this Variant represents
0164: *
0165: */
0166: public Variant(IDispatch idispatch) {
0167: type = COM.VT_DISPATCH;
0168: dispatchData = idispatch;
0169: }
0170:
0171: /**
0172: * Create a Variant object which represents an IUnknown interface as a VT_UNKNOWN.
0173: *
0174: * <p>The caller is expected to have appropriately invoked unknown.AddRef() before creating
0175: * this Variant.
0176: *
0177: * @param unknown the IUnknown object that this Variant represents
0178: *
0179: */
0180: public Variant(IUnknown unknown) {
0181: type = COM.VT_UNKNOWN;
0182: unknownData = unknown;
0183: }
0184:
0185: /**
0186: * Create a Variant object which represents a Java long as a VT_I8.
0187: *
0188: * @param val the Java long value that this Variant represents
0189: *
0190: *@since 3.2
0191: */
0192: public Variant(long val) {
0193: type = COM.VT_I8;
0194: longData = val;
0195: }
0196:
0197: /**
0198: * Create a Variant object which represents a Java String as a VT_BSTR.
0199: *
0200: * @param string the Java String value that this Variant represents
0201: *
0202: */
0203: public Variant(String string) {
0204: type = COM.VT_BSTR;
0205: stringData = string;
0206: }
0207:
0208: /**
0209: * Create a Variant object which represents a Java short as a VT_I2.
0210: *
0211: * @param val the Java short value that this Variant represents
0212: *
0213: */
0214: public Variant(short val) {
0215: type = COM.VT_I2;
0216: shortData = val;
0217: }
0218:
0219: /**
0220: * Create a Variant object which represents a Java boolean as a VT_BOOL.
0221: *
0222: * @param val the Java boolean value that this Variant represents
0223: *
0224: */
0225: public Variant(boolean val) {
0226: type = COM.VT_BOOL;
0227: booleanData = val;
0228: }
0229:
0230: /**
0231: * Calling dispose will release resources associated with this Variant.
0232: * If the resource is an IDispatch or IUnknown interface, Release will be called.
0233: * If the resource is a ByRef pointer, nothing is released.
0234: *
0235: * @since 2.1
0236: */
0237: public void dispose() {
0238: if ((type & COM.VT_BYREF) == COM.VT_BYREF) {
0239: return;
0240: }
0241:
0242: switch (type) {
0243: case COM.VT_DISPATCH:
0244: dispatchData.Release();
0245: break;
0246: case COM.VT_UNKNOWN:
0247: unknownData.Release();
0248: break;
0249: }
0250:
0251: }
0252:
0253: /**
0254: * Returns the OleAutomation object represented by this Variant.
0255: *
0256: * <p>If this Variant does not contain an OleAutomation object, an attempt is made to
0257: * coerce the Variant type into an OleAutomation object. If this fails, an error is
0258: * thrown. Note that OleAutomation objects must be disposed when no longer
0259: * needed.
0260: *
0261: * @return the OleAutomation object represented by this Variant
0262: *
0263: * @exception SWTException <ul>
0264: * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into an OleAutomation object</li>
0265: * </ul>
0266: */
0267: public OleAutomation getAutomation() {
0268: if (type == COM.VT_EMPTY) {
0269: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
0270: }
0271: if (type == COM.VT_DISPATCH) {
0272: return new OleAutomation(dispatchData);
0273: }
0274: // try to coerce the value to the desired type
0275: int /*long*/oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0276: | COM.GMEM_ZEROINIT, sizeof);
0277: int /*long*/newPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0278: | COM.GMEM_ZEROINIT, sizeof);
0279: try {
0280: getData(oldPtr);
0281: int result = COM.VariantChangeType(newPtr, oldPtr,
0282: (short) 0, COM.VT_DISPATCH);
0283: if (result != COM.S_OK)
0284: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
0285: Variant autoVar = new Variant();
0286: autoVar.setData(newPtr);
0287: return autoVar.getAutomation();
0288: } finally {
0289: COM.VariantClear(oldPtr);
0290: OS.GlobalFree(oldPtr);
0291: COM.VariantClear(newPtr); // Note: This must absolutely be done AFTER the
0292: // OleAutomation object is created as Variant Clear
0293: // will result in a Release being performed on the
0294: // Dispatch object
0295: OS.GlobalFree(newPtr);
0296: }
0297: }
0298:
0299: /**
0300: * Returns the IDispatch object represented by this Variant.
0301: *
0302: * <p>If this Variant does not contain an IDispatch object, an attempt is made to
0303: * coerce the Variant type into an IDIspatch object. If this fails, an error is
0304: * thrown.
0305: *
0306: * @since 2.0
0307: *
0308: * @return the IDispatch object represented by this Variant
0309: *
0310: * @exception SWTException <ul>
0311: * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into an IDispatch object</li>
0312: * </ul>
0313: */
0314: public IDispatch getDispatch() {
0315: if (type == COM.VT_EMPTY) {
0316: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
0317: }
0318: if (type == COM.VT_DISPATCH) {
0319: return dispatchData;
0320: }
0321: // try to coerce the value to the desired type
0322: int /*long*/oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0323: | COM.GMEM_ZEROINIT, sizeof);
0324: int /*long*/newPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0325: | COM.GMEM_ZEROINIT, sizeof);
0326: try {
0327: getData(oldPtr);
0328: int result = COM.VariantChangeType(newPtr, oldPtr,
0329: (short) 0, COM.VT_DISPATCH);
0330: if (result != COM.S_OK)
0331: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
0332: Variant autoVar = new Variant();
0333: autoVar.setData(newPtr);
0334: return autoVar.getDispatch();
0335: } finally {
0336: COM.VariantClear(oldPtr);
0337: OS.GlobalFree(oldPtr);
0338: COM.VariantClear(newPtr); // Note: This must absolutely be done AFTER the
0339: // OleAutomation object is created as Variant Clear
0340: // will result in a Release being performed on the
0341: // Dispatch object
0342: OS.GlobalFree(newPtr);
0343: }
0344: }
0345:
0346: /**
0347: * Returns the Java boolean represented by this Variant.
0348: *
0349: * <p>If this Variant does not contain a Java boolean, an attempt is made to
0350: * coerce the Variant type into a Java boolean. If this fails, an error is thrown.
0351: *
0352: * @return the Java boolean represented by this Variant
0353: *
0354: * @exception SWTException <ul>
0355: * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a boolean</li>
0356: * </ul>
0357: *
0358: */
0359: public boolean getBoolean() {
0360: if (type == COM.VT_EMPTY) {
0361: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
0362: }
0363: if (type == COM.VT_BOOL) {
0364: return booleanData;
0365: }
0366:
0367: // try to coerce the value to the desired type
0368: int /*long*/oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0369: | COM.GMEM_ZEROINIT, sizeof);
0370: int /*long*/newPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0371: | COM.GMEM_ZEROINIT, sizeof);
0372: try {
0373: getData(oldPtr);
0374: int result = COM.VariantChangeType(newPtr, oldPtr,
0375: (short) 0, COM.VT_BOOL);
0376: if (result != COM.S_OK)
0377: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
0378: Variant boolVar = new Variant();
0379: boolVar.setData(newPtr);
0380: return boolVar.getBoolean();
0381: } finally {
0382: COM.VariantClear(oldPtr);
0383: OS.GlobalFree(oldPtr);
0384: COM.VariantClear(newPtr);
0385: OS.GlobalFree(newPtr);
0386: }
0387: }
0388:
0389: /**
0390: * Returns a pointer to the referenced data represented by this Variant.
0391: *
0392: * <p>If this Variant does not contain a reference to data, zero is returned.
0393: *
0394: * @return a pointer to the referenced data represented by this Variant or 0
0395: *
0396: */
0397: public int /*long*/getByRef() {
0398: if (type == COM.VT_EMPTY) {
0399: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
0400: }
0401: if ((type & COM.VT_BYREF) == COM.VT_BYREF) {
0402: return byRefPtr;
0403: }
0404:
0405: return 0;
0406: }
0407:
0408: /**
0409: * Returns the Java byte represented by this Variant.
0410: *
0411: * <p>If this Variant does not contain a Java byte, an attempt is made to
0412: * coerce the Variant type into a Java byte. If this fails, an error is thrown.
0413: *
0414: * @return the Java byte represented by this Variant
0415: *
0416: * @exception SWTException <ul>
0417: * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a byte</li>
0418: * </ul>
0419: *
0420: * @since 3.3
0421: */
0422: public byte getByte() {
0423: if (type == COM.VT_EMPTY) {
0424: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
0425: }
0426: if (type == COM.VT_I1) {
0427: return byteData;
0428: }
0429:
0430: // try to coerce the value to the desired type
0431: int /*long*/oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0432: | COM.GMEM_ZEROINIT, sizeof);
0433: int /*long*/newPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0434: | COM.GMEM_ZEROINIT, sizeof);
0435: try {
0436: getData(oldPtr);
0437: int result = COM.VariantChangeType(newPtr, oldPtr,
0438: (short) 0, COM.VT_I1);
0439: if (result != COM.S_OK)
0440: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
0441: Variant byteVar = new Variant();
0442: byteVar.setData(newPtr);
0443: return byteVar.getByte();
0444: } finally {
0445: COM.VariantClear(oldPtr);
0446: OS.GlobalFree(oldPtr);
0447: COM.VariantClear(newPtr);
0448: OS.GlobalFree(newPtr);
0449: }
0450: }
0451:
0452: /**
0453: * Returns the Java char represented by this Variant.
0454: *
0455: * <p>If this Variant does not contain a Java char, an attempt is made to
0456: * coerce the Variant type into a Java char. If this fails, an error is thrown.
0457: *
0458: * @return the Java char represented by this Variant
0459: *
0460: * @exception SWTException <ul>
0461: * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a char</li>
0462: * </ul>
0463: *
0464: * @since 3.3
0465: */
0466: public char getChar() {
0467: if (type == COM.VT_EMPTY) {
0468: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
0469: }
0470: if (type == COM.VT_UI2) {
0471: return charData;
0472: }
0473:
0474: // try to coerce the value to the desired type
0475: int /*long*/oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0476: | COM.GMEM_ZEROINIT, sizeof);
0477: int /*long*/newPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0478: | COM.GMEM_ZEROINIT, sizeof);
0479: try {
0480: getData(oldPtr);
0481: int result = COM.VariantChangeType(newPtr, oldPtr,
0482: (short) 0, COM.VT_UI2);
0483: if (result != COM.S_OK)
0484: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
0485: Variant charVar = new Variant();
0486: charVar.setData(newPtr);
0487: return charVar.getChar();
0488: } finally {
0489: COM.VariantClear(oldPtr);
0490: OS.GlobalFree(oldPtr);
0491: COM.VariantClear(newPtr);
0492: OS.GlobalFree(newPtr);
0493: }
0494: }
0495:
0496: void getData(int /*long*/pData) {
0497: if (pData == 0)
0498: OLE.error(OLE.ERROR_OUT_OF_MEMORY);
0499:
0500: COM.VariantInit(pData);
0501:
0502: if ((type & COM.VT_BYREF) == COM.VT_BYREF) {
0503: //TODO - use VARIANT structure
0504: COM.MoveMemory(pData, new short[] { type }, 2);
0505: COM.MoveMemory(pData + 8, new int /*long*/[] { byRefPtr },
0506: OS.PTR_SIZEOF);
0507: return;
0508: }
0509:
0510: switch (type) {
0511: case COM.VT_EMPTY:
0512: case COM.VT_NULL:
0513: COM.MoveMemory(pData, new short[] { type }, 2);
0514: break;
0515: case COM.VT_BOOL:
0516: COM.MoveMemory(pData, new short[] { type }, 2);
0517: COM.MoveMemory(pData + 8,
0518: new short[] { (booleanData) ? COM.VARIANT_TRUE
0519: : COM.VARIANT_FALSE }, 2);
0520: break;
0521: case COM.VT_I1:
0522: COM.MoveMemory(pData, new short[] { type }, 2);
0523: COM.MoveMemory(pData + 8, new byte[] { byteData }, 1);
0524: break;
0525: case COM.VT_I2:
0526: COM.MoveMemory(pData, new short[] { type }, 2);
0527: COM.MoveMemory(pData + 8, new short[] { shortData }, 2);
0528: break;
0529: case COM.VT_UI2:
0530: COM.MoveMemory(pData, new short[] { type }, 2);
0531: COM.MoveMemory(pData + 8, new char[] { charData }, 2);
0532: break;
0533: case COM.VT_I4:
0534: COM.MoveMemory(pData, new short[] { type }, 2);
0535: COM.MoveMemory(pData + 8, new int[] { intData }, 4);
0536: break;
0537: case COM.VT_I8:
0538: COM.MoveMemory(pData, new short[] { type }, 2);
0539: COM.MoveMemory(pData + 8, new long[] { longData }, 8);
0540: break;
0541: case COM.VT_R4:
0542: COM.MoveMemory(pData, new short[] { type }, 2);
0543: COM.MoveMemory(pData + 8, new float[] { floatData }, 4);
0544: break;
0545: case COM.VT_R8:
0546: COM.MoveMemory(pData, new short[] { type }, 2);
0547: COM.MoveMemory(pData + 8, new double[] { doubleData }, 8);
0548: break;
0549: case COM.VT_DISPATCH:
0550: dispatchData.AddRef();
0551: COM.MoveMemory(pData, new short[] { type }, 2);
0552: COM.MoveMemory(pData + 8,
0553: new int /*long*/[] { dispatchData.getAddress() },
0554: OS.PTR_SIZEOF);
0555: break;
0556: case COM.VT_UNKNOWN:
0557: unknownData.AddRef();
0558: COM.MoveMemory(pData, new short[] { type }, 2);
0559: COM.MoveMemory(pData + 8, new int /*long*/[] { unknownData
0560: .getAddress() }, OS.PTR_SIZEOF);
0561: break;
0562: case COM.VT_BSTR:
0563: COM.MoveMemory(pData, new short[] { type }, 2);
0564: char[] data = (stringData + "\0").toCharArray();
0565: int /*long*/ptr = COM.SysAllocString(data);
0566: COM.MoveMemory(pData + 8, new int /*long*/[] { ptr },
0567: OS.PTR_SIZEOF);
0568: break;
0569:
0570: default:
0571: OLE.error(SWT.ERROR_NOT_IMPLEMENTED);
0572: }
0573: }
0574:
0575: /**
0576: * Returns the Java double represented by this Variant.
0577: *
0578: * <p>If this Variant does not contain a Java double, an attempt is made to
0579: * coerce the Variant type into a Java double. If this fails, an error is thrown.
0580: *
0581: * @return the Java double represented by this Variant
0582: *
0583: * @exception SWTException <ul>
0584: * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a double</li>
0585: * </ul>
0586: *
0587: * @since 3.2
0588: */
0589: public double getDouble() {
0590: if (type == COM.VT_EMPTY) {
0591: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
0592: }
0593: if (type == COM.VT_R8) {
0594: return doubleData;
0595: }
0596:
0597: // try to coerce the value to the desired type
0598: int /*long*/oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0599: | COM.GMEM_ZEROINIT, sizeof);
0600: int /*long*/newPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0601: | COM.GMEM_ZEROINIT, sizeof);
0602: try {
0603: getData(oldPtr);
0604: int result = COM.VariantChangeType(newPtr, oldPtr,
0605: (short) 0, COM.VT_R8);
0606: if (result != COM.S_OK)
0607: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
0608: Variant doubleVar = new Variant();
0609: doubleVar.setData(newPtr);
0610: return doubleVar.getDouble();
0611: } finally {
0612: COM.VariantClear(oldPtr);
0613: OS.GlobalFree(oldPtr);
0614: COM.VariantClear(newPtr);
0615: OS.GlobalFree(newPtr);
0616: }
0617: }
0618:
0619: /**
0620: * Returns the Java float represented by this Variant.
0621: *
0622: * <p>If this Variant does not contain a Java float, an attempt is made to
0623: * coerce the Variant type into a Java float. If this fails, an error is thrown.
0624: *
0625: * @return the Java float represented by this Variant
0626: *
0627: * @exception SWTException <ul>
0628: * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a float</li>
0629: * </ul>
0630: */
0631: public float getFloat() {
0632: if (type == COM.VT_EMPTY) {
0633: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
0634: }
0635: if (type == COM.VT_R4) {
0636: return floatData;
0637: }
0638:
0639: // try to coerce the value to the desired type
0640: int /*long*/oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0641: | COM.GMEM_ZEROINIT, sizeof);
0642: int /*long*/newPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0643: | COM.GMEM_ZEROINIT, sizeof);
0644: try {
0645: getData(oldPtr);
0646: int result = COM.VariantChangeType(newPtr, oldPtr,
0647: (short) 0, COM.VT_R4);
0648: if (result != COM.S_OK)
0649: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
0650: Variant floatVar = new Variant();
0651: floatVar.setData(newPtr);
0652: return floatVar.getFloat();
0653: } finally {
0654: COM.VariantClear(oldPtr);
0655: OS.GlobalFree(oldPtr);
0656: COM.VariantClear(newPtr);
0657: OS.GlobalFree(newPtr);
0658: }
0659:
0660: }
0661:
0662: /**
0663: * Returns the Java int represented by this Variant.
0664: *
0665: * <p>If this Variant does not contain a Java int, an attempt is made to
0666: * coerce the Variant type into a Java int. If this fails, an error is thrown.
0667: *
0668: * @return the Java int represented by this Variant
0669: *
0670: * @exception SWTException <ul>
0671: * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a int</li>
0672: * </ul>
0673: */
0674: public int getInt() {
0675: if (type == COM.VT_EMPTY) {
0676: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
0677: }
0678: if (type == COM.VT_I4) {
0679: return intData;
0680: }
0681:
0682: // try to coerce the value to the desired type
0683: int /*long*/oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0684: | COM.GMEM_ZEROINIT, sizeof);
0685: int /*long*/newPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0686: | COM.GMEM_ZEROINIT, sizeof);
0687: try {
0688: getData(oldPtr);
0689: int result = COM.VariantChangeType(newPtr, oldPtr,
0690: (short) 0, COM.VT_I4);
0691: if (result != COM.S_OK)
0692: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
0693: Variant intVar = new Variant();
0694: intVar.setData(newPtr);
0695: return intVar.getInt();
0696: } finally {
0697: COM.VariantClear(oldPtr);
0698: OS.GlobalFree(oldPtr);
0699: COM.VariantClear(newPtr);
0700: OS.GlobalFree(newPtr);
0701: }
0702: }
0703:
0704: /**
0705: * Returns the Java long represented by this Variant.
0706: *
0707: * <p>If this Variant does not contain a Java long, an attempt is made to
0708: * coerce the Variant type into a Java long. If this fails, an error is thrown.
0709: *
0710: * @return the Java long represented by this Variant
0711: *
0712: * @exception SWTException <ul>
0713: * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a long</li>
0714: * </ul>
0715: *
0716: * @since 3.2
0717: */
0718: public long getLong() {
0719: if (type == COM.VT_EMPTY) {
0720: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
0721: }
0722: if (type == COM.VT_I8) {
0723: return longData;
0724: }
0725:
0726: // try to coerce the value to the desired type
0727: int /*long*/oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0728: | COM.GMEM_ZEROINIT, sizeof);
0729: int /*long*/newPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0730: | COM.GMEM_ZEROINIT, sizeof);
0731: try {
0732: getData(oldPtr);
0733: int result = COM.VariantChangeType(newPtr, oldPtr,
0734: (short) 0, COM.VT_I8);
0735: if (result != COM.S_OK)
0736: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
0737: Variant longVar = new Variant();
0738: longVar.setData(newPtr);
0739: return longVar.getLong();
0740: } finally {
0741: COM.VariantClear(oldPtr);
0742: OS.GlobalFree(oldPtr);
0743: COM.VariantClear(newPtr);
0744: OS.GlobalFree(newPtr);
0745: }
0746: }
0747:
0748: /**
0749: * Returns the Java short represented by this Variant.
0750: *
0751: * <p>If this Variant does not contain a Java short, an attempt is made to
0752: * coerce the Variant type into a Java short. If this fails, an error is thrown.
0753: *
0754: * @return the Java short represented by this Variant
0755: *
0756: * @exception SWTException <ul>
0757: * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a short</li>
0758: * </ul>
0759: */
0760: public short getShort() {
0761: if (type == COM.VT_EMPTY) {
0762: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
0763: }
0764: if (type == COM.VT_I2) {
0765: return shortData;
0766: }
0767:
0768: // try to coerce the value to the desired type
0769: int /*long*/oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0770: | COM.GMEM_ZEROINIT, sizeof);
0771: int /*long*/newPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0772: | COM.GMEM_ZEROINIT, sizeof);
0773: try {
0774: getData(oldPtr);
0775: int result = COM.VariantChangeType(newPtr, oldPtr,
0776: (short) 0, COM.VT_I2);
0777: if (result != COM.S_OK)
0778: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
0779: Variant shortVar = new Variant();
0780: shortVar.setData(newPtr);
0781: return shortVar.getShort();
0782: } finally {
0783: COM.VariantClear(oldPtr);
0784: OS.GlobalFree(oldPtr);
0785: COM.VariantClear(newPtr);
0786: OS.GlobalFree(newPtr);
0787: }
0788:
0789: }
0790:
0791: /**
0792: * Returns the Java String represented by this Variant.
0793: *
0794: * <p>If this Variant does not contain a Java String, an attempt is made to
0795: * coerce the Variant type into a Java String. If this fails, an error is thrown.
0796: *
0797: * @return the Java String represented by this Variant
0798: *
0799: * @exception SWTException <ul>
0800: * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a String</li>
0801: * </ul>
0802: */
0803: public String getString() {
0804: if (type == COM.VT_EMPTY) {
0805: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
0806: }
0807: if (type == COM.VT_BSTR) {
0808: return stringData;
0809: }
0810:
0811: // try to coerce the value to the desired type
0812: int /*long*/oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0813: | COM.GMEM_ZEROINIT, sizeof);
0814: int /*long*/newPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0815: | COM.GMEM_ZEROINIT, sizeof);
0816: try {
0817: getData(oldPtr);
0818: int result = COM.VariantChangeType(newPtr, oldPtr,
0819: (short) 0, COM.VT_BSTR);
0820: if (result != COM.S_OK)
0821: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
0822:
0823: Variant stringVar = new Variant();
0824: stringVar.setData(newPtr);
0825: return stringVar.getString();
0826:
0827: } finally {
0828: COM.VariantClear(oldPtr);
0829: OS.GlobalFree(oldPtr);
0830: COM.VariantClear(newPtr);
0831: OS.GlobalFree(newPtr);
0832: }
0833: }
0834:
0835: /**
0836: * Returns the type of the variant type. This will be an OLE.VT_* value or
0837: * a bitwise combination of OLE.VT_* values as in the case of
0838: * OLE.VT_BSTR | OLE.VT_BYREF.
0839: *
0840: * @return the type of the variant data
0841: *
0842: * @since 2.0
0843: */
0844: public short getType() {
0845: return type;
0846: }
0847:
0848: /**
0849: * Returns the IUnknown object represented by this Variant.
0850: *
0851: * <p>If this Variant does not contain an IUnknown object, an attempt is made to
0852: * coerce the Variant type into an IUnknown object. If this fails, an error is
0853: * thrown.
0854: *
0855: * @return the IUnknown object represented by this Variant
0856: *
0857: * @exception SWTException <ul>
0858: * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into
0859: * an IUnknown object</li>
0860: * </ul>
0861: */
0862: public IUnknown getUnknown() {
0863: if (type == COM.VT_EMPTY) {
0864: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
0865: }
0866: if (type == COM.VT_UNKNOWN) {
0867: return unknownData;
0868: }
0869:
0870: // try to coerce the value to the desired type
0871: int /*long*/oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0872: | COM.GMEM_ZEROINIT, sizeof);
0873: int /*long*/newPtr = OS.GlobalAlloc(COM.GMEM_FIXED
0874: | COM.GMEM_ZEROINIT, sizeof);
0875: try {
0876: getData(oldPtr);
0877: int result = COM.VariantChangeType(newPtr, oldPtr,
0878: (short) 0, COM.VT_UNKNOWN);
0879: if (result != COM.S_OK)
0880: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
0881: Variant unknownVar = new Variant();
0882: unknownVar.setData(newPtr);
0883: return unknownVar.getUnknown();
0884: } finally {
0885: COM.VariantClear(oldPtr);
0886: OS.GlobalFree(oldPtr);
0887: COM.VariantClear(newPtr); // Note: This must absolutely be done AFTER the
0888: // IUnknown object is created as Variant Clear
0889: // will result in a Release being performed on the
0890: // Dispatch object
0891: OS.GlobalFree(newPtr);
0892: }
0893: }
0894:
0895: /**
0896: * Update the by reference value of this variant with a new boolean value.
0897: *
0898: * @param val the new boolean value
0899: *
0900: * @exception SWTException <ul>
0901: * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not
0902: * a (VT_BYREF | VT_BOOL) object</li>
0903: * </ul>
0904: *
0905: * @since 2.1
0906: */
0907: public void setByRef(boolean val) {
0908: if ((type & COM.VT_BYREF) == 0 || (type & COM.VT_BOOL) == 0) {
0909: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE);
0910: }
0911: COM.MoveMemory(byRefPtr, new short[] { val ? COM.VARIANT_TRUE
0912: : COM.VARIANT_FALSE }, 2);
0913: }
0914:
0915: /**
0916: * Update the by reference value of this variant with a new float value.
0917: *
0918: * @param val the new float value
0919: *
0920: * @exception SWTException <ul>
0921: * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not
0922: * a (VT_BYREF | VT_R4) object</li>
0923: * </ul>
0924: *
0925: * @since 2.1
0926: */
0927: public void setByRef(float val) {
0928: if ((type & COM.VT_BYREF) == 0 || (type & COM.VT_R4) == 0) {
0929: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE);
0930: }
0931: COM.MoveMemory(byRefPtr, new float[] { val }, 4);
0932: }
0933:
0934: /**
0935: * Update the by reference value of this variant with a new integer value.
0936: *
0937: * @param val the new integer value
0938: *
0939: * @exception SWTException <ul>
0940: * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not a (VT_BYREF | VT_I4) object</li>
0941: * </ul>
0942: *
0943: * @since 2.1
0944: */
0945: public void setByRef(int /*long*/val) {
0946: if ((type & COM.VT_BYREF) == 0 || (type & COM.VT_I4) == 0) {
0947: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE);
0948: }
0949: COM.MoveMemory(byRefPtr, new int /*long*/[] { val },
0950: OS.PTR_SIZEOF);
0951: }
0952:
0953: /**
0954: * Update the by reference value of this variant with a new short value.
0955: *
0956: * @param val the new short value
0957: *
0958: * @exception SWTException <ul>
0959: * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not a (VT_BYREF | VT_I2) object
0960: * </ul>
0961: *
0962: * @since 2.1
0963: */
0964: public void setByRef(short val) {
0965: if ((type & COM.VT_BYREF) == 0 || (type & COM.VT_I2) == 0) {
0966: OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE);
0967: }
0968: COM.MoveMemory(byRefPtr, new short[] { val }, 2);
0969: }
0970:
0971: void setData(int /*long*/pData) {
0972: if (pData == 0)
0973: OLE.error(OLE.ERROR_INVALID_ARGUMENT);
0974:
0975: //TODO - use VARIANT structure
0976: short[] dataType = new short[1];
0977: COM.MoveMemory(dataType, pData, 2);
0978: type = dataType[0];
0979:
0980: if ((type & COM.VT_BYREF) == COM.VT_BYREF) {
0981: int /*long*/[] newByRefPtr = new int /*long*/[1];
0982: OS.MoveMemory(newByRefPtr, pData + 8, OS.PTR_SIZEOF);
0983: byRefPtr = newByRefPtr[0];
0984: return;
0985: }
0986:
0987: switch (type) {
0988: case COM.VT_EMPTY:
0989: case COM.VT_NULL:
0990: break;
0991: case COM.VT_BOOL:
0992: short[] newBooleanData = new short[1];
0993: COM.MoveMemory(newBooleanData, pData + 8, 2);
0994: booleanData = (newBooleanData[0] != COM.VARIANT_FALSE);
0995: break;
0996: case COM.VT_I1:
0997: byte[] newByteData = new byte[1];
0998: COM.MoveMemory(newByteData, pData + 8, 1);
0999: byteData = newByteData[0];
1000: break;
1001: case COM.VT_I2:
1002: short[] newShortData = new short[1];
1003: COM.MoveMemory(newShortData, pData + 8, 2);
1004: shortData = newShortData[0];
1005: break;
1006: case COM.VT_UI2:
1007: char[] newCharData = new char[1];
1008: COM.MoveMemory(newCharData, pData + 8, 2);
1009: charData = newCharData[0];
1010: break;
1011: case COM.VT_I4:
1012: int[] newIntData = new int[1];
1013: OS.MoveMemory(newIntData, pData + 8, 4);
1014: intData = newIntData[0];
1015: break;
1016: case COM.VT_I8:
1017: long[] newLongData = new long[1];
1018: OS.MoveMemory(newLongData, pData + 8, 8);
1019: longData = newLongData[0];
1020: break;
1021: case COM.VT_R4:
1022: float[] newFloatData = new float[1];
1023: COM.MoveMemory(newFloatData, pData + 8, 4);
1024: floatData = newFloatData[0];
1025: break;
1026: case COM.VT_R8:
1027: double[] newDoubleData = new double[1];
1028: COM.MoveMemory(newDoubleData, pData + 8, 8);
1029: doubleData = newDoubleData[0];
1030: break;
1031: case COM.VT_DISPATCH: {
1032: int /*long*/[] ppvObject = new int /*long*/[1];
1033: OS.MoveMemory(ppvObject, pData + 8, OS.PTR_SIZEOF);
1034: if (ppvObject[0] == 0) {
1035: type = COM.VT_EMPTY;
1036: break;
1037: }
1038: dispatchData = new IDispatch(ppvObject[0]);
1039: dispatchData.AddRef();
1040: break;
1041: }
1042: case COM.VT_UNKNOWN: {
1043: int /*long*/[] ppvObject = new int /*long*/[1];
1044: OS.MoveMemory(ppvObject, pData + 8, OS.PTR_SIZEOF);
1045: if (ppvObject[0] == 0) {
1046: type = COM.VT_EMPTY;
1047: break;
1048: }
1049: unknownData = new IUnknown(ppvObject[0]);
1050: unknownData.AddRef();
1051: break;
1052: }
1053: case COM.VT_BSTR:
1054: // get the address of the memory in which the string resides
1055: int /*long*/[] hMem = new int /*long*/[1];
1056: OS.MoveMemory(hMem, pData + 8, OS.PTR_SIZEOF);
1057: if (hMem[0] == 0) {
1058: type = COM.VT_EMPTY;
1059: break;
1060: }
1061: // Get the size of the string from the OS - the size is expressed in number
1062: // of bytes - each unicode character is 2 bytes.
1063: int size = COM.SysStringByteLen(hMem[0]);
1064: if (size > 0) {
1065: // get the unicode character array from the global memory and create a String
1066: char[] buffer = new char[(size + 1) / 2]; // add one to avoid rounding errors
1067: COM.MoveMemory(buffer, hMem[0], size);
1068: stringData = new String(buffer);
1069: } else {
1070: stringData = ""; //$NON-NLS-1$
1071: }
1072: break;
1073:
1074: default:
1075: // try coercing it into one of the known forms
1076: int /*long*/newPData = OS.GlobalAlloc(OS.GMEM_FIXED
1077: | OS.GMEM_ZEROINIT, sizeof);
1078: if (COM.VariantChangeType(newPData, pData, (short) 0,
1079: COM.VT_R4) == COM.S_OK) {
1080: setData(newPData);
1081: } else if (COM.VariantChangeType(newPData, pData,
1082: (short) 0, COM.VT_I4) == COM.S_OK) {
1083: setData(newPData);
1084: } else if (COM.VariantChangeType(newPData, pData,
1085: (short) 0, COM.VT_BSTR) == COM.S_OK) {
1086: setData(newPData);
1087: }
1088: COM.VariantClear(newPData);
1089: OS.GlobalFree(newPData);
1090: break;
1091: }
1092: }
1093:
1094: /**
1095: * Returns a string containing a concise, human-readable
1096: * description of the receiver.
1097: *
1098: * @return a string representation of the Variant
1099: */
1100: public String toString() {
1101: switch (type) {
1102: case COM.VT_BOOL:
1103: return "VT_BOOL{" + booleanData + "}";
1104: case COM.VT_I1:
1105: return "VT_I1{" + byteData + "}";
1106: case COM.VT_I2:
1107: return "VT_I2{" + shortData + "}";
1108: case COM.VT_UI2:
1109: return "VT_UI2{" + charData + "}";
1110: case COM.VT_I4:
1111: return "VT_I4{" + intData + "}";
1112: case COM.VT_I8:
1113: return "VT_I8{" + longData + "}";
1114: case COM.VT_R4:
1115: return "VT_R4{" + floatData + "}";
1116: case COM.VT_R8:
1117: return "VT_R8{" + doubleData + "}";
1118: case COM.VT_BSTR:
1119: return "VT_BSTR{" + stringData + "}";
1120: case COM.VT_DISPATCH:
1121: return "VT_DISPATCH{"
1122: + (dispatchData == null ? 0 : dispatchData
1123: .getAddress()) + "}";
1124: case COM.VT_UNKNOWN:
1125: return "VT_UNKNOWN{"
1126: + (unknownData == null ? 0 : unknownData
1127: .getAddress()) + "}";
1128: case COM.VT_EMPTY:
1129: return "VT_EMPTY";
1130: case COM.VT_NULL:
1131: return "VT_NULL";
1132: }
1133: if ((type & COM.VT_BYREF) != 0) {
1134: return "VT_BYREF|" + (type & ~COM.VT_BYREF) + "{"
1135: + byRefPtr + "}";
1136: }
1137: return "Unsupported Type " + type;
1138: }
1139: }
|