001: /*******************************************************************************
002: * Copyright (c) 2000, 2005 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.swt.ole.win32;
011:
012: import org.eclipse.swt.internal.ole.win32.*;
013: import org.eclipse.swt.internal.win32.*;
014:
015: /**
016: * OleAutomation provides a generic mechanism for accessing functionality that is
017: * specific to a particular ActiveX Control or OLE Document.
018: *
019: * <p>The OLE Document or ActiveX Control must support the IDispatch interface in order to provide
020: * OleAutomation support. The additional functionality provided by the OLE Object is specified in
021: * its IDL file. The additional methods can either be to get property values (<code>getProperty</code>),
022: * to set property values (<code>setProperty</code>) or to invoke a method (<code>invoke</code> or
023: * <code>invokeNoReply</code>). Arguments are passed around in the form of <code>Variant</code>
024: * objects.
025: *
026: * <p>Here is a sample IDL fragment:
027: *
028: * <pre>
029: * interface IMyControl : IDispatch
030: * {
031: * [propget, id(0)] HRESULT maxFileCount([retval, out] int *c);
032: * [propput, id(0)] HRESULT maxFileCount([in] int c);
033: * [id(1)] HRESULT AddFile([in] BSTR fileName);
034: * };
035: * </pre>
036: *
037: * <p>An example of how to interact with this extended functionality is shown below:
038: *
039: * <code><pre>
040: * OleAutomation automation = new OleAutomation(myControlSite);
041: *
042: * // Look up the ID of the maxFileCount parameter
043: * int[] rgdispid = automation.getIDsOfNames(new String[]{"maxFileCount"});
044: * int maxFileCountID = rgdispid[0];
045: *
046: * // Set the property maxFileCount to 100:
047: * if (automation.setProperty(maxFileCountID, new Variant(100))) {
048: * System.out.println("Max File Count was successfully set.");
049: * }
050: *
051: * // Get the new value of the maxFileCount parameter:
052: * Variant pVarResult = automation.getProperty(maxFileCountID);
053: * if (pVarResult != null) {
054: * System.out.println("Max File Count is "+pVarResult.getInt());
055: * }
056: *
057: * // Invoke the AddFile method
058: * // Look up the IDs of the AddFile method and its parameter
059: * rgdispid = automation.getIDsOfNames(new String[]{"AddFile", "fileName"});
060: * int dispIdMember = rgdispid[0];
061: * int[] rgdispidNamedArgs = new int[] {rgdispid[1]};
062: *
063: * // Convert arguments to Variant objects
064: * Variant[] rgvarg = new Variant[1];
065: * String fileName = "C:\\testfile";
066: * rgvarg[0] = new Variant(fileName);
067: *
068: * // Call the method
069: * Variant pVarResult = automation.invoke(dispIdMember, rgvarg, rgdispidNamedArgs);
070: *
071: * // Check the return value
072: * if (pVarResult == null || pVarResult.getInt() != OLE.S_OK){
073: * System.out.println("Failed to add file "+fileName);
074: * }
075: *
076: * automation.dispose();
077: *
078: * </pre></code>
079: */
080: public final class OleAutomation {
081: private IDispatch objIDispatch;
082: private String exceptionDescription;
083: private ITypeInfo objITypeInfo;
084:
085: public// GOOGLE: make this public so we can instantiate our own
086: OleAutomation(IDispatch idispatch) {
087: if (idispatch == null)
088: OLE.error(OLE.ERROR_INVALID_INTERFACE_ADDRESS);
089: objIDispatch = idispatch;
090: objIDispatch.AddRef();
091:
092: int[] ppv = new int[1];
093: int result = objIDispatch.GetTypeInfo(0,
094: COM.LOCALE_USER_DEFAULT, ppv);
095: if (result == OLE.S_OK) {
096: objITypeInfo = new ITypeInfo(ppv[0]);
097: /*
098: * GOOGLE: According to MSDN, typeInfo is an [out,retval] param, which
099: * means the callee will have already called AddRef on the returned
100: * pointer. An additional AddRef here would cause a leak.
101: */
102: //objITypeInfo.AddRef();
103: }
104: }
105:
106: /**
107: * Creates an OleAutomation object for the specified client.
108: *
109: * @param clientSite the site for the OLE Document or ActiveX Control whose additional functionality
110: * you need to access
111: *
112: * @exception IllegalArgumentException <ul>
113: * <li>ERROR_INVALID_INTERFACE_ADDRESS when called with an invalid client site
114: * </ul>
115: */
116: public OleAutomation(OleClientSite clientSite) {
117: if (clientSite == null)
118: OLE.error(OLE.ERROR_INVALID_INTERFACE_ADDRESS);
119: objIDispatch = clientSite.getAutomationObject();
120:
121: int[] ppv = new int[1];
122: int result = objIDispatch.GetTypeInfo(0,
123: COM.LOCALE_USER_DEFAULT, ppv);
124: if (result == OLE.S_OK) {
125: objITypeInfo = new ITypeInfo(ppv[0]);
126: /*
127: * GOOGLE: According to MSDN, typeInfo is an [out,retval] param, which
128: * means the callee will have already called AddRef on the returned
129: * pointer. An additional AddRef would cause a leak.
130: */
131: //objITypeInfo.AddRef();
132: }
133: }
134:
135: /**
136: * Disposes the automation object.
137: * <p>
138: * This method releases the IDispatch interface on the OLE Document or ActiveX Control.
139: * Do not use the OleAutomation object after it has been disposed.
140: */
141: public void dispose() {
142:
143: if (objIDispatch != null) {
144: objIDispatch.Release();
145: }
146: objIDispatch = null;
147:
148: if (objITypeInfo != null) {
149: objITypeInfo.Release();
150: }
151: objITypeInfo = null;
152:
153: }
154:
155: int getAddress() {
156: return objIDispatch.getAddress();
157: }
158:
159: public String getHelpFile(int dispId) {
160: if (objITypeInfo == null)
161: return null;
162: String[] file = new String[1];
163: int rc = objITypeInfo.GetDocumentation(dispId, null, null,
164: null, file);
165: if (rc == OLE.S_OK)
166: return file[0];
167: return null;
168: }
169:
170: public String getDocumentation(int dispId) {
171: if (objITypeInfo == null)
172: return null;
173: String[] doc = new String[1];
174: int rc = objITypeInfo.GetDocumentation(dispId, null, doc, null,
175: null);
176: if (rc == OLE.S_OK)
177: return doc[0];
178: return null;
179: }
180:
181: public OlePropertyDescription getPropertyDescription(int index) {
182: if (objITypeInfo == null)
183: return null;
184: int[] ppVarDesc = new int[1];
185: int rc = objITypeInfo.GetVarDesc(index, ppVarDesc);
186: if (rc != OLE.S_OK)
187: return null;
188: VARDESC vardesc = new VARDESC();
189: COM.MoveMemory(vardesc, ppVarDesc[0], VARDESC.sizeof);
190:
191: OlePropertyDescription data = new OlePropertyDescription();
192: data.id = vardesc.memid;
193: data.name = getName(vardesc.memid);
194: data.type = vardesc.elemdescVar_tdesc_vt;
195: if (data.type == OLE.VT_PTR) {
196: short[] vt = new short[1];
197: COM.MoveMemory(vt, vardesc.elemdescVar_tdesc_union + 4, 2);
198: data.type = vt[0];
199: }
200: data.flags = vardesc.wVarFlags;
201: data.kind = vardesc.varkind;
202: data.description = getDocumentation(vardesc.memid);
203: data.helpFile = getHelpFile(vardesc.memid);
204:
205: objITypeInfo.ReleaseVarDesc(ppVarDesc[0]);
206: return data;
207: }
208:
209: public OleFunctionDescription getFunctionDescription(int index) {
210: if (objITypeInfo == null)
211: return null;
212: int[] ppFuncDesc = new int[1];
213: int rc = objITypeInfo.GetFuncDesc(index, ppFuncDesc);
214: if (rc != OLE.S_OK)
215: return null;
216: FUNCDESC funcdesc = new FUNCDESC();
217: COM.MoveMemory(funcdesc, ppFuncDesc[0], FUNCDESC.sizeof);
218:
219: OleFunctionDescription data = new OleFunctionDescription();
220:
221: data.id = funcdesc.memid;
222: data.optionalArgCount = funcdesc.cParamsOpt;
223: data.invokeKind = funcdesc.invkind;
224: data.funcKind = funcdesc.funckind;
225: data.flags = funcdesc.wFuncFlags;
226: data.callingConvention = funcdesc.callconv;
227: data.documentation = getDocumentation(funcdesc.memid);
228: data.helpFile = getHelpFile(funcdesc.memid);
229:
230: String[] names = getNames(funcdesc.memid, funcdesc.cParams + 1);
231: if (names.length > 0) {
232: data.name = names[0];
233: }
234: data.args = new OleParameterDescription[funcdesc.cParams];
235: for (int i = 0; i < data.args.length; i++) {
236: data.args[i] = new OleParameterDescription();
237: if (names.length > i + 1) {
238: data.args[i].name = names[i + 1];
239: }
240: short[] vt = new short[1];
241: COM.MoveMemory(vt, funcdesc.lprgelemdescParam + i * 16 + 4,
242: 2);
243: if (vt[0] == OLE.VT_PTR) {
244: int[] pTypedesc = new int[1];
245: COM.MoveMemory(pTypedesc, funcdesc.lprgelemdescParam
246: + i * 16, 4);
247: short[] vt2 = new short[1];
248: COM.MoveMemory(vt2, pTypedesc[0] + 4, 2);
249: vt[0] = (short) (vt2[0] | COM.VT_BYREF);
250: }
251: data.args[i].type = vt[0];
252: short[] wParamFlags = new short[1];
253: COM.MoveMemory(wParamFlags, funcdesc.lprgelemdescParam + i
254: * 16 + 12, 2);
255: data.args[i].flags = wParamFlags[0];
256: }
257:
258: data.returnType = funcdesc.elemdescFunc_tdesc_vt;
259: if (data.returnType == OLE.VT_PTR) {
260: short[] vt = new short[1];
261: COM
262: .MoveMemory(vt,
263: funcdesc.elemdescFunc_tdesc_union + 4, 2);
264: data.returnType = vt[0];
265: }
266:
267: objITypeInfo.ReleaseFuncDesc(ppFuncDesc[0]);
268: return data;
269: }
270:
271: public TYPEATTR getTypeInfoAttributes() {
272: if (objITypeInfo == null)
273: return null;
274: int[] ppTypeAttr = new int[1];
275: int rc = objITypeInfo.GetTypeAttr(ppTypeAttr);
276: if (rc != OLE.S_OK)
277: return null;
278: TYPEATTR typeattr = new TYPEATTR();
279: COM.MoveMemory(typeattr, ppTypeAttr[0], TYPEATTR.sizeof);
280: objITypeInfo.ReleaseTypeAttr(ppTypeAttr[0]);
281: return typeattr;
282: }
283:
284: public String getName(int dispId) {
285: if (objITypeInfo == null)
286: return null;
287: String[] name = new String[1];
288: int rc = objITypeInfo.GetDocumentation(dispId, name, null,
289: null, null);
290: if (rc == OLE.S_OK)
291: return name[0];
292: return null;
293: }
294:
295: public String[] getNames(int dispId, int maxSize) {
296: if (objITypeInfo == null)
297: return new String[0];
298: String[] names = new String[maxSize];
299: int[] count = new int[1];
300: int rc = objITypeInfo.GetNames(dispId, names, maxSize, count);
301: if (rc == OLE.S_OK) {
302: String[] newNames = new String[count[0]];
303: System.arraycopy(names, 0, newNames, 0, count[0]);
304: return newNames;
305: }
306: return new String[0];
307: }
308:
309: /**
310: * Returns the positive integer values (IDs) that are associated with the specified names by the
311: * IDispatch implementor. If you are trying to get the names of the parameters in a method, the first
312: * String in the names array must be the name of the method followed by the names of the parameters.
313: *
314: * @param names an array of names for which you require the identifiers
315: *
316: * @return positive integer values that are associated with the specified names in the same
317: * order as the names where provided; or null if the names are unknown
318: */
319: public int[] getIDsOfNames(String[] names) {
320:
321: int[] rgdispid = new int[names.length];
322: int result = objIDispatch.GetIDsOfNames(new GUID(), names,
323: names.length, COM.LOCALE_USER_DEFAULT, rgdispid);
324: if (result != COM.S_OK)
325: return null;
326:
327: return rgdispid;
328: }
329:
330: /**
331: * Returns a description of the last error encountered.
332: *
333: * @return a description of the last error encountered
334: */
335: public String getLastError() {
336:
337: return exceptionDescription;
338:
339: }
340:
341: /**
342: * Returns the value of the property specified by the dispIdMember.
343: *
344: * @param dispIdMember the ID of the property as specified by the IDL of the ActiveX Control; the
345: * value for the ID can be obtained using OleAutomation.getIDsOfNames
346: *
347: * @return the value of the property specified by the dispIdMember or null
348: */
349: public Variant getProperty(int dispIdMember) {
350: Variant pVarResult = new Variant();
351: int result = invoke(dispIdMember, COM.DISPATCH_PROPERTYGET,
352: null, null, pVarResult);
353:
354: // GOOGLE: better success test
355: // GOOGLE: force a dispose on the dangling Variant to prevent leaks.
356: if (result >= COM.S_OK)
357: return pVarResult;
358: else {
359: pVarResult.dispose();
360: return null;
361: }
362: }
363:
364: /**
365: * Returns the value of the property specified by the dispIdMember.
366: *
367: * @param dispIdMember the ID of the property as specified by the IDL of the ActiveX Control; the
368: * value for the ID can be obtained using OleAutomation.getIDsOfNames
369: *
370: * @param rgvarg an array of arguments for the method. All arguments are considered to be
371: * read only unless the Variant is a By Reference Variant type.
372: *
373: * @return the value of the property specified by the dispIdMember or null
374: *
375: * @since 2.0
376: */
377: public Variant getProperty(int dispIdMember, Variant[] rgvarg) {
378: Variant pVarResult = new Variant();
379: int result = invoke(dispIdMember, COM.DISPATCH_PROPERTYGET,
380: rgvarg, null, pVarResult);
381:
382: // GOOGLE: better success test
383: // GOOGLE: force a dispose on the dangling Variant to prevent leaks.
384: if (result >= COM.S_OK)
385: return pVarResult;
386: else {
387: pVarResult.dispose();
388: return null;
389: }
390: }
391:
392: /**
393: * Returns the value of the property specified by the dispIdMember.
394: *
395: * @param dispIdMember the ID of the property as specified by the IDL of the ActiveX Control; the
396: * value for the ID can be obtained using OleAutomation.getIDsOfNames
397: *
398: * @param rgvarg an array of arguments for the method. All arguments are considered to be
399: * read only unless the Variant is a By Reference Variant type.
400: *
401: * @param rgdispidNamedArgs an array of identifiers for the arguments specified in rgvarg; the
402: * parameter IDs must be in the same order as their corresponding values;
403: * all arguments must have an identifier - identifiers can be obtained using
404: * OleAutomation.getIDsOfNames
405: *
406: * @return the value of the property specified by the dispIdMember or null
407: *
408: * @since 2.0
409: */
410: public Variant getProperty(int dispIdMember, Variant[] rgvarg,
411: int[] rgdispidNamedArgs) {
412: Variant pVarResult = new Variant();
413: int result = invoke(dispIdMember, COM.DISPATCH_PROPERTYGET,
414: rgvarg, rgdispidNamedArgs, pVarResult);
415:
416: // GOOGLE: better success test
417: // GOOGLE: force a dispose on the dangling Variant to prevent leaks.
418: if (result >= COM.S_OK)
419: return pVarResult;
420: else {
421: pVarResult.dispose();
422: return null;
423: }
424: }
425:
426: /**
427: * Invokes a method on the OLE Object; the method has no parameters.
428: *
429: * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the
430: * value for the ID can be obtained using OleAutomation.getIDsOfNames
431: *
432: * @return the result of the method or null if the method failed to give result information
433: */
434: public Variant invoke(int dispIdMember) {
435: Variant pVarResult = new Variant();
436: int result = invoke(dispIdMember, COM.DISPATCH_METHOD, null,
437: null, pVarResult);
438:
439: // GOOGLE: better success test
440: // GOOGLE: force a dispose on the dangling Variant to prevent leaks.
441: if (result >= COM.S_OK)
442: return pVarResult;
443: else {
444: pVarResult.dispose();
445: return null;
446: }
447: }
448:
449: /**
450: * Invokes a method on the OLE Object; the method has no optional parameters.
451: *
452: * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the
453: * value for the ID can be obtained using OleAutomation.getIDsOfNames
454: *
455: * @param rgvarg an array of arguments for the method. All arguments are considered to be
456: * read only unless the Variant is a By Reference Variant type.
457: *
458: * @return the result of the method or null if the method failed to give result information
459: */
460: public Variant invoke(int dispIdMember, Variant[] rgvarg) {
461: Variant pVarResult = new Variant();
462: int result = invoke(dispIdMember, COM.DISPATCH_METHOD, rgvarg,
463: null, pVarResult);
464:
465: // GOOGLE: better success test
466: // GOOGLE: force a dispose on the dangling Variant to prevent leaks.
467: if (result >= COM.S_OK)
468: return pVarResult;
469: else {
470: pVarResult.dispose();
471: return null;
472: }
473: }
474:
475: /**
476: * Invokes a method on the OLE Object; the method has optional parameters. It is not
477: * necessary to specify all the optional parameters, only include the parameters for which
478: * you are providing values.
479: *
480: * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the
481: * value for the ID can be obtained using OleAutomation.getIDsOfNames
482: *
483: * @param rgvarg an array of arguments for the method. All arguments are considered to be
484: * read only unless the Variant is a By Reference Variant type.
485: *
486: * @param rgdispidNamedArgs an array of identifiers for the arguments specified in rgvarg; the
487: * parameter IDs must be in the same order as their corresponding values;
488: * all arguments must have an identifier - identifiers can be obtained using
489: * OleAutomation.getIDsOfNames
490: *
491: * @return the result of the method or null if the method failed to give result information
492: */
493: public Variant invoke(int dispIdMember, Variant[] rgvarg,
494: int[] rgdispidNamedArgs) {
495: Variant pVarResult = new Variant();
496: int result = invoke(dispIdMember, COM.DISPATCH_METHOD, rgvarg,
497: rgdispidNamedArgs, pVarResult);
498:
499: // GOOGLE: better success test
500: // GOOGLE: force a dispose on the dangling Variant to prevent leaks.
501: if (result >= COM.S_OK)
502: return pVarResult;
503: else {
504: pVarResult.dispose();
505: return null;
506: }
507: }
508:
509: private int invoke(int dispIdMember, int wFlags, Variant[] rgvarg,
510: int[] rgdispidNamedArgs, Variant pVarResult) {
511:
512: // get the IDispatch interface for the control
513: if (objIDispatch == null)
514: return COM.E_FAIL;
515:
516: // create a DISPPARAMS structure for the input parameters
517: DISPPARAMS pDispParams = new DISPPARAMS();
518: // store arguments in rgvarg
519: if (rgvarg != null && rgvarg.length > 0) {
520: pDispParams.cArgs = rgvarg.length;
521: pDispParams.rgvarg = OS
522: .GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT,
523: Variant.sizeof * rgvarg.length);
524: int offset = 0;
525: for (int i = rgvarg.length - 1; i >= 0; i--) {
526: rgvarg[i].getData(pDispParams.rgvarg + offset);
527: offset += Variant.sizeof;
528: }
529: }
530:
531: // if arguments have ids, store the ids in rgdispidNamedArgs
532: if (rgdispidNamedArgs != null && rgdispidNamedArgs.length > 0) {
533: pDispParams.cNamedArgs = rgdispidNamedArgs.length;
534: pDispParams.rgdispidNamedArgs = OS.GlobalAlloc(
535: COM.GMEM_FIXED | COM.GMEM_ZEROINIT,
536: 4 * rgdispidNamedArgs.length);
537: int offset = 0;
538: for (int i = rgdispidNamedArgs.length; i > 0; i--) {
539: COM.MoveMemory(pDispParams.rgdispidNamedArgs + offset,
540: new int[] { rgdispidNamedArgs[i - 1] }, 4);
541: offset += 4;
542: }
543: }
544:
545: // invoke the method
546: EXCEPINFO excepInfo = new EXCEPINFO();
547: int[] pArgErr = new int[1];
548: int pVarResultAddress = 0;
549: if (pVarResult != null)
550: pVarResultAddress = OS.GlobalAlloc(OS.GMEM_FIXED
551: | OS.GMEM_ZEROINIT, Variant.sizeof);
552: int result = objIDispatch.Invoke(dispIdMember, new GUID(),
553: COM.LOCALE_USER_DEFAULT, wFlags, pDispParams,
554: pVarResultAddress, excepInfo, pArgErr);
555:
556: if (pVarResultAddress != 0) {
557: pVarResult.setData(pVarResultAddress);
558: COM.VariantClear(pVarResultAddress);
559: OS.GlobalFree(pVarResultAddress);
560: }
561:
562: // free the Dispparams resources
563: if (pDispParams.rgdispidNamedArgs != 0) {
564: OS.GlobalFree(pDispParams.rgdispidNamedArgs);
565: }
566: if (pDispParams.rgvarg != 0) {
567: int offset = 0;
568: for (int i = 0, length = rgvarg.length; i < length; i++) {
569: COM.VariantClear(pDispParams.rgvarg + offset);
570: offset += Variant.sizeof;
571: }
572: OS.GlobalFree(pDispParams.rgvarg);
573: }
574:
575: // save error string and cleanup EXCEPINFO
576: manageExcepinfo(result, excepInfo);
577:
578: return result;
579: }
580:
581: /**
582: * Invokes a method on the OLE Object; the method has no parameters. In the early days of OLE,
583: * the IDispatch interface was not well defined and some applications (mainly Word) did not support
584: * a return value. For these applications, call this method instead of calling
585: * <code>public void invoke(int dispIdMember)</code>.
586: *
587: * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the
588: * value for the ID can be obtained using OleAutomation.getIDsOfNames
589: *
590: * @exception SWTException <ul>
591: * <li>ERROR_ACTION_NOT_PERFORMED when method invocation fails
592: * </ul>
593: */
594: public void invokeNoReply(int dispIdMember) {
595: int result = invoke(dispIdMember, COM.DISPATCH_METHOD, null,
596: null, null);
597: if (result != COM.S_OK)
598: OLE.error(OLE.ERROR_ACTION_NOT_PERFORMED, result);
599: }
600:
601: /**
602: * Invokes a method on the OLE Object; the method has no optional parameters. In the early days of OLE,
603: * the IDispatch interface was not well defined and some applications (mainly Word) did not support
604: * a return value. For these applications, call this method instead of calling
605: * <code>public void invoke(int dispIdMember, Variant[] rgvarg)</code>.
606: *
607: * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the
608: * value for the ID can be obtained using OleAutomation.getIDsOfNames
609: *
610: * @param rgvarg an array of arguments for the method. All arguments are considered to be
611: * read only unless the Variant is a By Reference Variant type.
612: *
613: * @exception SWTException <ul>
614: * <li>ERROR_ACTION_NOT_PERFORMED when method invocation fails
615: * </ul>
616: */
617: public void invokeNoReply(int dispIdMember, Variant[] rgvarg) {
618: int result = invoke(dispIdMember, COM.DISPATCH_METHOD, rgvarg,
619: null, null);
620: if (result != COM.S_OK)
621: OLE.error(OLE.ERROR_ACTION_NOT_PERFORMED, result);
622: }
623:
624: /**
625: * Invokes a method on the OLE Object; the method has optional parameters. It is not
626: * necessary to specify all the optional parameters, only include the parameters for which
627: * you are providing values. In the early days of OLE, the IDispatch interface was not well
628: * defined and some applications (mainly Word) did not support a return value. For these
629: * applications, call this method instead of calling
630: * <code>public void invoke(int dispIdMember, Variant[] rgvarg, int[] rgdispidNamedArgs)</code>.
631: *
632: * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the
633: * value for the ID can be obtained using OleAutomation.getIDsOfNames
634: *
635: * @param rgvarg an array of arguments for the method. All arguments are considered to be
636: * read only unless the Variant is a By Reference Variant type.
637: *
638: * @param rgdispidNamedArgs an array of identifiers for the arguments specified in rgvarg; the
639: * parameter IDs must be in the same order as their corresponding values;
640: * all arguments must have an identifier - identifiers can be obtained using
641: * OleAutomation.getIDsOfNames
642: *
643: * @exception SWTException <ul>
644: * <li>ERROR_ACTION_NOT_PERFORMED when method invocation fails
645: * </ul>
646: */
647: public void invokeNoReply(int dispIdMember, Variant[] rgvarg,
648: int[] rgdispidNamedArgs) {
649: int result = invoke(dispIdMember, COM.DISPATCH_METHOD, rgvarg,
650: rgdispidNamedArgs, null);
651: if (result != COM.S_OK)
652: OLE.error(OLE.ERROR_ACTION_NOT_PERFORMED, result);
653: }
654:
655: private void manageExcepinfo(int hResult, EXCEPINFO excepInfo) {
656:
657: // GOOGLE: better success test
658: if (hResult >= COM.S_OK) {
659: exceptionDescription = "No Error"; //$NON-NLS-1$
660: return;
661: }
662:
663: // extract exception info
664: if (hResult == COM.DISP_E_EXCEPTION) {
665: if (excepInfo.bstrDescription != 0) {
666: int size = COM
667: .SysStringByteLen(excepInfo.bstrDescription);
668: char[] buffer = new char[(size + 1) / 2];
669: COM.MoveMemory(buffer, excepInfo.bstrDescription, size);
670: exceptionDescription = new String(buffer);
671: } else {
672: exceptionDescription = "OLE Automation Error Exception "; //$NON-NLS-1$
673: if (excepInfo.wCode != 0) {
674: exceptionDescription += "code = " + excepInfo.wCode; //$NON-NLS-1$
675: } else if (excepInfo.scode != 0) {
676: exceptionDescription += "code = " + excepInfo.scode; //$NON-NLS-1$
677: }
678: }
679: } else {
680: exceptionDescription = "OLE Automation Error HResult : " + hResult; //$NON-NLS-1$
681: }
682:
683: // cleanup EXCEPINFO struct
684: if (excepInfo.bstrDescription != 0)
685: COM.SysFreeString(excepInfo.bstrDescription);
686: if (excepInfo.bstrHelpFile != 0)
687: COM.SysFreeString(excepInfo.bstrHelpFile);
688: if (excepInfo.bstrSource != 0)
689: COM.SysFreeString(excepInfo.bstrSource);
690: }
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 the new value of the property
698: *
699: * @return true if the operation was successful
700: */
701: public boolean setProperty(int dispIdMember, Variant rgvarg) {
702: Variant[] rgvarg2 = new Variant[] { rgvarg };
703: int[] rgdispidNamedArgs = new int[] { COM.DISPID_PROPERTYPUT };
704: int dwFlags = COM.DISPATCH_PROPERTYPUT;
705: if ((rgvarg.getType() & COM.VT_BYREF) == COM.VT_BYREF)
706: dwFlags = COM.DISPATCH_PROPERTYPUTREF;
707: Variant pVarResult = new Variant();
708: int result = invoke(dispIdMember, dwFlags, rgvarg2,
709: rgdispidNamedArgs, pVarResult);
710: // GOOGLE: force a dispose on the dangling Variant to prevent leaks.
711: pVarResult.dispose();
712: // GOOGLE: better success test
713: return (result >= COM.S_OK);
714: }
715:
716: /**
717: * Sets the property specified by the dispIdMember to a new value.
718: *
719: * @param dispIdMember the ID of the property as specified by the IDL of the ActiveX Control; the
720: * value for the ID can be obtained using OleAutomation.getIDsOfNames
721: * @param rgvarg an array of arguments for the method. All arguments are considered to be
722: * read only unless the Variant is a By Reference Variant type.
723: *
724: * @return true if the operation was successful
725: *
726: * @since 2.0
727: */
728: public boolean setProperty(int dispIdMember, Variant[] rgvarg) {
729: int[] rgdispidNamedArgs = new int[] { COM.DISPID_PROPERTYPUT };
730: int dwFlags = COM.DISPATCH_PROPERTYPUT;
731: for (int i = 0; i < rgvarg.length; i++) {
732: if ((rgvarg[i].getType() & COM.VT_BYREF) == COM.VT_BYREF)
733: dwFlags = COM.DISPATCH_PROPERTYPUTREF;
734: }
735: Variant pVarResult = new Variant();
736: int result = invoke(dispIdMember, dwFlags, rgvarg,
737: rgdispidNamedArgs, pVarResult);
738: // GOOGLE: force a dispose on the dangling Variant to prevent leaks.
739: pVarResult.dispose();
740: // GOOGLE: better success test
741: return (result >= COM.S_OK);
742: }
743: }
|