Skip to content

Commit

Permalink
Exception from COMBindingBaseObject swallows real reason + HRESULT
Browse files Browse the repository at this point in the history
The exception thrown from COMBindingBaseObject when instatiation fails
is misleading:

COM object with CLSID {0002DF01-0000-0000-C000-000000000046} not registered properly!

In the concrete case COM was not properly initialized, the same error now
reports (in german locale):

CoInitialize wurde nicht aufgerufen.(HRESULT: 800401f0) (puArgErr=)

For english locale this should be along the lines of:

CoInitialize was not called.(HRESULT: 800401f0) (puArgErr=)

The message now points out the correct problem (as far as the windows
error code translation works) and the HRESULT can be used for a locale
independend report + search.

Closes #646
  • Loading branch information
matthiasblaesing committed May 4, 2016
1 parent 0296115 commit 2c4a471
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 45 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Expand Up @@ -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
=============
Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -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.
*
Expand Down
@@ -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<br>
* Read-only COM property.<br>
*
* @return the URL of the resource that is currently displayed.
*/
public String getURL() {
return getStringProperty("LocationURL");
}
}
}

0 comments on commit 2c4a471

Please sign in to comment.