Visitar URL original
Remove COM initialization from object and enforce correct handling vi… · java-native-access/jna@844c56f · GitHub
Skip to content

Commit 844c56f

Browse files
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.
1 parent bf32054 commit 844c56f

23 files changed

Lines changed: 348 additions & 567 deletions

‎contrib/platform/src/com/sun/jna/platform/win32/COM/COMBindingBaseObject.java‎

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import com.sun.jna.ptr.IntByReference;
3535
import com.sun.jna.ptr.PointerByReference;
3636

37-
// TODO: Auto-generated Javadoc
3837
/**
3938
* Helper class to provide basic COM support.
4039
*
@@ -73,14 +72,10 @@ public COMBindingBaseObject(CLSID clsid, boolean useActiveInstance) {
7372

7473
public COMBindingBaseObject(CLSID clsid, boolean useActiveInstance,
7574
int dwClsContext) {
76-
// Initialize COM for this thread...
77-
HRESULT hr = Ole32.INSTANCE.CoInitializeEx(null, Ole32.COINIT_APARTMENTTHREADED);
78-
79-
if (COMUtils.FAILED(hr)) {
80-
Ole32.INSTANCE.CoUninitialize();
81-
throw new COMException("CoInitialize() failed!");
82-
}
83-
75+
assert COMUtils.comIsInitialized() : "COM not initialized";
76+
77+
HRESULT hr;
78+
8479
if (useActiveInstance) {
8580
hr = OleAuto.INSTANCE.GetActiveObject(clsid, null, this.pUnknown);
8681

@@ -107,20 +102,15 @@ public COMBindingBaseObject(CLSID clsid, boolean useActiveInstance,
107102

108103
public COMBindingBaseObject(String progId, boolean useActiveInstance,
109104
int dwClsContext) throws COMException {
110-
// Initialize COM for this thread...
111-
HRESULT hr = Ole32.INSTANCE.CoInitializeEx(null, Ole32.COINIT_APARTMENTTHREADED);
112-
113-
if (COMUtils.FAILED(hr)) {
114-
this.release();
115-
throw new COMException("CoInitialize() failed!");
116-
}
105+
assert COMUtils.comIsInitialized() : "COM not initialized";
106+
107+
HRESULT hr;
117108

118109
// Get CLSID for Word.Application...
119110
CLSID.ByReference clsid = new CLSID.ByReference();
120111
hr = Ole32.INSTANCE.CLSIDFromProgID(progId, clsid);
121112

122113
if (COMUtils.FAILED(hr)) {
123-
Ole32.INSTANCE.CoUninitialize();
124114
throw new COMException("CLSIDFromProgID() failed!");
125115
}
126116

@@ -194,10 +184,9 @@ public PointerByReference getIUnknownPointer() {
194184
* Release.
195185
*/
196186
public void release() {
197-
if (this.iDispatch != null)
187+
if (this.iDispatch != null) {
198188
this.iDispatch.Release();
199-
200-
Ole32.INSTANCE.CoUninitialize();
189+
}
201190
}
202191

203192
protected HRESULT oleMethod(int nType, VARIANT.ByReference pvResult,

‎contrib/platform/src/com/sun/jna/platform/win32/COM/COMUtils.java‎

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,21 @@
1515
import java.util.ArrayList;
1616

1717
import com.sun.jna.Native;
18+
import com.sun.jna.Pointer;
1819
import com.sun.jna.platform.win32.Advapi32;
1920
import com.sun.jna.platform.win32.Advapi32Util;
2021
import com.sun.jna.platform.win32.Advapi32Util.EnumKey;
2122
import com.sun.jna.platform.win32.Advapi32Util.InfoKey;
2223
import com.sun.jna.platform.win32.Kernel32Util;
2324
import com.sun.jna.platform.win32.OaIdl.EXCEPINFO;
25+
import com.sun.jna.platform.win32.Ole32;
26+
import com.sun.jna.platform.win32.W32Errors;
2427
import com.sun.jna.platform.win32.WinNT;
2528
import com.sun.jna.platform.win32.WinNT.HRESULT;
2629
import com.sun.jna.platform.win32.WinReg;
2730
import com.sun.jna.platform.win32.WinReg.HKEYByReference;
2831
import com.sun.jna.ptr.IntByReference;
2932

30-
// TODO: Auto-generated Javadoc
3133
/**
3234
* The Class COMUtils.
3335
*
@@ -182,6 +184,36 @@ public static ArrayList<COMInfo> getAllCOMInfoOnSystem() {
182184
return comInfos;
183185
}
184186

187+
/**
188+
* Check is COM was initialized correctly. The initialization status is not changed!
189+
*
190+
* <p>This is a debug function, not for normal usage!</p>
191+
*
192+
* @return
193+
*/
194+
public static boolean comIsInitialized() {
195+
WinNT.HRESULT hr = Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED);
196+
if (hr.equals(W32Errors.S_OK)) {
197+
// User failed - uninitialize again and return false
198+
Ole32.INSTANCE.CoUninitialize();
199+
return false;
200+
} else if (hr.equals(W32Errors.S_FALSE)) {
201+
// OK Variant 1 - User initialized COM with same threading module as
202+
// in this check. According to MSDN CoUninitialize needs to be called
203+
// in this case.
204+
Ole32.INSTANCE.CoUninitialize();
205+
return true;
206+
} else if (hr.intValue() == W32Errors.RPC_E_CHANGED_MODE) {
207+
return true;
208+
}
209+
// If another result than the checked ones above happens handling is
210+
// delegated to the "normal" COM exception handling and a COMException
211+
// will be raised.
212+
COMUtils.checkRC(hr);
213+
// The return will not be met, as COMUtils#checkRC will raise an exception
214+
return false;
215+
}
216+
185217
/**
186218
* The Class COMInfo.
187219
*

‎contrib/platform/src/com/sun/jna/platform/win32/COM/util/CallbackProxy.java‎

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import com.sun.jna.platform.win32.WinError;
3838
import com.sun.jna.platform.win32.WinNT.HRESULT;
3939
import com.sun.jna.platform.win32.COM.COMException;
40+
import com.sun.jna.platform.win32.COM.COMUtils;
4041
import com.sun.jna.platform.win32.COM.Dispatch;
4142
import com.sun.jna.platform.win32.COM.DispatchListener;
4243
import com.sun.jna.platform.win32.COM.IDispatch;
@@ -103,7 +104,7 @@ int fetchDispIdFromName(ComEventCallback annotation) {
103104

104105
void invokeOnThread(final DISPID dispIdMember, final REFIID riid, LCID lcid, WORD wFlags,
105106
final DISPPARAMS.ByReference pDispParams) {
106-
107+
107108
final Method eventMethod;
108109
if (CallbackProxy.this.dsipIdMap.containsKey(dispIdMember)) {
109110
eventMethod = CallbackProxy.this.dsipIdMap.get(dispIdMember);
@@ -204,13 +205,9 @@ public HRESULT Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
204205
DISPPARAMS.ByReference pDispParams, VARIANT.ByReference pVarResult, EXCEPINFO.ByReference pExcepInfo,
205206
IntByReference puArgErr) {
206207

207-
assert (! ComThread.getCurrentThreadIsCOM()) : "Assumption about COM threading broken.";
208-
ComThread.setCurrentThreadIsCOM(true);
209-
try {
210-
this.invokeOnThread(dispIdMember, riid, lcid, wFlags, pDispParams);
211-
} finally {
212-
ComThread.setCurrentThreadIsCOM(false);
213-
}
208+
assert COMUtils.comIsInitialized() : "Assumption about COM threading broken.";
209+
210+
this.invokeOnThread(dispIdMember, riid, lcid, wFlags, pDispParams);
214211

215212
return WinError.S_OK;
216213
}

‎contrib/platform/src/com/sun/jna/platform/win32/COM/util/ComThread.java‎

Lines changed: 0 additions & 157 deletions
This file was deleted.

0 commit comments

Comments
 (0)