From d80730b0849bf51a24fd309d2da0fcaf08ef5cce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Bl=C3=A4sing?= Date: Thu, 25 Feb 2016 19:07:11 +0100 Subject: [PATCH] Remove COM initialization from object and enforce correct handling via asserts The custom thread instantiated in the c.s.j.p.w.C.util.ProxyObject and then used as a dispatch for COM calls is a bootleneck and not following COM convention. If COM is initialized for a thread as COINIT_MULTITHREADED there is no reason to force dispatch through a central thread and if it is COINIT_APARTMENTTHREADED a message queue is needed: https://msdn.microsoft.com/de-de/library/windows/desktop/ms695279%28v=vs.85%29.aspx The change introduced here removes the dispatcher thread and the initialization routines from COMBindingBaseObject. In their place asserts are placed, that enforce correct COM initialization. The tests were adjusted accordingly. --- CHANGES.md | 1 + .../win32/COM/COMBindingBaseObject.java | 29 +-- .../sun/jna/platform/win32/COM/COMUtils.java | 34 ++- .../win32/COM/util/CallbackProxy.java | 13 +- .../platform/win32/COM/util/ComThread.java | 157 -------------- .../platform/win32/COM/util/EnumMoniker.java | 141 +++++-------- .../jna/platform/win32/COM/util/Factory.java | 195 +++++++----------- .../platform/win32/COM/util/ProxyObject.java | 114 ++++------ .../win32/COM/util/RunningObjectTable.java | 34 +-- .../sun/jna/platform/win32/COM/COMTest.java | 6 +- .../win32/COM/ComEventCallbacks_Test.java | 11 +- .../platform/win32/COM/EnumMoniker_Test.java | 20 +- .../jna/platform/win32/COM/IDispatchTest.java | 5 +- .../platform/win32/COM/IShellFolderTest.java | 6 +- .../jna/platform/win32/COM/ITypeInfoTest.java | 34 ++- .../jna/platform/win32/COM/ITypeLibTest.java | 4 + .../jna/platform/win32/COM/IUnknownTest.java | 5 +- .../win32/COM/RunningObjectTable_Test.java | 5 +- .../COM/ShellApplicationWindowsTest.java | 29 ++- .../platform/win32/COM/TypeLibUtilTest.java | 5 +- .../COM/util/ComEventCallbacks_Test.java | 10 +- .../COM/util/HybdridCOMInvocationTest.java | 30 +-- .../win32/COM/util/ProxyObject_Test.java | 17 +- .../COM/util/RunningObjectTable_Test.java | 11 +- 24 files changed, 349 insertions(+), 567 deletions(-) delete mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/ComThread.java diff --git a/CHANGES.md b/CHANGES.md index db4be767d3..a8d5569e55 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -49,6 +49,7 @@ Bug Fixes * [#588](https://github.com/java-native-access/jna/pull/588): Fix varargs calls on arm - [@twall](https://github.com/twall). * [#593](https://github.com/java-native-access/jna/pull/593): Improve binding of TypeLib bindings - [@matthiasblaesing](https://github.com/matthiasblaesing). * [#578](https://github.com/java-native-access/jna/pull/578): Fix COM CallbackHandlers, allow usage of VARIANTs directly in c.s.j.p.w.COM.util.ProxyObject and fix native memory leak in c.s.j.p.w.COM.util.ProxyObject - [@matthiasblaesing](https://github.com/matthiasblaesing) +* [#601](https://github.com/java-native-access/jna/pull/601): Remove COMThread and COM initialization from objects and require callers to initialize COM themselves. Asserts are added to guard correct usage. - [@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 55b2fe424b..857ecd2a14 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 @@ -34,7 +34,6 @@ import com.sun.jna.ptr.IntByReference; import com.sun.jna.ptr.PointerByReference; -// TODO: Auto-generated Javadoc /** * Helper class to provide basic COM support. * @@ -73,14 +72,10 @@ public COMBindingBaseObject(CLSID clsid, boolean useActiveInstance) { public COMBindingBaseObject(CLSID clsid, boolean useActiveInstance, int dwClsContext) { - // Initialize COM for this thread... - HRESULT hr = Ole32.INSTANCE.CoInitializeEx(null, Ole32.COINIT_APARTMENTTHREADED); - - if (COMUtils.FAILED(hr)) { - Ole32.INSTANCE.CoUninitialize(); - throw new COMException("CoInitialize() failed!"); - } - + assert COMUtils.comIsInitialized() : "COM not initialized"; + + HRESULT hr; + if (useActiveInstance) { hr = OleAuto.INSTANCE.GetActiveObject(clsid, null, this.pUnknown); @@ -107,20 +102,15 @@ public COMBindingBaseObject(CLSID clsid, boolean useActiveInstance, public COMBindingBaseObject(String progId, boolean useActiveInstance, int dwClsContext) throws COMException { - // Initialize COM for this thread... - HRESULT hr = Ole32.INSTANCE.CoInitializeEx(null, Ole32.COINIT_APARTMENTTHREADED); - - if (COMUtils.FAILED(hr)) { - this.release(); - throw new COMException("CoInitialize() failed!"); - } + 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); if (COMUtils.FAILED(hr)) { - Ole32.INSTANCE.CoUninitialize(); throw new COMException("CLSIDFromProgID() failed!"); } @@ -194,10 +184,9 @@ public PointerByReference getIUnknownPointer() { * Release. */ public void release() { - if (this.iDispatch != null) + if (this.iDispatch != null) { this.iDispatch.Release(); - - Ole32.INSTANCE.CoUninitialize(); + } } protected HRESULT oleMethod(int nType, VARIANT.ByReference pvResult, diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/COMUtils.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/COMUtils.java index 6cb36bd5e0..553ce32bfd 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/COM/COMUtils.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/COMUtils.java @@ -15,19 +15,21 @@ import java.util.ArrayList; import com.sun.jna.Native; +import com.sun.jna.Pointer; import com.sun.jna.platform.win32.Advapi32; import com.sun.jna.platform.win32.Advapi32Util; import com.sun.jna.platform.win32.Advapi32Util.EnumKey; import com.sun.jna.platform.win32.Advapi32Util.InfoKey; import com.sun.jna.platform.win32.Kernel32Util; import com.sun.jna.platform.win32.OaIdl.EXCEPINFO; +import com.sun.jna.platform.win32.Ole32; +import com.sun.jna.platform.win32.W32Errors; import com.sun.jna.platform.win32.WinNT; import com.sun.jna.platform.win32.WinNT.HRESULT; import com.sun.jna.platform.win32.WinReg; import com.sun.jna.platform.win32.WinReg.HKEYByReference; import com.sun.jna.ptr.IntByReference; -// TODO: Auto-generated Javadoc /** * The Class COMUtils. * @@ -182,6 +184,36 @@ public static ArrayList getAllCOMInfoOnSystem() { return comInfos; } + /** + * Check is COM was initialized correctly. The initialization status is not changed! + * + *

This is a debug function, not for normal usage!

+ * + * @return + */ + public static boolean comIsInitialized() { + WinNT.HRESULT hr = Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED); + if (hr.equals(W32Errors.S_OK)) { + // User failed - uninitialize again and return false + Ole32.INSTANCE.CoUninitialize(); + return false; + } else if (hr.equals(W32Errors.S_FALSE)) { + // OK Variant 1 - User initialized COM with same threading module as + // in this check. According to MSDN CoUninitialize needs to be called + // in this case. + Ole32.INSTANCE.CoUninitialize(); + return true; + } else if (hr.intValue() == W32Errors.RPC_E_CHANGED_MODE) { + return true; + } + // If another result than the checked ones above happens handling is + // delegated to the "normal" COM exception handling and a COMException + // will be raised. + COMUtils.checkRC(hr); + // The return will not be met, as COMUtils#checkRC will raise an exception + return false; + } + /** * The Class COMInfo. * diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/CallbackProxy.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/CallbackProxy.java index 4185e6bf36..376c59c9ad 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/CallbackProxy.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/CallbackProxy.java @@ -37,6 +37,7 @@ import com.sun.jna.platform.win32.WinError; import com.sun.jna.platform.win32.WinNT.HRESULT; import com.sun.jna.platform.win32.COM.COMException; +import com.sun.jna.platform.win32.COM.COMUtils; import com.sun.jna.platform.win32.COM.Dispatch; import com.sun.jna.platform.win32.COM.DispatchListener; import com.sun.jna.platform.win32.COM.IDispatch; @@ -103,7 +104,7 @@ int fetchDispIdFromName(ComEventCallback annotation) { void invokeOnThread(final DISPID dispIdMember, final REFIID riid, LCID lcid, WORD wFlags, final DISPPARAMS.ByReference pDispParams) { - + final Method eventMethod; if (CallbackProxy.this.dsipIdMap.containsKey(dispIdMember)) { eventMethod = CallbackProxy.this.dsipIdMap.get(dispIdMember); @@ -204,13 +205,9 @@ public HRESULT Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS.ByReference pDispParams, VARIANT.ByReference pVarResult, EXCEPINFO.ByReference pExcepInfo, IntByReference puArgErr) { - assert (! ComThread.getCurrentThreadIsCOM()) : "Assumption about COM threading broken."; - ComThread.setCurrentThreadIsCOM(true); - try { - this.invokeOnThread(dispIdMember, riid, lcid, wFlags, pDispParams); - } finally { - ComThread.setCurrentThreadIsCOM(false); - } + assert COMUtils.comIsInitialized() : "Assumption about COM threading broken."; + + this.invokeOnThread(dispIdMember, riid, lcid, wFlags, pDispParams); return WinError.S_OK; } diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/ComThread.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/ComThread.java deleted file mode 100644 index 07e6405fd1..0000000000 --- a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/ComThread.java +++ /dev/null @@ -1,157 +0,0 @@ -/* Copyright (c) 2014 Dr David H. Akehurst (itemis), All Rights Reserved - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - */ -package com.sun.jna.platform.win32.COM.util; - -import java.lang.Thread.UncaughtExceptionHandler; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import com.sun.jna.platform.win32.Ole32; -import com.sun.jna.platform.win32.WinNT; -import com.sun.jna.platform.win32.COM.COMUtils; - -public class ComThread { - ExecutorService executor; - Runnable firstTask; - boolean requiresInitialisation; - long timeoutMilliseconds; - UncaughtExceptionHandler uncaughtExceptionHandler; - - public ComThread(final String threadName, long timeoutMilliseconds, UncaughtExceptionHandler uncaughtExceptionHandler) { - this(threadName, timeoutMilliseconds, uncaughtExceptionHandler, Ole32.COINIT_MULTITHREADED); - } - - public ComThread(final String threadName, long timeoutMilliseconds, UncaughtExceptionHandler uncaughtExceptionHandler, final int coinitialiseExFlag) { - this.requiresInitialisation = true; - this.timeoutMilliseconds = timeoutMilliseconds; - this.uncaughtExceptionHandler = uncaughtExceptionHandler; - this.firstTask = new Runnable() { - @Override - public void run() { - // By definition this is a COM thread - ComThread.setCurrentThreadIsCOM(true); - try { - //If we do not use COINIT_MULTITHREADED, it is necessary to have - // a message loop see - - // [http://www.codeguru.com/cpp/com-tech/activex/apts/article.php/c5529/Understanding-COM-Apartments-Part-I.htm] - // [http://www.codeguru.com/cpp/com-tech/activex/apts/article.php/c5533/Understanding-COM-Apartments-Part-II.htm] - WinNT.HRESULT hr = Ole32.INSTANCE.CoInitializeEx(null, coinitialiseExFlag); - COMUtils.checkRC(hr); - ComThread.this.requiresInitialisation = false; - } catch (Throwable t) { - ComThread.this.uncaughtExceptionHandler.uncaughtException(Thread.currentThread(), t); - } - } - }; - executor = Executors.newSingleThreadExecutor(new ThreadFactory() { - - @Override - public Thread newThread(Runnable r) { - if (!ComThread.this.requiresInitialisation) { - // something has gone wrong! - throw new RuntimeException("ComThread executor has a problem."); - } - Thread thread = new Thread(r, threadName); - //make sure this is a daemon thread, or it will stop JVM existing - // if program does not call terminate(); - thread.setDaemon(true); - - thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() { - @Override - public void uncaughtException(Thread t, Throwable e) { - ComThread.this.requiresInitialisation = true; - ComThread.this.uncaughtExceptionHandler.uncaughtException(t, e); - } - }); - - return thread; - } - }); - - } - - /** - * Stop the COM Thread. - * - * @param timeoutMilliseconds - * number of milliseconds to wait for a clean shutdown before a - * forced shutdown is attempted - */ - public void terminate(long timeoutMilliseconds) { - try { - - executor.submit(new Runnable() { - @Override - public void run() { - Ole32.INSTANCE.CoUninitialize(); - } - }).get(timeoutMilliseconds, TimeUnit.MILLISECONDS); - - executor.shutdown(); - - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); - } catch (TimeoutException e) { - executor.shutdownNow(); - } - } - - @Override - protected void finalize() throws Throwable { - if (!executor.isShutdown()) { - this.terminate(100); - } - } - - // The currentThreadIsCOM is used if wrapper are used in a callback - // the callback is called in a new thread by the JNA runtime. As the - // call comes from COM it is asumed, that the thread is correctly - // initialized and can be used for COM calls (see MTA assumption above) - private static ThreadLocal currentThreadIsCOM = new ThreadLocal(); - - static void setCurrentThreadIsCOM(boolean isCOM) { - currentThreadIsCOM.set(isCOM); - } - - static boolean getCurrentThreadIsCOM() { - Boolean res = currentThreadIsCOM.get(); - if(res == null) { - return false; - } else { - return currentThreadIsCOM.get(); - } - } - - public T execute(Callable task) throws TimeoutException, InterruptedException, ExecutionException { - if(getCurrentThreadIsCOM()) { - try { - return task.call(); - } catch (Exception ex) { - throw new ExecutionException(ex); - } - } else { - if (this.requiresInitialisation) { - executor.execute(firstTask); - } - return executor.submit(task).get(this.timeoutMilliseconds, TimeUnit.MILLISECONDS); - } - } - -} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/EnumMoniker.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/EnumMoniker.java index f12bf8d2d1..dc66f5192c 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/EnumMoniker.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/EnumMoniker.java @@ -37,64 +37,39 @@ public class EnumMoniker implements Iterable { protected EnumMoniker(IEnumMoniker raw, com.sun.jna.platform.win32.COM.IRunningObjectTable rawRot, Factory factory) { + + assert COMUtils.comIsInitialized() : "COM not initialized"; + this.rawRot = rawRot; this.raw = raw; this.factory = factory; - this.comThread = factory.getComThread(); - - try { - WinNT.HRESULT hr = this.comThread.execute(new Callable() { - @Override - public WinNT.HRESULT call() throws Exception { - return EnumMoniker.this.raw.Reset(); - } - }); - COMUtils.checkRC(hr); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } catch (ExecutionException e) { - throw new RuntimeException(e); - } catch (TimeoutException e) { - throw new RuntimeException(e); - } + + WinNT.HRESULT hr = raw.Reset(); + COMUtils.checkRC(hr); this.cacheNext(); } - ComThread comThread; Factory factory; com.sun.jna.platform.win32.COM.IRunningObjectTable rawRot; IEnumMoniker raw; Moniker rawNext; protected void cacheNext() { - try { - final PointerByReference rgelt = new PointerByReference(); - final WinDef.ULONGByReference pceltFetched = new WinDef.ULONGByReference(); - - WinNT.HRESULT hr = EnumMoniker.this.comThread.execute(new Callable() { - @Override - public WinNT.HRESULT call() throws Exception { - return EnumMoniker.this.raw.Next(new WinDef.ULONG(1), rgelt, pceltFetched); - } - }); - - if (WinNT.S_OK.equals(hr) && pceltFetched.getValue().intValue() > 0) { - this.rawNext = new Moniker(rgelt.getValue()); - } else { - if (!WinNT.S_FALSE.equals(hr)) { - COMUtils.checkRC(hr); - } - this.rawNext = null; - } - - } catch (InterruptedException e) { - throw new RuntimeException(e); - } catch (ExecutionException e) { - throw new RuntimeException(e); - } catch (TimeoutException e) { - throw new RuntimeException(e); - } + assert COMUtils.comIsInitialized() : "COM not initialized"; + final PointerByReference rgelt = new PointerByReference(); + final WinDef.ULONGByReference pceltFetched = new WinDef.ULONGByReference(); + + WinNT.HRESULT hr = this.raw.Next(new WinDef.ULONG(1), rgelt, pceltFetched); + + if (WinNT.S_OK.equals(hr) && pceltFetched.getValue().intValue() > 0) { + this.rawNext = new Moniker(rgelt.getValue()); + } else { + if (!WinNT.S_FALSE.equals(hr)) { + COMUtils.checkRC(hr); + } + this.rawNext = null; + } } @Override @@ -108,51 +83,37 @@ public boolean hasNext() { @Override public IDispatch next() { - try { - - final Moniker moniker = EnumMoniker.this.rawNext; - final PointerByReference ppunkObject = new PointerByReference(); - WinNT.HRESULT hr = EnumMoniker.this.comThread.execute(new Callable() { - @Override - public WinNT.HRESULT call() throws Exception { - return EnumMoniker.this.rawRot.GetObject(moniker.getPointer(), ppunkObject); - } - }); - COMUtils.checkRC(hr); - - // To assist debug, can use the following code - // PointerByReference ppbc = new - // PointerByReference(); - // Ole32.INSTANCE.CreateBindCtx(new DWORD(), ppbc); - // - // BSTRByReference ppszDisplayName = new - // BSTRByReference(); - // hr = moniker.GetDisplayName(ppbc.getValue(), - // moniker.getPointer(), ppszDisplayName); - // COMUtils.checkRC(hr); - // String name = ppszDisplayName.getString(); - // Ole32.INSTANCE.CoTaskMemFree(ppszDisplayName.getPointer().getPointer(0)); - - // TODO: Can we assume that the object is an - // IDispatch ? - // Unknown unk = new - // Unknown(ppunkObject.getValue()); - - Dispatch dispatch = new Dispatch(ppunkObject.getValue()); - EnumMoniker.this.cacheNext(); - IDispatch d = EnumMoniker.this.factory.createProxy(IDispatch.class, dispatch); - //must release a COM Ref, GetObject returns a pointer with +1 - int n = dispatch.Release(); - return d; - - } catch (InterruptedException e) { - throw new RuntimeException(e); - } catch (ExecutionException e) { - throw new RuntimeException(e); - } catch (TimeoutException e) { - throw new RuntimeException(e); - } - + assert COMUtils.comIsInitialized() : "COM not initialized"; + + final Moniker moniker = EnumMoniker.this.rawNext; + final PointerByReference ppunkObject = new PointerByReference(); + WinNT.HRESULT hr = EnumMoniker.this.rawRot.GetObject(moniker.getPointer(), ppunkObject); + COMUtils.checkRC(hr); + + // To assist debug, can use the following code + // PointerByReference ppbc = new + // PointerByReference(); + // Ole32.INSTANCE.CreateBindCtx(new DWORD(), ppbc); + // + // BSTRByReference ppszDisplayName = new + // BSTRByReference(); + // hr = moniker.GetDisplayName(ppbc.getValue(), + // moniker.getPointer(), ppszDisplayName); + // COMUtils.checkRC(hr); + // String name = ppszDisplayName.getString(); + // Ole32.INSTANCE.CoTaskMemFree(ppszDisplayName.getPointer().getPointer(0)); + + // TODO: Can we assume that the object is an + // IDispatch ? + // Unknown unk = new + // Unknown(ppunkObject.getValue()); + + Dispatch dispatch = new Dispatch(ppunkObject.getValue()); + EnumMoniker.this.cacheNext(); + IDispatch d = EnumMoniker.this.factory.createProxy(IDispatch.class, dispatch); + //must release a COM Ref, GetObject returns a pointer with +1 + int n = dispatch.Release(); + return d; } @Override diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/Factory.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/Factory.java index ba367b18a8..990e0dae64 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/Factory.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/Factory.java @@ -29,6 +29,7 @@ import com.sun.jna.platform.win32.COM.Dispatch; import com.sun.jna.platform.win32.COM.IDispatch; import com.sun.jna.platform.win32.COM.util.annotation.ComObject; +import com.sun.jna.platform.win32.WinNT.HRESULT; import com.sun.jna.ptr.PointerByReference; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -44,17 +45,9 @@ public class Factory { * */ public Factory() { - this(new ComThread("Default Factory COM Thread", 5000, new Thread.UncaughtExceptionHandler() { - @Override - public void uncaughtException(Thread t, Throwable e) { - //ignore - } - })); + assert COMUtils.comIsInitialized() : "COM not initialized"; } - public Factory(ComThread comThread) { - this.comThread = comThread; - } @Override protected void finalize() throws Throwable { @@ -64,11 +57,6 @@ protected void finalize() throws Throwable { super.finalize(); } } - - ComThread comThread; - public ComThread getComThread() { - return this.comThread; - } /** * CoInitialize must be called be fore this method. Either explicitly or @@ -77,36 +65,26 @@ public ComThread getComThread() { * @return running object table */ public IRunningObjectTable getRunningObjectTable() { - try { - - final PointerByReference rotPtr = new PointerByReference(); + assert COMUtils.comIsInitialized() : "COM not initialized"; + + final PointerByReference rotPtr = new PointerByReference(); - WinNT.HRESULT hr = this.comThread.execute(new Callable() { - @Override - public WinNT.HRESULT call() throws Exception { - return Ole32.INSTANCE.GetRunningObjectTable(new WinDef.DWORD(0), rotPtr); - } - }); - COMUtils.checkRC(hr); - com.sun.jna.platform.win32.COM.RunningObjectTable raw = new com.sun.jna.platform.win32.COM.RunningObjectTable( - rotPtr.getValue()); - IRunningObjectTable rot = new RunningObjectTable(raw, this); - return rot; + HRESULT hr = Ole32.INSTANCE.GetRunningObjectTable(new WinDef.DWORD(0), rotPtr); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } catch (ExecutionException e) { - throw new RuntimeException(e); - } catch (TimeoutException e) { - throw new RuntimeException(e); - } - } + COMUtils.checkRC(hr); + com.sun.jna.platform.win32.COM.RunningObjectTable raw = new com.sun.jna.platform.win32.COM.RunningObjectTable( + rotPtr.getValue()); + IRunningObjectTable rot = new RunningObjectTable(raw, this); + return rot; + } /** * Creates a ProxyObject for the given interface and IDispatch pointer. * */ public T createProxy(Class comInterface, IDispatch dispatch) { + assert COMUtils.comIsInitialized() : "COM not initialized"; + ProxyObject jop = new ProxyObject(comInterface, dispatch, this); Object proxy = Proxy.newProxyInstance(comInterface.getClassLoader(), new Class[] { comInterface }, jop); T result = comInterface.cast(proxy); @@ -121,6 +99,8 @@ public T createProxy(Class comInterface, IDispatch dispatch) { * @return proxy object */ T createProxy(Class comInterface, long unknownId, IDispatch dispatch) { + assert COMUtils.comIsInitialized() : "COM not initialized"; + ProxyObject jop = new ProxyObject(comInterface, unknownId, dispatch, this); Object proxy = Proxy.newProxyInstance(comInterface.getClassLoader(), new Class[] { comInterface }, jop); T result = comInterface.cast(proxy); @@ -132,38 +112,26 @@ T createProxy(Class comInterface, long unknownId, IDispatch dispatch) { * returns a ProxyObject for the given interface. */ public T createObject(Class comInterface) { - try { - - ComObject comObectAnnotation = comInterface.getAnnotation(ComObject.class); - if (null == comObectAnnotation) { - throw new COMException( - "createObject: Interface must define a value for either clsId or progId via the ComInterface annotation"); - } - final GUID guid = this.discoverClsId(comObectAnnotation); - - final PointerByReference ptrDisp = new PointerByReference(); - WinNT.HRESULT hr = this.comThread.execute(new Callable() { - @Override - public WinNT.HRESULT call() throws Exception { - return Ole32.INSTANCE.CoCreateInstance(guid, null, WTypes.CLSCTX_SERVER, IDispatch.IID_IDISPATCH, - ptrDisp); - } - }); - COMUtils.checkRC(hr); - Dispatch d = new Dispatch(ptrDisp.getValue()); - T t = this.createProxy(comInterface,d); - //CoCreateInstance returns a pointer to COM object with a +1 reference count, so we must drop one - //Note: the createProxy adds one - int n = d.Release(); - return t; - - } catch (InterruptedException e) { - throw new RuntimeException(e); - } catch (ExecutionException e) { - throw new RuntimeException(e); - } catch (TimeoutException e) { - throw new RuntimeException(e); - } + assert COMUtils.comIsInitialized() : "COM not initialized"; + + ComObject comObectAnnotation = comInterface.getAnnotation(ComObject.class); + if (null == comObectAnnotation) { + throw new COMException( + "createObject: Interface must define a value for either clsId or progId via the ComInterface annotation"); + } + final GUID guid = this.discoverClsId(comObectAnnotation); + + final PointerByReference ptrDisp = new PointerByReference(); + WinNT.HRESULT hr = Ole32.INSTANCE.CoCreateInstance(guid, null, + WTypes.CLSCTX_SERVER, IDispatch.IID_IDISPATCH, ptrDisp); + + COMUtils.checkRC(hr); + Dispatch d = new Dispatch(ptrDisp.getValue()); + T t = this.createProxy(comInterface,d); + //CoCreateInstance returns a pointer to COM object with a +1 reference count, so we must drop one + //Note: the createProxy adds one + int n = d.Release(); + return t; } /** @@ -171,66 +139,45 @@ public WinNT.HRESULT call() throws Exception { * returns a ProxyObject for the given interface. */ public T fetchObject(Class comInterface) { - try { - ComObject comObectAnnotation = comInterface.getAnnotation(ComObject.class); - if (null == comObectAnnotation) { - throw new COMException( - "createObject: Interface must define a value for either clsId or progId via the ComInterface annotation"); - } - final GUID guid = this.discoverClsId(comObectAnnotation); + assert COMUtils.comIsInitialized() : "COM not initialized"; + + ComObject comObectAnnotation = comInterface.getAnnotation(ComObject.class); + if (null == comObectAnnotation) { + throw new COMException( + "createObject: Interface must define a value for either clsId or progId via the ComInterface annotation"); + } + final GUID guid = this.discoverClsId(comObectAnnotation); - final PointerByReference ptrDisp = new PointerByReference(); - WinNT.HRESULT hr = this.comThread.execute(new Callable() { - @Override - public WinNT.HRESULT call() throws Exception { - return OleAuto.INSTANCE.GetActiveObject(guid, null, ptrDisp); - } - }); - COMUtils.checkRC(hr); - Dispatch d = new Dispatch(ptrDisp.getValue()); - T t = this.createProxy(comInterface, d); - //GetActiveObject returns a pointer to COM object with a +1 reference count, so we must drop one - //Note: the createProxy adds one - d.Release(); - - return t; - } catch (InterruptedException e) { - throw new RuntimeException(e); - } catch (ExecutionException e) { - throw new RuntimeException(e); - } catch (TimeoutException e) { - throw new RuntimeException(e); - } - } + final PointerByReference ptrDisp = new PointerByReference(); + WinNT.HRESULT hr = OleAuto.INSTANCE.GetActiveObject(guid, null, ptrDisp); - GUID discoverClsId(ComObject annotation) { - try { - String clsIdStr = annotation.clsId(); - final String progIdStr = annotation.progId(); - if (null != clsIdStr && !clsIdStr.isEmpty()) { - return new CLSID(clsIdStr); - } else if (null != progIdStr && !progIdStr.isEmpty()) { - final CLSID.ByReference rclsid = new CLSID.ByReference(); + COMUtils.checkRC(hr); + Dispatch d = new Dispatch(ptrDisp.getValue()); + T t = this.createProxy(comInterface, d); + //GetActiveObject returns a pointer to COM object with a +1 reference count, so we must drop one + //Note: the createProxy adds one + d.Release(); - WinNT.HRESULT hr = this.comThread.execute(new Callable() { - @Override - public WinNT.HRESULT call() throws Exception { - return Ole32.INSTANCE.CLSIDFromProgID(progIdStr, rclsid); - } - }); + return t; + } - COMUtils.checkRC(hr); - return rclsid; - } else { - throw new COMException("ComObject must define a value for either clsId or progId"); - } - } catch (InterruptedException e) { - throw new RuntimeException(e); - } catch (ExecutionException e) { - throw new RuntimeException(e); - } catch (TimeoutException e) { - throw new RuntimeException(e); - } + GUID discoverClsId(ComObject annotation) { + assert COMUtils.comIsInitialized() : "COM not initialized"; + + String clsIdStr = annotation.clsId(); + final String progIdStr = annotation.progId(); + if (null != clsIdStr && !clsIdStr.isEmpty()) { + return new CLSID(clsIdStr); + } else if (null != progIdStr && !progIdStr.isEmpty()) { + final CLSID.ByReference rclsid = new CLSID.ByReference(); + + WinNT.HRESULT hr = Ole32.INSTANCE.CLSIDFromProgID(progIdStr, rclsid); + + COMUtils.checkRC(hr); + return rclsid; + } else { + throw new COMException("ComObject must define a value for either clsId or progId"); + } } // Proxy object release their COM interface reference latest in the diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/ProxyObject.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/ProxyObject.java index 8b91a2e8aa..9ceae1dbc8 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/ProxyObject.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/ProxyObject.java @@ -64,7 +64,6 @@ public class ProxyObject implements InvocationHandler, com.sun.jna.platform.win3 public ProxyObject(Class theInterface, IDispatch rawDispatch, Factory factory) { this.unknownId = -1; this.rawDispatch = rawDispatch; - this.comThread = factory.getComThread(); this.theInterface = theInterface; this.factory = factory; // make sure dispatch object knows we have a reference to it @@ -86,7 +85,6 @@ public ProxyObject(Class theInterface, IDispatch rawDispatch, Factory factory ProxyObject(Class theInterface, long unknownId, IDispatch rawDispatch, Factory factory) { this.unknownId = unknownId; this.rawDispatch = rawDispatch; - this.comThread = factory.getComThread(); this.theInterface = theInterface; this.factory = factory; // make sure dispatch object knows we have a reference to it @@ -102,6 +100,8 @@ public ProxyObject(Class theInterface, IDispatch rawDispatch, Factory factory long unknownId; long getUnknownId() { + assert COMUtils.comIsInitialized() : "COM not initialized"; + if (-1 == this.unknownId) { try { @@ -110,13 +110,8 @@ long getUnknownId() { Thread current = Thread.currentThread(); String tn = current.getName(); - HRESULT hr = this.comThread.execute(new Callable() { - @Override - public HRESULT call() throws Exception { - IID iid = com.sun.jna.platform.win32.COM.IUnknown.IID_IUNKNOWN; - return ProxyObject.this.getRawDispatch().QueryInterface(new REFIID(iid), ppvObject); - } - }); + IID iid = com.sun.jna.platform.win32.COM.IUnknown.IID_IUNKNOWN; + HRESULT hr = ProxyObject.this.getRawDispatch().QueryInterface(new REFIID(iid), ppvObject); if (WinNT.S_OK.equals(hr)) { Dispatch dispatch = new Dispatch(ppvObject.getValue()); @@ -151,7 +146,6 @@ public synchronized void dispose() { Class theInterface; Factory factory; - ComThread comThread; com.sun.jna.platform.win32.COM.IDispatch rawDispatch; @Override @@ -266,6 +260,8 @@ synchronized Object invokeSynchronised(final Object proxy, final java.lang.refle // ---------------------- IConnectionPoint ---------------------- ConnectionPoint fetchRawConnectionPoint(IID iid) throws InterruptedException, ExecutionException, TimeoutException { + assert COMUtils.comIsInitialized() : "COM not initialized"; + // query for ConnectionPointContainer IConnectionPointContainer cpc = this.queryInterface(IConnectionPointContainer.class); Dispatch rawCpcDispatch = (Dispatch) cpc.getRawDispatch(); @@ -274,12 +270,7 @@ ConnectionPoint fetchRawConnectionPoint(IID iid) throws InterruptedException, Ex // find connection point for comEventCallback interface final REFIID adviseRiid = new REFIID(iid.getPointer()); final PointerByReference ppCp = new PointerByReference(); - HRESULT hr = factory.getComThread().execute(new Callable() { - @Override - public HRESULT call() throws Exception { - return rawCpc.FindConnectionPoint(adviseRiid, ppCp); - } - }); + HRESULT hr = rawCpc.FindConnectionPoint(adviseRiid, ppCp); COMUtils.checkRC(hr); final ConnectionPoint rawCp = new ConnectionPoint(ppCp.getValue()); return rawCp; @@ -287,6 +278,8 @@ public HRESULT call() throws Exception { public IComEventCallbackCookie advise(Class comEventCallbackInterface, final IComEventCallbackListener comEventCallbackListener) { + assert COMUtils.comIsInitialized() : "COM not initialized"; + try { ComInterface comInterfaceAnnotation = comEventCallbackInterface.getAnnotation(ComInterface.class); if (null == comInterfaceAnnotation) { @@ -306,12 +299,7 @@ public IComEventCallbackCookie advise(Class comEventCallbackInterface, // set the dispatch listener to listen to events from the connection // point final DWORDByReference pdwCookie = new DWORDByReference(); - HRESULT hr = factory.getComThread().execute(new Callable() { - @Override - public HRESULT call() throws Exception { - return rawCp.Advise(rawListener, pdwCookie); - } - }); + HRESULT hr = rawCp.Advise(rawListener, pdwCookie); int n = rawCp.Release(); // release before check in case check // throws exception COMUtils.checkRC(hr); @@ -326,6 +314,8 @@ public HRESULT call() throws Exception { } public void unadvise(Class comEventCallbackInterface, final IComEventCallbackCookie cookie) { + assert COMUtils.comIsInitialized() : "COM not initialized"; + try { ComInterface comInterfaceAnnotation = comEventCallbackInterface.getAnnotation(ComInterface.class); if (null == comInterfaceAnnotation) { @@ -336,12 +326,7 @@ public void unadvise(Class comEventCallbackInterface, final IComEventCallback final ConnectionPoint rawCp = this.fetchRawConnectionPoint(iid); - HRESULT hr = factory.getComThread().execute(new Callable() { - @Override - public HRESULT call() throws Exception { - return rawCp.Unadvise(((ComEventCallbackCookie) cookie).getValue()); - } - }); + HRESULT hr = rawCp.Unadvise(((ComEventCallbackCookie) cookie).getValue()); rawCp.Release(); COMUtils.checkRC(hr); @@ -354,6 +339,8 @@ public HRESULT call() throws Exception { // --------------------- IDispatch ------------------------------ @Override public void setProperty(String name, T value) { + assert COMUtils.comIsInitialized() : "COM not initialized"; + VARIANT v = Convert.toVariant(value); WinNT.HRESULT hr = this.oleMethod(OleAuto.DISPATCH_PROPERTYPUT, null, this.getRawDispatch(), name, v); Convert.free(v, value); // Free value allocated by Convert#toVariant @@ -362,6 +349,8 @@ public void setProperty(String name, T value) { @Override public T getProperty(Class returnType, String name, Object... args) { + assert COMUtils.comIsInitialized() : "COM not initialized"; + VARIANT[] vargs; if (null == args) { vargs = new VARIANT[0]; @@ -386,6 +375,8 @@ public T getProperty(Class returnType, String name, Object... args) { @Override public T invokeMethod(Class returnType, String name, Object... args) { + assert COMUtils.comIsInitialized() : "COM not initialized"; + VARIANT[] vargs; if (null == args) { vargs = new VARIANT[0]; @@ -427,6 +418,8 @@ private T convertAndFreeReturn(VARIANT.ByReference result, Class returnTy @Override public T queryInterface(Class comInterface) throws COMException { + assert COMUtils.comIsInitialized() : "COM not initialized"; + try { ComInterface comInterfaceAnnotation = comInterface.getAnnotation(ComInterface.class); if (null == comInterfaceAnnotation) { @@ -436,12 +429,7 @@ public T queryInterface(Class comInterface) throws COMException { final IID iid = this.getIID(comInterfaceAnnotation); final PointerByReference ppvObject = new PointerByReference(); - HRESULT hr = this.comThread.execute(new Callable() { - @Override - public HRESULT call() throws Exception { - return ProxyObject.this.getRawDispatch().QueryInterface(new REFIID(iid), ppvObject); - } - }); + HRESULT hr = ProxyObject.this.getRawDispatch().QueryInterface(new REFIID(iid), ppvObject); if (WinNT.S_OK.equals(hr)) { Dispatch dispatch = new Dispatch(ppvObject.getValue()); @@ -552,33 +540,20 @@ protected HRESULT oleMethod(int nType, VARIANT.ByReference pvResult, IDispatch p */ protected HRESULT oleMethod(int nType, VARIANT.ByReference pvResult, final IDispatch pDisp, String name, VARIANT[] pArgs) throws COMException { - try { - if (pDisp == null) - throw new COMException("pDisp (IDispatch) parameter is null!"); - - // variable declaration - final WString[] ptName = new WString[] { new WString(name) }; - final DISPIDByReference pdispID = new DISPIDByReference(); - - // Get DISPID for name passed... - HRESULT hr = this.comThread.execute(new Callable() { - @Override - public HRESULT call() throws Exception { - HRESULT hr = pDisp.GetIDsOfNames(new REFIID(Guid.IID_NULL), ptName, 1, LOCALE_USER_DEFAULT, - pdispID); - return hr; - } - }); - COMUtils.checkRC(hr); + if (pDisp == null) + throw new COMException("pDisp (IDispatch) parameter is null!"); - return this.oleMethod(nType, pvResult, pDisp, pdispID.getValue(), pArgs); - } catch (InterruptedException e) { - throw new COMException(e); - } catch (ExecutionException e) { - throw new COMException(e); - } catch (TimeoutException e) { - throw new COMException(e); - } + // variable declaration + final WString[] ptName = new WString[] { new WString(name) }; + final DISPIDByReference pdispID = new DISPIDByReference(); + + // Get DISPID for name passed... + HRESULT hr = pDisp.GetIDsOfNames(new REFIID(Guid.IID_NULL), ptName, 1, LOCALE_USER_DEFAULT, + pdispID); + + COMUtils.checkRC(hr); + + return this.oleMethod(nType, pvResult, pDisp, pdispID.getValue(), pArgs); } /* @@ -587,6 +562,8 @@ public HRESULT call() throws Exception { protected HRESULT oleMethod(final int nType, final VARIANT.ByReference pvResult, final IDispatch pDisp, final DISPID dispId, VARIANT[] pArgs) throws COMException { + assert COMUtils.comIsInitialized() : "COM not initialized"; + if (pDisp == null) throw new COMException("pDisp (IDispatch) parameter is null!"); @@ -654,25 +631,12 @@ protected HRESULT oleMethod(final int nType, final VARIANT.ByReference pvResult, dp.write(); } - // Make the call! - try { - HRESULT hr = this.comThread.execute(new Callable() { - @Override - public HRESULT call() throws Exception { - return pDisp.Invoke(dispId, new REFIID(Guid.IID_NULL), LOCALE_SYSTEM_DEFAULT, + HRESULT hr = pDisp.Invoke(dispId, new REFIID(Guid.IID_NULL), LOCALE_SYSTEM_DEFAULT, new WinDef.WORD(finalNType), dp, pvResult, pExcepInfo, puArgErr); - } - }); + COMUtils.checkRC(hr, pExcepInfo, puArgErr); return hr; - } catch (InterruptedException e) { - throw new COMException(e); - } catch (ExecutionException e) { - throw new COMException(e); - } catch (TimeoutException e) { - throw new COMException(e); - } } } diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/RunningObjectTable.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/RunningObjectTable.java index 874461378e..acbcde1c69 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/RunningObjectTable.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/RunningObjectTable.java @@ -28,44 +28,30 @@ public class RunningObjectTable implements IRunningObjectTable { protected RunningObjectTable(com.sun.jna.platform.win32.COM.RunningObjectTable raw, Factory factory) { this.raw = raw; this.factory = factory; - this.comThread = factory.getComThread(); } Factory factory; - ComThread comThread; com.sun.jna.platform.win32.COM.RunningObjectTable raw; @Override public Iterable enumRunning() { + assert COMUtils.comIsInitialized() : "COM not initialized"; + + final PointerByReference ppenumMoniker = new PointerByReference(); - try { + WinNT.HRESULT hr = this.raw.EnumRunning(ppenumMoniker); - final PointerByReference ppenumMoniker = new PointerByReference(); - - WinNT.HRESULT hr = this.comThread.execute(new Callable() { - @Override - public WinNT.HRESULT call() throws Exception { - return RunningObjectTable.this.raw.EnumRunning(ppenumMoniker); - } - }); - COMUtils.checkRC(hr); - com.sun.jna.platform.win32.COM.EnumMoniker raw = new com.sun.jna.platform.win32.COM.EnumMoniker( - ppenumMoniker.getValue()); - - return new EnumMoniker(raw, this.raw, this.factory); - - } catch (InterruptedException e) { - throw new RuntimeException(e); - } catch (ExecutionException e) { - throw new RuntimeException(e); - } catch (TimeoutException e) { - throw new RuntimeException(e); - } + COMUtils.checkRC(hr); + com.sun.jna.platform.win32.COM.EnumMoniker raw = new com.sun.jna.platform.win32.COM.EnumMoniker( + ppenumMoniker.getValue()); + return new EnumMoniker(raw, this.raw, this.factory); } @Override public List getActiveObjectsByInterface(Class comInterface) { + assert COMUtils.comIsInitialized() : "COM not initialized"; + List result = new ArrayList(); for (IDispatch obj : this.enumRunning()) { diff --git a/contrib/platform/test/com/sun/jna/platform/win32/COM/COMTest.java b/contrib/platform/test/com/sun/jna/platform/win32/COM/COMTest.java index c601b8e216..f98c1e1519 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/COM/COMTest.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/COMTest.java @@ -31,7 +31,11 @@ * @author dblock[at]dblock[dot]org */ public class COMTest extends TestCase { - + + static { + ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); + } + public static void main(String[] args) { junit.textui.TestRunner.run(COMTest.class); } diff --git a/contrib/platform/test/com/sun/jna/platform/win32/COM/ComEventCallbacks_Test.java b/contrib/platform/test/com/sun/jna/platform/win32/COM/ComEventCallbacks_Test.java index 4b730f4c4c..4652cb6328 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/COM/ComEventCallbacks_Test.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/ComEventCallbacks_Test.java @@ -46,7 +46,10 @@ import org.junit.Assert; public class ComEventCallbacks_Test { - + static { + ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); + } + private final CLSID CLSID_InternetExplorer = new CLSID("{0002DF01-0000-0000-C000-000000000046}"); private final IID IID_IConnectionPointContainer = new IID("{B196B284-BAB4-101A-B69C-00AA00341D07}"); private final IID IID_DWebBrowserEvents2 = new IID("{34A715A0-6587-11D0-924A-0020AFC7AC4D}"); @@ -55,9 +58,9 @@ public class ComEventCallbacks_Test { private final WinDef.WORD methodFlags = new WinDef.WORD(OleAuto.DISPATCH_METHOD); private final WinDef.WORD propertyPutFlags = new WinDef.WORD(OleAuto.DISPATCH_PROPERTYPUT); - private DISPIDByReference dispIdVisible = new DISPIDByReference(); - private DISPIDByReference dispIdQuit = new DISPIDByReference(); - private DISPIDByReference dispIdNavigate = new DISPIDByReference(); + private final DISPIDByReference dispIdVisible = new DISPIDByReference(); + private final DISPIDByReference dispIdQuit = new DISPIDByReference(); + private final DISPIDByReference dispIdNavigate = new DISPIDByReference(); private PointerByReference ieApp; private Dispatch ieDispatch; diff --git a/contrib/platform/test/com/sun/jna/platform/win32/COM/EnumMoniker_Test.java b/contrib/platform/test/com/sun/jna/platform/win32/COM/EnumMoniker_Test.java index 102ccf9bca..3f74948a82 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/COM/EnumMoniker_Test.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/EnumMoniker_Test.java @@ -12,6 +12,7 @@ */ package com.sun.jna.platform.win32.COM; +import com.sun.jna.Pointer; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; @@ -33,7 +34,10 @@ import com.sun.jna.ptr.PointerByReference; public class EnumMoniker_Test { - + static { + ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); + } + @ComInterface(iid="{00020970-0000-0000-C000-000000000046}") interface Application { @ComProperty @@ -56,19 +60,23 @@ interface MsWordApp extends Application { @Before public void before() { + WinNT.HRESULT hr = Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED); + COMUtils.checkRC(hr); + this.factory = new Factory(); // Two COM objects are require to be running for these tests to work this.ob1 = this.factory.createObject(MsWordApp.class); this.ob2 = this.factory.createObject(MsWordApp.class); - - WinNT.HRESULT hr = Ole32.INSTANCE.CoInitialize(null); - COMUtils.checkRC(hr); } @After public void after() { - ob1.Quit(); - ob2.Quit(); + if(ob1 != null) { + ob1.Quit(); + } + if(ob2 != null) { + ob2.Quit(); + } Ole32.INSTANCE.CoUninitialize(); } diff --git a/contrib/platform/test/com/sun/jna/platform/win32/COM/IDispatchTest.java b/contrib/platform/test/com/sun/jna/platform/win32/COM/IDispatchTest.java index 3e3a4af58c..e7063a4826 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/COM/IDispatchTest.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/IDispatchTest.java @@ -30,7 +30,10 @@ import com.sun.jna.ptr.PointerByReference; public class IDispatchTest extends TestCase { - + static { + ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); + } + /** The Constant LOCALE_SYSTEM_DEFAULT. */ public final static LCID LOCALE_SYSTEM_DEFAULT = Kernel32.INSTANCE .GetSystemDefaultLCID(); diff --git a/contrib/platform/test/com/sun/jna/platform/win32/COM/IShellFolderTest.java b/contrib/platform/test/com/sun/jna/platform/win32/COM/IShellFolderTest.java index 401f05ec82..e6727ee1f1 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/COM/IShellFolderTest.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/IShellFolderTest.java @@ -12,7 +12,10 @@ import com.sun.jna.ptr.PointerByReference; public class IShellFolderTest extends TestCase { - + static { + ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); + } + private IShellFolder psfMyComputer; public static WinNT.HRESULT BindToCsidl(int csidl, Guid.REFIID riid, PointerByReference ppv) { @@ -36,7 +39,6 @@ public static WinNT.HRESULT BindToCsidl(int csidl, Guid.REFIID riid, PointerByRe } public void setUp() throws Exception { - Ole32.INSTANCE.CoInitialize(null); int CSIDL_DRIVES = 0x0011; WinNT.HRESULT hr = Ole32.INSTANCE.CoInitialize(null); assertTrue(COMUtils.SUCCEEDED(hr)); diff --git a/contrib/platform/test/com/sun/jna/platform/win32/COM/ITypeInfoTest.java b/contrib/platform/test/com/sun/jna/platform/win32/COM/ITypeInfoTest.java index 8872c249e5..732e34c206 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/COM/ITypeInfoTest.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/ITypeInfoTest.java @@ -12,8 +12,6 @@ */ package com.sun.jna.platform.win32.COM; -import junit.framework.TestCase; - import com.sun.jna.platform.win32.OaIdl.HREFTYPEByReference; import com.sun.jna.platform.win32.OaIdl.INVOKEKIND; import com.sun.jna.platform.win32.OaIdl.MEMBERID; @@ -27,29 +25,19 @@ import com.sun.jna.platform.win32.WinNT.HRESULT; import com.sun.jna.ptr.IntByReference; import com.sun.jna.ptr.PointerByReference; +import static junit.framework.TestCase.assertEquals; import org.junit.Ignore; +import org.junit.Test; /** * @author dblock[at]dblock[dot]org */ -public class ITypeInfoTest extends TestCase { - - public static void main(String[] args) { - junit.textui.TestRunner.run(ITypeInfoTest.class); - } - - public ITypeInfoTest() { - } - - @Override - protected void setUp() throws Exception { - } - - @Override - protected void tearDown() throws Exception { +public class ITypeInfoTest { + static { + ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); } - public ITypeInfo getTypeInfo() { + private ITypeInfo getTypeInfo() { TypeLibUtil shellTypeLib = new TypeLibUtil("{50A7E9B0-70EF-11D1-B75A-00A0C90564FE}", 1, 0); int typeInfoCount = shellTypeLib.getTypeInfoCount(); if (typeInfoCount == 0) @@ -58,7 +46,7 @@ public ITypeInfo getTypeInfo() { return typeInfo; } - public ITypeInfo[] getTypeInfos() { + private ITypeInfo[] getTypeInfos() { TypeLibUtil shellTypeLib = new TypeLibUtil("{50A7E9B0-70EF-11D1-B75A-00A0C90564FE}", 1, 0); int typeInfoCount = shellTypeLib.getTypeInfoCount(); if (typeInfoCount == 0) @@ -82,6 +70,7 @@ public void testGetFuncDesc() { public void testGetVarDesc() { } + @Test public void testGetNames() { ITypeInfo[] typeInfos = getTypeInfos(); MEMBERID memid = new MEMBERID(1); @@ -99,6 +88,7 @@ public void testGetNames() { throw new RuntimeException("Didn't find name for member in any of the type infos"); } + @Test public void testGetRefTypeOfImplType() { ITypeInfo typeInfo = getTypeInfo(); HREFTYPEByReference pRefType = new HREFTYPEByReference(); @@ -109,6 +99,7 @@ public void testGetRefTypeOfImplType() { //System.out.println("GetRefTypeOfImplType: " + pRefType.toString()); } + @Test public void testGetImplTypeFlags() { ITypeInfo typeInfo = getTypeInfo(); IntByReference pImplTypeFlags = new IntByReference(); @@ -119,6 +110,7 @@ public void testGetImplTypeFlags() { //System.out.println("GetImplTypeFlags: " + pImplTypeFlags.toString()); } + @Test public void testGetIDsOfNames() { ITypeInfo[] typeInfos = getTypeInfos(); LPOLESTR[] rgszNames = {new LPOLESTR("Help")}; @@ -138,6 +130,7 @@ public void testInvoke() { } + @Test public void testGetDocumentation() { ITypeInfo[] typeInfos = getTypeInfos(); MEMBERID memid = new MEMBERID(0); @@ -160,6 +153,7 @@ public void testGetDocumentation() { throw new RuntimeException("Didn't find documentation in any of the type infos"); } + @Test @Ignore("Needs a DLL that contains code") public void testGetDllEntry() { ITypeInfo[] typeInfos = getTypeInfos(); @@ -184,6 +178,7 @@ public void testGetDllEntry() { public void testGetRefTypeInfo() { } + @Test @Ignore("Needs a DLL that contains code") public void testAddressOfMember() { ITypeInfo[] typeInfos = getTypeInfos(); @@ -204,6 +199,7 @@ public void testCreateInstance() { } + @Test public void testGetMops() { ITypeInfo typeInfo = getTypeInfo(); MEMBERID memid = new MEMBERID(0); diff --git a/contrib/platform/test/com/sun/jna/platform/win32/COM/ITypeLibTest.java b/contrib/platform/test/com/sun/jna/platform/win32/COM/ITypeLibTest.java index a90b2f92be..0856b7d854 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/COM/ITypeLibTest.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/ITypeLibTest.java @@ -39,6 +39,10 @@ * @author dblock[at]dblock[dot]org */ public class ITypeLibTest extends TestCase { + static { + ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); + } + // Microsoft Shell Controls And Automation private static final String SHELL_CLSID = "{50A7E9B0-70EF-11D1-B75A-00A0C90564FE}"; // Version 1.0 diff --git a/contrib/platform/test/com/sun/jna/platform/win32/COM/IUnknownTest.java b/contrib/platform/test/com/sun/jna/platform/win32/COM/IUnknownTest.java index a683538636..450b0a07dd 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/COM/IUnknownTest.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/IUnknownTest.java @@ -23,7 +23,10 @@ import com.sun.jna.ptr.PointerByReference; public class IUnknownTest extends TestCase { - + static { + ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); + } + private Unknown createIUnknown() { try { PointerByReference pUnknown = new PointerByReference(); diff --git a/contrib/platform/test/com/sun/jna/platform/win32/COM/RunningObjectTable_Test.java b/contrib/platform/test/com/sun/jna/platform/win32/COM/RunningObjectTable_Test.java index 6765d5bfb4..1c895cd2b2 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/COM/RunningObjectTable_Test.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/RunningObjectTable_Test.java @@ -30,7 +30,10 @@ import com.sun.jna.ptr.PointerByReference; public class RunningObjectTable_Test { - + static { + ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); + } + @Before public void before() { HRESULT hr = Ole32.INSTANCE.CoInitialize(null); diff --git a/contrib/platform/test/com/sun/jna/platform/win32/COM/ShellApplicationWindowsTest.java b/contrib/platform/test/com/sun/jna/platform/win32/COM/ShellApplicationWindowsTest.java index e6cf492dce..6a91754f40 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/COM/ShellApplicationWindowsTest.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/ShellApplicationWindowsTest.java @@ -1,5 +1,7 @@ package com.sun.jna.platform.win32.COM; +import com.sun.jna.Pointer; +import com.sun.jna.platform.win32.Ole32; import java.util.Iterator; import java.util.NoSuchElementException; @@ -7,14 +9,22 @@ import com.sun.jna.platform.win32.Variant.VARIANT; import com.sun.jna.platform.win32.WinDef.LONG; -import junit.framework.TestCase; +import static junit.framework.TestCase.assertTrue; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; -public class ShellApplicationWindowsTest extends TestCase -{ +public class ShellApplicationWindowsTest { - @Override + static { + ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); + } + + @Before public void setUp() throws Exception { + Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED); + // Launch IE in a manner that should ensure it opens even if the system default browser is Chrome, Firefox, or something else. Runtime.getRuntime().exec("cmd /c start iexplore.exe -nohome \"about:blank\""); @@ -23,6 +33,7 @@ public void setUp() throws Exception Thread.sleep(3000); } + @Test public void testWindowsCount() { ShellApplication sa = new ShellApplication(); @@ -45,10 +56,12 @@ public void testWindowsCount() // Finally, did we find our page in the collection? assertTrue("No IE page was found", pageFound); + + Ole32.INSTANCE.CoUninitialize(); } - @Override - protected void tearDown() throws Exception + @After + public void tearDown() throws Exception { Runtime.getRuntime().exec("taskkill.exe /f /im iexplore.exe"); } @@ -183,8 +196,4 @@ public String getURL() return getStringProperty("LocationURL"); } } - - public static void main(String[] args) { - junit.textui.TestRunner.run(ShellApplicationWindowsTest.class); - } } diff --git a/contrib/platform/test/com/sun/jna/platform/win32/COM/TypeLibUtilTest.java b/contrib/platform/test/com/sun/jna/platform/win32/COM/TypeLibUtilTest.java index a37100d4e1..942ae5a2ff 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/COM/TypeLibUtilTest.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/TypeLibUtilTest.java @@ -28,7 +28,10 @@ * @author dblock[at]dblock[dot]org */ public class TypeLibUtilTest extends TestCase { - + static { + ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); + } + public static void main(String[] args) { junit.textui.TestRunner.run(TypeLibUtilTest.class); } diff --git a/contrib/platform/test/com/sun/jna/platform/win32/COM/util/ComEventCallbacks_Test.java b/contrib/platform/test/com/sun/jna/platform/win32/COM/util/ComEventCallbacks_Test.java index ea7adc1157..0280df09dc 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/COM/util/ComEventCallbacks_Test.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/util/ComEventCallbacks_Test.java @@ -12,6 +12,7 @@ */ package com.sun.jna.platform.win32.COM.util; +import com.sun.jna.Pointer; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -23,24 +24,29 @@ import com.sun.jna.platform.win32.COM.util.annotation.ComObject; import com.sun.jna.platform.win32.COM.util.annotation.ComProperty; import com.sun.jna.platform.win32.OaIdl; +import com.sun.jna.platform.win32.Ole32; import com.sun.jna.platform.win32.Variant; import com.sun.jna.platform.win32.Variant.VARIANT; import org.hamcrest.CoreMatchers; -import org.junit.Ignore; public class ComEventCallbacks_Test { + static { + ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); + } + Factory factory; @Before public void before() { + Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED); this.factory = new Factory(); } @After public void after() { this.factory.disposeAll(); - this.factory.getComThread().terminate(1000); + Ole32.INSTANCE.CoUninitialize(); } diff --git a/contrib/platform/test/com/sun/jna/platform/win32/COM/util/HybdridCOMInvocationTest.java b/contrib/platform/test/com/sun/jna/platform/win32/COM/util/HybdridCOMInvocationTest.java index c78223ec2c..363cb7f96b 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/COM/util/HybdridCOMInvocationTest.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/util/HybdridCOMInvocationTest.java @@ -1,5 +1,6 @@ package com.sun.jna.platform.win32.COM.util; +import com.sun.jna.Pointer; import com.sun.jna.platform.win32.COM.COMException; import com.sun.jna.platform.win32.COM.COMLateBindingObject; import com.sun.jna.platform.win32.COM.COMUtils; @@ -28,10 +29,11 @@ import com.sun.jna.ptr.PointerByReference; import java.util.logging.Level; import java.util.logging.Logger; -import junit.framework.TestCase; +import static org.hamcrest.CoreMatchers.is; +import org.junit.After; import org.junit.Test; -import static junit.framework.TestCase.assertEquals; -import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.*; +import org.junit.Before; /** * In the word COM bindings it was determined, that some methods can't be called @@ -44,7 +46,11 @@ * * A sample function is InchesToPoints from thw word typelibrary */ -public class HybdridCOMInvocationTest extends TestCase { +public class HybdridCOMInvocationTest { + + static { + ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); + } private static final Logger LOG = Logger.getLogger(HybdridCOMInvocationTest.class.getName()); @@ -53,16 +59,15 @@ public class HybdridCOMInvocationTest extends TestCase { 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(); + @After + public void tearDown() throws Exception { Ole32.INSTANCE.CoUninitialize(); } - @Override - protected void setUp() throws Exception { + @Before + public void setUp() throws Exception { // Initialize COM for this thread... - HRESULT hr = Ole32.INSTANCE.CoInitialize(null); + Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED); } @Test @@ -77,7 +82,8 @@ public void testOfficeInvocationProblemCOMUtil() { } // If this fails: remember: floats are not exact, if this happens replace // with a range check - assertEquals(72.0f, app.InchesToPoints(1F)); + assertThat(app.InchesToPoints(1F), is(72.0f)); + fact.disposeAll(); } @Test @@ -89,7 +95,7 @@ public void testOfficeInvocationProblemCOMBindingObject() { LOG.log(Level.INFO, "HybdridCOMInvocationTest test was not run, MS Word object could not be instantiated.", ex); return; } - assertEquals(72.0f, app.InchesToPoints(1F)); + assertThat(app.InchesToPoints(1F), is(72.0f)); } diff --git a/contrib/platform/test/com/sun/jna/platform/win32/COM/util/ProxyObject_Test.java b/contrib/platform/test/com/sun/jna/platform/win32/COM/util/ProxyObject_Test.java index a7bb257056..a3cd6bd6ee 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/COM/util/ProxyObject_Test.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/util/ProxyObject_Test.java @@ -12,6 +12,7 @@ */ package com.sun.jna.platform.win32.COM.util; +import com.sun.jna.Pointer; import static org.junit.Assert.*; import org.junit.After; @@ -22,9 +23,14 @@ import com.sun.jna.platform.win32.COM.util.annotation.ComObject; import com.sun.jna.platform.win32.COM.util.annotation.ComMethod; import com.sun.jna.platform.win32.COM.util.annotation.ComProperty; +import com.sun.jna.platform.win32.Ole32; public class ProxyObject_Test { + static { + ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); + } + @ComInterface(iid="{00020970-0000-0000-C000-000000000046}") interface Application extends IUnknown { @ComProperty @@ -42,9 +48,10 @@ interface MsWordApp extends Application { } Factory factory; - + @Before public void before() { + Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED); this.factory = new Factory(); //ensure there are no word applications running. while(true) { @@ -70,12 +77,8 @@ public void before() { @After public void after() { - try { - //wait for it to quit - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } + factory.disposeAll(); + Ole32.INSTANCE.CoUninitialize(); } diff --git a/contrib/platform/test/com/sun/jna/platform/win32/COM/util/RunningObjectTable_Test.java b/contrib/platform/test/com/sun/jna/platform/win32/COM/util/RunningObjectTable_Test.java index 968a219ba7..5ad76959e4 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/COM/util/RunningObjectTable_Test.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/util/RunningObjectTable_Test.java @@ -12,6 +12,7 @@ */ package com.sun.jna.platform.win32.COM.util; +import com.sun.jna.Pointer; import static org.junit.Assert.*; import java.util.List; @@ -25,9 +26,14 @@ import com.sun.jna.platform.win32.COM.util.annotation.ComObject; import com.sun.jna.platform.win32.COM.util.annotation.ComMethod; import com.sun.jna.platform.win32.COM.util.annotation.ComProperty; +import com.sun.jna.platform.win32.Ole32; public class RunningObjectTable_Test { + static { + ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); + } + @ComInterface(iid="{00020970-0000-0000-C000-000000000046}") interface Application extends IUnknown { @ComProperty @@ -46,9 +52,10 @@ interface MsWordApp extends Application { Factory factory; MsWordApp msWord; - + @Before public void before() { + Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED); this.factory = new Factory(); //ensure there is only one word application running. while(true) { @@ -85,6 +92,8 @@ public void after() { } catch (InterruptedException e) { e.printStackTrace(); } + factory.disposeAll(); + Ole32.INSTANCE.CoUninitialize(); } @Test