1 /******************************************************************************* 2 * Copyright (c) 2000, 2008 IBM Corporation and others. 3 * All rights reserved. This program and the accompanying materials 4 * are made available under the terms of the Eclipse Public License v1.0 5 * which accompanies this distribution, and is available at 6 * http://www.eclipse.org/legal/epl-v10.html 7 * 8 * Contributors: 9 * IBM Corporation - initial API and implementation 10 * Port to the D programming language: 11 * Frank Benoit <benoit@tionex.de> 12 *******************************************************************************/ 13 module org.eclipse.swt.ole.win32.Variant; 14 15 import org.eclipse.swt.SWT; 16 import org.eclipse.swt.SWTException; 17 import org.eclipse.swt.internal.ole.win32.extras; 18 import org.eclipse.swt.internal.ole.win32.COM; 19 import org.eclipse.swt.internal.ole.win32.COMTYPES; 20 import org.eclipse.swt.internal.ole.win32.OAIDL; 21 import org.eclipse.swt.internal.win32.OS; 22 23 import org.eclipse.swt.ole.win32.OleAutomation; 24 import org.eclipse.swt.ole.win32.OLE; 25 26 import java.lang.all; 27 28 /** 29 * 30 * A Variant is a generic OLE mechanism for passing data of different types via a common interface. 31 * 32 * <p>It is used within the OleAutomation object for getting a property, setting a property or invoking 33 * a method on an OLE Control or OLE Document. 34 * 35 */ 36 public final class Variant { 37 /** 38 * The size in bytes of a native VARIANT struct. 39 */ 40 /** 41 * A variant always takes up 16 bytes, no matter what you 42 * store in it. Objects, strings, and arrays are not physically 43 * stored in the Variant; in these cases, four bytes of the 44 * Variant are used to hold either an object reference, or a 45 * pointer to the string or array. The actual data are stored elsewhere. 46 */ 47 //public static final int sizeof = 16; 48 49 50 private short type; // OLE.VT_* type 51 private bool booleanData; 52 private byte byteData; 53 private short shortData; 54 private wchar charData; 55 private int intData; 56 private long longData; 57 private float floatData = 0; 58 private double doubleData = 0; 59 private String stringData; 60 private void* byRefPtr; 61 private IDispatch dispatchData; 62 private IUnknown unknownData; 63 64 /** 65 * Invokes platform specific functionality to copy a variant 66 * into operating system memory. 67 * <p> 68 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public 69 * API for <code>Variant</code>. It is marked public only so that it 70 * can be shared within the packages provided by SWT. It is not 71 * available on all platforms, and should never be called from 72 * application code. 73 * </p> 74 * 75 * @param pVarDest destination pointer to a variant 76 * @param varSrc source <code>Variant</code> 77 * 78 * @since 3.3 79 */ 80 public static void win32_copy (VARIANT* pVarDest, Variant varSrc) { 81 varSrc.getData (pVarDest); 82 } 83 84 /** 85 * Invokes platform specific functionality to wrap a variant 86 * that was allocated in operating system memory. 87 * <p> 88 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public 89 * API for <code>Variant</code>. It is marked public only so that it 90 * can be shared within the packages provided by SWT. It is not 91 * available on all platforms, and should never be called from 92 * application code. 93 * </p> 94 * 95 * @param pVariant pointer to a variant 96 * 97 * @return a new <code>Variant</code> 98 * 99 * @since 3.3 100 */ 101 public static Variant win32_new (VARIANT* pVariant) { 102 Variant variant = new Variant (); 103 variant.setData (pVariant); 104 return variant; 105 } 106 107 /** 108 * Create an empty Variant object with type VT_EMPTY. 109 * 110 * @since 2.0 111 */ 112 public this(){ 113 type = COM.VT_EMPTY; 114 } 115 /** 116 * Create a Variant object which represents a Java float as a VT_R4. 117 * 118 * @param val the Java float value that this Variant represents 119 * 120 */ 121 public this(float val) { 122 type = COM.VT_R4; 123 floatData = val; 124 125 } 126 /** 127 * Create a Variant object which represents a Java double as a VT_R8. 128 * 129 * @param val the Java double value that this Variant represents 130 * 131 * @since 3.2 132 */ 133 public this(double val) { 134 type = COM.VT_R8; 135 doubleData = val; 136 } 137 /** 138 * Create a Variant object which represents a Java int as a VT_I4. 139 * 140 * @param val the Java int value that this Variant represents 141 * 142 */ 143 public this(int val) { 144 type = COM.VT_I4; 145 intData = val; 146 } 147 public this(uint val) { 148 type = COM.VT_I4; 149 intData = val; 150 } 151 /** 152 * Create a Variant object which contains a reference to the data being transferred. 153 * 154 * <p>When creating a VT_BYREF Variant, you must give the full Variant type 155 * including VT_BYREF such as 156 * 157 * <pre><code>short byRefType = OLE.VT_BSTR | OLE.VT_BYREF</code></pre>. 158 * 159 * @param ptr a pointer to the data being transferred. 160 * @param byRefType the type of the data being transferred such as OLE.VT_BSTR | OLE.VT_BYREF 161 * 162 */ 163 public this(void* ptr, ushort byRefType) { 164 type = byRefType; 165 byRefPtr = ptr; 166 } 167 /** 168 * Create a Variant object which represents an IDispatch interface as a VT_Dispatch. 169 * 170 * @param automation the OleAutomation object that this Variant represents 171 * 172 */ 173 public this(OleAutomation automation) { 174 type = COM.VT_DISPATCH; 175 dispatchData = automation.getAddress(); 176 } 177 /** 178 * Create a Variant object which represents an IDispatch interface as a VT_Dispatch. 179 * <p>The caller is expected to have appropriately invoked unknown.AddRef() before creating 180 * this Variant. 181 * 182 * @since 2.0 183 * 184 * @param idispatch the IDispatch object that this Variant represents 185 * 186 */ 187 public this(IDispatch idispatch) { 188 type = COM.VT_DISPATCH; 189 dispatchData = idispatch; 190 } 191 /** 192 * Create a Variant object which represents an IUnknown interface as a VT_UNKNOWN. 193 * 194 * <p>The caller is expected to have appropriately invoked unknown.AddRef() before creating 195 * this Variant. 196 * 197 * @param unknown the IUnknown object that this Variant represents 198 * 199 */ 200 public this(IUnknown unknown) { 201 type = COM.VT_UNKNOWN; 202 unknownData = unknown; 203 } 204 /** 205 * Create a Variant object which represents a Java long as a VT_I8. 206 * 207 * @param val the Java long value that this Variant represents 208 * 209 * @since 3.2 210 */ 211 public this(long val) { 212 type = COM.VT_I8; 213 longData = val; 214 } 215 /** 216 * Create a Variant object which represents a Java String as a VT_BSTR. 217 * 218 * @param string the Java String value that this Variant represents 219 * 220 */ 221 public this(String string) { 222 type = COM.VT_BSTR; 223 stringData = string; 224 } 225 /** 226 * Create a Variant object which represents a Java short as a VT_I2. 227 * 228 * @param val the Java short value that this Variant represents 229 * 230 */ 231 public this(short val) { 232 type = COM.VT_I2; 233 shortData = val; 234 } 235 /** 236 * Create a Variant object which represents a Java bool as a VT_BOOL. 237 * 238 * @param val the Java bool value that this Variant represents 239 * 240 */ 241 public this(bool val) { 242 type = COM.VT_BOOL; 243 booleanData = val; 244 } 245 246 /** 247 * Calling dispose will release resources associated with this Variant. 248 * If the resource is an IDispatch or IUnknown interface, Release will be called. 249 * If the resource is a ByRef pointer, nothing is released. 250 * 251 * @since 2.1 252 */ 253 public void dispose() { 254 if ((type & COM.VT_BYREF) is COM.VT_BYREF) { 255 return; 256 } 257 258 switch (type) { 259 case COM.VT_DISPATCH : 260 dispatchData.Release(); 261 break; 262 case COM.VT_UNKNOWN : 263 unknownData.Release(); 264 break; 265 default: 266 } 267 268 } 269 /** 270 * Returns the OleAutomation object represented by this Variant. 271 * 272 * <p>If this Variant does not contain an OleAutomation object, an attempt is made to 273 * coerce the Variant type into an OleAutomation object. If this fails, an error is 274 * thrown. Note that OleAutomation objects must be disposed when no longer 275 * needed. 276 * 277 * @return the OleAutomation object represented by this Variant 278 * 279 * @exception SWTException <ul> 280 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into an OleAutomation object</li> 281 * </ul> 282 */ 283 public OleAutomation getAutomation() { 284 if (type is COM.VT_EMPTY) { 285 OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); 286 } 287 if (type is COM.VT_DISPATCH) { 288 return new OleAutomation(dispatchData); 289 } 290 // try to coerce the value to the desired type 291 VARIANT oldPtr, newPtr; 292 try { 293 getData(&oldPtr); 294 HRESULT result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_DISPATCH); 295 if (result !is COM.S_OK) 296 OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); 297 Variant autoVar = new Variant(); 298 autoVar.setData(&newPtr); 299 return autoVar.getAutomation(); 300 } finally { 301 COM.VariantClear(&oldPtr); 302 COM.VariantClear(&newPtr); // Note: This must absolutely be done AFTER the 303 // OleAutomation object is created as Variant Clear 304 // will result in a Release being performed on the 305 // Dispatch object 306 } 307 } 308 /** 309 * Returns the IDispatch object represented by this Variant. 310 * 311 * <p>If this Variant does not contain an IDispatch object, an attempt is made to 312 * coerce the Variant type into an IDIspatch object. If this fails, an error is 313 * thrown. 314 * 315 * @since 2.0 316 * 317 * @return the IDispatch object represented by this Variant 318 * 319 * @exception SWTException <ul> 320 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into an IDispatch object</li> 321 * </ul> 322 */ 323 public IDispatch getDispatch() { 324 if (type is COM.VT_EMPTY) { 325 OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); 326 } 327 328 if (type is COM.VT_DISPATCH) { 329 return dispatchData; 330 } 331 // try to coerce the value to the desired type 332 VARIANT oldPtr, newPtr; 333 try { 334 getData(&oldPtr); 335 HRESULT result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_DISPATCH); 336 if (result !is COM.S_OK) 337 OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); 338 Variant autoVar = new Variant(); 339 autoVar.setData(&newPtr); 340 return autoVar.getDispatch(); 341 } finally { 342 COM.VariantClear(&oldPtr); 343 COM.VariantClear(&newPtr); // Note: This must absolutely be done AFTER the 344 // OleAutomation object is created as Variant Clear 345 // will result in a Release being performed on the 346 // Dispatch object 347 } 348 } 349 /** 350 * Returns the Java bool represented by this Variant. 351 * 352 * <p>If this Variant does not contain a Java bool, an attempt is made to 353 * coerce the Variant type into a Java bool. If this fails, an error is thrown. 354 * 355 * @return the Java bool represented by this Variant 356 * 357 * @exception SWTException <ul> 358 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a bool</li> 359 * </ul> 360 * 361 */ 362 public bool getBoolean() { 363 if (type is COM.VT_EMPTY) { 364 OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); 365 } 366 if (type is COM.VT_BOOL) { 367 return booleanData; 368 } 369 // try to coerce the value to the desired type 370 VARIANT oldPtr, newPtr; 371 try { 372 getData(&oldPtr); 373 HRESULT result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_BOOL); 374 if (result !is COM.S_OK) 375 OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); 376 Variant boolVar = new Variant(); 377 boolVar.setData(&newPtr); 378 return boolVar.getBoolean(); 379 } finally { 380 COM.VariantClear(&oldPtr); 381 COM.VariantClear(&newPtr); 382 } 383 } 384 /** 385 * Returns a pointer to the referenced data represented by this Variant. 386 * 387 * <p>If this Variant does not contain a reference to data, zero is returned. 388 * 389 * @return a pointer to the referenced data represented by this Variant or 0 390 * 391 */ 392 public void* getByRef() { 393 if (type is COM.VT_EMPTY) { 394 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); 395 } 396 if ((type & COM.VT_BYREF)is COM.VT_BYREF) { 397 return byRefPtr; 398 } 399 400 return null; 401 } 402 /** 403 * Returns the Java byte represented by this Variant. 404 * 405 * <p>If this Variant does not contain a Java byte, an attempt is made to 406 * coerce the Variant type into a Java byte. If this fails, an error is thrown. 407 * 408 * @return the Java byte represented by this Variant 409 * 410 * @exception SWTException <ul> 411 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a byte</li> 412 * </ul> 413 * 414 * @since 3.3 415 */ 416 public byte getByte() { 417 if (type is COM.VT_EMPTY) { 418 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); 419 } 420 if (type is COM.VT_I1) { 421 return byteData; 422 } 423 424 // try to coerce the value to the desired type 425 VARIANT oldPtr, newPtr; 426 try { 427 getData(&oldPtr); 428 int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_I1); 429 if (result !is COM.S_OK) 430 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); 431 Variant byteVar = new Variant(); 432 byteVar.setData(&newPtr); 433 return byteVar.getByte(); 434 } finally { 435 COM.VariantClear(&oldPtr); 436 COM.VariantClear(&newPtr); 437 } 438 } 439 /** 440 * Returns the Java char represented by this Variant. 441 * 442 * <p>If this Variant does not contain a Java char, an attempt is made to 443 * coerce the Variant type into a Java char. If this fails, an error is thrown. 444 * 445 * @return the Java char represented by this Variant 446 * 447 * @exception SWTException <ul> 448 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a char</li> 449 * </ul> 450 * 451 * @since 3.3 452 */ 453 public wchar getChar() { 454 if (type is COM.VT_EMPTY) { 455 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); 456 } 457 if (type is COM.VT_UI2) { 458 return charData; 459 } 460 461 // try to coerce the value to the desired type 462 VARIANT oldPtr, newPtr; 463 try { 464 getData(&oldPtr); 465 int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_UI2); 466 if (result !is COM.S_OK) 467 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); 468 Variant charVar = new Variant(); 469 charVar.setData(&newPtr); 470 return charVar.getChar(); 471 } finally { 472 COM.VariantClear(&oldPtr); 473 COM.VariantClear(&newPtr); 474 } 475 } 476 void getData(VARIANT* pData){ 477 if (pData is null) OLE.error(OLE.ERROR_OUT_OF_MEMORY); 478 479 COM.VariantInit(pData); 480 481 // set type 482 pData.vt = type; 483 if ((type & COM.VT_BYREF) is COM.VT_BYREF) { 484 COM.MoveMemory((cast(void*)pData), &type, 2); 485 COM.MoveMemory((cast(void*)pData) + 8, &byRefPtr, 4); 486 return; 487 } 488 489 switch (type) { 490 case COM.VT_EMPTY : 491 case COM.VT_NULL : 492 COM.MoveMemory((cast(void*)pData), &type, 2); 493 break; 494 case COM.VT_BOOL : 495 COM.MoveMemory((cast(void*)pData), &type, 2); 496 auto v = booleanData ? COM.VARIANT_TRUE : COM.VARIANT_FALSE; 497 COM.MoveMemory((cast(void*)pData) + 8, &v, 2); 498 break; 499 case COM.VT_I1 : 500 COM.MoveMemory((cast(void*)pData), &type, 2); 501 COM.MoveMemory((cast(void*)pData) + 8, &byteData, 1); 502 break; 503 case COM.VT_I2 : 504 COM.MoveMemory((cast(void*)pData), &type, 2); 505 COM.MoveMemory((cast(void*)pData) + 8, &shortData, 2); 506 break; 507 case COM.VT_UI2 : 508 COM.MoveMemory((cast(void*)pData), &type, 2); 509 COM.MoveMemory((cast(void*)pData) + 8, &charData, 2); 510 break; 511 case COM.VT_I4 : 512 COM.MoveMemory((cast(void*)pData), &type, 2); 513 COM.MoveMemory((cast(void*)pData) + 8, &intData, 4); 514 break; 515 case COM.VT_I8 : 516 COM.MoveMemory((cast(void*)pData), &type, 2); 517 COM.MoveMemory((cast(void*)pData) + 8, &longData, 8); 518 break; 519 case COM.VT_R4 : 520 COM.MoveMemory((cast(void*)pData), &type, 2); 521 COM.MoveMemory((cast(void*)pData) + 8, &floatData, 4); 522 break; 523 case COM.VT_R8 : 524 COM.MoveMemory((cast(void*)pData), &type, 2); 525 COM.MoveMemory((cast(void*)pData) + 8, &doubleData, 8); 526 break; 527 case COM.VT_DISPATCH : 528 dispatchData.AddRef(); 529 COM.MoveMemory((cast(void*)pData), &type, 2); 530 auto v = cast(void*)dispatchData; 531 COM.MoveMemory((cast(void*)pData) + 8, &v, 4); 532 break; 533 case COM.VT_UNKNOWN : 534 unknownData.AddRef(); 535 COM.MoveMemory((cast(void*)pData), &type, 2); 536 auto v = cast(void*)dispatchData; 537 COM.MoveMemory((cast(void*)pData) + 8, &v, 4); 538 break; 539 case COM.VT_BSTR : 540 COM.MoveMemory((cast(void*)pData), &type, 2); 541 StringT data = StrToWCHARs(stringData); 542 auto ptr = COM.SysAllocString(data.ptr); 543 COM.MoveMemory((cast(void*)pData) + 8, &ptr, 4); 544 break; 545 546 default : 547 OLE.error(SWT.ERROR_NOT_IMPLEMENTED); 548 } 549 } 550 /** 551 * Returns the Java double represented by this Variant. 552 * 553 * <p>If this Variant does not contain a Java double, an attempt is made to 554 * coerce the Variant type into a Java double. If this fails, an error is thrown. 555 * 556 * @return the Java double represented by this Variant 557 * 558 * @exception SWTException <ul> 559 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a double</li> 560 * </ul> 561 * 562 * @since 3.2 563 */ 564 public double getDouble() { 565 if (type is COM.VT_EMPTY) { 566 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); 567 } 568 if (type is COM.VT_R8) { 569 return doubleData; 570 } 571 572 // try to coerce the value to the desired type 573 VARIANT oldPtr, newPtr; 574 try { 575 getData(&oldPtr); 576 int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_R8); 577 if (result !is COM.S_OK) 578 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); 579 Variant doubleVar = new Variant(); 580 doubleVar.setData(&newPtr); 581 return doubleVar.getDouble(); 582 } finally { 583 COM.VariantClear(&oldPtr); 584 COM.VariantClear(&newPtr); 585 } 586 } 587 588 /** 589 * Returns the Java float represented by this Variant. 590 * 591 * <p>If this Variant does not contain a Java float, an attempt is made to 592 * coerce the Variant type into a Java float. If this fails, an error is thrown. 593 * 594 * @return the Java float represented by this Variant 595 * 596 * @exception SWTException <ul> 597 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a float</li> 598 * </ul> 599 */ 600 public float getFloat() { 601 if (type is COM.VT_EMPTY) { 602 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); 603 } 604 if (type is COM.VT_R4) { 605 return floatData; 606 } 607 608 // try to coerce the value to the desired type 609 VARIANT oldPtr, newPtr; 610 try { 611 getData(&oldPtr); 612 int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_R4); 613 if (result !is COM.S_OK) 614 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); 615 Variant floatVar = new Variant(); 616 floatVar.setData(&newPtr); 617 return floatVar.getFloat(); 618 } finally { 619 COM.VariantClear(&oldPtr); 620 COM.VariantClear(&newPtr); 621 } 622 623 } 624 /** 625 * Returns the Java int represented by this Variant. 626 * 627 * <p>If this Variant does not contain a Java int, an attempt is made to 628 * coerce the Variant type into a Java int. If this fails, an error is thrown. 629 * 630 * @return the Java int represented by this Variant 631 * 632 * @exception SWTException <ul> 633 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a int</li> 634 * </ul> 635 */ 636 public int getInt() { 637 if (type is COM.VT_EMPTY) { 638 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); 639 } 640 if (type is COM.VT_I4) { 641 return intData; 642 } 643 644 // try to coerce the value to the desired type 645 VARIANT oldPtr, newPtr; 646 try { 647 getData(&oldPtr); 648 int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_I4); 649 if (result !is COM.S_OK) 650 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); 651 Variant intVar = new Variant(); 652 intVar.setData(&newPtr); 653 return intVar.getInt(); 654 } finally { 655 COM.VariantClear(&oldPtr); 656 COM.VariantClear(&newPtr); 657 } 658 } 659 /** 660 * Returns the Java long represented by this Variant. 661 * 662 * <p>If this Variant does not contain a Java long, an attempt is made to 663 * coerce the Variant type into a Java long. If this fails, an error is thrown. 664 * 665 * @return the Java long represented by this Variant 666 * 667 * @exception SWTException <ul> 668 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a long</li> 669 * </ul> 670 * 671 * @since 3.2 672 */ 673 public long getLong() { 674 if (type is COM.VT_EMPTY) { 675 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); 676 } 677 if (type is COM.VT_I8) { 678 return longData; 679 } 680 681 // try to coerce the value to the desired type 682 VARIANT oldPtr, newPtr; 683 try { 684 getData(&oldPtr); 685 int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_I8); 686 if (result !is COM.S_OK) 687 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); 688 Variant longVar = new Variant(); 689 longVar.setData(&newPtr); 690 return longVar.getLong(); 691 } finally { 692 COM.VariantClear(&oldPtr); 693 COM.VariantClear(&newPtr); 694 } 695 } 696 /** 697 * Returns the Java short represented by this Variant. 698 * 699 * <p>If this Variant does not contain a Java short, an attempt is made to 700 * coerce the Variant type into a Java short. If this fails, an error is thrown. 701 * 702 * @return the Java short represented by this Variant 703 * 704 * @exception SWTException <ul> 705 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a short</li> 706 * </ul> 707 */ 708 public short getShort() { 709 if (type is COM.VT_EMPTY) { 710 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); 711 } 712 if (type is COM.VT_I2) { 713 return shortData; 714 } 715 716 // try to coerce the value to the desired type 717 VARIANT oldPtr, newPtr; 718 try { 719 getData(&oldPtr); 720 int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_I2); 721 if (result !is COM.S_OK) 722 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); 723 Variant shortVar = new Variant(); 724 shortVar.setData(&newPtr); 725 return shortVar.getShort(); 726 } finally { 727 COM.VariantClear(&oldPtr); 728 COM.VariantClear(&newPtr); 729 } 730 731 } 732 /** 733 * Returns the Java String represented by this Variant. 734 * 735 * <p>If this Variant does not contain a Java String, an attempt is made to 736 * coerce the Variant type into a Java String. If this fails, an error is thrown. 737 * 738 * @return the Java String represented by this Variant 739 * 740 * @exception SWTException <ul> 741 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a String</li> 742 * </ul> 743 */ 744 public String getString() { 745 if (type is COM.VT_EMPTY) { 746 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); 747 } 748 if (type is COM.VT_BSTR) { 749 return stringData; 750 } 751 752 // try to coerce the value to the desired type 753 VARIANT oldPtr, newPtr; 754 try { 755 getData(&oldPtr); 756 int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_BSTR); 757 if (result !is COM.S_OK) 758 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); 759 760 Variant stringVar = new Variant(); 761 stringVar.setData(&newPtr); 762 return stringVar.getString(); 763 764 } finally { 765 COM.VariantClear(&oldPtr); 766 COM.VariantClear(&newPtr); 767 } 768 } 769 /** 770 * Returns the type of the variant type. This will be an OLE.VT_* value or 771 * a bitwise combination of OLE.VT_* values as in the case of 772 * OLE.VT_BSTR | OLE.VT_BYREF. 773 * 774 * @return the type of the variant data 775 * 776 * @since 2.0 777 */ 778 public short getType() { 779 return type; 780 } 781 /** 782 * Returns the IUnknown object represented by this Variant. 783 * 784 * <p>If this Variant does not contain an IUnknown object, an attempt is made to 785 * coerce the Variant type into an IUnknown object. If this fails, an error is 786 * thrown. 787 * 788 * @return the IUnknown object represented by this Variant 789 * 790 * @exception SWTException <ul> 791 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into 792 * an IUnknown object</li> 793 * </ul> 794 */ 795 public IUnknown getUnknown() { 796 if (type is COM.VT_EMPTY) { 797 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1); 798 } 799 if (type is COM.VT_UNKNOWN) { 800 return unknownData; 801 } 802 803 // try to coerce the value to the desired type 804 VARIANT oldPtr, newPtr; 805 try { 806 getData(&oldPtr); 807 int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_UNKNOWN); 808 if (result !is COM.S_OK) 809 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result); 810 Variant unknownVar = new Variant(); 811 unknownVar.setData(&newPtr); 812 return unknownVar.getUnknown(); 813 } finally { 814 COM.VariantClear(&oldPtr); 815 COM.VariantClear(&newPtr); // Note: This must absolutely be done AFTER the 816 // IUnknown object is created as Variant Clear 817 // will result in a Release being performed on the 818 // Dispatch object 819 } 820 } 821 /** 822 * Update the by reference value of this variant with a new bool value. 823 * 824 * @param val the new bool value 825 * 826 * @exception SWTException <ul> 827 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not 828 * a (VT_BYREF | VT_BOOL) object</li> 829 * </ul> 830 * 831 * @since 2.1 832 */ 833 public void setByRef(bool val) { 834 if ((type & COM.VT_BYREF) is 0 || (type & COM.VT_BOOL) is 0) { 835 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE); 836 } 837 auto v = val ? COM.VARIANT_TRUE : COM.VARIANT_FALSE; 838 COM.MoveMemory(byRefPtr, &v, 2); 839 } 840 /** 841 * Update the by reference value of this variant with a new float value. 842 * 843 * @param val the new float value 844 * 845 * @exception SWTException <ul> 846 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not 847 * a (VT_BYREF | VT_R4) object</li> 848 * </ul> 849 * 850 * @since 2.1 851 */ 852 public void setByRef(float val) { 853 if ((type & COM.VT_BYREF) is 0 || (type & COM.VT_R4) is 0) { 854 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE); 855 } 856 COM.MoveMemory(byRefPtr, &val, 4); 857 } 858 /** 859 * Update the by reference value of this variant with a new integer value. 860 * 861 * @param val the new integer value 862 * 863 * @exception SWTException <ul> 864 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not a (VT_BYREF | VT_I4) object</li> 865 * </ul> 866 * 867 * @since 2.1 868 */ 869 public void setByRef(int val) { 870 if ((type & COM.VT_BYREF) is 0 || (type & COM.VT_I4) is 0) { 871 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE); 872 } 873 COM.MoveMemory(byRefPtr, &val, 4); 874 } 875 /** 876 * Update the by reference value of this variant with a new short value. 877 * 878 * @param val the new short value 879 * 880 * @exception SWTException <ul> 881 * <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not a (VT_BYREF | VT_I2) object 882 * </ul> 883 * 884 * @since 2.1 885 */ 886 public void setByRef(short val) { 887 if ((type & COM.VT_BYREF) is 0 || (type & COM.VT_I2) is 0) { 888 OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE); 889 } 890 COM.MoveMemory(byRefPtr, &val, 2); 891 } 892 893 void setData(VARIANT* pData){ 894 if (pData is null) OLE.error(OLE.ERROR_INVALID_ARGUMENT); 895 896 short[1] dataType ; 897 COM.MoveMemory(dataType.ptr, (cast(void*)pData), 2); 898 type = dataType[0]; 899 900 if ((type & COM.VT_BYREF) is COM.VT_BYREF) { 901 void*[1] newByRefPtr; 902 OS.MoveMemory(newByRefPtr.ptr, (cast(void*)pData) + 8, 4); 903 byRefPtr = newByRefPtr[0]; 904 return; 905 } 906 907 switch (type) { 908 case COM.VT_EMPTY : 909 case COM.VT_NULL : 910 break; 911 case COM.VT_BOOL : 912 short[1] newBooleanData; 913 COM.MoveMemory(newBooleanData.ptr, (cast(void*)pData) + 8, 2); 914 booleanData = (newBooleanData[0] !is COM.VARIANT_FALSE); 915 break; 916 case COM.VT_I1 : 917 byte[1] newByteData; 918 COM.MoveMemory(newByteData.ptr, (cast(void*)pData) + 8, 1); 919 byteData = newByteData[0]; 920 break; 921 case COM.VT_I2 : 922 short[1] newShortData; 923 COM.MoveMemory(newShortData.ptr, (cast(void*)pData) + 8, 2); 924 shortData = newShortData[0]; 925 break; 926 case COM.VT_UI2 : 927 wchar[1] newCharData; 928 COM.MoveMemory(newCharData.ptr, (cast(void*)pData) + 8, 2); 929 charData = newCharData[0]; 930 break; 931 case COM.VT_I4 : 932 int[1] newIntData; 933 OS.MoveMemory(newIntData.ptr, (cast(void*)pData) + 8, 4); 934 intData = newIntData[0]; 935 break; 936 case COM.VT_I8 : 937 long[1] newLongData; 938 OS.MoveMemory(newLongData.ptr, (cast(void*)pData) + 8, 8); 939 longData = newLongData[0]; 940 break; 941 case COM.VT_R4 : 942 float[1] newFloatData; 943 COM.MoveMemory(newFloatData.ptr, (cast(void*)pData) + 8, 4); 944 floatData = newFloatData[0]; 945 break; 946 case COM.VT_R8 : 947 double[1] newDoubleData; 948 COM.MoveMemory(newDoubleData.ptr, (cast(void*)pData) + 8, 8); 949 doubleData = newDoubleData[0]; 950 break; 951 case COM.VT_DISPATCH : { 952 IDispatch[1] ppvObject; 953 OS.MoveMemory(ppvObject.ptr, (cast(void*)pData) + 8, 4); 954 if (ppvObject[0] is null) { 955 type = COM.VT_EMPTY; 956 break; 957 } 958 dispatchData = ppvObject[0]; 959 dispatchData.AddRef(); 960 break; 961 } 962 case COM.VT_UNKNOWN : { 963 IUnknown[1] ppvObject; 964 OS.MoveMemory(ppvObject.ptr, (cast(void*)pData) + 8, 4); 965 if (ppvObject[0] is null) { 966 type = COM.VT_EMPTY; 967 break; 968 } 969 unknownData = ppvObject[0]; 970 unknownData.AddRef(); 971 break; 972 } 973 case COM.VT_BSTR : 974 // get the address of the memory in which the string resides 975 wchar*[1] hMem; 976 OS.MoveMemory(hMem.ptr, (cast(void*)pData) + 8, 4); 977 if (hMem[0] is null) { 978 type = COM.VT_EMPTY; 979 break; 980 } 981 // Get the size of the string from the OS - the size is expressed in number 982 // of bytes - each unicode character is 2 bytes. 983 int size = COM.SysStringByteLen(hMem[0]); 984 if (size > 0){ 985 // get the unicode character array from the global memory and create a String 986 wchar[] buffer = new wchar[(size + 1) /2]; // add one to avoid rounding errors 987 COM.MoveMemory(buffer.ptr, hMem[0], size); 988 stringData = WCHARsToStr( buffer ); 989 } else { 990 stringData = ""; //$NON-NLS-1$ 991 } 992 break; 993 994 default : 995 // try coercing it into one of the known forms 996 auto newPData = cast(VARIANT*) OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof); 997 if (COM.VariantChangeType(newPData, pData, 0, COM.VT_R4) is COM.S_OK) { 998 setData(newPData); 999 } else if (COM.VariantChangeType(newPData, pData, 0, COM.VT_I4) is COM.S_OK) { 1000 setData(newPData); 1001 } else if (COM.VariantChangeType(newPData, pData, 0, COM.VT_BSTR) is COM.S_OK) { 1002 setData(newPData); 1003 } 1004 COM.VariantClear(newPData); 1005 OS.GlobalFree(newPData); 1006 break; 1007 } 1008 } 1009 1010 /** 1011 * Returns a string containing a concise, human-readable 1012 * description of the receiver. 1013 * 1014 * @return a string representation of the Variant 1015 */ 1016 override 1017 public String toString () { 1018 switch (type) { 1019 case COM.VT_BOOL : 1020 return "VT_BOOL{"~String_valueOf(booleanData)~"}"; 1021 case COM.VT_I1 : 1022 return "VT_I1{"~String_valueOf(byteData)~"}"; 1023 case COM.VT_I2 : 1024 return "VT_I2{"~String_valueOf(shortData)~"}"; 1025 case COM.VT_UI2 : 1026 return "VT_UI2{"~ dcharToString(charData) ~"}"; 1027 case COM.VT_I4 : 1028 return "VT_I4{"~String_valueOf(intData)~"}"; 1029 case COM.VT_I8 : 1030 return "VT_I8{"~String_valueOf(longData)~"}"; 1031 case COM.VT_R4 : 1032 return "VT_R4{"~String_valueOf(floatData)~"}"; 1033 case COM.VT_R8 : 1034 return "VT_R8{"~String_valueOf(doubleData)~"}"; 1035 case COM.VT_BSTR : 1036 return "VT_BSTR{"~stringData~"}"; 1037 case COM.VT_DISPATCH : 1038 return Format("VT_DISPATCH{{0x{:X}}", cast(void*) (dispatchData is null ? null : dispatchData)); 1039 case COM.VT_UNKNOWN : 1040 return Format("VT_UNKNOWN{{0x{:X}}", cast(void*) (unknownData is null ? null : unknownData)); 1041 case COM.VT_EMPTY : 1042 return "VT_EMPTY"; 1043 case COM.VT_NULL : 1044 return "VT_NULL"; 1045 default: 1046 } 1047 if ((type & COM.VT_BYREF) !is 0) { 1048 return Format("VT_BYREF|{}{{{}}",(type & ~cast(int)COM.VT_BYREF), byRefPtr ); 1049 } 1050 return "Unsupported Type "~String_valueOf(type); 1051 } 1052 }