-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Allow calling COM methods/getters requirering hybrid calling (METHOD+PROPERTYGET convention) #595
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
dblock
merged 1 commit into
java-native-access:master
from
matthiasblaesing:com_hybrid_calling_convention
Feb 16, 2016
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
170 changes: 170 additions & 0 deletions
170
contrib/platform/test/com/sun/jna/platform/win32/COM/util/HybdridCOMInvocationTest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,170 @@ | ||
| package com.sun.jna.platform.win32.COM.util; | ||
|
|
||
| import com.sun.jna.platform.win32.COM.COMException; | ||
| import com.sun.jna.platform.win32.COM.COMLateBindingObject; | ||
| import com.sun.jna.platform.win32.COM.COMUtils; | ||
| import com.sun.jna.platform.win32.COM.Dispatch; | ||
| import com.sun.jna.platform.win32.COM.util.annotation.ComInterface; | ||
| import com.sun.jna.platform.win32.COM.util.annotation.ComMethod; | ||
| import com.sun.jna.platform.win32.COM.util.annotation.ComObject; | ||
| import com.sun.jna.platform.win32.Guid; | ||
| import com.sun.jna.platform.win32.Guid.CLSID; | ||
| import com.sun.jna.platform.win32.Guid.GUID; | ||
| import com.sun.jna.platform.win32.Guid.IID; | ||
| import com.sun.jna.platform.win32.Guid.REFIID; | ||
| import com.sun.jna.platform.win32.Kernel32; | ||
| import com.sun.jna.platform.win32.OaIdl; | ||
| import com.sun.jna.platform.win32.OaIdl.DISPID; | ||
| import com.sun.jna.platform.win32.Ole32; | ||
| import com.sun.jna.platform.win32.OleAuto; | ||
| import com.sun.jna.platform.win32.Variant; | ||
| import com.sun.jna.platform.win32.Variant.VARIANT; | ||
| import com.sun.jna.platform.win32.WTypes; | ||
| import com.sun.jna.platform.win32.WinDef; | ||
| import com.sun.jna.platform.win32.WinDef.UINT; | ||
| import com.sun.jna.platform.win32.WinDef.WORD; | ||
| import com.sun.jna.platform.win32.WinNT.HRESULT; | ||
| import com.sun.jna.ptr.IntByReference; | ||
| import com.sun.jna.ptr.PointerByReference; | ||
| import java.util.logging.Level; | ||
| import java.util.logging.Logger; | ||
| import junit.framework.TestCase; | ||
| import org.junit.Test; | ||
| import static junit.framework.TestCase.assertEquals; | ||
| import static junit.framework.TestCase.assertTrue; | ||
|
|
||
| /** | ||
| * In the word COM bindings it was determined, that some methods can't be called | ||
| * with only wFlags OleAuto.DISPATCH_METHOD or OleAuto.DISPATCH_PROPERTYGET. | ||
| * | ||
| * For these methods both flags need to be set. | ||
| * | ||
| * https://www.delphitools.info/2013/04/30/gaining-visual-basic-ole-super-powers/ | ||
| * https://msdn.microsoft.com/en-us/library/windows/desktop/ms221486(v=vs.85).aspx | ||
| * | ||
| * A sample function is InchesToPoints from thw word typelibrary | ||
| */ | ||
| public class HybdridCOMInvocationTest extends TestCase { | ||
|
|
||
| private static final Logger LOG = Logger.getLogger(HybdridCOMInvocationTest.class.getName()); | ||
|
|
||
| private static final String CLSID_WORD_STRING = "{000209FF-0000-0000-C000-000000000046}"; | ||
| private static final String IID_APPLICATION_STRING = "{00020970-0000-0000-C000-000000000046}"; | ||
| private static final GUID CLSID_WORD = new GUID(CLSID_WORD_STRING); | ||
| private static final IID IID_APPLICATION = new IID(new GUID(IID_APPLICATION_STRING)); | ||
|
|
||
| @Override | ||
| protected void tearDown() throws Exception { | ||
| super.tearDown(); | ||
| Ole32.INSTANCE.CoUninitialize(); | ||
| } | ||
|
|
||
| @Override | ||
| protected void setUp() throws Exception { | ||
| // Initialize COM for this thread... | ||
| HRESULT hr = Ole32.INSTANCE.CoInitialize(null); | ||
| } | ||
|
|
||
| @Test | ||
| public void testOfficeInvocationProblemCOMUtil() { | ||
| Factory fact = new Factory(); | ||
| Application app; | ||
| try { | ||
| app = fact.createObject(Application.class); | ||
| } catch (COMException ex) { | ||
| LOG.log(Level.INFO, "HybdridCOMInvocationTest test was not run, MS Word object could not be instantiated.", ex); | ||
| return; | ||
| } | ||
| // If this fails: remember: floats are not exact, if this happens replace | ||
| // with a range check | ||
| assertEquals(72.0f, app.InchesToPoints(1F)); | ||
| } | ||
|
|
||
| @Test | ||
| public void testOfficeInvocationProblemCOMBindingObject() { | ||
| WordApplication app; | ||
| try { | ||
| app = new WordApplication(false); | ||
| } catch (COMException ex) { | ||
| LOG.log(Level.INFO, "HybdridCOMInvocationTest test was not run, MS Word object could not be instantiated.", ex); | ||
| return; | ||
| } | ||
| assertEquals(72.0f, app.InchesToPoints(1F)); | ||
| } | ||
|
|
||
|
|
||
| public void testOfficeInvocationDemonstration() { | ||
| // THIS IS NOT A TEST | ||
| // | ||
| // This reproduces the problem by using the dispatch directly. | ||
|
|
||
| PointerByReference pDispatch = new PointerByReference(); | ||
|
|
||
| HRESULT hr = Ole32.INSTANCE.CoCreateInstance(CLSID_WORD, null, | ||
| WTypes.CLSCTX_SERVER, IID_APPLICATION, pDispatch); | ||
|
|
||
| if(! COMUtils.SUCCEEDED(hr)) { | ||
| LOG.log(Level.INFO, "HybdridCOMInvocationTest test was not run, MS Word object could not be instantiated."); | ||
| return; | ||
| } | ||
|
|
||
| Dispatch dp = new Dispatch(pDispatch.getValue()); | ||
|
|
||
| // DispID of InchesToPoints | ||
| DISPID dispId = new OaIdl.DISPID(0x00000172); | ||
| // Interface _Application of MS Word type library | ||
| WinDef.LCID LOCALE_SYSTEM_DEFAULT = Kernel32.INSTANCE.GetSystemDefaultLCID(); | ||
| Variant.VARIANT.ByReference result = new Variant.VARIANT.ByReference(); | ||
| OaIdl.EXCEPINFO.ByReference pExcepInfo = new OaIdl.EXCEPINFO.ByReference(); | ||
| IntByReference puArgErr = new IntByReference(); | ||
|
|
||
| WORD wFlagsMethod = new WinDef.WORD(OleAuto.DISPATCH_METHOD); | ||
| WORD wFlagsGet = new WinDef.WORD(OleAuto.DISPATCH_PROPERTYGET); | ||
| WORD wFlagsCombined = new WinDef.WORD(OleAuto.DISPATCH_METHOD | OleAuto.DISPATCH_PROPERTYGET); | ||
|
|
||
| OleAuto.DISPPARAMS.ByReference pDispParams = new OleAuto.DISPPARAMS.ByReference(); | ||
| VARIANT[] params = new VARIANT[1]; | ||
| params[0] = new VARIANT(1f); | ||
| pDispParams.cArgs = new UINT(1); | ||
| pDispParams.cNamedArgs = new UINT(0); | ||
| pDispParams.rgvarg = new Variant.VariantArg.ByReference(params); | ||
| pDispParams.rgdispidNamedArgs = new OaIdl.DISPIDByReference(); | ||
|
|
||
| // Call InchesToPoints as a method | ||
| hr = dp.Invoke(dispId, new REFIID(Guid.IID_NULL), LOCALE_SYSTEM_DEFAULT, wFlagsMethod, pDispParams, result, pExcepInfo, puArgErr); | ||
| assertTrue(COMUtils.FAILED(hr)); | ||
|
|
||
| // Call InchesToPoints as a property getter | ||
| hr = dp.Invoke(dispId, new REFIID(Guid.IID_NULL), LOCALE_SYSTEM_DEFAULT, wFlagsGet, pDispParams, result, pExcepInfo, puArgErr); | ||
| assertTrue(COMUtils.FAILED(hr)); | ||
|
|
||
| // Call InchesToPoints as a hybrid | ||
| hr = dp.Invoke(dispId, new REFIID(Guid.IID_NULL), LOCALE_SYSTEM_DEFAULT, wFlagsCombined, pDispParams, result, pExcepInfo, puArgErr); | ||
| assertTrue(COMUtils.SUCCEEDED(hr)); | ||
|
|
||
| assertEquals(72.0f, result.floatValue()); | ||
| } | ||
|
|
||
| @ComObject(clsId = CLSID_WORD_STRING) | ||
| public static interface Application extends IDispatch, _Application { | ||
| } | ||
|
|
||
| @ComInterface(iid = IID_APPLICATION_STRING) | ||
| public static interface _Application { | ||
| @ComMethod | ||
| Float InchesToPoints(Float value); | ||
| } | ||
|
|
||
| public static class WordApplication extends COMLateBindingObject { | ||
|
|
||
| public WordApplication(boolean useActiveInstance) { | ||
| super(new CLSID(CLSID_WORD), useActiveInstance); | ||
| } | ||
|
|
||
| public Float InchesToPoints(Float value) { | ||
| VARIANT.ByReference pvResult = new VARIANT.ByReference(); | ||
| this.oleMethod(OleAuto.DISPATCH_METHOD , pvResult, this.getIDispatch(), "InchesToPoints", new VARIANT[] {new VARIANT(value)}); | ||
| return pvResult.floatValue(); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a nitpick, but maybe just say
It's consistent to checks above and we don't need the extra variable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This won't work - in ProxyObject the invocation is dispatched into a separate thread and for that the invoke is wrapped into a Callable, that won't capture ntype if it is not final and if it is final, it can't be changed. so one more variable is needed.
The previous comparisons in the code don't modify ntype.
It would be possible to apply the requested change in COMBindingBaseObject, but that code is identical to the code in ProxyObject and intentionally so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍