/*******************************************************************************
 * 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:
 *
 * <code><pre>
 *	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();
 *
 * </pre></code>
 *
 * @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 /*int*/[] ppv = new long /*int*/[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 /*int*/[] ppv = new long /*int*/[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 /*int*/[] ppvObject = new long /*int*/[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 /*int*/ 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 /*int*/[] ppVarDesc = new long /*int*/[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 /*int*/[] ppFuncDesc = new long /*int*/[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 /*int*/ [] pTypedesc = new long /*int*/ [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 /*int*/ [] ppTypeAttr = new long /*int*/ [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 /*int*/ address1 = objIDispatch.getAddress();
		long /*int*/ 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 /*int*/ 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);
}
}
