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