gt: 			float[] newFloatData = new float[1];
context: /*******************************************************************************
   * Copyright (c) 2000, 2010 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
   *******************************************************************************/
  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 {
  	/**
  	* The size in bytes of a native VARIANT struct.
  	*/
  	public static final int sizeof = VARIANT.sizeof;
  
  	private short type; // OLE.VT_* type
  	private boolean booleanData;
  	private byte    byteData;
  	private short   shortData;
  	private char    charData;
  	private int     intData;
  	private long    longData;
  	private float   floatData;
  	private double  doubleData;
  	private String  stringData;
  	private int /*long*/     byRefPtr;
  	private IDispatch dispatchData;
  	private IUnknown unknownData;
  
  	/**
  	 * A shared Variant instance with type VT_NULL.
  	 * 
  	 * @since 3.7
  	 */
  	public static final Variant NULL;
  	static {
  		NULL = new Variant ();
  		NULL.type = COM.VT_NULL;
  	}
  
  /**	 
   * 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>
   *
   * @noreference This method is not intended to be referenced by clients.
   *
   * @since 3.3
   */
  public static void win32_copy (int /*long*/ pVarDest, Variant varSrc) {
  	varSrc.getData (pVarDest);
  }
  
  /**	 
   * Invokes platform specific functionality to wrap a variant
   * that was allocated in 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 pVariant pointer to a variant
   *
   * @return a new <code>Variant</code>
   * 
   * @noreference This method is not intended to be referenced by clients.
   *
   * @since 3.3
   */
  public static Variant win32_new (int /*long*/ pVariant) {
  	Variant variant = new Variant ();
  	variant.setData (pVariant);
  	return variant;
  }
  
  /**
   * 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 /*long*/ 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 /*long*/ oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
  	int /*long*/ newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
  	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);
  		Variant 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);
  	}
  }
  /**
   * 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 /*long*/ oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
  	int /*long*/ newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
  	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);
  		Variant 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);
  	}
  }
  /**
   * 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 /*long*/ oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
  	int /*long*/ 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 /*long*/ 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 /*long*/ oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
  	int /*long*/ 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 /*long*/ oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
  	int /*long*/ 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 /*long*/ pData){
  	if (pData == 0) OLE.error(OLE.ERROR_OUT_OF_MEMORY);
  	
  	COM.VariantInit(pData);
  
  	if ((type & COM.VT_BYREF) == COM.VT_BYREF) {
  		//TODO - use VARIANT structure
  		COM.MoveMemory(pData, new short[] {type}, 2);
  		COM.MoveMemory(pData + 8, new int /*long*/[]{byRefPtr}, OS.PTR_SIZEOF);
  		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 short[]{(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_UI2 :
  			COM.MoveMemory(pData, new short[] {type}, 2);
  			COM.MoveMemory(pData + 8, new char[]{charData}, 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);
  			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 /*long*/[]{dispatchData.getAddress()}, OS.PTR_SIZEOF);
  			break;
  		case COM.VT_UNKNOWN :
  			unknownData.AddRef();
  			COM.MoveMemory(pData, new short[] {type}, 2);
  			COM.MoveMemory(pData + 8, new int /*long*/[]{unknownData.getAddress()}, OS.PTR_SIZEOF);
  			break;
  		case COM.VT_BSTR :
  			COM.MoveMemory(pData, new short[] {type}, 2);
  			char[] data = (stringData+"\0").toCharArray();
  			int /*long*/ ptr = COM.SysAllocString(data);
  			COM.MoveMemory(pData + 8, new int /*long*/[] {ptr}, OS.PTR_SIZEOF);
  			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 /*long*/ oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
      int /*long*/ 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 /*long*/ oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
  	int /*long*/ 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 /*long*/ oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
  	int /*long*/ 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 /*long*/ oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
  	int /*long*/ 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 /*long*/ oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
  	int /*long*/ 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 /*long*/ oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
  	int /*long*/ 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 /*long*/ oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
  	int /*long*/ newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
  	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);
  		Variant 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);
  	}
  }
  /**
   * 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 /*long*/ 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 /*long*/[]{val}, OS.PTR_SIZEOF);
  }
  /**
   * 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 /*long*/ pData){
  	if (pData == 0) OLE.error(OLE.ERROR_INVALID_ARGUMENT);
  
  	//TODO - use VARIANT structure
  	short[] dataType = new short[1];
  	COM.MoveMemory(dataType, pData, 2);
  	type = dataType[0];
  
  	if ((type & COM.VT_BYREF) == COM.VT_BYREF) {
  		int /*long*/[] newByRefPtr = new int /*long*/[1];
  		OS.MoveMemory(newByRefPtr, pData + 8, OS.PTR_SIZEOF);
  		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_UI2 :
  			char[] newCharData = new char[1];
  			COM.MoveMemory(newCharData, pData + 8, 2);
  			charData = newCharData[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_R4 :
  