]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleAutomation.java
Merge branch 'bug-623' into release/1.43.0
[simantics/platform.git] / bundles / org.eclipse.swt.win32.win32.x86_64 / src / org / eclipse / swt / ole / win32 / OleAutomation.java
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleAutomation.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/ole/win32/OleAutomation.java
new file mode 100644 (file)
index 0000000..5bf1444
--- /dev/null
@@ -0,0 +1,744 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.ole.win32;
+
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.ole.win32.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * OleAutomation provides a generic mechanism for accessing functionality that is
+ * specific to a particular ActiveX Control or OLE Document.
+ *
+ * <p>The OLE Document or ActiveX Control must support the IDispatch interface in order to provide
+ * OleAutomation support. The additional functionality provided by the OLE Object is specified in
+ * its IDL file.  The additional methods can either be to get property values (<code>getProperty</code>),
+ * to set property values (<code>setProperty</code>) or to invoke a method (<code>invoke</code> or
+ * <code>invokeNoReply</code>).  Arguments are passed around in the form of <code>Variant</code>
+ * objects.
+ *
+ * <p>Here is a sample IDL fragment:
+ *
+ * <pre>
+ *     interface IMyControl : IDispatch
+ *     {
+ *             [propget, id(0)] HRESULT maxFileCount([retval, out] int *c);
+ *             [propput, id(0)] HRESULT maxFileCount([in] int c);
+ *             [id(1)] HRESULT AddFile([in] BSTR fileName);
+ *     };
+ * </pre>
+ *
+ * <p>An example of how to interact with this extended functionality is shown below:
+ *
+ * <pre><code>
+ *     OleAutomation automation = new OleAutomation(myControlSite);
+ *
+ *     // Look up the ID of the maxFileCount parameter
+ *     int[] rgdispid = automation.getIDsOfNames(new String[]{"maxFileCount"});
+ *     int maxFileCountID = rgdispid[0];
+ *
+ *     // Set the property maxFileCount to 100:
+ *     if (automation.setProperty(maxFileCountID, new Variant(100))) {
+ *             System.out.println("Max File Count was successfully set.");
+ *     }
+ *
+ *     // Get the new value of the maxFileCount parameter:
+ *     Variant pVarResult = automation.getProperty(maxFileCountID);
+ *     if (pVarResult != null) {
+ *             System.out.println("Max File Count is "+pVarResult.getInt());
+ *     }
+ *
+ *     // Invoke the AddFile method
+ *     // Look up the IDs of the AddFile method and its parameter
+ *     rgdispid = automation.getIDsOfNames(new String[]{"AddFile", "fileName"});
+ *     int dispIdMember = rgdispid[0];
+ *     int[] rgdispidNamedArgs = new int[] {rgdispid[1]};
+ *
+ *     // Convert arguments to Variant objects
+ *     Variant[] rgvarg = new Variant[1];
+ *     String fileName = "C:\\testfile";
+ *     rgvarg[0] = new Variant(fileName);
+ *
+ *     // Call the method
+ *     Variant pVarResult = automation.invoke(dispIdMember, rgvarg, rgdispidNamedArgs);
+ *
+ *     // Check the return value
+ *     if (pVarResult == null || pVarResult.getInt() != OLE.S_OK){
+ *             System.out.println("Failed to add file "+fileName);
+ *     }
+ *
+ *     automation.dispose();
+ *
+ * </code></pre>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#ole">OLE and ActiveX snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Examples: OLEExample, OleWebBrowser</a>
+ */
+public final class OleAutomation {
+       private IUnknown objIUnknown;
+       private IDispatch objIDispatch;
+       private String exceptionDescription;
+       private ITypeInfo objITypeInfo;
+
+OleAutomation(IDispatch idispatch) {
+       if (idispatch == null) OLE.error(OLE.ERROR_INVALID_INTERFACE_ADDRESS);
+       objIDispatch = idispatch;
+       objIDispatch.AddRef();
+
+       long[] ppv = new long[1];
+       /* GetTypeInfo([in] iTInfo, [in] lcid, [out] ppTInfo)
+        * AddRef has already been called on ppTInfo by the callee and must be released by the caller.
+        */
+       int result = objIDispatch.GetTypeInfo(0, COM.LOCALE_USER_DEFAULT, ppv);
+       if (result == OLE.S_OK) {
+               objITypeInfo = new ITypeInfo(ppv[0]);
+       }
+}
+/**
+ * Creates an OleAutomation object for the specified client.
+ *
+ * @param clientSite the site for the OLE Document or ActiveX Control whose additional functionality
+ *        you need to access
+ *
+ * @exception IllegalArgumentException <ul>
+ *             <li>ERROR_INVALID_INTERFACE_ADDRESS when called with an invalid client site
+ *     </ul>
+ */
+public OleAutomation(OleClientSite clientSite) {
+       if (clientSite == null) OLE.error(OLE.ERROR_INVALID_INTERFACE_ADDRESS);
+       objIDispatch = clientSite.getAutomationObject();
+
+       long[] ppv = new long[1];
+       /* GetTypeInfo([in] iTInfo, [in] lcid, [out] ppTInfo)
+        * AddRef has already been called on ppTInfo by the callee and must be released by the caller.
+        */
+       int result = objIDispatch.GetTypeInfo(0, COM.LOCALE_USER_DEFAULT, ppv);
+       if (result == OLE.S_OK) {
+               objITypeInfo = new ITypeInfo(ppv[0]);
+       }
+}
+/**
+ * Creates an OleAutomation object for the specified <code>progID</code>.
+ *
+ * @param progId the unique program identifier of an OLE Document application;
+ *               the value of the ProgID key or the value of the VersionIndependentProgID key specified
+ *               in the registry for the desired OLE Document (for example, the VersionIndependentProgID
+ *               for Word is Word.Document)
+ *
+ * @exception SWTException
+ * <ul><li>ERROR_INVALID_CLASSID when the progId does not map to a registered CLSID
+ *     <li>ERROR_CANNOT_CREATE_OBJECT when failed to create OLE Object
+ *     <li>ERROR_INTERFACE_NOT_FOUND when the OLE object specified does not implement IDispatch
+ * </ul>
+ *
+ * @since 3.6
+ */
+public OleAutomation(String progId) {
+       try {
+               OS.OleInitialize(0);
+               GUID appClsid = getClassID(progId);
+               if (appClsid == null) {
+                       OS.OleUninitialize();
+                       OLE.error(OLE.ERROR_INVALID_CLASSID);
+               }
+               int flags = COM.CLSCTX_INPROC_SERVER | COM.CLSCTX_LOCAL_SERVER;
+               long[] ppvObject = new long[1];
+               int result = COM.CoCreateInstance(appClsid, 0, flags, COM.IIDIUnknown, ppvObject);
+               if (result != COM.S_OK) {
+                       OS.OleUninitialize();
+                       OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+               }
+               objIUnknown = new IUnknown(ppvObject[0]);
+
+               ppvObject[0] = 0;
+               result = objIUnknown.QueryInterface(COM.IIDIDispatch, ppvObject);
+               if (result != COM.S_OK) OLE.error(OLE.ERROR_INTERFACE_NOT_FOUND);
+               objIDispatch = new IDispatch(ppvObject[0]);
+
+               ppvObject[0] = 0;
+               result = objIDispatch.GetTypeInfo(0, COM.LOCALE_USER_DEFAULT, ppvObject);
+               if (result == OLE.S_OK) {
+                       objITypeInfo = new ITypeInfo(ppvObject[0]);
+               }
+       } catch (SWTException e) {
+               dispose();
+               throw e;
+       }
+}
+/**
+ * Disposes the automation object.
+ * <p>
+ * This method releases the IDispatch interface on the OLE Document or ActiveX Control.
+ * Do not use the OleAutomation object after it has been disposed.
+ */
+public void dispose() {
+
+       if (objIDispatch != null){
+               objIDispatch.Release();
+       }
+       objIDispatch = null;
+
+       if (objITypeInfo != null){
+               objITypeInfo.Release();
+       }
+       objITypeInfo = null;
+
+       if (objIUnknown != null){
+               objIUnknown.Release();
+               OS.OleUninitialize();
+       }
+       objIUnknown = null;
+}
+long getAddress() {
+       return objIDispatch.getAddress();
+}
+GUID getClassID(String clientName) {
+       // create a GUID struct to hold the result
+       GUID guid = new GUID();
+
+       // create a null terminated array of char
+       char[] buffer = null;
+       if (clientName != null) {
+               int count = clientName.length();
+               buffer = new char[count + 1];
+               clientName.getChars(0, count, buffer, 0);
+       }
+       if (COM.CLSIDFromProgID(buffer, guid) != COM.S_OK){
+               int result = COM.CLSIDFromString(buffer, guid);
+               if (result != COM.S_OK) return null;
+       }
+       return guid;
+}
+/**
+ * Returns the fully qualified name of the Help file for the given member ID.
+ *
+ * @param dispId the member ID whose Help file is being retrieved.
+ * @return a string representing the fully qualified name of a Help
+ * file or null.
+ */
+public String getHelpFile(int dispId) {
+       if (objITypeInfo == null) return null;
+       String[] file = new String[1];
+       int rc = objITypeInfo.GetDocumentation(dispId, null, null, null, file );
+       if (rc == OLE.S_OK) return file[0];
+       return null;
+}
+/**
+ * Returns the documentation string for the given member ID.
+ *
+ * @param dispId the member ID in which the documentation is being retrieved.
+ * @return the documentation string if it exists; otherwise return null.
+ */
+public String getDocumentation(int dispId) {
+       if (objITypeInfo == null) return null;
+       String[] doc = new String[1];
+       int rc = objITypeInfo.GetDocumentation(dispId, null, doc, null, null );
+       if (rc == OLE.S_OK) return doc[0];
+       return null;
+}
+/**
+ * Returns the property description of a variable at the given index.
+ *
+ * @param index the index of a variable whose property is being retrieved.
+ * @return an OlePropertyDescription for a variable at the given index.
+ */
+public OlePropertyDescription getPropertyDescription(int index) {
+       if (objITypeInfo == null) return null;
+       long[] ppVarDesc = new long[1];
+       int rc = objITypeInfo.GetVarDesc(index, ppVarDesc);
+       if (rc != OLE.S_OK) return null;
+       VARDESC vardesc = new VARDESC();
+       COM.MoveMemory(vardesc, ppVarDesc[0], VARDESC.sizeof);
+
+       OlePropertyDescription data = new OlePropertyDescription();
+       data.id = vardesc.memid;
+       data.name = getName(vardesc.memid);
+       data.type = vardesc.elemdescVar_tdesc_vt;
+       if (data.type == OLE.VT_PTR) {
+               short[] vt = new short[1];
+               OS.MoveMemory(vt, vardesc.elemdescVar_tdesc_union + C.PTR_SIZEOF, 2);
+               data.type = vt[0];
+       }
+       data.flags = vardesc.wVarFlags;
+       data.kind = vardesc.varkind;
+       data.description = getDocumentation(vardesc.memid);
+       data.helpFile = getHelpFile(vardesc.memid);
+
+       objITypeInfo.ReleaseVarDesc(ppVarDesc[0]);
+       return data;
+}
+/**
+ * Returns the description of a function at the given index.
+ *
+ * @param index the index of a function whose property is being retrieved.
+ * @return an OleFunctionDescription for a function at the given index.
+ */
+public OleFunctionDescription getFunctionDescription(int index) {
+       if (objITypeInfo == null) return null;
+       long[] ppFuncDesc = new long[1];
+       int rc = objITypeInfo.GetFuncDesc(index, ppFuncDesc);
+       if (rc != OLE.S_OK) return null;
+       FUNCDESC funcdesc = new FUNCDESC();
+       COM.MoveMemory(funcdesc, ppFuncDesc[0], FUNCDESC.sizeof);
+
+       OleFunctionDescription data = new OleFunctionDescription();
+
+       data.id = funcdesc.memid;
+       data.optionalArgCount = funcdesc.cParamsOpt;
+       data.invokeKind = funcdesc.invkind;
+       data.funcKind = funcdesc.funckind;
+       data.flags = funcdesc.wFuncFlags;
+       data.callingConvention = funcdesc.callconv;
+       data.documentation = getDocumentation(funcdesc.memid);
+       data.helpFile = getHelpFile(funcdesc.memid);
+
+       String[] names = getNames(funcdesc.memid, funcdesc.cParams + 1);
+       if (names.length > 0) {
+               data.name = names[0];
+       }
+       data.args = new OleParameterDescription[funcdesc.cParams];
+       for (int i = 0; i < data.args.length; i++) {
+               data.args[i] = new OleParameterDescription();
+               if (names.length > i + 1) {
+                       data.args[i].name = names[i + 1];
+               }
+               //TODO 0- use structures
+               short[] vt = new short[1];
+               OS.MoveMemory(vt, funcdesc.lprgelemdescParam + i * COM.ELEMDESC_sizeof() + C.PTR_SIZEOF, 2);
+               if (vt[0] == OLE.VT_PTR) {
+                       long [] pTypedesc = new long [1];
+                       OS.MoveMemory(pTypedesc, funcdesc.lprgelemdescParam + i * COM.ELEMDESC_sizeof(), C.PTR_SIZEOF);
+                       short[] vt2 = new short[1];
+                       OS.MoveMemory(vt2, pTypedesc[0] + C.PTR_SIZEOF, 2);
+                       vt[0] = (short)(vt2[0] | COM.VT_BYREF);
+               }
+               data.args[i].type = vt[0];
+               short[] wParamFlags = new short[1];
+               OS.MoveMemory(wParamFlags, funcdesc.lprgelemdescParam + i * COM.ELEMDESC_sizeof() + COM.TYPEDESC_sizeof () + C.PTR_SIZEOF, 2);
+               data.args[i].flags = wParamFlags[0];
+       }
+
+       data.returnType = funcdesc.elemdescFunc_tdesc_vt;
+       if (data.returnType == OLE.VT_PTR) {
+               short[] vt = new short[1];
+               OS.MoveMemory(vt, funcdesc.elemdescFunc_tdesc_union + C.PTR_SIZEOF, 2);
+               data.returnType = vt[0];
+       }
+
+       objITypeInfo.ReleaseFuncDesc(ppFuncDesc[0]);
+       return data;
+}
+/**
+ * Returns the type info of the current object referenced by the automation.
+ * The type info contains information about the object such as the function descriptions,
+ * the member descriptions and attributes of the type.
+ *
+ * @return the type info of the receiver
+ */
+public TYPEATTR getTypeInfoAttributes() {
+       if (objITypeInfo == null) return null;
+       long [] ppTypeAttr = new long [1];
+       int rc = objITypeInfo.GetTypeAttr(ppTypeAttr);
+       if (rc != OLE.S_OK) return null;
+       TYPEATTR typeattr = new TYPEATTR();
+       COM.MoveMemory(typeattr, ppTypeAttr[0], TYPEATTR.sizeof);
+       objITypeInfo.ReleaseTypeAttr(ppTypeAttr[0]);
+       return typeattr;
+}
+/**
+ * Returns the name of the given member ID.
+ *
+ * @param dispId the member ID in which the name is being retrieved.
+ * @return the name if it exists; otherwise return null.
+ */
+public String getName(int dispId) {
+       if (objITypeInfo == null) return null;
+       String[] name = new String[1];
+       int rc = objITypeInfo.GetDocumentation(dispId, name, null, null, null );
+       if (rc == OLE.S_OK) return name[0];
+       return null;
+}
+/**
+ * Returns the name of a function and parameter names for the specified function ID.
+ *
+ * @param dispId the function ID in which the name and parameters are being retrieved.
+ * @param maxSize the maximum number of names to retrieve.
+ * @return an array of name containing the function name and the parameter names
+ */
+public String[] getNames(int dispId, int maxSize) {
+       if (objITypeInfo == null) return new String[0];
+       String[] names = new String[maxSize];
+       int[] count = new int[1];
+       int rc = objITypeInfo.GetNames(dispId, names, maxSize, count);
+       if (rc == OLE.S_OK) {
+               String[] newNames = new String[count[0]];
+               System.arraycopy(names, 0, newNames, 0, count[0]);
+               return newNames;
+       }
+       return new String[0];
+}
+/**
+ * Returns the positive integer values (IDs) that are associated with the specified names by the
+ * IDispatch implementor.  If you are trying to get the names of the parameters in a method, the first
+ * String in the names array must be the name of the method followed by the names of the parameters.
+ *
+ * @param names an array of names for which you require the identifiers
+ *
+ * @return positive integer values that are associated with the specified names in the same
+ *         order as the names where provided; or null if the names are unknown
+ */
+public int[] getIDsOfNames(String[] names) {
+
+       int[] rgdispid = new int[names.length];
+       int result = objIDispatch.GetIDsOfNames(new GUID(), names, names.length, COM.LOCALE_USER_DEFAULT, rgdispid);
+       if (result != COM.S_OK) return null;
+
+       return rgdispid;
+}
+/**
+ * Returns a description of the last error encountered.
+ *
+ * @return a description of the last error encountered
+ */
+public String getLastError() {
+
+       return exceptionDescription;
+
+}
+/**
+ * Returns the value of the property specified by the dispIdMember.
+ *
+ * @param dispIdMember the ID of the property as specified by the IDL of the ActiveX Control; the
+ *        value for the ID can be obtained using OleAutomation.getIDsOfNames
+ *
+ * @return the value of the property specified by the dispIdMember or null
+ */
+public Variant getProperty(int dispIdMember) {
+       Variant pVarResult = new Variant();
+       int result = invoke(dispIdMember, COM.DISPATCH_PROPERTYGET, null, null, pVarResult);
+       return (result == OLE.S_OK) ? pVarResult : null;
+}
+/**
+ * Returns the value of the property specified by the dispIdMember.
+ *
+ * @param dispIdMember the ID of the property as specified by the IDL of the ActiveX Control; the
+ *        value for the ID can be obtained using OleAutomation.getIDsOfNames
+ *
+ * @param rgvarg an array of arguments for the method.  All arguments are considered to be
+ *        read only unless the Variant is a By Reference Variant type.
+ *
+ * @return the value of the property specified by the dispIdMember or null
+ *
+ * @since 2.0
+ */
+public Variant getProperty(int dispIdMember, Variant[] rgvarg) {
+       Variant pVarResult = new Variant();
+       int result = invoke(dispIdMember, COM.DISPATCH_PROPERTYGET, rgvarg, null, pVarResult);
+       return (result == OLE.S_OK) ? pVarResult : null;
+
+}
+/**
+ * Returns the value of the property specified by the dispIdMember.
+ *
+ * @param dispIdMember the ID of the property as specified by the IDL of the ActiveX Control; the
+ *        value for the ID can be obtained using OleAutomation.getIDsOfNames
+ *
+ * @param rgvarg an array of arguments for the method.  All arguments are considered to be
+ *        read only unless the Variant is a By Reference Variant type.
+ *
+ * @param rgdispidNamedArgs an array of identifiers for the arguments specified in rgvarg; the
+ *        parameter IDs must be in the same order as their corresponding values;
+ *        all arguments must have an identifier - identifiers can be obtained using
+ *        OleAutomation.getIDsOfNames
+ *
+ * @return the value of the property specified by the dispIdMember or null
+ *
+ * @since 2.0
+ */
+public Variant getProperty(int dispIdMember, Variant[] rgvarg, int[] rgdispidNamedArgs) {
+       Variant pVarResult = new Variant();
+       int result = invoke(dispIdMember, COM.DISPATCH_PROPERTYGET, rgvarg, rgdispidNamedArgs, pVarResult);
+       return (result == OLE.S_OK) ? pVarResult : null;
+}
+@Override
+public boolean equals(Object object) {
+       if (object == this) return true;
+       if (object instanceof OleAutomation) {
+               if (objIDispatch == null) return false;
+               OleAutomation oleAutomation = ((OleAutomation) object);
+               if (oleAutomation.objIDispatch == null) return false;
+               long address1 = objIDispatch.getAddress();
+               long address2 = oleAutomation.objIDispatch.getAddress();
+               return address1 == address2;
+       }
+       return false;
+}
+/**
+ * Invokes a method on the OLE Object; the method has no parameters.
+ *
+ * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the
+ *        value for the ID can be obtained using OleAutomation.getIDsOfNames
+ *
+ * @return the result of the method or null if the method failed to give result information
+ */
+public Variant invoke(int dispIdMember) {
+       Variant pVarResult = new Variant();
+       int result = invoke(dispIdMember, COM.DISPATCH_METHOD, null, null, pVarResult);
+       return (result == COM.S_OK) ? pVarResult : null;
+}
+/**
+ * Invokes a method on the OLE Object; the method has no optional parameters.
+ *
+ * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the
+ *        value for the ID can be obtained using OleAutomation.getIDsOfNames
+ *
+ * @param rgvarg an array of arguments for the method.  All arguments are considered to be
+ *        read only unless the Variant is a By Reference Variant type.
+ *
+ * @return the result of the method or null if the method failed to give result information
+ */
+public Variant invoke(int dispIdMember, Variant[] rgvarg) {
+       Variant pVarResult = new Variant();
+       int result = invoke(dispIdMember, COM.DISPATCH_METHOD, rgvarg, null, pVarResult);
+       return (result == COM.S_OK) ? pVarResult : null;
+}
+/**
+ * Invokes a method on the OLE Object; the method has optional parameters.  It is not
+ * necessary to specify all the optional parameters, only include the parameters for which
+ * you are providing values.
+ *
+ * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the
+ *        value for the ID can be obtained using OleAutomation.getIDsOfNames
+ *
+ * @param rgvarg an array of arguments for the method.  All arguments are considered to be
+ *        read only unless the Variant is a By Reference Variant type.
+ *
+ * @param rgdispidNamedArgs an array of identifiers for the arguments specified in rgvarg; the
+ *        parameter IDs must be in the same order as their corresponding values;
+ *        all arguments must have an identifier - identifiers can be obtained using
+ *        OleAutomation.getIDsOfNames
+ *
+ * @return the result of the method or null if the method failed to give result information
+ */
+public Variant invoke(int dispIdMember, Variant[] rgvarg, int[] rgdispidNamedArgs) {
+       Variant pVarResult = new Variant();
+       int result = invoke(dispIdMember, COM.DISPATCH_METHOD, rgvarg, rgdispidNamedArgs, pVarResult);
+       return (result == COM.S_OK) ? pVarResult : null;
+}
+private int invoke(int dispIdMember, int wFlags, Variant[] rgvarg, int[] rgdispidNamedArgs, Variant pVarResult) {
+
+       // get the IDispatch interface for the control
+       if (objIDispatch == null) return COM.E_FAIL;
+
+       // create a DISPPARAMS structure for the input parameters
+       DISPPARAMS pDispParams = new DISPPARAMS();
+       // store arguments in rgvarg
+       if (rgvarg != null && rgvarg.length > 0) {
+               pDispParams.cArgs = rgvarg.length;
+               pDispParams.rgvarg = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, VARIANT.sizeof * rgvarg.length);
+               int offset = 0;
+               for (int i = rgvarg.length - 1; i >= 0 ; i--) {
+                       rgvarg[i].getData(pDispParams.rgvarg + offset);
+                       offset += VARIANT.sizeof;
+               }
+       }
+
+       // if arguments have ids, store the ids in rgdispidNamedArgs
+       if (rgdispidNamedArgs != null && rgdispidNamedArgs.length > 0) {
+               pDispParams.cNamedArgs = rgdispidNamedArgs.length;
+               pDispParams.rgdispidNamedArgs = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, 4 * rgdispidNamedArgs.length);
+               int offset = 0;
+               for (int i = rgdispidNamedArgs.length; i > 0; i--) {
+                       OS.MoveMemory(pDispParams.rgdispidNamedArgs + offset, new int[] {rgdispidNamedArgs[i-1]}, 4);
+                       offset += 4;
+               }
+       }
+
+       // invoke the method
+       EXCEPINFO excepInfo = new EXCEPINFO();
+       int[] pArgErr = new int[1];
+       long pVarResultAddress = 0;
+       if (pVarResult != null) pVarResultAddress = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof);
+       int result = objIDispatch.Invoke(dispIdMember, new GUID(), COM.LOCALE_USER_DEFAULT, wFlags, pDispParams, pVarResultAddress, excepInfo, pArgErr);
+
+       if (pVarResultAddress != 0){
+               pVarResult.setData(pVarResultAddress);
+               COM.VariantClear(pVarResultAddress);
+               OS.GlobalFree(pVarResultAddress);
+       }
+
+       // free the Dispparams resources
+       if (pDispParams.rgdispidNamedArgs != 0){
+               OS.GlobalFree(pDispParams.rgdispidNamedArgs);
+       }
+       if (pDispParams.rgvarg != 0) {
+               int offset = 0;
+               for (int i = 0, length = rgvarg.length; i < length; i++){
+                       COM.VariantClear(pDispParams.rgvarg + offset);
+                       offset += VARIANT.sizeof;
+               }
+               OS.GlobalFree(pDispParams.rgvarg);
+       }
+
+       // save error string and cleanup EXCEPINFO
+       manageExcepinfo(result, excepInfo);
+
+       return result;
+}
+/**
+ * Invokes a method on the OLE Object; the method has no parameters.  In the early days of OLE,
+ * the IDispatch interface was not well defined and some applications (mainly Word) did not support
+ * a return value.  For these applications, call this method instead of calling
+ * <code>public void invoke(int dispIdMember)</code>.
+ *
+ * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the
+ *        value for the ID can be obtained using OleAutomation.getIDsOfNames
+ *
+ * @exception org.eclipse.swt.SWTException <ul>
+ *             <li>ERROR_ACTION_NOT_PERFORMED when method invocation fails
+ *     </ul>
+ */
+public void invokeNoReply(int dispIdMember) {
+       int result = invoke(dispIdMember, COM.DISPATCH_METHOD, null, null, null);
+       if (result != COM.S_OK)
+               OLE.error(OLE.ERROR_ACTION_NOT_PERFORMED, result);
+}
+/**
+ * Invokes a method on the OLE Object; the method has no optional parameters.  In the early days of OLE,
+ * the IDispatch interface was not well defined and some applications (mainly Word) did not support
+ * a return value.  For these applications, call this method instead of calling
+ * <code>public void invoke(int dispIdMember, Variant[] rgvarg)</code>.
+ *
+ * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the
+ *        value for the ID can be obtained using OleAutomation.getIDsOfNames
+ *
+ * @param rgvarg an array of arguments for the method.  All arguments are considered to be
+ *        read only unless the Variant is a By Reference Variant type.
+ *
+ * @exception org.eclipse.swt.SWTException <ul>
+ *             <li>ERROR_ACTION_NOT_PERFORMED when method invocation fails
+ *     </ul>
+ */
+public void invokeNoReply(int dispIdMember, Variant[] rgvarg) {
+       int result = invoke(dispIdMember, COM.DISPATCH_METHOD, rgvarg, null, null);
+       if (result != COM.S_OK)
+               OLE.error(OLE.ERROR_ACTION_NOT_PERFORMED, result);
+}
+/**
+ * Invokes a method on the OLE Object; the method has optional parameters.  It is not
+ * necessary to specify all the optional parameters, only include the parameters for which
+ * you are providing values.  In the early days of OLE, the IDispatch interface was not well
+ * defined and some applications (mainly Word) did not support a return value.  For these
+ * applications, call this method instead of calling
+ * <code>public void invoke(int dispIdMember, Variant[] rgvarg, int[] rgdispidNamedArgs)</code>.
+ *
+ * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the
+ *        value for the ID can be obtained using OleAutomation.getIDsOfNames
+ *
+ * @param rgvarg an array of arguments for the method.  All arguments are considered to be
+ *        read only unless the Variant is a By Reference Variant type.
+ *
+ * @param rgdispidNamedArgs an array of identifiers for the arguments specified in rgvarg; the
+ *        parameter IDs must be in the same order as their corresponding values;
+ *        all arguments must have an identifier - identifiers can be obtained using
+ *        OleAutomation.getIDsOfNames
+ *
+ * @exception org.eclipse.swt.SWTException <ul>
+ *             <li>ERROR_ACTION_NOT_PERFORMED when method invocation fails
+ *     </ul>
+ */
+public void invokeNoReply(int dispIdMember, Variant[] rgvarg, int[] rgdispidNamedArgs) {
+       int result = invoke(dispIdMember, COM.DISPATCH_METHOD, rgvarg, rgdispidNamedArgs, null);
+       if (result != COM.S_OK)
+               OLE.error(OLE.ERROR_ACTION_NOT_PERFORMED, result);
+}
+private void manageExcepinfo(int hResult, EXCEPINFO excepInfo) {
+
+       if (hResult == COM.S_OK){
+               exceptionDescription = "No Error"; //$NON-NLS-1$
+               return;
+       }
+
+       // extract exception info
+       if (hResult == COM.DISP_E_EXCEPTION) {
+               if (excepInfo.bstrDescription != 0){
+                       int size = COM.SysStringByteLen(excepInfo.bstrDescription);
+                       char[] buffer = new char[(size + 1) /2];
+                       OS.MoveMemory(buffer, excepInfo.bstrDescription, size);
+                       exceptionDescription = new String(buffer);
+               } else {
+                       exceptionDescription = "OLE Automation Error Exception "; //$NON-NLS-1$
+                       if (excepInfo.wCode != 0){
+                               exceptionDescription += "code = "+excepInfo.wCode; //$NON-NLS-1$
+                       } else if (excepInfo.scode != 0){
+                               exceptionDescription += "code = "+excepInfo.scode; //$NON-NLS-1$
+                       }
+               }
+       } else {
+               exceptionDescription = "OLE Automation Error HResult : " + hResult; //$NON-NLS-1$
+       }
+
+       // cleanup EXCEPINFO struct
+       if (excepInfo.bstrDescription != 0)
+               COM.SysFreeString(excepInfo.bstrDescription);
+       if (excepInfo.bstrHelpFile != 0)
+               COM.SysFreeString(excepInfo.bstrHelpFile);
+       if (excepInfo.bstrSource != 0)
+               COM.SysFreeString(excepInfo.bstrSource);
+}
+/**
+ * Sets the property specified by the dispIdMember to a new value.
+ *
+ * @param dispIdMember the ID of the property as specified by the IDL of the ActiveX Control; the
+ *                     value for the ID can be obtained using OleAutomation.getIDsOfNames
+ * @param rgvarg the new value of the property
+ *
+ * @return true if the operation was successful
+ */
+public boolean setProperty(int dispIdMember, Variant rgvarg) {
+       Variant[] rgvarg2 = new Variant[] {rgvarg};
+       int[] rgdispidNamedArgs = new int[] {COM.DISPID_PROPERTYPUT};
+       int dwFlags = COM.DISPATCH_PROPERTYPUT;
+       if ((rgvarg.getType() & COM.VT_BYREF) == COM.VT_BYREF)
+               dwFlags = COM.DISPATCH_PROPERTYPUTREF;
+       Variant pVarResult = new Variant();
+       int result = invoke(dispIdMember, dwFlags, rgvarg2, rgdispidNamedArgs, pVarResult);
+       return (result == COM.S_OK);
+}
+/**
+ * Sets the property specified by the dispIdMember to a new value.
+ *
+ * @param dispIdMember the ID of the property as specified by the IDL of the ActiveX Control; the
+ *                     value for the ID can be obtained using OleAutomation.getIDsOfNames
+ * @param rgvarg an array of arguments for the method.  All arguments are considered to be
+ *                     read only unless the Variant is a By Reference Variant type.
+ *
+ * @return true if the operation was successful
+ *
+ * @since 2.0
+ */
+public boolean setProperty(int dispIdMember, Variant[] rgvarg) {
+       int[] rgdispidNamedArgs = new int[] {COM.DISPID_PROPERTYPUT};
+       int dwFlags = COM.DISPATCH_PROPERTYPUT;
+       for (int i = 0; i < rgvarg.length; i++) {
+               if ((rgvarg[i].getType() & COM.VT_BYREF) == COM.VT_BYREF)
+               dwFlags = COM.DISPATCH_PROPERTYPUTREF;
+       }
+       Variant pVarResult = new Variant();
+       int result = invoke(dispIdMember, dwFlags, rgvarg, rgdispidNamedArgs, pVarResult);
+       return (result == COM.S_OK);
+}
+}