1 /*******************************************************************************
2 * Copyright (c) 2000, 2017 IBM Corporation and others.
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
9 * SPDX-License-Identifier: EPL-2.0
12 * IBM Corporation - initial API and implementation
13 *******************************************************************************/
14 package org.eclipse.swt.ole.win32;
16 import org.eclipse.swt.*;
17 import org.eclipse.swt.internal.*;
18 import org.eclipse.swt.internal.ole.win32.*;
19 import org.eclipse.swt.internal.win32.*;
22 * A Variant is a generic OLE mechanism for passing data of different types via a common interface.
24 * <p>It is used within the OleAutomation object for getting a property, setting a property or invoking
25 * a method on an OLE Control or OLE Document.
28 public final class Variant {
30 * The size in bytes of a native VARIANT struct.
32 public static final int sizeof = VARIANT.sizeof;
34 private short type; // OLE.VT_* type
35 private boolean booleanData;
36 private byte byteData;
37 private short shortData;
38 private char charData;
40 private long longData;
41 private float floatData;
42 private double doubleData;
43 private String stringData;
44 private long byRefPtr;
45 private IDispatch dispatchData;
46 private IUnknown unknownData;
49 * A shared Variant instance with type VT_NULL.
53 public static final Variant NULL;
55 NULL = new Variant ();
56 NULL.type = COM.VT_NULL;
60 * Invokes platform specific functionality to copy a variant
61 * into operating system memory.
63 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
64 * API for <code>Variant</code>. It is marked public only so that it
65 * can be shared within the packages provided by SWT. It is not
66 * available on all platforms, and should never be called from
70 * @param pVarDest destination pointer to a variant
71 * @param varSrc source <code>Variant</code>
73 * @noreference This method is not intended to be referenced by clients.
77 public static void win32_copy (long pVarDest, Variant varSrc) {
78 varSrc.getData (pVarDest);
82 * Invokes platform specific functionality to wrap a variant
83 * that was allocated in operating system memory.
85 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
86 * API for <code>Variant</code>. It is marked public only so that it
87 * can be shared within the packages provided by SWT. It is not
88 * available on all platforms, and should never be called from
92 * @param pVariant pointer to a variant
94 * @return a new <code>Variant</code>
96 * @noreference This method is not intended to be referenced by clients.
100 public static Variant win32_new (long pVariant) {
101 Variant variant = new Variant ();
102 variant.setData (pVariant);
107 * Create an empty Variant object with type VT_EMPTY.
115 * Create a Variant object which represents a Java float as a VT_R4.
117 * @param val the Java float value that this Variant represents
120 public Variant(float val) {
125 * Create a Variant object which represents a Java double as a VT_R8.
127 * @param val the Java double value that this Variant represents
131 public Variant(double val) {
136 * Create a Variant object which represents a Java int as a VT_I4.
138 * @param val the Java int value that this Variant represents
141 public Variant(int val) {
146 * Create a Variant object which contains a reference to the data being transferred.
148 * <p>When creating a VT_BYREF Variant, you must give the full Variant type
149 * including VT_BYREF such as
151 * <pre><code>short byRefType = OLE.VT_BSTR | OLE.VT_BYREF</code></pre>.
153 * @param ptr a pointer to the data being transferred.
154 * @param byRefType the type of the data being transferred such as OLE.VT_BSTR | OLE.VT_BYREF
157 public Variant(long ptr, short byRefType) {
162 * Create a Variant object which represents an IDispatch interface as a VT_Dispatch.
164 * @param automation the OleAutomation object that this Variant represents
167 public Variant(OleAutomation automation) {
168 type = COM.VT_DISPATCH;
169 dispatchData = new IDispatch(automation.getAddress());
172 * Create a Variant object which represents an IDispatch interface as a VT_Dispatch.
173 * <p>The caller is expected to have appropriately invoked unknown.AddRef() before creating
178 * @param idispatch the IDispatch object that this Variant represents
181 public Variant(IDispatch idispatch) {
182 type = COM.VT_DISPATCH;
183 dispatchData = idispatch;
186 * Create a Variant object which represents an IUnknown interface as a VT_UNKNOWN.
188 * <p>The caller is expected to have appropriately invoked unknown.AddRef() before creating
191 * @param unknown the IUnknown object that this Variant represents
194 public Variant(IUnknown unknown) {
195 type = COM.VT_UNKNOWN;
196 unknownData = unknown;
199 * Create a Variant object which represents a Java long as a VT_I8.
201 * @param val the Java long value that this Variant represents
205 public Variant(long val) {
210 * Create a Variant object which represents a Java String as a VT_BSTR.
212 * @param string the Java String value that this Variant represents
215 public Variant(String string) {
220 * Create a Variant object which represents a Java short as a VT_I2.
222 * @param val the Java short value that this Variant represents
225 public Variant(short val) {
230 * Create a Variant object which represents a Java boolean as a VT_BOOL.
232 * @param val the Java boolean value that this Variant represents
235 public Variant(boolean val) {
241 * Calling dispose will release resources associated with this Variant.
242 * If the resource is an IDispatch or IUnknown interface, Release will be called.
243 * If the resource is a ByRef pointer, nothing is released.
247 public void dispose() {
248 if ((type & COM.VT_BYREF) == COM.VT_BYREF) {
253 case COM.VT_DISPATCH :
254 dispatchData.Release();
256 case COM.VT_UNKNOWN :
257 unknownData.Release();
263 * Returns the OleAutomation object represented by this Variant.
265 * <p>If this Variant does not contain an OleAutomation object, an attempt is made to
266 * coerce the Variant type into an OleAutomation object. If this fails, an error is
267 * thrown. Note that OleAutomation objects must be disposed when no longer
270 * @return the OleAutomation object represented by this Variant
272 * @exception SWTException <ul>
273 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into an OleAutomation object</li>
276 public OleAutomation getAutomation() {
277 if (type == COM.VT_EMPTY) {
278 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
280 if (type == COM.VT_DISPATCH) {
281 return new OleAutomation(dispatchData);
283 // try to coerce the value to the desired type
284 long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
285 long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
288 int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_DISPATCH);
289 if (result != COM.S_OK)
290 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
291 Variant autoVar = new Variant();
292 autoVar.setData(newPtr);
293 return autoVar.getAutomation();
295 COM.VariantClear(oldPtr);
296 OS.GlobalFree(oldPtr);
297 COM.VariantClear(newPtr); // Note: This must absolutely be done AFTER the
298 // OleAutomation object is created as Variant Clear
299 // will result in a Release being performed on the
301 OS.GlobalFree(newPtr);
305 * Returns the IDispatch object represented by this Variant.
307 * <p>If this Variant does not contain an IDispatch object, an attempt is made to
308 * coerce the Variant type into an IDIspatch object. If this fails, an error is
313 * @return the IDispatch object represented by this Variant
315 * @exception SWTException <ul>
316 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into an IDispatch object</li>
319 public IDispatch getDispatch() {
320 if (type == COM.VT_EMPTY) {
321 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
323 if (type == COM.VT_DISPATCH) {
326 // try to coerce the value to the desired type
327 long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
328 long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
331 int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_DISPATCH);
332 if (result != COM.S_OK)
333 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
334 Variant autoVar = new Variant();
335 autoVar.setData(newPtr);
336 return autoVar.getDispatch();
338 COM.VariantClear(oldPtr);
339 OS.GlobalFree(oldPtr);
340 COM.VariantClear(newPtr); // Note: This must absolutely be done AFTER the
341 // OleAutomation object is created as Variant Clear
342 // will result in a Release being performed on the
344 OS.GlobalFree(newPtr);
348 * Returns the Java boolean represented by this Variant.
350 * <p>If this Variant does not contain a Java boolean, an attempt is made to
351 * coerce the Variant type into a Java boolean. If this fails, an error is thrown.
353 * @return the Java boolean represented by this Variant
355 * @exception SWTException <ul>
356 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a boolean</li>
360 public boolean getBoolean() {
361 if (type == COM.VT_EMPTY) {
362 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
364 if (type == COM.VT_BOOL) {
368 // try to coerce the value to the desired type
369 long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
370 long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
373 int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_BOOL);
374 if (result != COM.S_OK)
375 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
376 Variant boolVar = new Variant();
377 boolVar.setData(newPtr);
378 return boolVar.getBoolean();
380 COM.VariantClear(oldPtr);
381 OS.GlobalFree(oldPtr);
382 COM.VariantClear(newPtr);
383 OS.GlobalFree(newPtr);
387 * Returns a pointer to the referenced data represented by this Variant.
389 * <p>If this Variant does not contain a reference to data, zero is returned.
391 * @return a pointer to the referenced data represented by this Variant or 0
394 public long getByRef() {
395 if (type == COM.VT_EMPTY) {
396 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
398 if ((type & COM.VT_BYREF)== COM.VT_BYREF) {
405 * Returns the Java byte represented by this Variant.
407 * <p>If this Variant does not contain a Java byte, an attempt is made to
408 * coerce the Variant type into a Java byte. If this fails, an error is thrown.
410 * @return the Java byte represented by this Variant
412 * @exception SWTException <ul>
413 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a byte</li>
418 public byte getByte() {
419 if (type == COM.VT_EMPTY) {
420 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
422 if (type == COM.VT_I1) {
426 // try to coerce the value to the desired type
427 long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
428 long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
431 int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_I1);
432 if (result != COM.S_OK)
433 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
434 Variant byteVar = new Variant();
435 byteVar.setData(newPtr);
436 return byteVar.getByte();
438 COM.VariantClear(oldPtr);
439 OS.GlobalFree(oldPtr);
440 COM.VariantClear(newPtr);
441 OS.GlobalFree(newPtr);
445 * Returns the Java char represented by this Variant.
447 * <p>If this Variant does not contain a Java char, an attempt is made to
448 * coerce the Variant type into a Java char. If this fails, an error is thrown.
450 * @return the Java char represented by this Variant
452 * @exception SWTException <ul>
453 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a char</li>
458 public char getChar() {
459 if (type == COM.VT_EMPTY) {
460 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
462 if (type == COM.VT_UI2) {
466 // try to coerce the value to the desired type
467 long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
468 long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
471 int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_UI2);
472 if (result != COM.S_OK)
473 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
474 Variant charVar = new Variant();
475 charVar.setData(newPtr);
476 return charVar.getChar();
478 COM.VariantClear(oldPtr);
479 OS.GlobalFree(oldPtr);
480 COM.VariantClear(newPtr);
481 OS.GlobalFree(newPtr);
484 void getData(long pData){
485 if (pData == 0) OLE.error(OLE.ERROR_OUT_OF_MEMORY);
487 COM.VariantInit(pData);
489 if ((type & COM.VT_BYREF) == COM.VT_BYREF) {
490 //TODO - use VARIANT structure
491 OS.MoveMemory(pData, new short[] {type}, 2);
492 OS.MoveMemory(pData + 8, new long[]{byRefPtr}, C.PTR_SIZEOF);
499 OS.MoveMemory(pData, new short[] {type}, 2);
502 OS.MoveMemory(pData, new short[] {type}, 2);
503 OS.MoveMemory(pData + 8, new short[]{(booleanData) ? OS.VARIANT_TRUE : OS.VARIANT_FALSE}, 2);
506 OS.MoveMemory(pData, new short[] {type}, 2);
507 OS.MoveMemory(pData + 8, new byte[]{byteData}, 1);
510 OS.MoveMemory(pData, new short[] {type}, 2);
511 OS.MoveMemory(pData + 8, new short[]{shortData}, 2);
514 OS.MoveMemory(pData, new short[] {type}, 2);
515 OS.MoveMemory(pData + 8, new char[]{charData}, 2);
518 OS.MoveMemory(pData, new short[] {type}, 2);
519 OS.MoveMemory(pData + 8, new int[]{intData}, 4);
522 OS.MoveMemory(pData, new short[] {type}, 2);
523 OS.MoveMemory(pData + 8, new long[]{longData}, 8);
526 OS.MoveMemory(pData, new short[] {type}, 2);
527 OS.MoveMemory(pData + 8, new float[]{floatData}, 4);
530 OS.MoveMemory(pData, new short[] {type}, 2);
531 OS.MoveMemory(pData + 8, new double[]{doubleData}, 8);
533 case COM.VT_DISPATCH :
534 dispatchData.AddRef();
535 OS.MoveMemory(pData, new short[] {type}, 2);
536 OS.MoveMemory(pData + 8, new long[]{dispatchData.getAddress()}, C.PTR_SIZEOF);
538 case COM.VT_UNKNOWN :
539 unknownData.AddRef();
540 OS.MoveMemory(pData, new short[] {type}, 2);
541 OS.MoveMemory(pData + 8, new long[]{unknownData.getAddress()}, C.PTR_SIZEOF);
544 OS.MoveMemory(pData, new short[] {type}, 2);
545 char[] data = (stringData+"\0").toCharArray();
546 long ptr = COM.SysAllocString(data);
547 OS.MoveMemory(pData + 8, new long[] {ptr}, C.PTR_SIZEOF);
551 OLE.error(SWT.ERROR_NOT_IMPLEMENTED);
555 * Returns the Java double represented by this Variant.
557 * <p>If this Variant does not contain a Java double, an attempt is made to
558 * coerce the Variant type into a Java double. If this fails, an error is thrown.
560 * @return the Java double represented by this Variant
562 * @exception SWTException <ul>
563 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a double</li>
568 public double getDouble() {
569 if (type == COM.VT_EMPTY) {
570 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
572 if (type == COM.VT_R8) {
576 // try to coerce the value to the desired type
577 long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
578 long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
581 int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_R8);
582 if (result != COM.S_OK)
583 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
584 Variant doubleVar = new Variant();
585 doubleVar.setData(newPtr);
586 return doubleVar.getDouble();
588 COM.VariantClear(oldPtr);
589 OS.GlobalFree(oldPtr);
590 COM.VariantClear(newPtr);
591 OS.GlobalFree(newPtr);
596 * Returns the Java float represented by this Variant.
598 * <p>If this Variant does not contain a Java float, an attempt is made to
599 * coerce the Variant type into a Java float. If this fails, an error is thrown.
601 * @return the Java float represented by this Variant
603 * @exception SWTException <ul>
604 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a float</li>
607 public float getFloat() {
608 if (type == COM.VT_EMPTY) {
609 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
611 if (type == COM.VT_R4) {
615 // try to coerce the value to the desired type
616 long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
617 long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
620 int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_R4);
621 if (result != COM.S_OK)
622 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
623 Variant floatVar = new Variant();
624 floatVar.setData(newPtr);
625 return floatVar.getFloat();
627 COM.VariantClear(oldPtr);
628 OS.GlobalFree(oldPtr);
629 COM.VariantClear(newPtr);
630 OS.GlobalFree(newPtr);
635 * Returns the Java int represented by this Variant.
637 * <p>If this Variant does not contain a Java int, an attempt is made to
638 * coerce the Variant type into a Java int. If this fails, an error is thrown.
640 * @return the Java int represented by this Variant
642 * @exception SWTException <ul>
643 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a int</li>
646 public int getInt() {
647 if (type == COM.VT_EMPTY) {
648 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
650 if (type == COM.VT_I4) {
654 // try to coerce the value to the desired type
655 long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
656 long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
659 int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_I4);
660 if (result != COM.S_OK)
661 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
662 Variant intVar = new Variant();
663 intVar.setData(newPtr);
664 return intVar.getInt();
666 COM.VariantClear(oldPtr);
667 OS.GlobalFree(oldPtr);
668 COM.VariantClear(newPtr);
669 OS.GlobalFree(newPtr);
673 * Returns the Java long represented by this Variant.
675 * <p>If this Variant does not contain a Java long, an attempt is made to
676 * coerce the Variant type into a Java long. If this fails, an error is thrown.
678 * @return the Java long represented by this Variant
680 * @exception SWTException <ul>
681 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a long</li>
686 public long getLong() {
687 if (type == COM.VT_EMPTY) {
688 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
690 if (type == COM.VT_I8) {
694 // try to coerce the value to the desired type
695 long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
696 long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
699 int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_I8);
700 if (result != COM.S_OK)
701 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
702 Variant longVar = new Variant();
703 longVar.setData(newPtr);
704 return longVar.getLong();
706 COM.VariantClear(oldPtr);
707 OS.GlobalFree(oldPtr);
708 COM.VariantClear(newPtr);
709 OS.GlobalFree(newPtr);
713 * Returns the Java short represented by this Variant.
715 * <p>If this Variant does not contain a Java short, an attempt is made to
716 * coerce the Variant type into a Java short. If this fails, an error is thrown.
718 * @return the Java short represented by this Variant
720 * @exception SWTException <ul>
721 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a short</li>
724 public short getShort() {
725 if (type == COM.VT_EMPTY) {
726 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
728 if (type == COM.VT_I2) {
732 // try to coerce the value to the desired type
733 long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
734 long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
737 int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_I2);
738 if (result != COM.S_OK)
739 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
740 Variant shortVar = new Variant();
741 shortVar.setData(newPtr);
742 return shortVar.getShort();
744 COM.VariantClear(oldPtr);
745 OS.GlobalFree(oldPtr);
746 COM.VariantClear(newPtr);
747 OS.GlobalFree(newPtr);
752 * Returns the Java String represented by this Variant.
754 * <p>If this Variant does not contain a Java String, an attempt is made to
755 * coerce the Variant type into a Java String. If this fails, an error is thrown.
757 * @return the Java String represented by this Variant
759 * @exception SWTException <ul>
760 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a String</li>
763 public String getString() {
764 if (type == COM.VT_EMPTY) {
765 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
767 if (type == COM.VT_BSTR) {
771 // try to coerce the value to the desired type
772 long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
773 long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
776 int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_BSTR);
777 if (result != COM.S_OK)
778 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
780 Variant stringVar = new Variant();
781 stringVar.setData(newPtr);
782 return stringVar.getString();
785 COM.VariantClear(oldPtr);
786 OS.GlobalFree(oldPtr);
787 COM.VariantClear(newPtr);
788 OS.GlobalFree(newPtr);
792 * Returns the type of the variant type. This will be an OLE.VT_* value or
793 * a bitwise combination of OLE.VT_* values as in the case of
794 * OLE.VT_BSTR | OLE.VT_BYREF.
796 * @return the type of the variant data
800 public short getType() {
804 * Returns the IUnknown object represented by this Variant.
806 * <p>If this Variant does not contain an IUnknown object, an attempt is made to
807 * coerce the Variant type into an IUnknown object. If this fails, an error is
810 * @return the IUnknown object represented by this Variant
812 * @exception SWTException <ul>
813 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into
814 * an IUnknown object</li>
817 public IUnknown getUnknown() {
818 if (type == COM.VT_EMPTY) {
819 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
821 if (type == COM.VT_UNKNOWN) {
825 // try to coerce the value to the desired type
826 long oldPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
827 long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, sizeof);
830 int result = COM.VariantChangeType(newPtr, oldPtr, (short) 0, COM.VT_UNKNOWN);
831 if (result != COM.S_OK)
832 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
833 Variant unknownVar = new Variant();
834 unknownVar.setData(newPtr);
835 return unknownVar.getUnknown();
837 COM.VariantClear(oldPtr);
838 OS.GlobalFree(oldPtr);
839 COM.VariantClear(newPtr); // Note: This must absolutely be done AFTER the
840 // IUnknown object is created as Variant Clear
841 // will result in a Release being performed on the
843 OS.GlobalFree(newPtr);
847 * Update the by reference value of this variant with a new boolean value.
849 * @param val the new boolean value
851 * @exception SWTException <ul>
852 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not
853 * a (VT_BYREF | VT_BOOL) object</li>
858 public void setByRef(boolean val) {
859 if ((type & COM.VT_BYREF) == 0 || (type & COM.VT_BOOL) == 0) {
860 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE);
862 OS.MoveMemory(byRefPtr, new short[]{val ? OS.VARIANT_TRUE : OS.VARIANT_FALSE}, 2);
865 * Update the by reference value of this variant with a new float value.
867 * @param val the new float value
869 * @exception SWTException <ul>
870 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not
871 * a (VT_BYREF | VT_R4) object</li>
876 public void setByRef(float val) {
877 if ((type & COM.VT_BYREF) == 0 || (type & COM.VT_R4) == 0) {
878 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE);
880 OS.MoveMemory(byRefPtr, new float[]{val}, 4);
883 * Update the by reference value of this variant with a new integer value.
885 * @param val the new integer value
887 * @exception SWTException <ul>
888 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not a (VT_BYREF | VT_I4) object</li>
893 public void setByRef(long val) {
894 if ((type & COM.VT_BYREF) == 0 || (type & COM.VT_I8) == 0) {
895 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE);
897 OS.MoveMemory(byRefPtr, new long[]{val}, C.PTR_SIZEOF);
900 * Update the by reference value of this variant with a new short value.
902 * @param val the new short value
904 * @exception SWTException <ul>
905 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not a (VT_BYREF | VT_I2) object
910 public void setByRef(short val) {
911 if ((type & COM.VT_BYREF) == 0 || (type & COM.VT_I2) == 0) {
912 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE);
914 OS.MoveMemory(byRefPtr, new short[]{val}, 2);
916 void setData(long pData){
917 if (pData == 0) OLE.error(SWT.ERROR_INVALID_ARGUMENT);
919 //TODO - use VARIANT structure
920 short[] dataType = new short[1];
921 OS.MoveMemory(dataType, pData, 2);
924 if ((type & COM.VT_BYREF) == COM.VT_BYREF) {
925 long[] newByRefPtr = new long[1];
926 OS.MoveMemory(newByRefPtr, pData + 8, C.PTR_SIZEOF);
927 byRefPtr = newByRefPtr[0];
936 short[] newBooleanData = new short[1];
937 OS.MoveMemory(newBooleanData, pData + 8, 2);
938 booleanData = (newBooleanData[0] != OS.VARIANT_FALSE);
941 byte[] newByteData = new byte[1];
942 OS.MoveMemory(newByteData, pData + 8, 1);
943 byteData = newByteData[0];
946 short[] newShortData = new short[1];
947 OS.MoveMemory(newShortData, pData + 8, 2);
948 shortData = newShortData[0];
951 char[] newCharData = new char[1];
952 OS.MoveMemory(newCharData, pData + 8, 2);
953 charData = newCharData[0];
956 int[] newIntData = new int[1];
957 OS.MoveMemory(newIntData, pData + 8, 4);
958 intData = newIntData[0];
961 long[] newLongData = new long[1];
962 OS.MoveMemory(newLongData, pData + 8, 8);
963 longData = newLongData[0];
966 float[] newFloatData = new float[1];
967 OS.MoveMemory(newFloatData, pData + 8, 4);
968 floatData = newFloatData[0];
971 double[] newDoubleData = new double[1];
972 OS.MoveMemory(newDoubleData, pData + 8, 8);
973 doubleData = newDoubleData[0];
975 case COM.VT_DISPATCH : {
976 long[] ppvObject = new long[1];
977 OS.MoveMemory(ppvObject, pData + 8, C.PTR_SIZEOF);
978 if (ppvObject[0] == 0) {
982 dispatchData = new IDispatch(ppvObject[0]);
983 dispatchData.AddRef();
986 case COM.VT_UNKNOWN : {
987 long[] ppvObject = new long[1];
988 OS.MoveMemory(ppvObject, pData + 8, C.PTR_SIZEOF);
989 if (ppvObject[0] == 0) {
993 unknownData = new IUnknown(ppvObject[0]);
994 unknownData.AddRef();
998 // get the address of the memory in which the string resides
999 long[] hMem = new long[1];
1000 OS.MoveMemory(hMem, pData + 8, C.PTR_SIZEOF);
1002 type = COM.VT_EMPTY;
1005 // Get the size of the string from the OS - the size is expressed in number
1006 // of bytes - each unicode character is 2 bytes.
1007 int size = COM.SysStringByteLen(hMem[0]);
1009 // get the unicode character array from the global memory and create a String
1010 char[] buffer = new char[(size + 1) /2]; // add one to avoid rounding errors
1011 OS.MoveMemory(buffer, hMem[0], size);
1012 stringData = new String(buffer);
1014 stringData = ""; //$NON-NLS-1$
1019 // try coercing it into one of the known forms
1020 long newPData = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, sizeof);
1021 if (COM.VariantChangeType(newPData, pData, (short) 0, COM.VT_R8) == COM.S_OK) {
1023 } else if (COM.VariantChangeType(newPData, pData, (short) 0, COM.VT_I8) == COM.S_OK) {
1025 } else if (COM.VariantChangeType(newPData, pData, (short) 0, COM.VT_BSTR) == COM.S_OK) {
1028 COM.VariantClear(newPData);
1029 OS.GlobalFree(newPData);
1034 * Returns a string containing a concise, human-readable
1035 * description of the receiver.
1037 * @return a string representation of the Variant
1040 public String toString () {
1043 return "VT_BOOL{"+booleanData+"}";
1045 return "VT_I1{"+byteData+"}";
1047 return "VT_I2{"+shortData+"}";
1049 return "VT_UI2{"+charData+"}";
1051 return "VT_I4{"+intData+"}";
1053 return "VT_I8{"+longData+"}";
1055 return "VT_R4{"+floatData+"}";
1057 return "VT_R8{"+doubleData+"}";
1059 return "VT_BSTR{"+stringData+"}";
1060 case COM.VT_DISPATCH :
1061 return "VT_DISPATCH{"+(dispatchData == null ? 0 : dispatchData.getAddress())+"}";
1062 case COM.VT_UNKNOWN :
1063 return "VT_UNKNOWN{"+(unknownData == null ? 0 : unknownData.getAddress())+"}";
1069 if ((type & COM.VT_BYREF) != 0) {
1070 return "VT_BYREF|"+(type & ~COM.VT_BYREF)+"{"+byRefPtr+"}";
1072 return "Unsupported Type "+type;