diff --git a/CHANGES.md b/CHANGES.md
index 672f0aa4e1..f4e03016cc 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -68,6 +68,7 @@ Bug Fixes
* [#610](https://github.com/java-native-access/jna/pull/610): Fixed issue #604: Kernel32#GetLastError() always returns ERROR_SUCCESS [@lgoldstein](https://github.com/lgoldstein).
* [#633](https://github.com/java-native-access/jna/pull/633): Restore default usage of platform native encoding for Java strings passed to native functions (was hard-coded to UTF-8 in 4.0 and later) [@amake](https://github.com/amake)
* [#634](https://github.com/java-native-access/jna/pull/634): Improve BSTR handling and add `SysStringByteLen` and `SysStringLen` to `com.sun.jna.platform.win32.OleAuto` - [@matthiasblaesing](https://github.com/matthiasblaesing).
+* [#646](https://github.com/java-native-access/jna/issues/646): `platform.win32.COM.COMBindingBaseObject` swallows reason if instantiation fails - [@matthiasblaesing](https://github.com/matthiasblaesing).
Release 4.2.1
=============
diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/COMBindingBaseObject.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/COMBindingBaseObject.java
index 857ecd2a14..dcefeaa605 100644
--- a/contrib/platform/src/com/sun/jna/platform/win32/COM/COMBindingBaseObject.java
+++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/COMBindingBaseObject.java
@@ -15,6 +15,7 @@
import com.sun.jna.WString;
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.REFIID;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.OaIdl;
@@ -74,52 +75,34 @@ public COMBindingBaseObject(CLSID clsid, boolean useActiveInstance,
int dwClsContext) {
assert COMUtils.comIsInitialized() : "COM not initialized";
- HRESULT hr;
-
- if (useActiveInstance) {
- hr = OleAuto.INSTANCE.GetActiveObject(clsid, null, this.pUnknown);
-
- if (COMUtils.SUCCEEDED(hr)) {
- this.iUnknown = new Unknown(this.pUnknown.getValue());
- hr = iUnknown.QueryInterface(new REFIID( IDispatch.IID_IDISPATCH),
- this.pDispatch);
- } else {
- hr = Ole32.INSTANCE.CoCreateInstance(clsid, null, dwClsContext,
- IDispatch.IID_IDISPATCH, this.pDispatch);
- }
- } else {
- hr = Ole32.INSTANCE.CoCreateInstance(clsid, null, dwClsContext,
- IDispatch.IID_IDISPATCH, this.pDispatch);
- }
-
- if (COMUtils.FAILED(hr)) {
- throw new COMException("COM object with CLSID "
- + clsid.toGuidString() + " not registered properly!");
- }
-
- this.iDispatch = new Dispatch(this.pDispatch.getValue());
+ init(useActiveInstance, clsid, dwClsContext);
}
public COMBindingBaseObject(String progId, boolean useActiveInstance,
int dwClsContext) throws COMException {
assert COMUtils.comIsInitialized() : "COM not initialized";
-
- HRESULT hr;
- // Get CLSID for Word.Application...
CLSID.ByReference clsid = new CLSID.ByReference();
- hr = Ole32.INSTANCE.CLSIDFromProgID(progId, clsid);
+ HRESULT hr = Ole32.INSTANCE.CLSIDFromProgID(progId, clsid);
- if (COMUtils.FAILED(hr)) {
- throw new COMException("CLSIDFromProgID() failed!");
- }
+ COMUtils.checkRC(hr);
+
+ init(useActiveInstance, clsid, dwClsContext);
+ }
+
+ public COMBindingBaseObject(String progId, boolean useActiveInstance)
+ throws COMException {
+ this(progId, useActiveInstance, WTypes.CLSCTX_SERVER);
+ }
+ private void init(boolean useActiveInstance, GUID clsid, int dwClsContext) throws COMException {
+ HRESULT hr;
if (useActiveInstance) {
hr = OleAuto.INSTANCE.GetActiveObject(clsid, null, this.pUnknown);
if (COMUtils.SUCCEEDED(hr)) {
this.iUnknown = new Unknown(this.pUnknown.getValue());
- hr = iUnknown.QueryInterface(new REFIID(IDispatch.IID_IDISPATCH),
+ hr = iUnknown.QueryInterface(new REFIID( IDispatch.IID_IDISPATCH),
this.pDispatch);
} else {
hr = Ole32.INSTANCE.CoCreateInstance(clsid, null, dwClsContext,
@@ -129,21 +112,12 @@ public COMBindingBaseObject(String progId, boolean useActiveInstance,
hr = Ole32.INSTANCE.CoCreateInstance(clsid, null, dwClsContext,
IDispatch.IID_IDISPATCH, this.pDispatch);
}
-
- if (COMUtils.FAILED(hr)) {
- throw new COMException("COM object with ProgID '" + progId
- + "' and CLSID " + clsid.toGuidString()
- + " not registered properly!");
- }
-
+
+ COMUtils.checkRC(hr);
+
this.iDispatch = new Dispatch(this.pDispatch.getValue());
}
-
- public COMBindingBaseObject(String progId, boolean useActiveInstance)
- throws COMException {
- this(progId, useActiveInstance, WTypes.CLSCTX_SERVER);
- }
-
+
/**
* Gets the i dispatch.
*
diff --git a/contrib/platform/test/com/sun/jna/platform/win32/COM/ComExceptionWithoutInitializationTest.java b/contrib/platform/test/com/sun/jna/platform/win32/COM/ComExceptionWithoutInitializationTest.java
new file mode 100644
index 0000000000..cf3cf226ed
--- /dev/null
+++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/ComExceptionWithoutInitializationTest.java
@@ -0,0 +1,54 @@
+package com.sun.jna.platform.win32.COM;
+
+import com.sun.jna.platform.win32.Guid;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+
+public class ComExceptionWithoutInitializationTest {
+
+ @Test
+ public void testCorrectExceptionOnFailedInitialization() {
+ String message = null;
+ try {
+ InternetExplorer ie = new InternetExplorer();
+ } catch (COMException ex) {
+ message = ex.getMessage();
+ }
+
+ // This invocation must raise an exception, as the COM thread is not
+ // initialized, in the message it is expected, that the HRESULT is reported
+ // and the HRESULT resulting from calling into COM with it being initialized
+ // is 800401f0. The message is also expected to point the to correct
+ // initialization via CoInitialize
+ assertNotNull(message);
+ assertTrue(message.contains("HRESULT"));
+ assertTrue(message.contains("800401f0"));
+ assertTrue(message.contains("CoInitialize"));
+ }
+
+ /**
+ * InternetExplorer / IWebBrowser2 - see
+ * http://msdn.microsoft.com/en-us/library/aa752127(v=vs.85).aspx
+ */
+ private static class InternetExplorer extends COMLateBindingObject {
+
+ public InternetExplorer(IDispatch iDispatch) {
+ super(iDispatch);
+ }
+
+ public InternetExplorer() {
+ super(new Guid.CLSID("{0002DF01-0000-0000-C000-000000000046}"), true);
+ }
+
+ /**
+ * IWebBrowser2::get_LocationURL
+ * Read-only COM property.
+ *
+ * @return the URL of the resource that is currently displayed.
+ */
+ public String getURL() {
+ return getStringProperty("LocationURL");
+ }
+ }
+}