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.OleAutomation; 14 15 16 import org.eclipse.swt.internal.ole.win32.COM; 17 import org.eclipse.swt.internal.ole.win32.COMTYPES; 18 import org.eclipse.swt.internal.ole.win32.OAIDL; 19 // import org.eclipse.swt.internal.ole.win32.DISPPARAMS; 20 // import org.eclipse.swt.internal.ole.win32.EXCEPINFO; 21 // import org.eclipse.swt.internal.ole.win32.FUNCDESC; 22 // import org.eclipse.swt.internal.ole.win32.GUID; 23 // import org.eclipse.swt.internal.ole.win32.IDispatch; 24 // import org.eclipse.swt.internal.ole.win32.ITypeInfo; 25 // import org.eclipse.swt.internal.ole.win32.TYPEATTR; 26 // import org.eclipse.swt.internal.ole.win32.VARDESC; 27 import org.eclipse.swt.internal.win32.OS; 28 29 import org.eclipse.swt.ole.win32.OleClientSite; 30 import org.eclipse.swt.ole.win32.OlePropertyDescription; 31 import org.eclipse.swt.ole.win32.OleFunctionDescription; 32 import org.eclipse.swt.ole.win32.OleParameterDescription; 33 import org.eclipse.swt.ole.win32.Variant; 34 import org.eclipse.swt.ole.win32.OLE; 35 36 import java.lang.all; 37 38 version(Tango){ 39 } else { // Phobos 40 static import std.algorithm; 41 } 42 43 /** 44 * OleAutomation provides a generic mechanism for accessing functionality that is 45 * specific to a particular ActiveX Control or OLE Document. 46 * 47 * <p>The OLE Document or ActiveX Control must support the IDispatch interface in order to provide 48 * OleAutomation support. The additional functionality provided by the OLE Object is specified in 49 * its IDL file. The additional methods can either be to get property values (<code>getProperty</code>), 50 * to set property values (<code>setProperty</code>) or to invoke a method (<code>invoke</code> or 51 * <code>invokeNoReply</code>). Arguments are passed around in the form of <code>Variant</code> 52 * objects. 53 * 54 * <p>Here is a sample IDL fragment: 55 * 56 * <pre> 57 * interface IMyControl : IDispatch 58 * { 59 * [propget, id(0)] HRESULT maxFileCount([retval, out] int *c); 60 * [propput, id(0)] HRESULT maxFileCount([in] int c); 61 * [id(1)] HRESULT AddFile([in] BSTR fileName); 62 * }; 63 * </pre> 64 * 65 * <p>An example of how to interact with this extended functionality is shown below: 66 * 67 * <code><pre> 68 * OleAutomation automation = new OleAutomation(myControlSite); 69 * 70 * // Look up the ID of the maxFileCount parameter 71 * int[] rgdispid = automation.getIDsOfNames(new String[]{"maxFileCount"}); 72 * int maxFileCountID = rgdispid[0]; 73 * 74 * // Set the property maxFileCount to 100: 75 * if (automation.setProperty(maxFileCountID, new Variant(100))) { 76 * System.out.println("Max File Count was successfully set."); 77 * } 78 * 79 * // Get the new value of the maxFileCount parameter: 80 * Variant pVarResult = automation.getProperty(maxFileCountID); 81 * if (pVarResult !is null) { 82 * System.out.println("Max File Count is "+pVarResult.getInt()); 83 * } 84 * 85 * // Invoke the AddFile method 86 * // Look up the IDs of the AddFile method and its parameter 87 * rgdispid = automation.getIDsOfNames(new String[]{"AddFile", "fileName"}); 88 * int dispIdMember = rgdispid[0]; 89 * int[] rgdispidNamedArgs = new int[] {rgdispid[1]}; 90 * 91 * // Convert arguments to Variant objects 92 * Variant[] rgvarg = new Variant[1]; 93 * String fileName = "C:\\testfile"; 94 * rgvarg[0] = new Variant(fileName); 95 * 96 * // Call the method 97 * Variant pVarResult = automation.invoke(dispIdMember, rgvarg, rgdispidNamedArgs); 98 * 99 * // Check the return value 100 * if (pVarResult is null || pVarResult.getInt() !is OLE.S_OK){ 101 * System.out.println("Failed to add file "+fileName); 102 * } 103 * 104 * automation.dispose(); 105 * 106 * </pre></code> 107 * 108 * @see <a href="http://www.eclipse.org/swt/snippets/#ole">OLE and ActiveX snippets</a> 109 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Examples: OLEExample, OleWebBrowser</a> 110 */ 111 public final class OleAutomation { 112 private IDispatch objIDispatch; 113 private String exceptionDescription; 114 private ITypeInfo objITypeInfo; 115 116 this(IDispatch idispatch) { 117 if (idispatch is null) OLE.error(OLE.ERROR_INVALID_INTERFACE_ADDRESS); 118 objIDispatch = idispatch; 119 objIDispatch.AddRef(); 120 121 int result = objIDispatch.GetTypeInfo(0, COM.LOCALE_USER_DEFAULT, &objITypeInfo); 122 if (result is OLE.S_OK) { 123 objITypeInfo.AddRef(); 124 } 125 } 126 /** 127 * Creates an OleAutomation object for the specified client. 128 * 129 * @param clientSite the site for the OLE Document or ActiveX Control whose additional functionality 130 * you need to access 131 * 132 * @exception IllegalArgumentException <ul> 133 * <li>ERROR_INVALID_INTERFACE_ADDRESS when called with an invalid client site 134 * </ul> 135 */ 136 public this(OleClientSite clientSite) { 137 if (clientSite is null) OLE.error(OLE.ERROR_INVALID_INTERFACE_ADDRESS); 138 objIDispatch = clientSite.getAutomationObject(); 139 140 auto result = objIDispatch.GetTypeInfo(0, COM.LOCALE_USER_DEFAULT, &objITypeInfo); 141 if (result is OLE.S_OK) { 142 objITypeInfo.AddRef(); 143 } 144 } 145 /** 146 * Disposes the automation object. 147 * <p> 148 * This method releases the IDispatch interface on the OLE Document or ActiveX Control. 149 * Do not use the OleAutomation object after it has been disposed. 150 */ 151 public void dispose() { 152 153 if (objIDispatch !is null){ 154 objIDispatch.Release(); 155 } 156 objIDispatch = null; 157 158 if (objITypeInfo !is null){ 159 objITypeInfo.Release(); 160 } 161 objITypeInfo = null; 162 163 } 164 IDispatch getAddress() { 165 return objIDispatch; 166 } 167 /** 168 * Returns the fully qualified name of the Help file for the given member ID. 169 * 170 * @param dispId the member ID whose Help file is being retrieved. 171 * @return a string representing the fully qualified name of a Help 172 * file or null. 173 */ 174 public String getHelpFile(int dispId) { 175 if (objITypeInfo is null) return null; 176 BSTR file; 177 HRESULT rc = objITypeInfo.GetDocumentation(dispId, null, null, null, &file ); 178 if (rc is OLE.S_OK) { 179 String str = WCHARzToStr( file, -1 ); 180 COM.SysFreeString(file); 181 return str; 182 } 183 return null; 184 } 185 /** 186 * Returns the documentation string for the given member ID. 187 * 188 * @param dispId the member ID in which the documentation is being retrieved. 189 * @return the documentation string if it exists; otherwise return null. 190 */ 191 public String getDocumentation(int dispId) { 192 if (objITypeInfo is null) return null; 193 BSTR doc; 194 HRESULT rc = objITypeInfo.GetDocumentation(dispId, null, &doc, null, null ); 195 if (rc == OLE.S_OK) { 196 String s = WCHARzToStr(doc, -1); 197 COM.SysFreeString(doc); 198 return s; 199 } 200 return null; 201 } 202 /** 203 * Returns the property description of a variable at the given index. 204 * 205 * @param index the index of a variable whose property is being retrieved. 206 * @return an OlePropertyDescription for a variable at the given index. 207 */ 208 public OlePropertyDescription getPropertyDescription(int index) { 209 if (objITypeInfo is null) return null; 210 VARDESC* vardesc; 211 HRESULT rc = objITypeInfo.GetVarDesc(index, &vardesc); 212 if (rc != OLE.S_OK) return null; 213 // VARDESC* vardesc = new VARDESC(); 214 // COM.MoveMemory(vardesc, ppVarDesc[0], VARDESC.sizeof); 215 216 OlePropertyDescription data = new OlePropertyDescription(); 217 data.id = vardesc.memid; 218 data.name = getName(vardesc.memid); 219 data.type = vardesc.elemdescVar.tdesc.vt; 220 if (data.type == OLE.VT_PTR) { 221 // short[] vt = new short[1]; 222 // COM.MoveMemory(vt, vardesc.elemdescVar.tdesc_union + 4, 2); 223 // TODO: 224 data.type = vardesc.elemdescVar.tdesc.vt; 225 } 226 data.flags = vardesc.wVarFlags; 227 data.kind = vardesc.varkind; 228 data.description = getDocumentation(vardesc.memid); 229 data.helpFile = getHelpFile(vardesc.memid); 230 231 objITypeInfo.ReleaseVarDesc(vardesc); 232 return data; 233 } 234 /** 235 * Returns the description of a function at the given index. 236 * 237 * @param index the index of a function whose property is being retrieved. 238 * @return an OleFunctionDescription for a function at the given index. 239 */ 240 public OleFunctionDescription getFunctionDescription(int index) { 241 if (objITypeInfo is null) return null; 242 FUNCDESC* funcdesc; 243 HRESULT rc = objITypeInfo.GetFuncDesc(index, &funcdesc); 244 if (rc != OLE.S_OK) return null; 245 246 OleFunctionDescription data = new OleFunctionDescription(); 247 248 data.id = funcdesc.memid; 249 data.optionalArgCount = funcdesc.cParamsOpt; 250 data.invokeKind = funcdesc.invkind; 251 data.funcKind = funcdesc.funckind; 252 data.flags = funcdesc.wFuncFlags; 253 data.callingConvention = funcdesc.callconv; 254 data.documentation = getDocumentation(funcdesc.memid); 255 data.helpFile = getHelpFile(funcdesc.memid); 256 257 String[] names = getNames(funcdesc.memid, funcdesc.cParams + 1); 258 if (names.length > 0) { 259 data.name = names[0]; 260 } 261 data.args = new OleParameterDescription[funcdesc.cParams]; 262 for (int i = 0; i < data.args.length; i++) { 263 data.args[i] = new OleParameterDescription(); 264 if (names.length > i + 1) { 265 data.args[i].name = names[i + 1]; 266 } 267 short[1] vt; 268 COM.MoveMemory(vt.ptr, (cast(void*)funcdesc.lprgelemdescParam) + i * 16 + 4, 2); 269 if (vt[0] is OLE.VT_PTR) { 270 int[1] pTypedesc; 271 COM.MoveMemory(pTypedesc.ptr, (cast(void*)funcdesc.lprgelemdescParam) + i * 16, 4); 272 short[1] vt2; 273 COM.MoveMemory(vt2.ptr, pTypedesc[0] + 4, 2); 274 vt[0] = cast(short)(vt2[0] | COM.VT_BYREF); 275 } 276 data.args[i].type = vt[0]; 277 short[1] wParamFlags; 278 COM.MoveMemory(wParamFlags.ptr, (cast(void*)funcdesc.lprgelemdescParam) + i * 16 + 12, 2); 279 data.args[i].flags = wParamFlags[0]; 280 } 281 282 data.returnType = funcdesc.elemdescFunc.tdesc.vt; 283 if (data.returnType is OLE.VT_PTR) { 284 ushort[1] vt; 285 COM.MoveMemory(vt.ptr, funcdesc.elemdescFunc.tdesc.u.lpadesc, 2); 286 data.returnType = vt[0]; 287 } 288 289 objITypeInfo.ReleaseFuncDesc(funcdesc); 290 return data; 291 } 292 /** 293 * Returns the type info of the current object referenced by the automation. 294 * The type info contains information about the object such as the function descriptions, 295 * the member descriptions and attributes of the type. 296 * 297 * @return the type info of the receiver 298 */ 299 public TYPEATTR* getTypeInfoAttributes() { 300 if (objITypeInfo is null) return null; 301 TYPEATTR* ppTypeAttr; 302 HRESULT rc = objITypeInfo.GetTypeAttr(&ppTypeAttr); 303 if (rc !is OLE.S_OK) return null; 304 TYPEATTR* typeattr = new TYPEATTR(); 305 COM.MoveMemory(typeattr, ppTypeAttr, TYPEATTR.sizeof); 306 objITypeInfo.ReleaseTypeAttr(ppTypeAttr); 307 return typeattr; 308 } 309 /** 310 * Returns the name of the given member ID. 311 * 312 * @param dispId the member ID in which the name is being retrieved. 313 * @return the name if it exists; otherwise return null. 314 */ 315 public String getName(int dispId) { 316 if (objITypeInfo is null) return null; 317 BSTR name; 318 HRESULT rc = objITypeInfo.GetDocumentation(dispId, &name, null, null, null ); 319 if (rc == OLE.S_OK) { 320 String s = WCHARzToStr(name, -1); 321 COM.SysFreeString(name); 322 return s; 323 } 324 return null; 325 } 326 /** 327 * Returns the name of a function and parameter names for the specified function ID. 328 * 329 * @param dispId the function ID in which the name and parameters are being retrieved. 330 * @param maxSize the maximum number of names to retrieve. 331 * @return an array of name containing the function name and the parameter names 332 */ 333 public String[] getNames(int dispId, int maxSize) { 334 if (objITypeInfo is null) return new String[0]; 335 BSTR[] names = new BSTR[maxSize]; 336 uint count; 337 HRESULT rc = objITypeInfo.GetNames(dispId, names.ptr, maxSize, &count); 338 if (rc == OLE.S_OK) { 339 String[] newNames = new String[count]; 340 for(int i=0; i<count; ++i){ 341 newNames[i] = WCHARzToStr(names[i], -1); 342 COM.SysFreeString(names[i]); 343 } 344 return newNames; 345 } 346 return null; 347 } 348 /** 349 * Returns the positive integer values (IDs) that are associated with the specified names by the 350 * IDispatch implementor. If you are trying to get the names of the parameters in a method, the first 351 * String in the names array must be the name of the method followed by the names of the parameters. 352 * 353 * @param names an array of names for which you require the identifiers 354 * 355 * @return positive integer values that are associated with the specified names in the same 356 * order as the names where provided; or null if the names are unknown 357 */ 358 public int[] getIDsOfNames(String[] names) { 359 360 int count = cast(int)/*64bit*/names.length; 361 LPCWSTR[] wcNames = new LPCWSTR[count]; 362 for(int i=0; i<count; ++i){ 363 wcNames[i] = StrToWCHARz(names[i]); 364 } 365 int[] rgdispid = new int[count]; 366 // TODO: NULL GUID ?? 367 GUID id; 368 HRESULT result = objIDispatch.GetIDsOfNames(&id, wcNames.ptr, count, COM.LOCALE_USER_DEFAULT, rgdispid.ptr); 369 if (result != COM.S_OK) return null; 370 371 return rgdispid; 372 } 373 /** 374 * Returns a description of the last error encountered. 375 * 376 * @return a description of the last error encountered 377 */ 378 public String getLastError() { 379 380 return exceptionDescription; 381 382 } 383 /** 384 * Returns the value of the property specified by the dispIdMember. 385 * 386 * @param dispIdMember the ID of the property as specified by the IDL of the ActiveX Control; the 387 * value for the ID can be obtained using OleAutomation.getIDsOfNames 388 * 389 * @return the value of the property specified by the dispIdMember or null 390 */ 391 public Variant getProperty(int dispIdMember) { 392 Variant pVarResult = new Variant(); 393 HRESULT result = invoke(dispIdMember, COM.DISPATCH_PROPERTYGET, null, null, pVarResult); 394 return (result is OLE.S_OK) ? pVarResult : null; 395 } 396 /** 397 * Returns the value of the property specified by the dispIdMember. 398 * 399 * @param dispIdMember the ID of the property as specified by the IDL of the ActiveX Control; the 400 * value for the ID can be obtained using OleAutomation.getIDsOfNames 401 * 402 * @param rgvarg an array of arguments for the method. All arguments are considered to be 403 * read only unless the Variant is a By Reference Variant type. 404 * 405 * @return the value of the property specified by the dispIdMember or null 406 * 407 * @since 2.0 408 */ 409 public Variant getProperty(int dispIdMember, Variant[] rgvarg) { 410 Variant pVarResult = new Variant(); 411 HRESULT result = invoke(dispIdMember, COM.DISPATCH_PROPERTYGET, rgvarg, null, pVarResult); 412 return (result is OLE.S_OK) ? pVarResult : null; 413 414 } 415 /** 416 * Returns the value of the property specified by the dispIdMember. 417 * 418 * @param dispIdMember the ID of the property as specified by the IDL of the ActiveX Control; the 419 * value for the ID can be obtained using OleAutomation.getIDsOfNames 420 * 421 * @param rgvarg an array of arguments for the method. All arguments are considered to be 422 * read only unless the Variant is a By Reference Variant type. 423 * 424 * @param rgdispidNamedArgs an array of identifiers for the arguments specified in rgvarg; the 425 * parameter IDs must be in the same order as their corresponding values; 426 * all arguments must have an identifier - identifiers can be obtained using 427 * OleAutomation.getIDsOfNames 428 * 429 * @return the value of the property specified by the dispIdMember or null 430 * 431 * @since 2.0 432 */ 433 public Variant getProperty(int dispIdMember, Variant[] rgvarg, int[] rgdispidNamedArgs) { 434 Variant pVarResult = new Variant(); 435 HRESULT result = invoke(dispIdMember, COM.DISPATCH_PROPERTYGET, rgvarg, rgdispidNamedArgs, pVarResult); 436 return (result is OLE.S_OK) ? pVarResult : null; 437 } 438 439 /** 440 * Invokes a method on the OLE Object; the method has no parameters. 441 * 442 * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the 443 * value for the ID can be obtained using OleAutomation.getIDsOfNames 444 * 445 * @return the result of the method or null if the method failed to give result information 446 */ 447 public Variant invoke(int dispIdMember) { 448 Variant pVarResult = new Variant(); 449 HRESULT result = invoke(dispIdMember, COM.DISPATCH_METHOD, null, null, pVarResult); 450 return (result is COM.S_OK) ? pVarResult : null; 451 } 452 /** 453 * Invokes a method on the OLE Object; the method has no optional parameters. 454 * 455 * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the 456 * value for the ID can be obtained using OleAutomation.getIDsOfNames 457 * 458 * @param rgvarg an array of arguments for the method. All arguments are considered to be 459 * read only unless the Variant is a By Reference Variant type. 460 * 461 * @return the result of the method or null if the method failed to give result information 462 */ 463 public Variant invoke(int dispIdMember, Variant[] rgvarg) { 464 Variant pVarResult = new Variant(); 465 HRESULT result = invoke(dispIdMember, COM.DISPATCH_METHOD, rgvarg, null, pVarResult); 466 return (result is COM.S_OK) ? pVarResult : null; 467 } 468 /** 469 * Invokes a method on the OLE Object; the method has optional parameters. It is not 470 * necessary to specify all the optional parameters, only include the parameters for which 471 * you are providing values. 472 * 473 * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the 474 * value for the ID can be obtained using OleAutomation.getIDsOfNames 475 * 476 * @param rgvarg an array of arguments for the method. All arguments are considered to be 477 * read only unless the Variant is a By Reference Variant type. 478 * 479 * @param rgdispidNamedArgs an array of identifiers for the arguments specified in rgvarg; the 480 * parameter IDs must be in the same order as their corresponding values; 481 * all arguments must have an identifier - identifiers can be obtained using 482 * OleAutomation.getIDsOfNames 483 * 484 * @return the result of the method or null if the method failed to give result information 485 */ 486 public Variant invoke(int dispIdMember, Variant[] rgvarg, int[] rgdispidNamedArgs) { 487 Variant pVarResult = new Variant(); 488 HRESULT result = invoke(dispIdMember, COM.DISPATCH_METHOD, rgvarg, rgdispidNamedArgs, pVarResult); 489 return (result is COM.S_OK) ? pVarResult : null; 490 } 491 private int invoke(int dispIdMember, ushort wFlags, Variant[] rgvarg, int[] rgdispidNamedArgs, Variant pVarResult) { 492 assert(objIDispatch); 493 494 // get the IDispatch interface for the control 495 if (objIDispatch is null) return COM.E_FAIL; 496 497 // create a DISPPARAMS structure for the input parameters 498 DISPPARAMS pDispParams; 499 500 // store arguments in rgvarg 501 if (rgvarg !is null && rgvarg.length > 0) { 502 VARIANT[] tempArgs = new VARIANT[rgvarg.length]; 503 for (int i = 0; i < rgvarg.length ; ++i) { 504 rgvarg[i].getData(&tempArgs[i]); 505 } 506 // the reverse sequency 507 version(Tango){ 508 tempArgs.reverse; 509 } else { // Phobos 510 std.algorithm.reverse(tempArgs); 511 } 512 pDispParams.cArgs = cast(int)/*64bit*/tempArgs.length; 513 pDispParams.rgvarg = tempArgs.ptr; 514 } 515 516 // if arguments have ids, store the ids in rgdispidNamedArgs 517 if (rgdispidNamedArgs !is null && rgdispidNamedArgs.length > 0) { 518 DISPID[] tempArgs = rgdispidNamedArgs.dup; 519 // the reverse sequency 520 version(Tango){ 521 tempArgs.reverse; 522 } else { // Phobos 523 std.algorithm.reverse(tempArgs); 524 } 525 pDispParams.cNamedArgs = cast(int)/*64bit*/tempArgs.length; 526 pDispParams.rgdispidNamedArgs = tempArgs.ptr; 527 } 528 529 // invoke the method 530 EXCEPINFO excepInfo; 531 uint pArgErr; 532 VARIANT* pVarResultAddress = null; 533 if (pVarResult !is null) 534 pVarResultAddress = new VARIANT(); 535 536 GUID id; // IID_NULL 537 /* 538 HRESULT Invoke( 539 [in] DISPID dispIdMember, 540 [in] REFIID riid, 541 [in] LCID lcid, 542 [in] WORD wFlags, 543 [in, out] DISPPARAMS * pDispParams, 544 [out] VARIANT * pVarResult, 545 [out] EXCEPINFO * pExcepInfo, 546 [out] UINT * puArgErr 547 ); 548 */ 549 HRESULT result = objIDispatch.Invoke(dispIdMember, &id, COM.LOCALE_USER_DEFAULT, wFlags, &pDispParams, pVarResultAddress, &excepInfo, &pArgErr); 550 551 if (pVarResultAddress !is null){ 552 pVarResult.setData(pVarResultAddress); 553 COM.VariantClear(pVarResultAddress); 554 } 555 556 // free the Dispparams resources 557 if (pDispParams.rgvarg !is null) { 558 for (int i = 0, length = cast(int)/*64bit*/rgvarg.length; i < length; i++){ 559 COM.VariantClear(&pDispParams.rgvarg[i]); 560 } 561 pDispParams.rgvarg = null; 562 } 563 pDispParams.rgdispidNamedArgs = null; 564 565 // save error string and cleanup EXCEPINFO 566 manageExcepinfo(result, &excepInfo); 567 568 return result; 569 } 570 /** 571 * Invokes a method on the OLE Object; the method has no parameters. In the early days of OLE, 572 * the IDispatch interface was not well defined and some applications (mainly Word) did not support 573 * a return value. For these applications, call this method instead of calling 574 * <code>public void invoke(int dispIdMember)</code>. 575 * 576 * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the 577 * value for the ID can be obtained using OleAutomation.getIDsOfNames 578 * 579 * @exception org.eclipse.swt.SWTException <ul> 580 * <li>ERROR_ACTION_NOT_PERFORMED when method invocation fails 581 * </ul> 582 */ 583 public void invokeNoReply(int dispIdMember) { 584 HRESULT result = invoke(dispIdMember, COM.DISPATCH_METHOD, null, null, null); 585 if (result !is COM.S_OK) 586 OLE.error(__FILE__, __LINE__, OLE.ERROR_ACTION_NOT_PERFORMED, result); 587 } 588 /** 589 * Invokes a method on the OLE Object; the method has no optional parameters. In the early days of OLE, 590 * the IDispatch interface was not well defined and some applications (mainly Word) did not support 591 * a return value. For these applications, call this method instead of calling 592 * <code>public void invoke(int dispIdMember, Variant[] rgvarg)</code>. 593 * 594 * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the 595 * value for the ID can be obtained using OleAutomation.getIDsOfNames 596 * 597 * @param rgvarg an array of arguments for the method. All arguments are considered to be 598 * read only unless the Variant is a By Reference Variant type. 599 * 600 * @exception org.eclipse.swt.SWTException <ul> 601 * <li>ERROR_ACTION_NOT_PERFORMED when method invocation fails 602 * </ul> 603 */ 604 public void invokeNoReply(int dispIdMember, Variant[] rgvarg) { 605 int result = invoke(dispIdMember, COM.DISPATCH_METHOD, rgvarg, null, null); 606 if (result !is COM.S_OK) 607 OLE.error(__FILE__, __LINE__, OLE.ERROR_ACTION_NOT_PERFORMED, result); 608 } 609 /** 610 * Invokes a method on the OLE Object; the method has optional parameters. It is not 611 * necessary to specify all the optional parameters, only include the parameters for which 612 * you are providing values. In the early days of OLE, the IDispatch interface was not well 613 * defined and some applications (mainly Word) did not support a return value. For these 614 * applications, call this method instead of calling 615 * <code>public void invoke(int dispIdMember, Variant[] rgvarg, int[] rgdispidNamedArgs)</code>. 616 * 617 * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the 618 * value for the ID can be obtained using OleAutomation.getIDsOfNames 619 * 620 * @param rgvarg an array of arguments for the method. All arguments are considered to be 621 * read only unless the Variant is a By Reference Variant type. 622 * 623 * @param rgdispidNamedArgs an array of identifiers for the arguments specified in rgvarg; the 624 * parameter IDs must be in the same order as their corresponding values; 625 * all arguments must have an identifier - identifiers can be obtained using 626 * OleAutomation.getIDsOfNames 627 * 628 * @exception org.eclipse.swt.SWTException <ul> 629 * <li>ERROR_ACTION_NOT_PERFORMED when method invocation fails 630 * </ul> 631 */ 632 public void invokeNoReply(int dispIdMember, Variant[] rgvarg, int[] rgdispidNamedArgs) { 633 HRESULT result = invoke(dispIdMember, COM.DISPATCH_METHOD, rgvarg, rgdispidNamedArgs, null); 634 if (result !is COM.S_OK) 635 OLE.error(__FILE__, __LINE__, OLE.ERROR_ACTION_NOT_PERFORMED, result); 636 } 637 private void manageExcepinfo(int hResult, EXCEPINFO* excepInfo) { 638 639 if (hResult is COM.S_OK){ 640 exceptionDescription = "No Error"; //$NON-NLS-1$ 641 return; 642 } 643 644 // extract exception info 645 if (hResult is COM.DISP_E_EXCEPTION) { 646 if (excepInfo.bstrDescription !is null){ 647 exceptionDescription = WCHARzToStr(excepInfo.bstrDescription); 648 } else { 649 exceptionDescription = ("OLE Automation Error Exception "); //$NON-NLS-1$ 650 if (excepInfo.wCode != 0){ 651 exceptionDescription ~= "code = "; 652 exceptionDescription ~= cast(int)(excepInfo.wCode); //$NON-NLS-1$ 653 } else if (excepInfo.scode != 0){ 654 exceptionDescription ~= "code = "; 655 exceptionDescription ~= (excepInfo.scode); //$NON-NLS-1$ 656 } 657 } 658 } else { 659 exceptionDescription = ("OLE Automation Error HResult : ") ~ toHex(hResult); //$NON-NLS-1$ 660 } 661 662 // cleanup EXCEPINFO struct 663 if (excepInfo.bstrDescription !is null) 664 COM.SysFreeString(excepInfo.bstrDescription); 665 if (excepInfo.bstrHelpFile !is null) 666 COM.SysFreeString(excepInfo.bstrHelpFile); 667 if (excepInfo.bstrSource !is null) 668 COM.SysFreeString(excepInfo.bstrSource); 669 } 670 /** 671 * Sets the property specified by the dispIdMember to a new value. 672 * 673 * @param dispIdMember the ID of the property as specified by the IDL of the ActiveX Control; the 674 * value for the ID can be obtained using OleAutomation.getIDsOfNames 675 * @param rgvarg the new value of the property 676 * 677 * @return true if the operation was successful 678 */ 679 public bool setProperty(int dispIdMember, Variant rgvarg) { 680 681 Variant[] rgvarg2 = new Variant[1]; 682 rgvarg2[0] = rgvarg; 683 int[] rgdispidNamedArgs; 684 rgdispidNamedArgs ~= COM.DISPID_PROPERTYPUT; 685 ushort dwFlags = COM.DISPATCH_PROPERTYPUT; 686 if ((rgvarg.getType() & COM.VT_BYREF) == COM.VT_BYREF) 687 dwFlags = COM.DISPATCH_PROPERTYPUTREF; 688 Variant pVarResult = new Variant(); 689 HRESULT result = invoke(dispIdMember, dwFlags, rgvarg2, rgdispidNamedArgs, pVarResult); 690 return (result == COM.S_OK); 691 } 692 /** 693 * Sets the property specified by the dispIdMember to a new value. 694 * 695 * @param dispIdMember the ID of the property as specified by the IDL of the ActiveX Control; the 696 * value for the ID can be obtained using OleAutomation.getIDsOfNames 697 * @param rgvarg an array of arguments for the method. All arguments are considered to be 698 * read only unless the Variant is a By Reference Variant type. 699 * 700 * @return true if the operation was successful 701 * 702 * @since 2.0 703 */ 704 public bool setProperty(int dispIdMember, Variant[] rgvarg) { 705 int[] rgdispidNamedArgs; 706 rgdispidNamedArgs ~= COM.DISPID_PROPERTYPUT; 707 ushort dwFlags = COM.DISPATCH_PROPERTYPUT; 708 for (int i = 0; i < rgvarg.length; i++) { 709 if ((rgvarg[i].getType() & COM.VT_BYREF) == COM.VT_BYREF) 710 dwFlags = COM.DISPATCH_PROPERTYPUTREF; 711 } 712 Variant pVarResult = new Variant(); 713 HRESULT result = invoke(dispIdMember, dwFlags, rgvarg, rgdispidNamedArgs, pVarResult); 714 return (result == COM.S_OK); 715 } 716 } 717