From d6675fa7ae5f9d2193be7290b6ab4ca5c08fc491 Mon Sep 17 00:00:00 2001 From: "Dr. David H. Akehurst" Date: Mon, 16 Mar 2015 09:39:49 -0400 Subject: [PATCH] Improved COM support in com.sun.jna.platform.win32.COM.util. Use of interfaces and annotations to provide easier implementation of COM interfaces (uses InvocationHandler). Support for COM event callbacks. Support for COM interface discovery by iteration over the RunningObjectTable. --- CHANGES.md | 12 +- contrib/msoffice/.classpath | 4 +- contrib/msoffice/jnatest.xls | Bin 22016 -> 28160 bytes .../win32/COM/office/MSOfficeDemo.java | 4 +- .../COM/util/office/MSOfficeExcelDemo.java | 100 +++ .../COM/util/office/MSOfficeWordDemo.java | 109 +++ .../office/excel/ComExcel_Application.java | 10 + .../COM/util/office/excel/ComIAppEvents.java | 12 + .../util/office/excel/ComIApplication.java | 32 + .../COM/util/office/excel/ComIRange.java | 25 + .../COM/util/office/excel/ComIWorkbook.java | 13 + .../COM/util/office/excel/ComIWorkbooks.java | 19 + .../COM/util/office/excel/ComIWorksheet.java | 19 + .../COM/util/office/word/ComIApplication.java | 43 ++ .../COM/util/office/word/ComIDocument.java | 25 + .../COM/util/office/word/ComIDocuments.java | 28 + .../COM/util/office/word/ComISelection.java | 24 + .../util/office/word/ComWord_Application.java | 21 + .../util/office/word/WdOriginalFormat.java | 29 + .../COM/util/office/word/WdSaveFormat.java | 54 ++ contrib/platform/.classpath | 5 +- contrib/platform/.project | 2 +- .../win32/COM/COMBindingBaseObject.java | 14 +- .../win32/COM/COMEarlyBindingObject.java | 12 +- .../jna/platform/win32/COM/COMException.java | 2 +- .../platform/win32/COM/ConnectionPoint.java | 56 ++ .../win32/COM/ConnectionPointContainer.java | 50 ++ .../sun/jna/platform/win32/COM/Dispatch.java | 8 +- .../platform/win32/COM/DispatchListener.java | 104 +++ .../platform/win32/COM/DispatchVTable.java | 89 +++ .../jna/platform/win32/COM/EnumMoniker.java | 71 ++ .../platform/win32/COM/IConnectionPoint.java | 66 ++ .../win32/COM/IConnectionPointContainer.java | 35 + .../sun/jna/platform/win32/COM/IDispatch.java | 8 +- .../platform/win32/COM/IDispatchCallback.java | 18 + .../jna/platform/win32/COM/IEnumMoniker.java | 94 +++ .../sun/jna/platform/win32/COM/IMoniker.java | 94 +++ .../sun/jna/platform/win32/COM/IPersist.java | 40 ++ .../platform/win32/COM/IPersistStream.java | 57 ++ .../win32/COM/IRunningObjectTable.java | 152 ++++ .../sun/jna/platform/win32/COM/IStream.java | 29 + .../sun/jna/platform/win32/COM/IUnknown.java | 3 +- .../platform/win32/COM/IUnknownCallback.java | 19 + .../sun/jna/platform/win32/COM/Moniker.java | 173 +++++ .../win32/COM/RunningObjectTable.java | 110 +++ .../sun/jna/platform/win32/COM/Unknown.java | 3 +- .../platform/win32/COM/UnknownListener.java | 66 ++ .../jna/platform/win32/COM/UnknownVTable.java | 49 ++ .../AbstractComEventCallbackListener.java | 29 + .../win32/COM/util/CallbackProxy.java | 273 ++++++++ .../COM/util/ComEventCallbackCookie.java | 28 + .../platform/win32/COM/util/ComThread.java | 129 ++++ .../jna/platform/win32/COM/util/Convert.java | 92 +++ .../platform/win32/COM/util/EnumMoniker.java | 166 +++++ .../jna/platform/win32/COM/util/Factory.java | 278 ++++++++ .../jna/platform/win32/COM/util/IComEnum.java | 17 + .../COM/util/IComEventCallbackCookie.java | 17 + .../COM/util/IComEventCallbackListener.java | 23 + .../win32/COM/util/IConnectionPoint.java | 39 ++ .../COM/util/IConnectionPointContainer.java | 21 + .../platform/win32/COM/util/IDispatch.java | 24 + .../win32/COM/util/IRawDispatchHandle.java | 24 + .../win32/COM/util/IRunningObjectTable.java | 41 ++ .../jna/platform/win32/COM/util/IUnknown.java | 35 + .../platform/win32/COM/util/ProxyObject.java | 648 ++++++++++++++++++ .../win32/COM/util/RunningObjectTable.java | 83 +++ .../COM/util/annotation/ComEventCallback.java | 27 + .../COM/util/annotation/ComInterface.java | 26 + .../win32/COM/util/annotation/ComMethod.java | 27 + .../win32/COM/util/annotation/ComObject.java | 27 + .../COM/util/annotation/ComProperty.java | 26 + .../src/com/sun/jna/platform/win32/Guid.java | 15 + .../src/com/sun/jna/platform/win32/Ole32.java | 62 +- .../com/sun/jna/platform/win32/Variant.java | 14 + .../win32/COM/ComEventCallbacks_Test.java | 204 ++++++ .../COM/ConnectionPointContainer_Test.java | 242 +++++++ .../platform/win32/COM/EnumMoniker_Test.java | 233 +++++++ .../jna/platform/win32/COM/IDispatchTest.java | 3 +- .../jna/platform/win32/COM/IUnknownTest.java | 3 +- .../win32/COM/RunningObjectTable_Test.java | 182 +++++ .../COM/util/ComEventCallbacks_Test.java | 268 ++++++++ .../win32/COM/util/ProxyObject_Test.java | 130 ++++ .../COM/util/RunningObjectTable_Test.java | 133 ++++ .../com/sun/jna/platform/win32/GuidTest.java | 14 + 84 files changed, 5579 insertions(+), 36 deletions(-) create mode 100644 contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/MSOfficeExcelDemo.java create mode 100644 contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/MSOfficeWordDemo.java create mode 100644 contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComExcel_Application.java create mode 100644 contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIAppEvents.java create mode 100644 contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIApplication.java create mode 100644 contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIRange.java create mode 100644 contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIWorkbook.java create mode 100644 contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIWorkbooks.java create mode 100644 contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIWorksheet.java create mode 100644 contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/ComIApplication.java create mode 100644 contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/ComIDocument.java create mode 100644 contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/ComIDocuments.java create mode 100644 contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/ComISelection.java create mode 100644 contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/ComWord_Application.java create mode 100644 contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/WdOriginalFormat.java create mode 100644 contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/WdSaveFormat.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/ConnectionPoint.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/ConnectionPointContainer.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/DispatchListener.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/DispatchVTable.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/EnumMoniker.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/IConnectionPoint.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/IConnectionPointContainer.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/IDispatchCallback.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/IEnumMoniker.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/IMoniker.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/IPersist.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/IPersistStream.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/IRunningObjectTable.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/IStream.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/IUnknownCallback.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/Moniker.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/RunningObjectTable.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/UnknownListener.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/UnknownVTable.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/AbstractComEventCallbackListener.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/CallbackProxy.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/ComEventCallbackCookie.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/ComThread.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/Convert.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/EnumMoniker.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/Factory.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/IComEnum.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/IComEventCallbackCookie.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/IComEventCallbackListener.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/IConnectionPoint.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/IConnectionPointContainer.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/IDispatch.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/IRawDispatchHandle.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/IRunningObjectTable.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/IUnknown.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/ProxyObject.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/RunningObjectTable.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/annotation/ComEventCallback.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/annotation/ComInterface.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/annotation/ComMethod.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/annotation/ComObject.java create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/COM/util/annotation/ComProperty.java create mode 100644 contrib/platform/test/com/sun/jna/platform/win32/COM/ComEventCallbacks_Test.java create mode 100644 contrib/platform/test/com/sun/jna/platform/win32/COM/ConnectionPointContainer_Test.java create mode 100644 contrib/platform/test/com/sun/jna/platform/win32/COM/EnumMoniker_Test.java create mode 100644 contrib/platform/test/com/sun/jna/platform/win32/COM/RunningObjectTable_Test.java create mode 100644 contrib/platform/test/com/sun/jna/platform/win32/COM/util/ComEventCallbacks_Test.java create mode 100644 contrib/platform/test/com/sun/jna/platform/win32/COM/util/ProxyObject_Test.java create mode 100644 contrib/platform/test/com/sun/jna/platform/win32/COM/util/RunningObjectTable_Test.java diff --git a/CHANGES.md b/CHANGES.md index 9357f529da..322bd92c63 100755 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,12 +1,16 @@ -NOTE: as of JNA 4.0, JNA is now dual-licensed under LGPL and ASL (see LICENSE). +NOTE: as of JNA 4.0, JNA is now dual-licensed under LGPL and ASL (see LICENSE). NOTE: JNI native support is typically incompatible between minor versions, and almost always incompatible between major versions. -Release 4.2 -=========== +Release 4.2 (Next) +================== Features -------- + +* [#387](https://github.com/twall/jna/pull/397): Use of interfaces and annotations to provide easier implementation of COM interfaces (with `InvocationHandler`) - [@dhakehurst](https://github.com/dhakehurst). +* [#387](https://github.com/twall/jna/pull/397): Support for COM event callbacks - [@dhakehurst](https://github.com/dhakehurst). +* [#387](https://github.com/twall/jna/pull/397): Support for COM interface discovery by iteration over `RunningObjectTable` - [@dhakehurst](https://github.com/dhakehurst). * Updated AIX natives and build - [@twall](https://github.com/twall). * [#290](https://github.com/twall/jna/pull/290): Improved the stacktrace for the exceptions thrown by `com.sun.jna.Structure` - [@ebourg](https://github.com/ebourg). * [#332](https://github.com/twall/jna/pull/332): Added Win32 Monitor Configuration API in `com.sun.jna.platform.win32.Dxva2` - [@msteiger](https://github.com/msteiger). @@ -40,7 +44,7 @@ Bug Fixes * [#382](https://github.com/twall/jna/pull/382): Fixed memory allocation in `com.sun.jna.platform.win32.WTypes.LPWSTR` and `LPSTR` constructors - [@junak-michal](https://github.com/junak-michal). * Fix publish doc links - [@bhamail](https://github.com/bhamail). * [#388](https://github.com/twall/jna/issues/388): Ensure native library always opened with provided flags - [@zolyfarkas](https://github.com/zolyfarkas). -* [#403](https://github.com/twall/jna/pull/403): Make com.sun.jna.platform.win32.COM.COMUtils.SUCCEEDED and FAILED conform to MSDN specification for said macros - [@lwahonen](https://github.com/lwahonen). +* [#403](https://github.com/twall/jna/pull/403): Fix `com.sun.jna.platform.win32.COM.COMUtils.SUCCEEDED` and `FAILED` - [@lwahonen](https://github.com/lwahonen). Release 4.1 =========== diff --git a/contrib/msoffice/.classpath b/contrib/msoffice/.classpath index 8648c074a2..34c74501c1 100644 --- a/contrib/msoffice/.classpath +++ b/contrib/msoffice/.classpath @@ -2,7 +2,7 @@ - - + + diff --git a/contrib/msoffice/jnatest.xls b/contrib/msoffice/jnatest.xls index 8da722704c14a3e3a60a75eb526105a1a8e2576b..6077e40a432103a9a651ea187b16e50078424fd0 100644 GIT binary patch delta 4175 zcmbVQdu&tJ8UK!bV_!dFC$?kf;W&=%B+kQ$UpSC7BoHX1O-W!-rV^T#-OX2DT` zi6(U2{#-MEUD*oVLt~?KbcJSG$_9c;Y|}L8kTwYf6j;?wn?^_3pCa;%hc- z>W%I__n!0pe&6#voVk;1?k1b}J6AyFDgt$n8H-4b=|H}qDj4Z~TkL;=z#zOT_p16I8PY%tHHA&@YyWiS>)6JxM4 z7iTdD@~(bOb%q9Db(V%}u<8NAvJO1EWJ_n3laZtaABu%;re@s`g-O^2(=bMF0dT-g zU=)pv-CWj+Z)$Y28QBSvOG`ThI~0%`;PSZKO>Vb;u)cl3oBbH5cL>#>0=sN{$ClXe zPPvc^)KIxB)a;k@&^M>5nf19NE}x4G zAM|z&lA30yr$2(`;u@R;n&lo!s0ODD(g{t_CfAnsL9S4;Ek|c(=d#uaG*aZ3wPx{> zVy>4u%9eHKLPKy2Kh{K)-vc||)0Ex6n_oI)DojlMyG) zHfH4VWi;J0+KP)0>kjKccw3Sw#@9*4gg-O2n9VsdX^URPd!|Y}YSv)PU}PnD&}1`P zvr>Pj7wNiyMoWoM{L}EY1+V3R3RjmDF)u0{KEc-vehgQ%yhpYagAJye{KjhnJ#Q?MV~%dL)$&3gI_Bxh%Qn zUg}-E^+$=NLe6q8!%|)&u{>RqHC*~USCbpr+++kp*I#`F@7Gz1OtedoVUZ=nxIb;R z>3Hln(eV zKSA-Hp=XpP*%-uO3UAk!;a3{E+l;hf(jwhG8XFpScE=_rlHzP0i7llil2MwYLoiP1 z>!!B}n805Lo|#330F86XR8n-xQ3c9W0ZGQ`fH6sG`Nd_M=2Rr>&68E7G&!{69`kAhY?aD`A%L<(;r_xhG72^q{QoP0~cEdTfde~p9)I%%YYTEKNrD+bRJX~@#gOmz3QI4jiik-+5lZFoDgxC~M z#FFAJIYgnQ#BxXiVz|TiWU~%d(YY7;W)hND&*zDkkcK|)QO2*^^#e))+VF(0q9aCn zvx_2EjS4Na^9XGnOH7dJfSgNdqzG*#UlUZBF?_wblp^|=Bp**iX%;_~CtoJXb5m(K zzz2=tNHKKKP7B+k(^I?(x5oBSB0A+Tg^uRTc7jY(GNeMJ!gpeQaHK)w=VpqqHM)zI zjacAIG;@xxll298-&2p{nc!L_1GexmIL{hrT5`3pk=kBrU#1qRy-Mv3YO7iR+zeoM z3%(m3tG4hWlyj+afNr>KpVc zY*L5M_XHerI(}eWzRs-2pZ9!HECQ#XD@{SxEk4oz|8fj&_}?6ddn3uscC`0f*f9+B zyUQj>8Q1s{-L$#FJl*`9dK4%7tBiak`}>q$@o;~G_<5JvslCFK3#YgAv4sm;x<17N zuk?D7oBiw#1~!k;3Hr$90SnDA*dCuA-#Z$MCHC^22tKurE4{TWxk-E`1;YN-Zj2?knBf&VO$PK5k?#K-@&@Et`9OA6hL;X1*|kLc3X u|M7=E_E0d={{X-P!V`G0z>j`GQ2cEJJ`fJ5JY22_4-_2GH%YG&4*m_d4T|#s delta 4064 zcmai1eQZ)CN)$N6%c5WjplpLXIe0!g8SB!Ea$$VMq8g%uK>6BEY)$64D* zl>D)(leUiFv#wQIp|Vdt+Ip`|O`rfE}Kwn-by@Xmd996v+U zXWjSiJNKO5`JHp`J-%<|I-7Zo&3YvU>B|aGPhI|gHihuEypD}&%eS(}~*5P`Mygz?+e;Yfx$D4@sFu>l3RN6JxduOih65GT6bMns}mskU-ofmLA(r4CE zmkgB)ulCjH1wOVB??k528qf+?0H?>NALMGqX?8}D*y(j}+Ii9N4pG$8;Kv}q&$Yj! zJHQ{Q?Scbf0Ej<15efOcxL(+S1A+x#5~`RL-w^f_u`bPu``+hBejB^ArFcn`N4)`E zwQ{$cf^d%G3!n@qbg5ChNz9gWWimDc6v8ZLoK`2n8kGP)SKzy}#okfIV08w>zKUP7v9twGfsnQ9~Tx$I*mE_5yDP+sL}>NhvSBJjUFm- z!eGbW8tQchSOE;Jref?8MSRXsfO|xnVKazOlaU8C&CrfFjl~J07LSO7nkEROULVuA z;X&$Fk+mKV8^6X{@I&J>?1#A9RKb3PPn#t6W1KTpv!CEOQ$0I@pO{v&lUSM8#!g{> zUKcz4gXi~+TnSezDqV#7ZYcDY^DQT6-@qeS^&{u>)URVR3s}!AtW{3>q$` z=79&`3A!H=dCOQ)rxm|n?qzNGZh0^B;_ZrF=EGH$omy^%Q{?-o!+~q;bvh0w;5CQ0 zm>m+==b)^_-Htk3<1nVx<|-;NwuF~8h{H!HW>P_TiO6u|FwNgiqa*fa`NjhZo-Mpj#- zlS3bT`UQUMEXBvG%mNLDs~Rh45M+o#9Q*{Tp*ms)1F7D=ahlZf^^d_f*e!RLAA9mWZJOr224RYwyn}1W(XH)9OoQ>s6WL7Szio_c~a@KLi6E&q+ zA=#9Wyiz9@MWjrGcuH#EqIc7xyHcs}>t88O+|>%FD^;a9P@T;wJA@1U@83G7L|x9K z4ra1=ygKFMLbc-Z7^SePCL1N2?uGte-uR1xQlUnfs7ayB)hHdvjb7|65zY6G2npaVPVkoi>UKB-$Dh ztcRs6XHSSfaOU{iX)lu63y=4kb<4%;58%Zcir07Q6t8@eK2xc;FU_XWAGmXVmefnd z8vfVB7ip)fa&eJj#8u6iA4!XT>IznmP0P`EAVJ$Pk+rFr)|E7*qCri4kQ;T>r*Ixi zy?!VC`g(mDqy1hCUj{>HaQn>AsBoH^9N9Z0C&Z`K9)%J`dkQ9Dglg>&$oM_au1*Uy zfeD~nj>*HL(W&T2LOh&fSei6JH|?_+wP6^g{We8y1kX0?I;@4}8BH=F)~RiD8gkZ4 z`qT6eHBRm#ltijlf)-k4^rY|3(bp&Qa`Yv5oF;yE+RhAa9^8g-R23YRZ{=b_F*)2o z&WKn#y7`t}!F*aZl=cm=5qT&Yo=k|_)P6PPNs-KAWF%8cq69FBv#r7I5@@ArM22IL zTQNDhPmW2C$WO%+;wCkKurg^?0LCc9TS|(eu#YDT&oGshI7CF&s;xB^S`yd! zIwiYFg%CeVg(!CZPr@k}D7DVbhj6Av*Uk9<$4b8Svp^+ZLfo1IYo(HMUs&AU+}vZM za+8DMzZau$ISeXMe%#qyxjDJ+#Q6^?Pn^}NTtq4dxvXrT0Bi-wV*Z4xpw7 zFK&DdKk@g{xwJ-;*HEW&3t`l{5{l!L76OfOk|P8OFo4ScC`_ePa+)BLr*E|%DD zUctW^sbYbi8kJ~XU6k)l`d5Lw{A2Uzp2kFHtE%=q%)F1v+v*T;tBaC~woaw{H}W6D{Y z>-t6*QP20{K!cMedP`t8|e9PcsMpOIT4CWTSKAnuqCU+vq;EDU<6&W_Vg*-Fc0KPNz^9U=2g%t?^2 WPG=;LN$Ndh=Ay-m1o1Bwc>fRCu)Dkf diff --git a/contrib/msoffice/src/com/sun/jna/platform/win32/COM/office/MSOfficeDemo.java b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/office/MSOfficeDemo.java index 49967d4374..f4d6658cbd 100644 --- a/contrib/msoffice/src/com/sun/jna/platform/win32/COM/office/MSOfficeDemo.java +++ b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/office/MSOfficeDemo.java @@ -18,8 +18,8 @@ public static void main(String[] args) { + File.separator; public MSOfficeDemo() { - this.testMSWord(); - // this.testMSExcel(); + //this.testMSWord(); + this.testMSExcel(); } public void testMSWord() { diff --git a/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/MSOfficeExcelDemo.java b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/MSOfficeExcelDemo.java new file mode 100644 index 0000000000..a7a49b7d06 --- /dev/null +++ b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/MSOfficeExcelDemo.java @@ -0,0 +1,100 @@ +/* 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.office; + +import java.io.File; + +import com.sun.jna.platform.win32.COM.office.MSExcel; +import com.sun.jna.platform.win32.COM.util.AbstractComEventCallbackListener; +import com.sun.jna.platform.win32.COM.util.Factory; +import com.sun.jna.platform.win32.COM.util.office.excel.ComExcel_Application; +import com.sun.jna.platform.win32.COM.util.office.excel.ComIAppEvents; +import com.sun.jna.platform.win32.COM.util.office.excel.ComIApplication; +import com.sun.jna.platform.win32.COM.util.office.excel.ComIRange; +import com.sun.jna.platform.win32.COM.util.office.excel.ComIWorksheet; +import com.sun.jna.platform.win32.COM.util.office.word.ComWord_Application; + +public class MSOfficeExcelDemo { + + /** + * @param args + */ + public static void main(String[] args) { + new MSOfficeExcelDemo(); + } + + private String currentWorkingDir = new File("").getAbsolutePath() + File.separator; + + public MSOfficeExcelDemo() { + this.testMSExcel(); + } + + public void testMSExcel() { + ComExcel_Application excelObject = null; + ComIApplication msExcel = null; + Factory factory = null; + try { + factory = new Factory(); + excelObject = factory.createObject(ComExcel_Application.class); + msExcel = excelObject.queryInterface(ComIApplication.class); + System.out.println("MSExcel version: " + msExcel.getVersion()); + msExcel.setVisible(true); + // msExcel.newExcelBook(); + msExcel.getWorkbooks().Open(currentWorkingDir + "jnatest.xls"); + msExcel.getActiveSheet().getRange("A1").setValue("Hello from JNA!"); + // wait 1sec. before closing + Thread.currentThread().sleep(1000); +// // close and save the active sheet +// msExcel.getActiveWorkbook().Close(true); +// msExcel.setVisible(true); +// // msExcel.newExcelBook(); +// msExcel.getWorkbooks().Open(currentWorkingDir + "jnatest.xls"); +// msExcel.getActiveSheet().getRange("A2").setValue("Hello again from JNA!"); + + class Listener extends AbstractComEventCallbackListener implements ComIAppEvents { + boolean SheetSelectionChange_called; + + @Override + public void errorReceivingCallbackEvent(String message, Exception exception) { + } + + @Override + public void SheetSelectionChange(ComIWorksheet sheet, ComIRange target) { + SheetSelectionChange_called = true; + } + + }; + Listener listener = new Listener(); + msExcel.advise(ComIAppEvents.class, listener); +// +// msExcel.getActiveSheet().getRange("A5").Activate(); +// +// Thread.currentThread().sleep(500); + + // close and save the active sheet + msExcel.getActiveWorkbook().Close(true); + + msExcel.Quit(); + msExcel = null; + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (null != msExcel) { + msExcel.Quit(); + } + if (null != factory) { + factory.disposeAll(); + } + } + } +} diff --git a/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/MSOfficeWordDemo.java b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/MSOfficeWordDemo.java new file mode 100644 index 0000000000..f03467993f --- /dev/null +++ b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/MSOfficeWordDemo.java @@ -0,0 +1,109 @@ +/* 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.office; + +import java.io.File; + +import com.sun.jna.platform.win32.COM.COMException; +import com.sun.jna.platform.win32.COM.util.Factory; +import com.sun.jna.platform.win32.COM.util.office.word.ComIApplication; +import com.sun.jna.platform.win32.COM.util.office.word.ComWord_Application; +import com.sun.jna.platform.win32.COM.util.office.word.WdOriginalFormat; +import com.sun.jna.platform.win32.COM.util.office.word.WdSaveFormat; + +public class MSOfficeWordDemo { + + /** + * @param args + */ + public static void main(String[] args) { + new MSOfficeWordDemo(); + } + + private String currentWorkingDir = new File("").getAbsolutePath() + File.separator; + + public MSOfficeWordDemo() { + this.testMSWord(); + } + + public void testMSWord() { + ComWord_Application msWordObject = null; + ComIApplication msWord = null; + Factory factory = null; + try { + String tempDir = System.getProperty("java.io.tmpdir"); + System.out.println("Files in temp dir: "+tempDir); + + factory = new Factory(); + msWordObject = factory.createObject(ComWord_Application.class); + msWord = msWordObject.queryInterface(ComIApplication.class); + + System.out.println("MSWord version: " + msWord.getVersion()); + + msWord.setVisible(true); + // msWord.newDocument(); + msWord.getDocuments().Open(currentWorkingDir + "jnatest.doc"); + msWord.getSelection().TypeText("Hello from JNA! \n\n"); + // wait 10sec. before closing + Thread.sleep(1000); + // save in different formats + // pdf format is only supported in MSWord 2007 and above + msWord.getActiveDocument().SaveAs(tempDir+"\\jnatestSaveAs.doc", WdSaveFormat.wdFormatDocument); + msWord.getActiveDocument().SaveAs(tempDir+"\\jnatestSaveAs.pdf", WdSaveFormat.wdFormatPDF); + msWord.getActiveDocument().SaveAs(tempDir+"\\jnatestSaveAs.rtf", WdSaveFormat.wdFormatRTF); + msWord.getActiveDocument().SaveAs(tempDir+"\\jnatestSaveAs.html", WdSaveFormat.wdFormatHTML); + // close and save the document + msWord.getActiveDocument().Close(false); + msWord.getDocuments().Add(); + // msWord.openDocument(currentWorkingDir + "jnatest.doc", true); + msWord.getSelection() + .TypeText( + "Hello from JNA! \n Please notice that JNA can control MS Word via the new COM interface! \nHere we are creating a new word document and we save it to the 'TEMP' directory!"); + // save with no user prompt + msWord.getActiveDocument().SaveAs(tempDir+"\\jnatestNewDoc1.docx", WdSaveFormat.wdFormatDocumentDefault); + msWord.getActiveDocument().SaveAs(tempDir+"\\jnatestNewDoc2.docx", WdSaveFormat.wdFormatDocumentDefault); + msWord.getActiveDocument().SaveAs(tempDir+"\\jnatestNewDoc3.docx", WdSaveFormat.wdFormatDocumentDefault); + // close and save the document + msWord.getActiveDocument().Close(false); + // open 3 documents + msWord.getDocuments().Open(tempDir+"\\jnatestNewDoc1.docx"); + msWord.getSelection().TypeText("Hello some changes from JNA!\n"); + msWord.getDocuments().Open(tempDir+"\\jnatestNewDoc2.docx"); + msWord.getSelection().TypeText("Hello some changes from JNA!\n"); + msWord.getDocuments().Open(tempDir+"\\jnatestNewDoc3.docx"); + msWord.getSelection().TypeText("Hello some changes from JNA!\n"); + // save the document and prompt the user + msWord.getDocuments().Save(false, WdOriginalFormat.wdPromptUser); + // wait then close word + msWord.Quit(); + msWord = null; + } catch (InterruptedException ie) { + ie.printStackTrace(); + } catch (COMException e) { + if (e.getExcepInfo() != null) { + System.out.println("bstrSource: " + e.getExcepInfo().bstrSource); + System.out.println("bstrDescription: " + e.getExcepInfo().bstrDescription); + } + + // print stack trace + e.printStackTrace(); + } finally { + if (msWord != null) { + msWord.Quit(); + } + if (null != factory) { + factory.getComThread().terminate(500); + } + } + } +} diff --git a/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComExcel_Application.java b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComExcel_Application.java new file mode 100644 index 0000000000..07cc479b48 --- /dev/null +++ b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComExcel_Application.java @@ -0,0 +1,10 @@ +package com.sun.jna.platform.win32.COM.util.office.excel; + +import com.sun.jna.platform.win32.COM.util.IUnknown; +import com.sun.jna.platform.win32.COM.util.annotation.ComMethod; +import com.sun.jna.platform.win32.COM.util.annotation.ComObject; + +@ComObject(progId="Excel.Application") +public interface ComExcel_Application extends IUnknown { + +} diff --git a/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIAppEvents.java b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIAppEvents.java new file mode 100644 index 0000000000..381abef705 --- /dev/null +++ b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIAppEvents.java @@ -0,0 +1,12 @@ +package com.sun.jna.platform.win32.COM.util.office.excel; + +import com.sun.jna.platform.win32.COM.util.annotation.ComEventCallback; +import com.sun.jna.platform.win32.COM.util.annotation.ComInterface; + +@ComInterface(iid="{00024413-0000-0000-C000-000000000046}") +public interface ComIAppEvents { + + @ComEventCallback(dispid=1558) + public void SheetSelectionChange(ComIWorksheet sheet, ComIRange target); + +} diff --git a/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIApplication.java b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIApplication.java new file mode 100644 index 0000000000..11f7cec543 --- /dev/null +++ b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIApplication.java @@ -0,0 +1,32 @@ +package com.sun.jna.platform.win32.COM.util.office.excel; + +import com.sun.jna.platform.win32.COM.util.IConnectionPoint; +import com.sun.jna.platform.win32.COM.util.IUnknown; +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.ComProperty; + +@ComInterface(iid="{000208D5-0000-0000-C000-000000000046}") +public interface ComIApplication extends IUnknown, IConnectionPoint { + + @ComProperty + String getVersion(); + + @ComProperty + boolean getVisible(); + + @ComProperty + void setVisible(boolean value); + + @ComProperty + ComIWorkbooks getWorkbooks(); + + @ComProperty + ComIWorksheet getActiveSheet(); + + @ComProperty + ComIWorkbook getActiveWorkbook(); + + @ComMethod + void Quit(); +} diff --git a/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIRange.java b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIRange.java new file mode 100644 index 0000000000..4d79f20f44 --- /dev/null +++ b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIRange.java @@ -0,0 +1,25 @@ +package com.sun.jna.platform.win32.COM.util.office.excel; + +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.ComProperty; + +@ComInterface(iid = "{00020846-0000-0000-C000-000000000046}") +public interface ComIRange { + + @ComProperty + ComIApplication getApplication(); + + @ComProperty + String getText(); + + @ComMethod + void Select(); + + @ComProperty + void setValue(String value); + + @ComMethod + void Activate(); + +} diff --git a/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIWorkbook.java b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIWorkbook.java new file mode 100644 index 0000000000..375a684510 --- /dev/null +++ b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIWorkbook.java @@ -0,0 +1,13 @@ +package com.sun.jna.platform.win32.COM.util.office.excel; + +import com.sun.jna.platform.win32.COM.util.annotation.ComInterface; +import com.sun.jna.platform.win32.COM.util.annotation.ComMethod; + +@ComInterface(iid="{0002096B-0000-0000-C000-000000000046}") +public interface ComIWorkbook { + + @ComMethod + void Close(boolean saveChanges); + + +} diff --git a/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIWorkbooks.java b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIWorkbooks.java new file mode 100644 index 0000000000..c9174c23c2 --- /dev/null +++ b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIWorkbooks.java @@ -0,0 +1,19 @@ +package com.sun.jna.platform.win32.COM.util.office.excel; + +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.ComProperty; + +@ComInterface(iid = "{000208DB-0000-0000-C000-000000000046}") +public interface ComIWorkbooks { + + @ComProperty + long getCount(); + + @ComMethod + ComIWorkbook Item(long index); + + @ComMethod + ComIWorkbook Open(Object FileName); + +} diff --git a/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIWorksheet.java b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIWorksheet.java new file mode 100644 index 0000000000..2687f80d27 --- /dev/null +++ b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/excel/ComIWorksheet.java @@ -0,0 +1,19 @@ +package com.sun.jna.platform.win32.COM.util.office.excel; + +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.ComProperty; + +@ComInterface(iid="{000208D8-0000-0000-C000-000000000046}") +public interface ComIWorksheet { + + @ComProperty + String getName(); + + @ComProperty + ComIRange getRange(String cell1); + + @ComProperty + ComIApplication getApplication(); + +} diff --git a/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/ComIApplication.java b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/ComIApplication.java new file mode 100644 index 0000000000..10a18b21e8 --- /dev/null +++ b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/ComIApplication.java @@ -0,0 +1,43 @@ +/* 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.office.word; + +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.ComProperty; + +@ComInterface(iid="{00020970-0000-0000-C000-000000000046}") +public interface ComIApplication { + + @ComProperty + String getVersion(); + + @ComProperty + boolean getVisible(); + + @ComProperty + void setVisible(boolean value); + + @ComProperty + ComIDocuments getDocuments(); + + @ComProperty + ComISelection getSelection(); + + @ComProperty + ComIDocument getActiveDocument(); + + @ComMethod + void Quit(); + +} diff --git a/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/ComIDocument.java b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/ComIDocument.java new file mode 100644 index 0000000000..e370130b8e --- /dev/null +++ b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/ComIDocument.java @@ -0,0 +1,25 @@ +/* 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.office.word; + +import com.sun.jna.platform.win32.COM.util.annotation.ComMethod; + +public interface ComIDocument { + + @ComMethod + void SaveAs(String string, WdSaveFormat wdFormatDocument); + + @ComMethod + void Close(boolean saveChanges); + +} diff --git a/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/ComIDocuments.java b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/ComIDocuments.java new file mode 100644 index 0000000000..2096de5af5 --- /dev/null +++ b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/ComIDocuments.java @@ -0,0 +1,28 @@ +/* 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.office.word; + +import com.sun.jna.platform.win32.COM.util.annotation.ComMethod; + +public interface ComIDocuments { + + @ComMethod + ComIDocument Open(String fileName); + + @ComMethod + ComIDocument Add(); + + @ComMethod + void Save(boolean noPrompt, WdOriginalFormat originalFormat); + +} diff --git a/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/ComISelection.java b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/ComISelection.java new file mode 100644 index 0000000000..53d59b4f90 --- /dev/null +++ b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/ComISelection.java @@ -0,0 +1,24 @@ +/* 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.office.word; + +import com.sun.jna.platform.win32.COM.util.annotation.ComInterface; +import com.sun.jna.platform.win32.COM.util.annotation.ComMethod; + +@ComInterface +public interface ComISelection { + + @ComMethod + void TypeText(String text); + +} diff --git a/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/ComWord_Application.java b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/ComWord_Application.java new file mode 100644 index 0000000000..af7a26e2d9 --- /dev/null +++ b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/ComWord_Application.java @@ -0,0 +1,21 @@ +/* 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.office.word; + +import com.sun.jna.platform.win32.COM.util.IUnknown; +import com.sun.jna.platform.win32.COM.util.annotation.ComObject; + +@ComObject(progId="Word.Application") +public interface ComWord_Application extends IUnknown { + +} diff --git a/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/WdOriginalFormat.java b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/WdOriginalFormat.java new file mode 100644 index 0000000000..b7f4bbee46 --- /dev/null +++ b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/WdOriginalFormat.java @@ -0,0 +1,29 @@ +/* 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.office.word; + +import com.sun.jna.platform.win32.COM.util.IComEnum; + +public enum WdOriginalFormat implements IComEnum { + wdOriginalDocumentFormat(1), // Original document format. + wdPromptUser(2), // Prompt user to select a document format. + wdWordDocument(0); // Microsoft Word document format. + + private WdOriginalFormat(long value) { + this.value = value; + } + private long value; + public long getValue() { + return this.value; + } +} diff --git a/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/WdSaveFormat.java b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/WdSaveFormat.java new file mode 100644 index 0000000000..7b7fce9fb1 --- /dev/null +++ b/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/word/WdSaveFormat.java @@ -0,0 +1,54 @@ +/* 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.office.word; + +import com.sun.jna.platform.win32.COM.util.IComEnum; + +public enum WdSaveFormat implements IComEnum { + wdFormatDocument(0), // Microsoft Office Word 97 - 2003 binary file format. + wdFormatDOSText(4), // Microsoft DOS text format. + wdFormatDOSTextLineBreaks(5), // Microsoft DOS text with line breaks preserved. + wdFormatEncodedText(7), // Encoded text format. + wdFormatFilteredHTML(10), // Filtered HTML format. + wdFormatFlatXML(19), // Open XML file format saved as a single XML file. + wdFormatFlatXMLMacroEnabled(20), // Open XML file format with macros enabled saved as a single XML file. + wdFormatFlatXMLTemplate(21), // Open XML template format saved as a XML single file. + wdFormatFlatXMLTemplateMacroEnabled(22), // Open XML template format with macros enabled saved as a single XML file. + wdFormatOpenDocumentText(23), // OpenDocument Text format. + wdFormatHTML(8), // Standard HTML format. + wdFormatRTF(6), // Rich text format (RTF). + wdFormatStrictOpenXMLDocument(24), // Strict Open XML document format. + wdFormatTemplate(1), // Word template format. + wdFormatText(2), // Microsoft Windows text format. + wdFormatTextLineBreaks(3), //Windows text format with line breaks preserved. + wdFormatUnicodeText( 7), //Unicode text format. + wdFormatWebArchive(9), //Web archive format. + wdFormatXML(11), //Extensible Markup Language (XML) format. + wdFormatDocument97( 0), // Microsoft Word 97 document format. + wdFormatDocumentDefault(16), // Word default document file format. For Word 2010, this is the DOCX format. + wdFormatPDF( 17), //PDF format. + wdFormatTemplate97( 1), // Word 97 template format. + wdFormatXMLDocument( 12), //XML document format. + wdFormatXMLDocumentMacroEnabled(13), //XML document format with macros enabled. + wdFormatXMLTemplate(14), //XML template format. + wdFormatXMLTemplateMacroEnabled(15), //XML template format with macros enabled. + wdFormatXPS(18); + + private WdSaveFormat(long value) { + this.value = value; + } + private long value; + public long getValue() { + return this.value; + } +} diff --git a/contrib/platform/.classpath b/contrib/platform/.classpath index 91a28a2ee6..77917d7b3f 100644 --- a/contrib/platform/.classpath +++ b/contrib/platform/.classpath @@ -2,9 +2,8 @@ - - - + + diff --git a/contrib/platform/.project b/contrib/platform/.project index eb21a1889c..2cad830e2f 100644 --- a/contrib/platform/.project +++ b/contrib/platform/.project @@ -1,6 +1,6 @@ - platform + com.sun.jna.platform 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 9bdfcace8d..3a219cf620 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.REFIID; import com.sun.jna.platform.win32.Kernel32; import com.sun.jna.platform.win32.OaIdl; import com.sun.jna.platform.win32.OaIdl.DISPID; @@ -26,6 +27,7 @@ import com.sun.jna.platform.win32.Variant.VARIANT; import com.sun.jna.platform.win32.Variant.VariantArg; import com.sun.jna.platform.win32.WTypes; +import com.sun.jna.platform.win32.WinDef; import com.sun.jna.platform.win32.WinDef.LCID; import com.sun.jna.platform.win32.WinDef.UINT; import com.sun.jna.platform.win32.WinNT.HRESULT; @@ -84,7 +86,7 @@ public COMBindingBaseObject(CLSID clsid, boolean useActiveInstance, if (COMUtils.SUCCEEDED(hr)) { this.iUnknown = new Unknown(this.pUnknown.getValue()); - hr = iUnknown.QueryInterface(IDispatch.IID_IDISPATCH, + hr = iUnknown.QueryInterface(new REFIID.ByValue( IDispatch.IID_IDISPATCH), this.pDispatch); } else { hr = Ole32.INSTANCE.CoCreateInstance(clsid, null, dwClsContext, @@ -127,7 +129,7 @@ public COMBindingBaseObject(String progId, boolean useActiveInstance, if (COMUtils.SUCCEEDED(hr)) { this.iUnknown = new Unknown(this.pUnknown.getValue()); - hr = iUnknown.QueryInterface(IDispatch.IID_IDISPATCH, + hr = iUnknown.QueryInterface(new REFIID.ByValue(IDispatch.IID_IDISPATCH), this.pDispatch); } else { hr = Ole32.INSTANCE.CoCreateInstance(clsid, null, dwClsContext, @@ -209,7 +211,7 @@ protected HRESULT oleMethod(int nType, VARIANT.ByReference pvResult, DISPIDByReference pdispID = new DISPIDByReference(); // Get DISPID for name passed... - HRESULT hr = pDisp.GetIDsOfNames(Guid.IID_NULL, ptName, 1, + HRESULT hr = pDisp.GetIDsOfNames(new REFIID.ByValue(Guid.IID_NULL), ptName, 1, LOCALE_USER_DEFAULT, pdispID); COMUtils.checkRC(hr); @@ -228,7 +230,7 @@ protected HRESULT oleMethod(int nType, VARIANT.ByReference pvResult, // variable declaration int _argsLen = 0; VARIANT[] _args = null; - DISPPARAMS dp = new DISPPARAMS(); + DISPPARAMS.ByReference dp = new DISPPARAMS.ByReference(); EXCEPINFO.ByReference pExcepInfo = new EXCEPINFO.ByReference(); IntByReference puArgErr = new IntByReference(); @@ -261,8 +263,8 @@ protected HRESULT oleMethod(int nType, VARIANT.ByReference pvResult, } // Make the call! - HRESULT hr = pDisp.Invoke(dispId, Guid.IID_NULL, LOCALE_SYSTEM_DEFAULT, - new DISPID(nType), dp, pvResult, pExcepInfo, puArgErr); + HRESULT hr = pDisp.Invoke(dispId, new REFIID.ByValue(Guid.IID_NULL), LOCALE_SYSTEM_DEFAULT, + new WinDef.WORD(nType), dp, pvResult, pExcepInfo, puArgErr); COMUtils.checkRC(hr, pExcepInfo, puArgErr); return hr; diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/COMEarlyBindingObject.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/COMEarlyBindingObject.java index 07220e0d4a..34a23b50e8 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/COM/COMEarlyBindingObject.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/COMEarlyBindingObject.java @@ -15,6 +15,7 @@ import com.sun.jna.WString; import com.sun.jna.platform.win32.Guid.CLSID; import com.sun.jna.platform.win32.Guid.IID; +import com.sun.jna.platform.win32.Guid.REFIID; import com.sun.jna.platform.win32.OaIdl.DISPID; import com.sun.jna.platform.win32.OaIdl.DISPIDByReference; import com.sun.jna.platform.win32.OaIdl.EXCEPINFO; @@ -25,6 +26,7 @@ import com.sun.jna.platform.win32.WinDef.LCID; import com.sun.jna.platform.win32.WinDef.UINT; import com.sun.jna.platform.win32.WinDef.UINTByReference; +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; @@ -57,7 +59,7 @@ protected void setProperty(DISPID dispId, boolean value) { } @Override - public HRESULT QueryInterface(IID riid, PointerByReference ppvObject) { + public HRESULT QueryInterface(REFIID.ByValue riid, PointerByReference ppvObject) { return this.getIDispatch().QueryInterface(riid, ppvObject); } @@ -83,16 +85,16 @@ public HRESULT GetTypeInfo(UINT iTInfo, LCID lcid, } @Override - public HRESULT GetIDsOfNames(IID riid, WString[] rgszNames, int cNames, + public HRESULT GetIDsOfNames(REFIID.ByValue riid, WString[] rgszNames, int cNames, LCID lcid, DISPIDByReference rgDispId) { return this.getIDispatch().GetIDsOfNames(riid, rgszNames, cNames, lcid, rgDispId); } @Override - public HRESULT Invoke(DISPID dispIdMember, IID riid, LCID lcid, - DISPID wFlags, DISPPARAMS pDispParams, ByReference pVarResult, - EXCEPINFO.ByReference pExcepInfo, + public HRESULT Invoke(DISPID dispIdMember, REFIID.ByValue riid, LCID lcid, + WORD wFlags, DISPPARAMS.ByReference pDispParams, + VARIANT.ByReference pVarResult, EXCEPINFO.ByReference pExcepInfo, IntByReference puArgErr) { return this.getIDispatch().Invoke(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/COMException.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/COMException.java index eefc7d6c26..8431a63733 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/COM/COMException.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/COMException.java @@ -72,7 +72,7 @@ public COMException(String message) { */ public COMException(String message, EXCEPINFO pExcepInfo, IntByReference puArgErr) { - super(message + " (puArgErr=" + puArgErr.getValue() + ")"); + super(message + " (puArgErr=" + (null==puArgErr?"":puArgErr.getValue()) + ")"); this.pExcepInfo = pExcepInfo; this.puArgErr = puArgErr; } diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/ConnectionPoint.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/ConnectionPoint.java new file mode 100644 index 0000000000..fb5132f134 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/ConnectionPoint.java @@ -0,0 +1,56 @@ +/* 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; + +import com.sun.jna.Pointer; +import com.sun.jna.platform.win32.Guid.IID; +import com.sun.jna.platform.win32.WinDef.DWORD; +import com.sun.jna.platform.win32.WinDef.DWORDByReference; +import com.sun.jna.platform.win32.WinNT.HRESULT; + +public class ConnectionPoint extends Unknown implements IConnectionPoint { + + public ConnectionPoint(Pointer pointer) { + super(pointer); + } + + @Override + public HRESULT GetConnectionInterface(IID iid) { + final int vTableId = 3; + return (HRESULT) this._invokeNativeObject(vTableId, new Object[] { this.getPointer(), iid }, HRESULT.class); + } + + void GetConnectionPointContainer() { + final int vTableId = 4; + + } + + @Override + public HRESULT Advise(IUnknownCallback pUnkSink, DWORDByReference pdwCookie) { + final int vTableId = 5; + + return (HRESULT) this._invokeNativeObject(vTableId, new Object[] { this.getPointer(), pUnkSink.getPointer(), + pdwCookie }, HRESULT.class); + } + + @Override + public HRESULT Unadvise(DWORD dwCookie) { + final int vTableId = 6; + + return (HRESULT) this._invokeNativeObject(vTableId, new Object[] { this.getPointer(), dwCookie }, HRESULT.class); + } + + void EnumConnections() { + final int vTableId = 7; + } +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/ConnectionPointContainer.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/ConnectionPointContainer.java new file mode 100644 index 0000000000..481905c1fb --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/ConnectionPointContainer.java @@ -0,0 +1,50 @@ +/* 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; + +import com.sun.jna.Pointer; +import com.sun.jna.platform.win32.Guid.REFIID; +import com.sun.jna.platform.win32.WinNT.HRESULT; +import com.sun.jna.ptr.PointerByReference; + +public class ConnectionPointContainer extends Unknown implements + IConnectionPointContainer { + + public ConnectionPointContainer(Pointer pointer) { + super(pointer); + } + + public HRESULT EnumConnectionPoints() { + // I think the magic number here is worked out by counting the number of + // methods in the full interface, as this inherits IUnknown, which + // has 3 methods, we start here at 3 (0 indexed). + final int vTableId = 3; + + +// return (HRESULT) this._invokeNativeObject(3, +// new Object[] { this.getPointer(), riid, ppCP }, HRESULT.class); + throw new UnsupportedOperationException(); + } + + @Override + public HRESULT FindConnectionPoint(REFIID riid, PointerByReference ppCP) { + // I think the magic number here is worked out by counting the number of + // methods in the full interface, + // this as this inherits IUnknown, which has 3 methods, we have here 4. + // second in this class + final int vTableId = 4; + return (HRESULT) this._invokeNativeObject(vTableId, + new Object[] { this.getPointer(), riid, ppCP }, HRESULT.class); + } + +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/Dispatch.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/Dispatch.java index 71fd3d546f..c5f6577c42 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/COM/Dispatch.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/Dispatch.java @@ -16,6 +16,7 @@ import com.sun.jna.Structure; import com.sun.jna.WString; import com.sun.jna.platform.win32.Guid.IID; +import com.sun.jna.platform.win32.Guid.REFIID; import com.sun.jna.platform.win32.OaIdl.DISPID; import com.sun.jna.platform.win32.OaIdl.DISPIDByReference; import com.sun.jna.platform.win32.OaIdl.EXCEPINFO; @@ -24,6 +25,7 @@ import com.sun.jna.platform.win32.WinDef.LCID; import com.sun.jna.platform.win32.WinDef.UINT; import com.sun.jna.platform.win32.WinDef.UINTByReference; +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; @@ -97,7 +99,7 @@ public HRESULT GetTypeInfo(UINT iTInfo, LCID lcid, * the rg disp id * @return the hresult */ - public HRESULT GetIDsOfNames(IID riid, WString[] rgszNames, int cNames, + public HRESULT GetIDsOfNames(REFIID.ByValue riid, WString[] rgszNames, int cNames, LCID lcid, DISPIDByReference rgDispId) { return (HRESULT) this._invokeNativeObject(5, new Object[] { this.getPointer(), riid, rgszNames, cNames, @@ -125,8 +127,8 @@ public HRESULT GetIDsOfNames(IID riid, WString[] rgszNames, int cNames, * the pu arg err * @return the hresult */ - public HRESULT Invoke(DISPID dispIdMember, IID riid, LCID lcid, - DISPID wFlags, DISPPARAMS pDispParams, + public HRESULT Invoke(DISPID dispIdMember, REFIID.ByValue riid, LCID lcid, + WORD wFlags, DISPPARAMS.ByReference pDispParams, VARIANT.ByReference pVarResult, EXCEPINFO.ByReference pExcepInfo, IntByReference puArgErr) { return (HRESULT) this diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/DispatchListener.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/DispatchListener.java new file mode 100644 index 0000000000..0043ab114f --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/DispatchListener.java @@ -0,0 +1,104 @@ +/* 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; + +import java.util.Arrays; +import java.util.List; + +import com.sun.jna.CallbackThreadInitializer; +import com.sun.jna.Native; +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import com.sun.jna.WString; +import com.sun.jna.platform.win32.Guid.REFIID; +import com.sun.jna.platform.win32.OaIdl.DISPID; +import com.sun.jna.platform.win32.OaIdl.DISPIDByReference; +import com.sun.jna.platform.win32.OaIdl.EXCEPINFO; +import com.sun.jna.platform.win32.OleAuto.DISPPARAMS; +import com.sun.jna.platform.win32.Variant.VARIANT; +import com.sun.jna.platform.win32.WinDef.LCID; +import com.sun.jna.platform.win32.WinDef.UINT; +import com.sun.jna.platform.win32.WinDef.UINTByReference; +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; + +public class DispatchListener extends Structure { + public DispatchListener(IDispatchCallback callback) { + this.vtbl = this.constructVTable(); + this.initVTable(callback); + super.write(); + } + public DispatchVTable.ByReference vtbl; + + @Override + protected List getFieldOrder() { + return Arrays.asList(new String[] { "vtbl" }); + } + + protected DispatchVTable.ByReference constructVTable() { + return new DispatchVTable.ByReference(); + } + + protected void initVTable(final IDispatchCallback callback) { + this.vtbl.QueryInterfaceCallback = new DispatchVTable.QueryInterfaceCallback() { + @Override + public HRESULT invoke(Pointer thisPointer, REFIID.ByValue refid, PointerByReference ppvObject) { + return callback.QueryInterface(refid, ppvObject); + } + }; + this.vtbl.AddRefCallback = new DispatchVTable.AddRefCallback() { + @Override + public int invoke(Pointer thisPointer) { + return callback.AddRef(); + } + }; + this.vtbl.ReleaseCallback = new DispatchVTable.ReleaseCallback() { + @Override + public int invoke(Pointer thisPointer) { + return callback.Release(); + } + }; + this.vtbl.GetTypeInfoCountCallback = new DispatchVTable.GetTypeInfoCountCallback() { + @Override + public HRESULT invoke(Pointer thisPointer, UINTByReference pctinfo) { + return callback.GetTypeInfoCount(pctinfo); + } + }; + this.vtbl.GetTypeInfoCallback = new DispatchVTable.GetTypeInfoCallback() { + @Override + public HRESULT invoke(Pointer thisPointer, UINT iTInfo, LCID lcid, PointerByReference ppTInfo) { + return callback.GetTypeInfo(iTInfo, lcid, ppTInfo); + } + }; + this.vtbl.GetIDsOfNamesCallback = new DispatchVTable.GetIDsOfNamesCallback() { + @Override + public HRESULT invoke(Pointer thisPointer, REFIID.ByValue riid, WString[] rgszNames, int cNames, LCID lcid, + DISPIDByReference rgDispId) { + return callback.GetIDsOfNames(riid, rgszNames, cNames, lcid, rgDispId); + } + }; + this.vtbl.InvokeCallback = new DispatchVTable.InvokeCallback() { + @Override + public HRESULT invoke(Pointer thisPointer, DISPID dispIdMember, REFIID.ByValue riid, LCID lcid, WORD wFlags, + DISPPARAMS.ByReference pDispParams, VARIANT.ByReference pVarResult, EXCEPINFO.ByReference pExcepInfo, + IntByReference puArgErr) { + + return callback.Invoke(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); + } + }; + + } + +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/DispatchVTable.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/DispatchVTable.java new file mode 100644 index 0000000000..16fb47fd51 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/DispatchVTable.java @@ -0,0 +1,89 @@ +/* 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; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import com.sun.jna.WString; +import com.sun.jna.platform.win32.COM.UnknownVTable.AddRefCallback; +import com.sun.jna.platform.win32.COM.UnknownVTable.QueryInterfaceCallback; +import com.sun.jna.platform.win32.COM.UnknownVTable.ReleaseCallback; +import com.sun.jna.platform.win32.Guid.REFIID; +import com.sun.jna.platform.win32.OaIdl.DISPID; +import com.sun.jna.platform.win32.OaIdl.DISPIDByReference; +import com.sun.jna.platform.win32.OaIdl.EXCEPINFO; +import com.sun.jna.platform.win32.OleAuto.DISPPARAMS; +import com.sun.jna.platform.win32.Variant.VARIANT; +import com.sun.jna.platform.win32.WinDef.LCID; +import com.sun.jna.platform.win32.WinDef.UINT; +import com.sun.jna.platform.win32.WinDef.UINTByReference; +import com.sun.jna.platform.win32.WinDef.WORD; +import com.sun.jna.platform.win32.WinNT; +import com.sun.jna.ptr.IntByReference; +import com.sun.jna.ptr.PointerByReference; +import com.sun.jna.win32.DLLCallback; +import com.sun.jna.win32.StdCallLibrary; + +public class DispatchVTable extends Structure { + public static class ByReference extends DispatchVTable implements Structure.ByReference { + } + + public QueryInterfaceCallback QueryInterfaceCallback; + public AddRefCallback AddRefCallback; + public ReleaseCallback ReleaseCallback; + public GetTypeInfoCountCallback GetTypeInfoCountCallback; + public GetTypeInfoCallback GetTypeInfoCallback; + public GetIDsOfNamesCallback GetIDsOfNamesCallback; + public InvokeCallback InvokeCallback; + + @Override + protected List getFieldOrder() { + return Arrays.asList(new String[] { "QueryInterfaceCallback", "AddRefCallback", "ReleaseCallback","GetTypeInfoCountCallback", "GetTypeInfoCallback", + "GetIDsOfNamesCallback", "InvokeCallback" }); + } + + public static interface QueryInterfaceCallback extends StdCallLibrary.StdCallCallback { + WinNT.HRESULT invoke(Pointer thisPointer, REFIID.ByValue refid, PointerByReference ppvObject); + } + + public static interface AddRefCallback extends StdCallLibrary.StdCallCallback { + int invoke(Pointer thisPointer); + } + + public static interface ReleaseCallback extends StdCallLibrary.StdCallCallback { + int invoke(Pointer thisPointer); + } + + public static interface GetTypeInfoCountCallback extends StdCallLibrary.StdCallCallback { + WinNT.HRESULT invoke(Pointer thisPointer, UINTByReference pctinfo); + } + + public static interface GetTypeInfoCallback extends StdCallLibrary.StdCallCallback { + WinNT.HRESULT invoke(Pointer thisPointer, UINT iTInfo, LCID lcid, PointerByReference ppTInfo); + } + + public static interface GetIDsOfNamesCallback extends StdCallLibrary.StdCallCallback { + WinNT.HRESULT invoke(Pointer thisPointer, REFIID.ByValue riid, WString[] rgszNames, int cNames, LCID lcid, + DISPIDByReference rgDispId); + } + + public static interface InvokeCallback extends StdCallLibrary.StdCallCallback { + WinNT.HRESULT invoke(Pointer thisPointer, DISPID dispIdMember, REFIID.ByValue riid, LCID lcid, WORD wFlags, + DISPPARAMS.ByReference pDispParams, VARIANT.ByReference pVarResult, EXCEPINFO.ByReference pExcepInfo, + IntByReference puArgErr); + } +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/EnumMoniker.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/EnumMoniker.java new file mode 100644 index 0000000000..38127674ea --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/EnumMoniker.java @@ -0,0 +1,71 @@ +/* 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; + +import com.sun.jna.Pointer; +import com.sun.jna.platform.win32.WinNT; +import com.sun.jna.platform.win32.WinDef.ULONG; +import com.sun.jna.platform.win32.WinDef.ULONGByReference; +import com.sun.jna.platform.win32.WinNT.HRESULT; +import com.sun.jna.ptr.PointerByReference; + +public class EnumMoniker extends Unknown implements IEnumMoniker { + + public EnumMoniker(Pointer pointer) { + super(pointer); + } + + // The magic number values for (vTableId) below, are worked out by + // counting the number of methods in the full interface (0 indexed), as this + // inherits IUnknown, which has 3 methods, we start here at 3. + + @Override + public HRESULT Next(ULONG celt, PointerByReference rgelt, ULONGByReference pceltFetched) { + final int vTableId = 3; + + WinNT.HRESULT hr = (WinNT.HRESULT) this._invokeNativeObject(vTableId, new Object[] { this.getPointer(), celt, + rgelt, pceltFetched }, WinNT.HRESULT.class); + + return hr; + } + + @Override + public HRESULT Skip(ULONG celt) { + final int vTableId = 4; + + WinNT.HRESULT hr = (WinNT.HRESULT) this._invokeNativeObject(vTableId, new Object[] { this.getPointer(), celt }, + WinNT.HRESULT.class); + + return hr; + } + + @Override + public HRESULT Reset() { + final int vTableId = 5; + + WinNT.HRESULT hr = (WinNT.HRESULT) this._invokeNativeObject(vTableId, new Object[] { this.getPointer(), }, + WinNT.HRESULT.class); + + return hr; + } + + @Override + public HRESULT Clone(PointerByReference ppenum) { + final int vTableId = 6; + + WinNT.HRESULT hr = (WinNT.HRESULT) this._invokeNativeObject(vTableId, + new Object[] { this.getPointer(), ppenum }, WinNT.HRESULT.class); + + return hr; + } +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/IConnectionPoint.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/IConnectionPoint.java new file mode 100644 index 0000000000..643f741794 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/IConnectionPoint.java @@ -0,0 +1,66 @@ +/* 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; + +import com.sun.jna.platform.win32.Guid.IID; +import com.sun.jna.platform.win32.WinDef.DWORD; +import com.sun.jna.platform.win32.WinDef.DWORDByReference; +import com.sun.jna.platform.win32.WinNT.HRESULT; +import com.sun.jna.platform.win32.WinNT; + +public interface IConnectionPoint extends IUnknown { + final static IID IID_IConnectionPoint = new IID( + "B196B286-BAB4-101A-B69C-00AA00341D07"); + + /** + * + * + * @param iid + * @return + */ + HRESULT GetConnectionInterface(IID iid); + + /** + * + * When Advise is called, the called COM object will callback 'QueryInterface' asking for a number of + * different interfaces, for example: + * - {00000003-0000-0000-C000-000000000046} - IMarshal + * - {00000003-0000-0000-C000-000000000046} + * - {0000001B-0000-0000-C000-000000000046} - IdentityUnmarshal + * - {00000000-0000-0000-C000-000000000046} - IUnknown + * - {00000018-0000-0000-C000-000000000046} - IStdMarshalInfo + * - {00000019-0000-0000-C000-000000000046} - IExternalConnection + * - {4C1E39E1-E3E3-4296-AA86-EC938D896E92} - (some unknown private interface) + * - interface of this ConnectionPoint + * + * + * {@code + * HRESULT Advise( + * [in] IUnknown *pUnkSink, + * [out] DWORD *pdwCookie + * ); + * } + * + * @param pUnkSink + * @param pdwCookie + * @return + */ + WinNT.HRESULT Advise(IUnknownCallback pUnkSink, DWORDByReference pdwCookie); + + /** + * + * @param dwCookie + * @return + */ + HRESULT Unadvise(DWORD dwCookie); +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/IConnectionPointContainer.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/IConnectionPointContainer.java new file mode 100644 index 0000000000..e0e354002d --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/IConnectionPointContainer.java @@ -0,0 +1,35 @@ +/* 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; + +import com.sun.jna.platform.win32.Guid.IID; +import com.sun.jna.platform.win32.Guid.REFIID; +import com.sun.jna.platform.win32.WinNT.HRESULT; +import com.sun.jna.ptr.PointerByReference; + +public interface IConnectionPointContainer extends IUnknown { + public final static IID IID_IConnectionPointContainer = new IID("B196B284-BAB4-101A-B69C-00AA00341D07"); + + /** + * @code{ + * HRESULT FindConnectionPoint( + * [in] REFIID riid, + * [out] IConnectionPoint **ppCP + * ); + * } + * @param riid + * @param ppCP + * @return + */ + public HRESULT FindConnectionPoint( REFIID riid, PointerByReference ppCP ); +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/IDispatch.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/IDispatch.java index 8906ab543e..e4904cb983 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/COM/IDispatch.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/IDispatch.java @@ -14,6 +14,7 @@ import com.sun.jna.WString; import com.sun.jna.platform.win32.Guid.IID; +import com.sun.jna.platform.win32.Guid.REFIID; import com.sun.jna.platform.win32.OaIdl.DISPID; import com.sun.jna.platform.win32.OaIdl.DISPIDByReference; import com.sun.jna.platform.win32.OaIdl.EXCEPINFO; @@ -22,6 +23,7 @@ import com.sun.jna.platform.win32.WinDef.LCID; import com.sun.jna.platform.win32.WinDef.UINT; import com.sun.jna.platform.win32.WinDef.UINTByReference; +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; @@ -45,11 +47,11 @@ public interface IDispatch extends IUnknown { public HRESULT GetTypeInfo(UINT iTInfo, LCID lcid, PointerByReference ppTInfo); - public HRESULT GetIDsOfNames(IID riid, WString[] rgszNames, int cNames, + public HRESULT GetIDsOfNames(REFIID.ByValue riid, WString[] rgszNames, int cNames, LCID lcid, DISPIDByReference rgDispId); - public HRESULT Invoke(DISPID dispIdMember, IID riid, LCID lcid, - DISPID wFlags, DISPPARAMS pDispParams, + public HRESULT Invoke(DISPID dispIdMember, REFIID.ByValue riid, LCID lcid, + WORD wFlags, DISPPARAMS.ByReference pDispParams, VARIANT.ByReference pVarResult, EXCEPINFO.ByReference pExcepInfo, IntByReference puArgErr); } diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/IDispatchCallback.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/IDispatchCallback.java new file mode 100644 index 0000000000..2140cfd295 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/IDispatchCallback.java @@ -0,0 +1,18 @@ +/* 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; + + +public interface IDispatchCallback extends IDispatch, IUnknownCallback { + +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/IEnumMoniker.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/IEnumMoniker.java new file mode 100644 index 0000000000..b3f3618f99 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/IEnumMoniker.java @@ -0,0 +1,94 @@ +/* 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; + +import com.sun.jna.ptr.PointerByReference; +import com.sun.jna.platform.win32.Guid.IID; +import com.sun.jna.platform.win32.WinDef.ULONG; +import com.sun.jna.platform.win32.WinDef.ULONGByReference; +import com.sun.jna.platform.win32.WinNT.HRESULT; + +/** + * Enumerates the components of a moniker or the monikers in a table of monikers. + * + * @see MSDN + * + */ +public interface IEnumMoniker extends IUnknown { + + public final static IID IID = new IID("{00000102-0000-0000-C000-000000000046}"); + + /** + * Creates a new enumerator that contains the same enumeration state as the + * current one. + * + * This method makes it possible to record a particular point in the + * enumeration sequence and then return to that point at a later time. The + * caller must release this new enumerator separately from the first + * enumerator. + * + * {@code + * HRESULT Clone( + * [out] IEnumMoniker **ppenum + * ); + * } + * + * @see MSDN + */ + HRESULT Clone(PointerByReference ppenum); + + /** + * Retrieves the specified number of items in the enumeration sequence. + * + * Note: The caller is responsible for calling Release through each pointer + * enumerated. + * + * {@code + * HRESULT Next( + * [in] ULONG celt, + * [out] IMoniker **rgelt, + * [in, out] ULONG *pceltFetched + * ); + * } + * + * @see MSDN + * + */ + HRESULT Next(ULONG celt, PointerByReference rgelt, ULONGByReference pceltFetched); + + /** + * Resets the enumeration sequence to the beginning. + * + * {@code + * HRESULT Reset(); + * } + * + * @see MSDN + * + */ + HRESULT Reset(); + + /** + * Skips over the specified number of items in the enumeration sequence. + * + * {@code + * HRESULT Skip( + * [in] ULONG celt + * ); + * } + * + * @see MSDN + * + */ + HRESULT Skip(ULONG celt); +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/IMoniker.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/IMoniker.java new file mode 100644 index 0000000000..7535089a1d --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/IMoniker.java @@ -0,0 +1,94 @@ +/* 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; + +import com.sun.jna.Pointer; +import com.sun.jna.platform.win32.WTypes.BSTRByReference; +import com.sun.jna.platform.win32.WTypes.LPSTR; +import com.sun.jna.platform.win32.WinNT.HRESULT; + + +/** + * Enables you to use a moniker object, which contains information that uniquely + * identifies a COM object. + * + * (Unimplemented, placeholder only at present) + * + * @see MSDN + * + */ +public interface IMoniker extends IPersistStream { + + /** + * Binds to the specified object. The binding process involves finding the + * object, putting it into the running state if necessary, and providing the + * caller with a pointer to a specified interface on the identified object. + * + * {@code + * HRESULT BindToObject( + * [in] IBindCtx *pbc, + * [in] IMoniker *pmkToLeft, + * [in] REFIID riidResult, + * [out] void **ppvResult + * ); + * } + * + * @see MSDN + */ + void BindToObject(); + + void BindToStorage(); + + void Reduce(); + + void ComposeWith(); + + void Enum(); + + void IsEqual(); + + void Hash(); + + void IsRunning(); + + void GetTimeOfLastChange(); + + void Inverse(); + + void CommonPrefixWith(); + + /** + * Retrieves the display name for the moniker. + * + * {@code + * HRESULT GetDisplayName( + * [in] IBindCtx *pbc, + * [in] IMoniker *pmkToLeft, + * [out] LPOLESTR *ppszDisplayName + * ); + * + * @see MSDN + * + * } + */ + HRESULT GetDisplayName(Pointer pbc, Pointer pmkToLeft, BSTRByReference ppszDisplayName); + + void ParseDisplayName(); + + void IsSystemMoniker(); + + void RelativePathTo(); +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/IPersist.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/IPersist.java new file mode 100644 index 0000000000..8b60559db5 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/IPersist.java @@ -0,0 +1,40 @@ +/* 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; + +import com.sun.jna.platform.win32.Guid.CLSID; + +/** + * Provides the CLSID of an object that can be stored persistently in the + * system. Allows the object to specify which object handler to use in the + * client process, as it is used in the default implementation of marshaling. + * + * @see MSDN + * + */ +public interface IPersist extends IUnknown { + + /** + * Retrieves the class identifier (CLSID) of the object. + * + * {@code + * HRESULT GetClassID( + * [out] CLSID *pClassID + * ); + * } + * + * MSDN + */ + CLSID GetClassID(); +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/IPersistStream.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/IPersistStream.java new file mode 100644 index 0000000000..5604e373f5 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/IPersistStream.java @@ -0,0 +1,57 @@ +/* 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; + + +/** + * Enables the saving and loading of objects that use a simple serial stream for their storage needs. + * + * @see MSDN + * + */ +public interface IPersistStream extends IPersist { + + /** + * Determines whether an object has changed since it was last saved to its + * stream. + * + * (Unimplemented) + * + */ + boolean IsDirty(); + + /** + * Initializes an object from the stream where it was saved previously + * + * (Unimplemented) + * + */ + + void Load(IStream stm); + + /** + * Saves an object to the specified stream. + * + * (Unimplemented) + * + */ + void Save(IStream stm); + + /** + * Retrieves the size of the stream needed to save the object. + * + * (Unimplemented) + * + */ + void GetSizeMax(); +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/IRunningObjectTable.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/IRunningObjectTable.java new file mode 100644 index 0000000000..9a5709a3e5 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/IRunningObjectTable.java @@ -0,0 +1,152 @@ +/* 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; + +import com.sun.jna.Pointer; +import com.sun.jna.platform.win32.Guid.IID; +import com.sun.jna.platform.win32.WinBase.FILETIME; +import com.sun.jna.platform.win32.WinDef.DWORD; +import com.sun.jna.platform.win32.WinDef.DWORDByReference; +import com.sun.jna.platform.win32.WinNT.HRESULT; +import com.sun.jna.ptr.PointerByReference; + +/** + * Manages access to the running object table (ROT), a globally accessible + * look-up table on each workstation. + * + * @see MSDN + * + */ +public interface IRunningObjectTable extends IUnknown { + + public final static IID IID = new IID("{00000010-0000-0000-C000-000000000046}"); + + /** + * Creates and returns a pointer to an enumerator that can list the monikers + * of all the objects currently registered in the running object table + * (ROT). + * + * {@code + * HRESULT EnumRunning( + * [out] IEnumMoniker **ppenumMoniker + * ); + * } + * + * @see MSDN + * + */ + HRESULT EnumRunning(PointerByReference ppenumMoniker); + + /** + * + * Determines whether the object identified by the specified moniker is + * running, and if it is, retrieves a pointer to that object. + * + * {@code + * HRESULT GetObject( + * [in] IMoniker *pmkObjectName, + * [out] IUnknown **ppunkObject + * ); + * } + * + * @see MSDN + * + */ + HRESULT GetObject(Pointer pmkObjectName, PointerByReference ppunkObject); + + /** + * Retrieves the time that an object was last modified. + * + * {@code + * HRESULT GetTimeOfLastChange( + * [in] IMoniker *pmkObjectName, + * [out] FILETIME *pfiletime + * ); + * } + * + * @see MSDN + * + */ + HRESULT GetTimeOfLastChange(Pointer pmkObjectName, FILETIME.ByReference pfiletime); + + /** + * Determines whether the object identified by the specified moniker is + * currently running. + * + * {@code + * HRESULT IsRunning( + * [in] IMoniker *pmkObjectName + * ); + * } + * + * @see MSDN + * + */ + HRESULT IsRunning(Pointer pmkObjectName); + + /** + * Records the time that a running object was last modified. + * + * {@code + * HRESULT NoteChangeTime( + * [in] DWORD dwRegister, + * [in] FILETIME *pfiletime + * ); + * } + * + * @see MSDN + * + */ + HRESULT NoteChangeTime(DWORD dwRegister, FILETIME pfiletime); + + /** + * Registers an object and its identifying moniker in the running object + * table (ROT). + * + * {@code + * HRESULT Register( + * [in] DWORD grfFlags, + * [in] IUnknown *punkObject, + * [in] IMoniker *pmkObjectName, + * [out] DWORD *pdwRegister + * ); + * } + * + * @see MSDN + * + */ + HRESULT Register(DWORD grfFlags, Pointer punkObject, Pointer pmkObjectName, DWORDByReference pdwRegister); + + /** + * Removes an entry from the running object table (ROT) that was previously + * registered by a call to IRunningObjectTable.Register. + * + * {@code + * HRESULT Revoke( + * [in] DWORD dwRegister + * ); + * } + * + * @see MSDN + * + */ + HRESULT Revoke(DWORD dwRegister); +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/IStream.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/IStream.java new file mode 100644 index 0000000000..a7fa02570d --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/IStream.java @@ -0,0 +1,29 @@ +/* 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; + +/** + * The IStream interface lets you read and write data to stream objects. Stream + * objects contain the data in a structured storage object, where storages + * provide the structure. Simple data can be written directly to a stream but, + * most frequently, streams are elements nested within a storage object. They + * are similar to standard files. + * + * (Place holder, incomplete) + * + * @see MSDN + * + */ +public interface IStream { + +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/IUnknown.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/IUnknown.java index 073cbe0e60..061f6114e8 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/COM/IUnknown.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/IUnknown.java @@ -13,6 +13,7 @@ package com.sun.jna.platform.win32.COM; import com.sun.jna.platform.win32.Guid.IID; +import com.sun.jna.platform.win32.Guid.REFIID; import com.sun.jna.platform.win32.WinNT.HRESULT; import com.sun.jna.ptr.PointerByReference; @@ -31,7 +32,7 @@ public interface IUnknown { public final static IID IID_IUNKNOWN = new IID( "{00000000-0000-0000-C000-000000000046}"); - public HRESULT QueryInterface(IID riid, PointerByReference ppvObject); + public HRESULT QueryInterface(REFIID.ByValue riid, PointerByReference ppvObject); public int AddRef(); diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/IUnknownCallback.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/IUnknownCallback.java new file mode 100644 index 0000000000..d1ae76c95f --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/IUnknownCallback.java @@ -0,0 +1,19 @@ +/* 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; + +import com.sun.jna.Pointer; + +public interface IUnknownCallback extends IUnknown { + Pointer getPointer(); +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/Moniker.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/Moniker.java new file mode 100644 index 0000000000..db695646d5 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/Moniker.java @@ -0,0 +1,173 @@ +/* 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; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import com.sun.jna.WString; +import com.sun.jna.platform.win32.WTypes.BSTRByReference; +import com.sun.jna.platform.win32.WTypes.LPSTR; +import com.sun.jna.platform.win32.WinNT; +import com.sun.jna.platform.win32.Guid.CLSID; +import com.sun.jna.platform.win32.WinNT.HRESULT; + +public class Moniker extends Unknown implements IMoniker { + + public static class ByReference extends Moniker implements Structure.ByReference { + } + + public Moniker() { + } + + public Moniker(Pointer pointer) { + super(pointer); + } + + // There are 8 virtual methods in the ancestors of this class/interfaces + static final int vTableIdStart = 7; + + @Override + public void BindToObject() { + final int vTableId = vTableIdStart + 1; + + throw new UnsupportedOperationException(); + } + + @Override + public void BindToStorage() { + final int vTableId = vTableIdStart + 2; + + throw new UnsupportedOperationException(); + } + + @Override + public void Reduce() { + final int vTableId = vTableIdStart + 3; + + throw new UnsupportedOperationException(); + } + + @Override + public void ComposeWith() { + final int vTableId = vTableIdStart + 4; + + throw new UnsupportedOperationException(); + } + + @Override + public void Enum() { + final int vTableId = vTableIdStart + 5; + + throw new UnsupportedOperationException(); + } + + @Override + public void IsEqual() { + final int vTableId = vTableIdStart + 6; + + throw new UnsupportedOperationException(); + } + + @Override + public void Hash() { + final int vTableId = vTableIdStart + 7; + + throw new UnsupportedOperationException(); + } + + @Override + public void IsRunning() { + final int vTableId = vTableIdStart + 8; + + throw new UnsupportedOperationException(); + } + + @Override + public void GetTimeOfLastChange() { + final int vTableId = vTableIdStart + 9; + + throw new UnsupportedOperationException(); + } + + @Override + public void Inverse() { + final int vTableId = vTableIdStart + 10; + + throw new UnsupportedOperationException(); + } + + @Override + public void CommonPrefixWith() { + final int vTableId = vTableIdStart + 11; + + throw new UnsupportedOperationException(); + } + + @Override + public void RelativePathTo() { + final int vTableId = vTableIdStart + 12; + + throw new UnsupportedOperationException(); + } + + @Override + public HRESULT GetDisplayName(Pointer pbc, Pointer pmkToLeft, BSTRByReference ppszDisplayName) { + final int vTableId = vTableIdStart + 13; + + WinNT.HRESULT hr = (WinNT.HRESULT) this._invokeNativeObject(vTableId, new Object[] { this.getPointer(), pbc, + pmkToLeft, ppszDisplayName }, WinNT.HRESULT.class); + + return hr; + } + + @Override + public void ParseDisplayName() { + final int vTableId = vTableIdStart + 14; + + throw new UnsupportedOperationException(); + } + + @Override + public void IsSystemMoniker() { + final int vTableId = vTableIdStart + 15; + + throw new UnsupportedOperationException(); + } + + // ------------------------ IPersistStream ---------------------------- + @Override + public boolean IsDirty() { + throw new UnsupportedOperationException(); + } + + @Override + public void Load(IStream stm) { + throw new UnsupportedOperationException(); + } + + @Override + public void Save(IStream stm) { + throw new UnsupportedOperationException(); + } + + @Override + public void GetSizeMax() { + throw new UnsupportedOperationException(); + } + + @Override + public CLSID GetClassID() { + throw new UnsupportedOperationException(); + } + +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/RunningObjectTable.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/RunningObjectTable.java new file mode 100644 index 0000000000..e635c500d8 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/RunningObjectTable.java @@ -0,0 +1,110 @@ +/* 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; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import com.sun.jna.platform.win32.WinBase.FILETIME; +import com.sun.jna.platform.win32.WinDef.DWORD; +import com.sun.jna.platform.win32.WinDef.DWORDByReference; +import com.sun.jna.platform.win32.WinNT; +import com.sun.jna.platform.win32.WinNT.HRESULT; +import com.sun.jna.ptr.PointerByReference; + +public class RunningObjectTable extends Unknown implements IRunningObjectTable { + + public static class ByReference extends RunningObjectTable implements Structure.ByReference { + } + + public RunningObjectTable() { + } + + public RunningObjectTable(Pointer pointer) { + super(pointer); + } + + // The magic number values for (vTableId) below, are worked out by + // counting the number of methods in the full interface (0 indexed), as this + // inherits IUnknown, which has 3 methods, we start here at 3. + + @Override + public HRESULT Register(DWORD grfFlags, Pointer punkObject, Pointer pmkObjectName, DWORDByReference pdwRegister) { + final int vTableId = 3; + + WinNT.HRESULT hr = (WinNT.HRESULT) this._invokeNativeObject(vTableId, new Object[] { this.getPointer(), + grfFlags, punkObject, pmkObjectName, pdwRegister }, WinNT.HRESULT.class); + + return hr; + } + + @Override + public HRESULT Revoke(DWORD dwRegister) { + final int vTableId = 4; + + WinNT.HRESULT hr = (WinNT.HRESULT) this._invokeNativeObject(vTableId, new Object[] { this.getPointer(), + dwRegister }, WinNT.HRESULT.class); + + return hr; + } + + @Override + public HRESULT IsRunning(Pointer pmkObjectName) { + final int vTableId = 5; + + WinNT.HRESULT hr = (WinNT.HRESULT) this._invokeNativeObject(vTableId, new Object[] { this.getPointer(), + pmkObjectName }, WinNT.HRESULT.class); + + return hr; + } + + @Override + public HRESULT GetObject(Pointer pmkObjectName, PointerByReference ppunkObject) { + final int vTableId = 6; + + WinNT.HRESULT hr = (WinNT.HRESULT) this._invokeNativeObject(vTableId, new Object[] { this.getPointer(), + pmkObjectName, ppunkObject }, WinNT.HRESULT.class); + + return hr; + } + + @Override + public HRESULT NoteChangeTime(DWORD dwRegister, FILETIME pfiletime) { + final int vTableId = 7; + + WinNT.HRESULT hr = (WinNT.HRESULT) this._invokeNativeObject(vTableId, new Object[] { this.getPointer(), + dwRegister, pfiletime }, WinNT.HRESULT.class); + + return hr; + } + + @Override + public HRESULT GetTimeOfLastChange(Pointer pmkObjectName, FILETIME.ByReference pfiletime) { + final int vTableId = 8; + + WinNT.HRESULT hr = (WinNT.HRESULT) this._invokeNativeObject(vTableId, new Object[] { this.getPointer(), + pmkObjectName, pfiletime }, WinNT.HRESULT.class); + + return hr; + } + + @Override + public HRESULT EnumRunning(PointerByReference ppenumMoniker) { + final int vTableId = 9; + + WinNT.HRESULT hr = (WinNT.HRESULT) this._invokeNativeObject(vTableId, new Object[] { this.getPointer(), + ppenumMoniker }, WinNT.HRESULT.class); + + return hr; + } + +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/Unknown.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/Unknown.java index 366be7d050..a3d993bff4 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/COM/Unknown.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/Unknown.java @@ -15,6 +15,7 @@ import com.sun.jna.Pointer; import com.sun.jna.Structure; import com.sun.jna.platform.win32.Guid.IID; +import com.sun.jna.platform.win32.Guid.REFIID; import com.sun.jna.platform.win32.WinNT.HRESULT; import com.sun.jna.ptr.PointerByReference; @@ -55,7 +56,7 @@ public Unknown(Pointer pvInstance) { * the ppv object * @return the hresult */ - public HRESULT QueryInterface(IID riid, PointerByReference ppvObject) { + public HRESULT QueryInterface(REFIID.ByValue riid, PointerByReference ppvObject) { return (HRESULT) this._invokeNativeObject(0, new Object[] { this.getPointer(), riid, ppvObject }, HRESULT.class); diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/UnknownListener.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/UnknownListener.java new file mode 100644 index 0000000000..8c9322b1bb --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/UnknownListener.java @@ -0,0 +1,66 @@ +/* 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; + +import java.util.Arrays; +import java.util.List; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import com.sun.jna.platform.win32.Guid; +import com.sun.jna.platform.win32.Guid.REFIID; +import com.sun.jna.platform.win32.WinError; +import com.sun.jna.platform.win32.WinNT.HRESULT; +import com.sun.jna.ptr.PointerByReference; + +public class UnknownListener extends Structure { + + public UnknownListener(IUnknownCallback callback) { + this.vtbl = this.constructVTable(); + this.initVTable(callback); + super.write(); + } + + public UnknownVTable.ByReference vtbl; + + @Override + protected List getFieldOrder() { + return Arrays.asList(new String[] { "vtbl" }); + } + + protected UnknownVTable.ByReference constructVTable() { + return new UnknownVTable.ByReference(); + } + + protected void initVTable(final IUnknownCallback callback) { + this.vtbl.QueryInterfaceCallback = new UnknownVTable.QueryInterfaceCallback() { + @Override + public HRESULT invoke(Pointer thisPointer, REFIID.ByValue refid, PointerByReference ppvObject) { + return callback.QueryInterface(refid, ppvObject); + } + }; + this.vtbl.AddRefCallback = new UnknownVTable.AddRefCallback() { + @Override + public int invoke(Pointer thisPointer) { + return callback.AddRef(); + } + }; + this.vtbl.ReleaseCallback = new UnknownVTable.ReleaseCallback() { + @Override + public int invoke(Pointer thisPointer) { + return callback.Release(); + } + }; + } + +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/UnknownVTable.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/UnknownVTable.java new file mode 100644 index 0000000000..ec53e1be8b --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/UnknownVTable.java @@ -0,0 +1,49 @@ +/* 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; + +import java.util.Arrays; +import java.util.List; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import com.sun.jna.platform.win32.Guid.REFIID; +import com.sun.jna.platform.win32.WinNT; +import com.sun.jna.ptr.PointerByReference; +import com.sun.jna.win32.StdCallLibrary; + +public class UnknownVTable extends Structure { + public static class ByReference extends UnknownVTable implements Structure.ByReference { + } + + public QueryInterfaceCallback QueryInterfaceCallback; + public AddRefCallback AddRefCallback; + public ReleaseCallback ReleaseCallback; + + @Override + protected List getFieldOrder() { + return Arrays.asList(new String[] { "QueryInterfaceCallback", "AddRefCallback", "ReleaseCallback" }); + } + + public static interface QueryInterfaceCallback extends StdCallLibrary.StdCallCallback { + WinNT.HRESULT invoke(Pointer thisPointer, REFIID.ByValue refid, PointerByReference ppvObject); + } + + public static interface AddRefCallback extends StdCallLibrary.StdCallCallback { + int invoke(Pointer thisPointer); + } + + public static interface ReleaseCallback extends StdCallLibrary.StdCallCallback { + int invoke(Pointer thisPointer); + } +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/AbstractComEventCallbackListener.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/AbstractComEventCallbackListener.java new file mode 100644 index 0000000000..0204d83da4 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/AbstractComEventCallbackListener.java @@ -0,0 +1,29 @@ +/* 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 com.sun.jna.platform.win32.COM.IDispatchCallback; + +public abstract class AbstractComEventCallbackListener implements IComEventCallbackListener { + + public AbstractComEventCallbackListener() { + this.dispatchCallback = null; + } + + IDispatchCallback dispatchCallback; + public void setDispatchCallbackListener(IDispatchCallback dispatchCallback) { + this.dispatchCallback = dispatchCallback; + } + + +} 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 new file mode 100644 index 0000000000..7a8ccc31ee --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/CallbackProxy.java @@ -0,0 +1,273 @@ +/* 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.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +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 com.sun.jna.Pointer; +import com.sun.jna.WString; +import com.sun.jna.platform.win32.Guid; +import com.sun.jna.platform.win32.WinDef; +import com.sun.jna.platform.win32.Guid.IID; +import com.sun.jna.platform.win32.Guid.REFIID; +import com.sun.jna.platform.win32.OaIdl.DISPID; +import com.sun.jna.platform.win32.OaIdl.DISPIDByReference; +import com.sun.jna.platform.win32.OaIdl.EXCEPINFO; +import com.sun.jna.platform.win32.OleAuto.DISPPARAMS; +import com.sun.jna.platform.win32.Variant; +import com.sun.jna.platform.win32.Variant.VARIANT; +import com.sun.jna.platform.win32.Variant.VariantArg; +import com.sun.jna.platform.win32.WinDef.LCID; +import com.sun.jna.platform.win32.WinDef.UINT; +import com.sun.jna.platform.win32.WinDef.UINTByReference; +import com.sun.jna.platform.win32.WinDef.WORD; +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.Dispatch; +import com.sun.jna.platform.win32.COM.DispatchListener; +import com.sun.jna.platform.win32.COM.IDispatch; +import com.sun.jna.platform.win32.COM.IDispatchCallback; +import com.sun.jna.platform.win32.COM.Unknown; +import com.sun.jna.platform.win32.COM.util.annotation.ComEventCallback; +import com.sun.jna.platform.win32.COM.util.annotation.ComInterface; +import com.sun.jna.ptr.IntByReference; +import com.sun.jna.ptr.PointerByReference; + +public class CallbackProxy implements IDispatchCallback { + + public CallbackProxy(Factory factory, Class comEventCallbackInterface, + IComEventCallbackListener comEventCallbackListener) { + this.factory = factory; + this.comEventCallbackInterface = comEventCallbackInterface; + this.comEventCallbackListener = comEventCallbackListener; + this.listenedToRiid = this.createRIID(comEventCallbackInterface); + this.dsipIdMap = this.createDispIdMap(comEventCallbackInterface); + this.dispatchListener = new DispatchListener(this); + this.executorService = Executors.newSingleThreadExecutor(new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread thread = new Thread(r, "COM Event Callback executor"); + thread.setDaemon(true); + thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() { + @Override + public void uncaughtException(Thread t, Throwable e) { + CallbackProxy.this.factory.comThread.uncaughtExceptionHandler.uncaughtException(t, e); + } + }); + return thread; + } + }); + } + + Factory factory; + Class comEventCallbackInterface; + IComEventCallbackListener comEventCallbackListener; + REFIID.ByValue listenedToRiid; + public DispatchListener dispatchListener; + Map dsipIdMap; + ExecutorService executorService; + + REFIID.ByValue createRIID(Class comEventCallbackInterface) { + ComInterface comInterfaceAnnotation = comEventCallbackInterface.getAnnotation(ComInterface.class); + if (null == comInterfaceAnnotation) { + throw new COMException( + "advise: Interface must define a value for either iid via the ComInterface annotation"); + } + String iidStr = comInterfaceAnnotation.iid(); + if (null == iidStr || iidStr.isEmpty()) { + throw new COMException("ComInterface must define a value for iid"); + } + return new REFIID.ByValue(new IID(iidStr).getPointer()); + } + + Map createDispIdMap(Class comEventCallbackInterface) { + Map map = new HashMap(); + + for (Method meth : comEventCallbackInterface.getMethods()) { + ComEventCallback annotation = meth.getAnnotation(ComEventCallback.class); + if (null != annotation) { + int dispId = annotation.dispid(); + if (-1 == dispId) { + dispId = this.fetchDispIdFromName(annotation); + } + map.put(new DISPID(dispId), meth); + } + } + + return map; + } + + int fetchDispIdFromName(ComEventCallback annotation) { + // TODO + return -1; + } + + void invokeOnThread(final DISPID dispIdMember, final REFIID.ByValue riid, LCID lcid, WORD wFlags, + final DISPPARAMS.ByReference pDispParams) { + // decode arguments + // must decode them on this thread, and create a proxy for any COM objects (IDispatch) + // this will AddRef on the COM object so that it is not cleaned up before we can use it + // on the thread that does the java callback. + List rjargs = new ArrayList(); + if (pDispParams.cArgs.intValue() > 0) { + VariantArg vargs = pDispParams.rgvarg; + vargs.setArraySize(pDispParams.cArgs.intValue()); + for (Variant.VARIANT varg : vargs.variantArg) { + Object jarg = Convert.toJavaObject(varg); + if (jarg instanceof IDispatch) { + IDispatch dispatch = (IDispatch) jarg; + //get raw IUnknown interface + PointerByReference ppvObject = new PointerByReference(); + IID iid = com.sun.jna.platform.win32.COM.IUnknown.IID_IUNKNOWN; + dispatch.QueryInterface(new REFIID.ByValue(iid), ppvObject); + Unknown rawUnk = new Unknown(ppvObject.getValue()); + long unknownId = Pointer.nativeValue( rawUnk.getPointer() ); + int n = rawUnk.Release(); + //Note: unlike in other places, there is currently no COM ref already added for this pointer + IUnknown unk = CallbackProxy.this.factory.createProxy(IUnknown.class, unknownId, dispatch); + rjargs.add(unk); + } else { + rjargs.add(jarg); + } + } + } + final List jargs = new ArrayList(rjargs); + Runnable invokation = new Runnable() { + @Override + public void run() { + try { + if (CallbackProxy.this.dsipIdMap.containsKey(dispIdMember)) { + Method eventMethod = CallbackProxy.this.dsipIdMap.get(dispIdMember); + if (eventMethod.getParameterTypes().length != jargs.size()) { + CallbackProxy.this.comEventCallbackListener.errorReceivingCallbackEvent( + "Trying to invoke method " + eventMethod + " with " + jargs.size() + " arguments", + null); + } else { + try { + // need to convert arguments maybe + List margs = new ArrayList(); + Class[] params = eventMethod.getParameterTypes(); + for (int i = 0; i < eventMethod.getParameterTypes().length; ++i) { + Class paramType = params[i]; + Object jobj = jargs.get(i); + if (jobj != null && paramType.getAnnotation(ComInterface.class) != null) { + if (jobj instanceof IUnknown) { + IUnknown unk = (IUnknown) jobj; + Object mobj = unk.queryInterface(paramType); + margs.add(mobj); + } else { + throw new RuntimeException("Cannot convert argument " + jobj.getClass() + + " to ComInterface " + paramType); + } + } else { + margs.add(jobj); + } + } + eventMethod.invoke(comEventCallbackListener, margs.toArray()); + } catch (Exception e) { + CallbackProxy.this.comEventCallbackListener.errorReceivingCallbackEvent( + "Exception invoking method " + eventMethod, e); + } + } + } else { + CallbackProxy.this.comEventCallbackListener.errorReceivingCallbackEvent( + "No method found with dispId = " + dispIdMember, null); + } + } catch (Exception e) { + CallbackProxy.this.comEventCallbackListener.errorReceivingCallbackEvent( + "Exception receiving callback event ", e); + } + } + }; + this.executorService.execute(invokation); + } + + @Override + public Pointer getPointer() { + return this.dispatchListener.getPointer(); + } + + // ------------------------ IDispatch ------------------------------ + @Override + public HRESULT GetTypeInfoCount(UINTByReference pctinfo) { + return new HRESULT(WinError.E_NOTIMPL); + } + + @Override + public HRESULT GetTypeInfo(UINT iTInfo, LCID lcid, PointerByReference ppTInfo) { + return new HRESULT(WinError.E_NOTIMPL); + } + + @Override + public HRESULT GetIDsOfNames(REFIID.ByValue riid, WString[] rgszNames, int cNames, LCID lcid, + DISPIDByReference rgDispId) { + return new HRESULT(WinError.E_NOTIMPL); + } + + @Override + public HRESULT Invoke(DISPID dispIdMember, REFIID.ByValue riid, LCID lcid, WORD wFlags, + DISPPARAMS.ByReference pDispParams, VARIANT.ByReference pVarResult, EXCEPINFO.ByReference pExcepInfo, + IntByReference puArgErr) { + + this.invokeOnThread(dispIdMember, riid, lcid, wFlags, pDispParams); + + return WinError.S_OK; + } + + // ------------------------ IUnknown ------------------------------ + @Override + public HRESULT QueryInterface(REFIID.ByValue refid, PointerByReference ppvObject) { + if (null == ppvObject) { + return new HRESULT(WinError.E_POINTER); + } + + if (refid.equals(this.listenedToRiid)) { + ppvObject.setValue(this.getPointer()); + return WinError.S_OK; + } + + if (new Guid.IID(refid.getPointer()).equals(Unknown.IID_IUNKNOWN)) { + ppvObject.setValue(this.getPointer()); + return WinError.S_OK; + } + + if (new Guid.IID(refid.getPointer()).equals(Dispatch.IID_IDISPATCH)) { + ppvObject.setValue(this.getPointer()); + return WinError.S_OK; + } + + return new HRESULT(WinError.E_NOINTERFACE); + } + + public int AddRef() { + return 0; + } + + public int Release() { + return 0; + } + +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/ComEventCallbackCookie.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/ComEventCallbackCookie.java new file mode 100644 index 0000000000..7436f49e32 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/ComEventCallbackCookie.java @@ -0,0 +1,28 @@ +/* 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 com.sun.jna.platform.win32.WinDef.DWORD; + +public class ComEventCallbackCookie implements IComEventCallbackCookie { + + public ComEventCallbackCookie(DWORD value) { + this.value = value; + } + + DWORD value; + public DWORD getValue() { + return this.value; + } + +} 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 new file mode 100644 index 0000000000..3ac5c13407 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/ComThread.java @@ -0,0 +1,129 @@ +/* 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() { + 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); + } + } + + public T execute(Callable task) throws TimeoutException, InterruptedException, ExecutionException { + 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/Convert.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/Convert.java new file mode 100644 index 0000000000..4b0f03a55c --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/Convert.java @@ -0,0 +1,92 @@ +/* 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.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Date; + +import com.sun.jna.platform.win32.WTypes; +import com.sun.jna.platform.win32.WinDef; +import com.sun.jna.platform.win32.Variant.VARIANT; + +public class Convert { + + public static VARIANT toVariant(Object value) { + if (value instanceof Boolean) { + return new VARIANT((Boolean) value); + } else if (value instanceof Long) { + return new VARIANT(new WinDef.LONG((Long) value)); + } else if (value instanceof Integer) { + return new VARIANT((Integer) value); + } else if (value instanceof Short) { + return new VARIANT(new WinDef.SHORT((Short) value)); + } else if (value instanceof Float) { + return new VARIANT((Float) value); + } else if (value instanceof Double) { + return new VARIANT((Double) value); + } else if (value instanceof String) { + return new VARIANT((String) value); + } else if (value instanceof Date) { + return new VARIANT((Date) value); + } else if (value instanceof Proxy) { + InvocationHandler ih = Proxy.getInvocationHandler(value); + ProxyObject pobj = (ProxyObject) ih; + return new VARIANT(pobj.getRawDispatch()); + } + if (value instanceof IComEnum) { + IComEnum enm = (IComEnum) value; + return new VARIANT(new WinDef.LONG(enm.getValue())); + } else { + return null; + } + } + + public static Object toJavaObject(VARIANT value) { + if (null==value) return null; + Object vobj = value.getValue(); + if (vobj instanceof WinDef.BOOL) { + return ((WinDef.BOOL) vobj).booleanValue(); + } else if (vobj instanceof WinDef.LONG) { + return ((WinDef.LONG) vobj).longValue(); + } else if (vobj instanceof WinDef.SHORT) { + return ((WinDef.SHORT) vobj).shortValue(); + } else if (vobj instanceof WinDef.UINT) { + return ((WinDef.UINT) vobj).intValue(); + } else if (vobj instanceof WinDef.WORD) { + return ((WinDef.WORD) vobj).intValue(); + } else if (vobj instanceof WTypes.BSTR) { + return ((WTypes.BSTR) vobj).getValue(); + } + return vobj; + } + + public static T toComEnum(Class enumType, Object value) { + try { + Method m = enumType.getMethod("values"); + T[] values = (T[])m.invoke(null); + for(T t: values) { + if (value.equals(t.getValue())) { + return t; + } + } + } catch (NoSuchMethodException e) { + } catch (IllegalAccessException e) { + } catch (IllegalArgumentException e) { + } catch (InvocationTargetException e) { + } + return null; + } +} 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 new file mode 100644 index 0000000000..f12bf8d2d1 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/EnumMoniker.java @@ -0,0 +1,166 @@ +/* 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.util.Iterator; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +import com.sun.jna.platform.win32.WinDef; +import com.sun.jna.platform.win32.WinNT; +import com.sun.jna.platform.win32.COM.COMUtils; +import com.sun.jna.platform.win32.COM.Dispatch; +import com.sun.jna.platform.win32.COM.IEnumMoniker; +import com.sun.jna.platform.win32.COM.Moniker; +import com.sun.jna.ptr.PointerByReference; + +/** + * Enumerates the components of a moniker or the monikers in a table of + * monikers. + * + * @see MSDN + * + */ +public class EnumMoniker implements Iterable { + + protected EnumMoniker(IEnumMoniker raw, com.sun.jna.platform.win32.COM.IRunningObjectTable rawRot, + Factory factory) { + 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); + } + + 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); + } + } + + @Override + public Iterator iterator() { + return new Iterator() { + + @Override + public boolean hasNext() { + return null != EnumMoniker.this.rawNext; + } + + @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); + } + + } + + @Override + public void remove() { + throw new UnsupportedOperationException("remove"); + } + + }; + } + +} 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 new file mode 100644 index 0000000000..e14a88624b --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/Factory.java @@ -0,0 +1,278 @@ +/* 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.reflect.Proxy; +import java.util.HashSet; +import java.util.Set; +import java.util.WeakHashMap; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +import com.sun.jna.platform.win32.Guid.CLSID; +import com.sun.jna.platform.win32.Guid.GUID; +import com.sun.jna.platform.win32.Ole32; +import com.sun.jna.platform.win32.OleAuto; +import com.sun.jna.platform.win32.WTypes; +import com.sun.jna.platform.win32.WinDef; +import com.sun.jna.platform.win32.WinNT; +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.IDispatch; +import com.sun.jna.platform.win32.COM.util.annotation.ComObject; +import com.sun.jna.ptr.PointerByReference; + +public class Factory { + + /** + * Creates a utility COM Factory and a ComThread on which all COM calls are executed. + * NOTE: Remember to call factory.getComThread().terminate() at some appropriate point. + * + */ + public Factory() { + this(new ComThread("Default Factory COM Thread", 5000, new Thread.UncaughtExceptionHandler() { + @Override + public void uncaughtException(Thread t, Throwable e) { + //ignore + } + })); + } + + public Factory(ComThread comThread) { + this.comThread = comThread; + this.registeredObjects = new WeakHashMap(); + } + + @Override + protected void finalize() throws Throwable { + try { + this.disposeAll(); + } finally { + super.finalize(); + } + } + + ComThread comThread; + public ComThread getComThread() { + return this.comThread; + } + + /** + * CoInitialize must be called be fore this method. Either explicitly or + * implicitly via other methods. + * + * @return + */ + public IRunningObjectTable getRunningObjectTable() { + try { + + 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; + + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } catch (TimeoutException e) { + throw new RuntimeException(e); + } + } + + /** + * Creates a ProxyObject for the given interface and IDispatch pointer. + * + */ + public T createProxy(Class comInterface, IDispatch dispatch) { + ProxyObject jop = new ProxyObject(comInterface, dispatch, this); + Object proxy = Proxy.newProxyInstance(comInterface.getClassLoader(), new Class[] { comInterface }, jop); + T result = comInterface.cast(proxy); + return result; + } + + /** only for use when creating ProxyObjects from Callbacks + * + * @param comInterface + * @param unk + * @param dispatch + * @return + */ + T createProxy(Class comInterface, long unknownId, IDispatch dispatch) { + ProxyObject jop = new ProxyObject(comInterface, unknownId, dispatch, this); + Object proxy = Proxy.newProxyInstance(comInterface.getClassLoader(), new Class[] { comInterface }, jop); + T result = comInterface.cast(proxy); + return result; + } + + /** + * Creates a new COM object (CoCreateInstance) for the given progId and + * 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); + } + } + + /** + * Gets and existing COM object (GetActiveObject) for the given progId and + * 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); + + 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); + } + } + + 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(); + + WinNT.HRESULT hr = this.comThread.execute(new Callable() { + @Override + public WinNT.HRESULT call() throws Exception { + return Ole32.INSTANCE.CLSIDFromProgID(progIdStr, rclsid); + } + }); + + 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); + } + } + + //factory needs to keep a register of all handles to COM objects so that it can clean them up properly + // (if java had an out of scope clean up destructor like C++, this wouldn't be needed) + WeakHashMap registeredObjects; + public void register(ProxyObject proxyObject) { + synchronized (this.registeredObjects) { + //ProxyObject identity resolves to the underlying native pointer value + // different java ProxyObjects will resolve to the same pointer + // thus we need to count the number of references. + if (this.registeredObjects.containsKey(proxyObject)) { + int r = this.registeredObjects.get(proxyObject); + this.registeredObjects.put(proxyObject, r+1); + } else { + this.registeredObjects.put(proxyObject, 1); + } + } + } + + public void unregister(ProxyObject proxyObject, int d) { + synchronized (this.registeredObjects) { + if (this.registeredObjects.containsKey(proxyObject)) { + int r = this.registeredObjects.get(proxyObject); + if (r > 1) { + this.registeredObjects.put(proxyObject, r-d); + } else { + this.registeredObjects.remove(proxyObject); + } + } else { + throw new RuntimeException("Tried to dispose a ProxyObject that is not registered"); + } + + } + } + + public void disposeAll() { + synchronized (this.registeredObjects) { + Set s = new HashSet(this.registeredObjects.keySet()); + for(ProxyObject proxyObject : s) { + int r = this.registeredObjects.get(proxyObject); + proxyObject.dispose(r); + } + this.registeredObjects.clear(); + } + } +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IComEnum.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IComEnum.java new file mode 100644 index 0000000000..4e50344208 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IComEnum.java @@ -0,0 +1,17 @@ +/* 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; + +public interface IComEnum { + long getValue(); +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IComEventCallbackCookie.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IComEventCallbackCookie.java new file mode 100644 index 0000000000..9897e617cf --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IComEventCallbackCookie.java @@ -0,0 +1,17 @@ +/* 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; + +public interface IComEventCallbackCookie { + +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IComEventCallbackListener.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IComEventCallbackListener.java new file mode 100644 index 0000000000..6ad2ae184a --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IComEventCallbackListener.java @@ -0,0 +1,23 @@ +/* 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 com.sun.jna.platform.win32.COM.IDispatchCallback; + +public interface IComEventCallbackListener { + + void setDispatchCallbackListener(IDispatchCallback dispatchCallback); + + void errorReceivingCallbackEvent(String message, Exception exception); + +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IConnectionPoint.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IConnectionPoint.java new file mode 100644 index 0000000000..9311e53394 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IConnectionPoint.java @@ -0,0 +1,39 @@ +/* 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 com.sun.jna.platform.win32.COM.COMException; + +public interface IConnectionPoint { + + /** + * Set up the comEventCallbackListener to receive callback events from the target COM object + * + * @param comEventCallbackInterface - the COM interface that the listener will receive events from + * @param comEventCallback - and object that will receive the callback events + * @return - a cookie that can be used to detach (unadvise) the event callback listener + * + * throws COMException if an error occurs trying to set up the listener on the target COM object, + * see exception cause for details. + * + */ + IComEventCallbackCookie advise(Class comEventCallbackInterface, IComEventCallbackListener comEventCallbackListener) throws COMException; + + /** + * Stop listening for callback events + * + * @param comEventCallbackInterface - the interface that is being listened to + * @param cookie - the cookie that was returned when advise was called + */ + void unadvise(Class comEventCallbackInterface, final IComEventCallbackCookie cookie); +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IConnectionPointContainer.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IConnectionPointContainer.java new file mode 100644 index 0000000000..7a95144bba --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IConnectionPointContainer.java @@ -0,0 +1,21 @@ +/* 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 com.sun.jna.platform.win32.COM.util.annotation.ComInterface; +import com.sun.jna.platform.win32.COM.util.annotation.ComMethod; + +@ComInterface(iid="{B196B284-BAB4-101A-B69C-00AA00341D07}") +public interface IConnectionPointContainer extends IRawDispatchHandle { + +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IDispatch.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IDispatch.java new file mode 100644 index 0000000000..f3d57b0179 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IDispatch.java @@ -0,0 +1,24 @@ +/* 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; + +/** + * Java friendly version of {@link com.sun.jna.platform.win32.COM.IDispatch}. + * + */ +public interface IDispatch extends IUnknown { + + void setProperty(String name, T value); + T getProperty(Class returnType, String name, Object... args); + T invokeMethod(Class returnType, String name, Object... args); +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IRawDispatchHandle.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IRawDispatchHandle.java new file mode 100644 index 0000000000..b7219cf088 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IRawDispatchHandle.java @@ -0,0 +1,24 @@ +/* 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 com.sun.jna.platform.win32.COM.IDispatch; + +/** + * IF you want to access the underlying raw (com.sun.jna.platform.win32.COM.IDispatch) object + * then have your @ComObject or @ComInterface interface extends this interface. + * + */ +public interface IRawDispatchHandle { + IDispatch getRawDispatch(); +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IRunningObjectTable.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IRunningObjectTable.java new file mode 100644 index 0000000000..6ddc37b401 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IRunningObjectTable.java @@ -0,0 +1,41 @@ +/* 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.util.List; + +/** + * Java friendly version of + * {@link com.sun.jna.platform.win32.COM.IRunningObjectTable} + * + */ +public interface IRunningObjectTable { + + /** + * Creates and returns an enumerator of all the objects currently registered + * in the running object table (ROT). + * + */ + Iterable enumRunning(); + + /** + * Gets all the active (running) objects that support the give interface. + * + * Enumerates the running objects (via enumRunning), and returns a list of + * those for which queryInterface(iid) gives a valid result. + * + * @param iid + * @return + */ + List getActiveObjectsByInterface(Class comInterface); +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IUnknown.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IUnknown.java new file mode 100644 index 0000000000..32720ab001 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/IUnknown.java @@ -0,0 +1,35 @@ +/* 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 com.sun.jna.platform.win32.COM.COMException; +import com.sun.jna.platform.win32.COM.util.annotation.ComInterface; + +/** + * Java friendly version of the IUnknown interface. + * + * + */ +@ComInterface(iid="{00000000-0000-0000-C000-000000000046}") +public interface IUnknown { + /** + * Returns a proxy object for the given interface. Assuming that the + * interface is annotated with a ComInterface annotation that provides a + * valid iid. + * + * Will throw COMException if an error occurs trying to retrieve the requested interface, + * see exception cause for details. + * + */ + T queryInterface(Class comInterface) throws COMException; +} 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 new file mode 100644 index 0000000000..1aca3177ae --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/ProxyObject.java @@ -0,0 +1,648 @@ +/* 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.reflect.InvocationHandler; +import java.lang.reflect.Proxy; +import java.util.Date; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +import com.sun.jna.Pointer; +import com.sun.jna.WString; +import com.sun.jna.platform.win32.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.Kernel32Util; +import com.sun.jna.platform.win32.OaIdl; +import com.sun.jna.platform.win32.OaIdl.DISPID; +import com.sun.jna.platform.win32.OaIdl.DISPIDByReference; +import com.sun.jna.platform.win32.OaIdl.EXCEPINFO; +import com.sun.jna.platform.win32.OleAuto; +import com.sun.jna.platform.win32.OleAuto.DISPPARAMS; +import com.sun.jna.platform.win32.Variant; +import com.sun.jna.platform.win32.Variant.VARIANT; +import com.sun.jna.platform.win32.Variant.VariantArg; +import com.sun.jna.platform.win32.WTypes; +import com.sun.jna.platform.win32.WinDef; +import com.sun.jna.platform.win32.WinDef.DWORDByReference; +import com.sun.jna.platform.win32.WinDef.LCID; +import com.sun.jna.platform.win32.WinDef.UINT; +import com.sun.jna.platform.win32.WinNT; +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.ConnectionPoint; +import com.sun.jna.platform.win32.COM.ConnectionPointContainer; +import com.sun.jna.platform.win32.COM.Dispatch; +import com.sun.jna.platform.win32.COM.IDispatch; +import com.sun.jna.platform.win32.COM.IDispatchCallback; +import com.sun.jna.platform.win32.COM.Unknown; +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.ComProperty; +import com.sun.jna.ptr.IntByReference; +import com.sun.jna.ptr.PointerByReference; + +/** + * This object acts as the invocation handler for interfaces annotated with + * ComInterface. It wraps all (necessary) low level COM calls and executes them + * on a 'ComThread' held by the Factory object. + */ +public class ProxyObject implements InvocationHandler, com.sun.jna.platform.win32.COM.util.IDispatch, + IRawDispatchHandle { + + 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 + // (for debug it is usefult to be able to see how many refs are present + int n = this.rawDispatch.AddRef(); + this.getUnknownId(); // pre cache/calculate it + factory.register(this); + } + + /** when proxy is created for arguments on a call back, they are already on the + * com thread, and hence calling 'getUnknownId' will not work as it uses the ComThread + * however, the unknown pointer value is passed in; + * + * @param theInterface + * @param rawUnk + * @param rawDispatch + * @param 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 + // (for debug it is usefult to be able to see how many refs are present + int n = this.rawDispatch.AddRef(); + factory.register(this); + } + + // cached value of the IUnknown interface pointer + // Rules of COM state that querying for the IUnknown interface must return + // an identical pointer value + long unknownId; + + long getUnknownId() { + if (-1 == this.unknownId) { + try { + + final PointerByReference ppvObject = new PointerByReference(); + + 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.ByValue(iid), ppvObject); + } + }); + + if (WinNT.S_OK.equals(hr)) { + Dispatch dispatch = new Dispatch(ppvObject.getValue()); + this.unknownId = Pointer.nativeValue(dispatch.getPointer()); + // QueryInterface returns a COM object pointer with a +1 + // reference, we must drop one, + // Note: createProxy adds one; + int n = dispatch.Release(); + } else { + String formatMessageFromHR = Kernel32Util.formatMessage(hr); + throw new COMException("getUnknownId: " + formatMessageFromHR); + } + } catch (Exception e) { + throw new COMException("Error occured when trying get Unknown Id ", e); + } + } + return this.unknownId; + } + + @Override + protected void finalize() throws Throwable { + this.dispose(1); + } + + public void dispose(int r) { + if (((Dispatch) this.rawDispatch).getPointer().equals(Pointer.NULL)) { + // do nothing, already disposed + } else { + for (int i = 0; i < r; ++i) { + // catch result to help with debug + int n = this.rawDispatch.Release(); + int n2 = n; + } + this.factory.unregister(this, r); + ((Dispatch) this.rawDispatch).setPointer(Pointer.NULL); + } + } + + Class theInterface; + Factory factory; + ComThread comThread; + com.sun.jna.platform.win32.COM.IDispatch rawDispatch; + + public com.sun.jna.platform.win32.COM.IDispatch getRawDispatch() { + return this.rawDispatch; + } + + // -------------------- Object ------------------------- + + /* + * The QueryInterface rule state that 'a call to QueryInterface with + * IID_IUnknown must always return the same physical pointer value.' + * + * [http://msdn.microsoft.com/en-us/library/ms686590%28VS.85%29.aspx] + * + * therefore we can compare the pointers + */ + public boolean equals(Object arg) { + if (null == arg) { + return false; + } else if (arg instanceof ProxyObject) { + ProxyObject other = (ProxyObject) arg; + return this.getUnknownId() == other.getUnknownId(); + } else if (Proxy.isProxyClass(arg.getClass())) { + InvocationHandler handler = Proxy.getInvocationHandler(arg); + if (handler instanceof ProxyObject) { + try { + ProxyObject other = (ProxyObject) handler; + return this.getUnknownId() == other.getUnknownId(); + } catch (Exception e) { + // if can't do this comparison, return false + // (queryInterface may throw if COM objects become invalid) + return false; + } + } else { + return false; + } + } else { + return false; + } + }; + + @Override + public int hashCode() { + return Long.valueOf(this.getUnknownId()).intValue(); + // this returns the native pointer peer value + // return this.getRawDispatch().hashCode(); + } + + @Override + public String toString() { + return this.theInterface.getName() + "{unk=" + this.hashCode() + "}"; + } + + // --------------------- InvocationHandler ----------------------------- + @Override + public Object invoke(final Object proxy, final java.lang.reflect.Method method, final Object[] args) + throws Throwable { + return this.invokeSynchronised(proxy, method, args); + } + + /* + * may not necessary for this method to be synchronised as all calls to COM + * are on their own , single, thread. However, might be best not to overlap + * calls to COM object with advise, unadvise, queryInterface, etc. + */ + synchronized Object invokeSynchronised(final Object proxy, final java.lang.reflect.Method method, + final Object[] args) throws Throwable { + if (method.equals(Object.class.getMethod("toString"))) { + return this.toString(); + } else if (method.equals(Object.class.getMethod("equals", Object.class))) { + return this.equals(args[0]); + } else if (method.equals(Object.class.getMethod("hashCode"))) { + return this.hashCode(); + } else if (method.equals(IRawDispatchHandle.class.getMethod("getRawDispatch"))) { + return this.getRawDispatch(); + } else if (method.equals(IUnknown.class.getMethod("queryInterface", Class.class))) { + return this.queryInterface((Class) args[0]); + } else if (method.equals(IConnectionPoint.class.getMethod("advise", Class.class, + IComEventCallbackListener.class))) { + return this.advise((Class) args[0], (IComEventCallbackListener) args[1]); + } else if (method.equals(IConnectionPoint.class.getMethod("unadvise", Class.class, + IComEventCallbackCookie.class))) { + this.unadvise((Class) args[0], (IComEventCallbackCookie) args[1]); + return null; + } + + Class returnType = method.getReturnType(); + boolean isVoid = Void.TYPE.equals(returnType); + + ComProperty prop = method.getAnnotation(ComProperty.class); + if (null != prop) { + if (isVoid) { + String propName = this.getMutatorName(method, prop); + this.setProperty(propName, args[0]); + return null; + } else { + String propName = this.getAccessorName(method, prop); + return this.getProperty(returnType, propName, args); + } + } + + ComMethod meth = method.getAnnotation(ComMethod.class); + if (null != meth) { + String methName = this.getMethodName(method, meth); + Object res = this.invokeMethod(returnType, methName, args); + return res; + } + + return null; + } + + // ---------------------- IConnectionPoint ---------------------- + ConnectionPoint fetchRawConnectionPoint(IID iid) throws InterruptedException, ExecutionException, TimeoutException { + // query for ConnectionPointContainer + IConnectionPointContainer cpc = this.queryInterface(IConnectionPointContainer.class); + Dispatch rawCpcDispatch = (Dispatch) cpc.getRawDispatch(); + final ConnectionPointContainer rawCpc = new ConnectionPointContainer(rawCpcDispatch.getPointer()); + + // 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); + } + }); + COMUtils.checkRC(hr); + final ConnectionPoint rawCp = new ConnectionPoint(ppCp.getValue()); + return rawCp; + } + + public IComEventCallbackCookie advise(Class comEventCallbackInterface, + final IComEventCallbackListener comEventCallbackListener) { + try { + ComInterface comInterfaceAnnotation = comEventCallbackInterface.getAnnotation(ComInterface.class); + if (null == comInterfaceAnnotation) { + throw new COMException( + "advise: Interface must define a value for either iid via the ComInterface annotation"); + } + final IID iid = this.getIID(comInterfaceAnnotation); + + final ConnectionPoint rawCp = this.fetchRawConnectionPoint(iid); + + // create the dispatch listener + final IDispatchCallback rawListener = new CallbackProxy(this.factory, comEventCallbackInterface, + comEventCallbackListener); + // store it the comEventCallback argument, so it is not garbage + // collected. + comEventCallbackListener.setDispatchCallbackListener(rawListener); + // 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); + } + }); + int n = rawCp.Release(); // release before check in case check + // throws exception + COMUtils.checkRC(hr); + + // return the cookie so that a call to stop listening can be made + return new ComEventCallbackCookie(pdwCookie.getValue()); + + } catch (Exception e) { + throw new COMException("Error occured in advise when trying to connect the listener " + + comEventCallbackListener, e); + } + } + + public void unadvise(Class comEventCallbackInterface, final IComEventCallbackCookie cookie) { + try { + ComInterface comInterfaceAnnotation = comEventCallbackInterface.getAnnotation(ComInterface.class); + if (null == comInterfaceAnnotation) { + throw new COMException( + "unadvise: Interface must define a value for iid via the ComInterface annotation"); + } + IID iid = this.getIID(comInterfaceAnnotation); + + 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()); + } + }); + + rawCp.Release(); + COMUtils.checkRC(hr); + + } catch (Exception e) { + throw new COMException("Error occured in unadvise when trying to disconnect the listener from " + this, e); + } + } + + // --------------------- IDispatch ------------------------------ + @Override + public void setProperty(String name, T value) { + VARIANT v = Convert.toVariant(value); + WinNT.HRESULT hr = this.oleMethod(OleAuto.DISPATCH_PROPERTYPUT, null, this.getRawDispatch(), name, v); + COMUtils.checkRC(hr); + } + + @Override + public T getProperty(Class returnType, String name, Object... args) { + VARIANT[] vargs; + if (null == args) { + vargs = new VARIANT[0]; + } else { + vargs = new VARIANT[args.length]; + } + for (int i = 0; i < vargs.length; ++i) { + vargs[i] = Convert.toVariant(args[i]); + } + Variant.VARIANT.ByReference result = new Variant.VARIANT.ByReference(); + WinNT.HRESULT hr = this.oleMethod(OleAuto.DISPATCH_PROPERTYGET, result, this.getRawDispatch(), name, vargs); + COMUtils.checkRC(hr); + Object jobj = Convert.toJavaObject(result); + if (IComEnum.class.isAssignableFrom(returnType)) { + return (T) Convert.toComEnum((Class) returnType, jobj); + } + if (jobj instanceof IDispatch) { + IDispatch d = (IDispatch) jobj; + T t = this.factory.createProxy(returnType, d); + // must release a COM reference, createProxy adds one, as does the + // call + int n = d.Release(); + return t; + } + return (T) jobj; + } + + @Override + public T invokeMethod(Class returnType, String name, Object... args) { + VARIANT[] vargs; + if (null == args) { + vargs = new VARIANT[0]; + } else { + vargs = new VARIANT[args.length]; + } + for (int i = 0; i < vargs.length; ++i) { + vargs[i] = Convert.toVariant(args[i]); + } + Variant.VARIANT.ByReference result = new Variant.VARIANT.ByReference(); + WinNT.HRESULT hr = this.oleMethod(OleAuto.DISPATCH_METHOD, result, this.getRawDispatch(), name, vargs); + COMUtils.checkRC(hr); + + Object jobj = Convert.toJavaObject(result); + if (IComEnum.class.isAssignableFrom(returnType)) { + return (T) Convert.toComEnum((Class) returnType, jobj); + } + if (jobj instanceof IDispatch) { + IDispatch d = (IDispatch) jobj; + T t = this.factory.createProxy(returnType, d); + // must release a COM reference, createProxy adds one, as does the + // call + int n = d.Release(); + return t; + } + return (T) jobj; + } + + @Override + public T queryInterface(Class comInterface) throws COMException { + try { + ComInterface comInterfaceAnnotation = comInterface.getAnnotation(ComInterface.class); + if (null == comInterfaceAnnotation) { + throw new COMException( + "queryInterface: Interface must define a value for iid via the ComInterface annotation"); + } + 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.ByValue(iid), ppvObject); + } + }); + + if (WinNT.S_OK.equals(hr)) { + Dispatch dispatch = new Dispatch(ppvObject.getValue()); + T t = this.factory.createProxy(comInterface, dispatch); + // QueryInterface returns a COM object pointer with a +1 + // reference, we must drop one, + // Note: createProxy adds one; + int n = dispatch.Release(); + return t; + } else { + String formatMessageFromHR = Kernel32Util.formatMessage(hr); + throw new COMException("queryInterface: " + formatMessageFromHR); + } + } catch (Exception e) { + throw new COMException("Error occured when trying to query for interface " + comInterface.getName(), e); + } + } + + IID getIID(ComInterface annotation) { + String iidStr = annotation.iid(); + if (null != iidStr && !iidStr.isEmpty()) { + return new IID(iidStr); + } else { + throw new COMException("ComInterface must define a value for iid"); + } + } + + // --------------------- ProxyObject --------------------- + + private String getAccessorName(java.lang.reflect.Method method, ComProperty prop) { + if (prop.name().isEmpty()) { + String methName = method.getName(); + if (methName.startsWith("get")) { + return methName.replaceFirst("get", ""); + } else { + throw new RuntimeException( + "Property Accessor name must start with 'get', or set the anotation 'name' value"); + } + } else { + return prop.name(); + } + } + + private String getMutatorName(java.lang.reflect.Method method, ComProperty prop) { + if (prop.name().isEmpty()) { + String methName = method.getName(); + if (methName.startsWith("set")) { + return methName.replaceFirst("set", ""); + } else { + throw new RuntimeException( + "Property Mutator name must start with 'set', or set the anotation 'name' value"); + } + } else { + return prop.name(); + } + } + + private String getMethodName(java.lang.reflect.Method method, ComMethod meth) { + if (meth.name().isEmpty()) { + String methName = method.getName(); + return methName; + } else { + return meth.name(); + } + } + + /** The Constant LOCALE_USER_DEFAULT. */ + public final static LCID LOCALE_USER_DEFAULT = Kernel32.INSTANCE.GetUserDefaultLCID(); + + /** The Constant LOCALE_SYSTEM_DEFAULT. */ + public final static LCID LOCALE_SYSTEM_DEFAULT = Kernel32.INSTANCE.GetSystemDefaultLCID(); + + /* + * @see com.sun.jna.platform.win32.COM.COMBindingBaseObject#oleMethod + */ + protected HRESULT oleMethod(int nType, VARIANT.ByReference pvResult, IDispatch pDisp, String name, VARIANT pArg) + throws COMException { + return this.oleMethod(nType, pvResult, pDisp, name, new VARIANT[] { pArg }); + } + + /* + * @see com.sun.jna.platform.win32.COM.COMBindingBaseObject#oleMethod + */ + protected HRESULT oleMethod(int nType, VARIANT.ByReference pvResult, IDispatch pDisp, DISPID dispId, VARIANT pArg) + throws COMException { + return this.oleMethod(nType, pvResult, pDisp, dispId, new VARIANT[] { pArg }); + } + + /* + * @see com.sun.jna.platform.win32.COM.COMBindingBaseObject#oleMethod + */ + protected HRESULT oleMethod(int nType, VARIANT.ByReference pvResult, IDispatch pDisp, String name) + throws COMException { + return this.oleMethod(nType, pvResult, pDisp, name, (VARIANT[]) null); + } + + /* + * @see com.sun.jna.platform.win32.COM.COMBindingBaseObject#oleMethod + */ + protected HRESULT oleMethod(int nType, VARIANT.ByReference pvResult, IDispatch pDisp, DISPID dispId) + throws COMException { + + return this.oleMethod(nType, pvResult, pDisp, dispId, (VARIANT[]) null); + } + + /* + * @see com.sun.jna.platform.win32.COM.COMBindingBaseObject#oleMethod + */ + 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.ByValue(Guid.IID_NULL), ptName, 1, LOCALE_USER_DEFAULT, + pdispID); + return hr; + } + }); + COMUtils.checkRC(hr); + + 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); + } + } + + /* + * @see com.sun.jna.platform.win32.COM.COMBindingBaseObject#oleMethod + */ + protected HRESULT oleMethod(final int nType, final VARIANT.ByReference pvResult, final IDispatch pDisp, + final DISPID dispId, VARIANT[] pArgs) throws COMException { + + if (pDisp == null) + throw new COMException("pDisp (IDispatch) parameter is null!"); + + // variable declaration + int _argsLen = 0; + VARIANT[] _args = null; + final DISPPARAMS.ByReference dp = new DISPPARAMS.ByReference(); + final EXCEPINFO.ByReference pExcepInfo = new EXCEPINFO.ByReference(); + final IntByReference puArgErr = new IntByReference(); + + // make parameter reverse ordering as expected by COM runtime + if ((pArgs != null) && (pArgs.length > 0)) { + _argsLen = pArgs.length; + _args = new VARIANT[_argsLen]; + + int revCount = _argsLen; + for (int i = 0; i < _argsLen; i++) { + _args[i] = pArgs[--revCount]; + } + } + + // Handle special-case for property-puts! + if (nType == OleAuto.DISPATCH_PROPERTYPUT) { + dp.cNamedArgs = new UINT(_argsLen); + dp.rgdispidNamedArgs = new DISPIDByReference(OaIdl.DISPID_PROPERTYPUT); + } + + // Build DISPPARAMS + if (_argsLen > 0) { + dp.cArgs = new UINT(_args.length); + // make pointer of variant array + dp.rgvarg = new VariantArg.ByReference(_args); + + // write 'DISPPARAMS' structure to memory + 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.ByValue(Guid.IID_NULL), LOCALE_SYSTEM_DEFAULT, + new WinDef.WORD(nType), 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 new file mode 100644 index 0000000000..874461378e --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/RunningObjectTable.java @@ -0,0 +1,83 @@ +/* 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.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +import com.sun.jna.platform.win32.WinNT; +import com.sun.jna.platform.win32.COM.COMException; +import com.sun.jna.platform.win32.COM.COMUtils; +import com.sun.jna.ptr.PointerByReference; + +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() { + + try { + + 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); + } + + } + + @Override + public List getActiveObjectsByInterface(Class comInterface) { + List result = new ArrayList(); + + for (IDispatch obj : this.enumRunning()) { + try { + T dobj = obj.queryInterface(comInterface); + + result.add(dobj); + } catch (COMException ex) { + + } + } + + return result; + } +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/annotation/ComEventCallback.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/annotation/ComEventCallback.java new file mode 100644 index 0000000000..ad72ce7ccc --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/annotation/ComEventCallback.java @@ -0,0 +1,27 @@ +/* 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.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD }) +@Inherited +public @interface ComEventCallback { + int dispid() default -1; // default to dispid unknown + String name() default ""; +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/annotation/ComInterface.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/annotation/ComInterface.java new file mode 100644 index 0000000000..ff4f898c71 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/annotation/ComInterface.java @@ -0,0 +1,26 @@ +/* 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.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE }) +@Inherited +public @interface ComInterface { + String iid() default ""; +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/annotation/ComMethod.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/annotation/ComMethod.java new file mode 100644 index 0000000000..ce8e4e8c20 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/annotation/ComMethod.java @@ -0,0 +1,27 @@ +/* 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.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD }) +@Inherited +public @interface ComMethod { + String name() default ""; + int dispId() default -1; //default to dispid unknown +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/annotation/ComObject.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/annotation/ComObject.java new file mode 100644 index 0000000000..fea5158b75 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/annotation/ComObject.java @@ -0,0 +1,27 @@ +/* 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.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE }) +@Inherited +public @interface ComObject { + String clsId() default ""; + String progId() default ""; +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/COM/util/annotation/ComProperty.java b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/annotation/ComProperty.java new file mode 100644 index 0000000000..6104c1dbaa --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/COM/util/annotation/ComProperty.java @@ -0,0 +1,26 @@ +/* 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.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD }) +@Inherited +public @interface ComProperty { + String name() default ""; +} diff --git a/contrib/platform/src/com/sun/jna/platform/win32/Guid.java b/contrib/platform/src/com/sun/jna/platform/win32/Guid.java index bcf7ca358a..7427dfbe39 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/Guid.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/Guid.java @@ -37,6 +37,21 @@ public interface Guid { */ public static class GUID extends Structure { + public static class ByValue extends GUID implements Structure.ByValue { + public ByValue() {} + public ByValue(GUID guid) { + super(guid.getPointer()); + + Data1 = guid.Data1; + Data2 = guid.Data2; + Data3 = guid.Data3; + Data4 = guid.Data4; + } + public ByValue(Pointer memory) { + super(memory); + } + } + /** * The Class ByReference. * diff --git a/contrib/platform/src/com/sun/jna/platform/win32/Ole32.java b/contrib/platform/src/com/sun/jna/platform/win32/Ole32.java index aa6b32b220..e344d394c3 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/Ole32.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/Ole32.java @@ -15,9 +15,9 @@ import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.WString; -import com.sun.jna.platform.win32.BaseTSD.SIZE_T; import com.sun.jna.platform.win32.Guid.CLSID; import com.sun.jna.platform.win32.Guid.GUID; +import com.sun.jna.platform.win32.WinDef.DWORD; import com.sun.jna.platform.win32.WinDef.LPVOID; import com.sun.jna.platform.win32.WinNT.HRESULT; import com.sun.jna.ptr.PointerByReference; @@ -257,7 +257,7 @@ HRESULT CoCreateInstance(GUID rclsid, Pointer pUnkOuter, int dwClsContext, * @return If the function succeeds, it returns the reallocated memory block. Otherwise, it returns NULL. */ Pointer CoTaskMemRealloc(Pointer pv, long cb); - + /** * Frees a block of task memory previously allocated through a call to the {@link #CoTaskMemAlloc} or * {@link #CoTaskMemRealloc} function. The function uses the default OLE allocator. The number of bytes @@ -267,4 +267,62 @@ HRESULT CoCreateInstance(GUID rclsid, Pointer pUnkOuter, int dwClsContext, */ void CoTaskMemFree(Pointer pv); + /** + * Retrieves a pointer to the default OLE task memory allocator. + * + * {@code + * HRESULT CoGetMalloc( + * [In] DWORD dwMemContext, + * [Out] LPMALLOC *ppMalloc + * ); + * + * @see MSDN + * + */ + HRESULT CoGetMalloc(DWORD dwMemContext, PointerByReference ppMalloc); + + /** + * Returns a pointer to the IRunningObjectTable interface on the local running object table (ROT). + * + * {@code + * HRESULT GetRunningObjectTable( + * [In] DWORD reserved, + * [Out] LPRUNNINGOBJECTTABLE *pprot + * ); + * } + * + * + * @see MSDN + */ + HRESULT GetRunningObjectTable(DWORD reserved, PointerByReference pprot); + + /** + * Returns a pointer to an implementation of IBindCtx (a bind context object). + * + * {@code + * HRESULT CreateBindCtx( + * [In] DWORD reserved, + * [Out] LPBC *ppbc + * ); + * } + * + * + * @see MSDN + */ + HRESULT CreateBindCtx(DWORD reserved, PointerByReference ppbc); + + /** + * Determines whether a remote object is connected to the corresponding in-process object. + * + * {@code + * BOOL CoIsHandlerConnected( + * [In] LPUNKNOWN pUnk + * ); + * } + * + * @see MSDN + * + */ + boolean CoIsHandlerConnected(Pointer pUnk); + } diff --git a/contrib/platform/src/com/sun/jna/platform/win32/Variant.java b/contrib/platform/src/com/sun/jna/platform/win32/Variant.java index 37a6870501..1d3a897425 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/Variant.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/Variant.java @@ -692,6 +692,13 @@ public ByReference(VARIANT[] variantArg) { public VariantArg() { } + /** + * construct VariantArg cast onto pre-allocated memory + */ + public VariantArg(Pointer pointer) { + super(pointer); + } + public VariantArg(VARIANT[] variantArg) { this.variantArg = variantArg; } @@ -700,5 +707,12 @@ public VariantArg(VARIANT[] variantArg) { protected List getFieldOrder() { return Arrays.asList(new String[] { "variantArg" }); } + + public void setArraySize(int size) { + this.variantArg = new VARIANT[size]; + this.read(); + } + + } } 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 new file mode 100644 index 0000000000..a059e905a5 --- /dev/null +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/ComEventCallbacks_Test.java @@ -0,0 +1,204 @@ +/* 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; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.sun.jna.Pointer; +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.IID; +import com.sun.jna.platform.win32.Guid.REFIID; +import com.sun.jna.platform.win32.Kernel32; +import com.sun.jna.platform.win32.OaIdl.DISPID; +import com.sun.jna.platform.win32.OaIdl.DISPIDByReference; +import com.sun.jna.platform.win32.OaIdl.EXCEPINFO; +import com.sun.jna.platform.win32.Ole32; +import com.sun.jna.platform.win32.OleAuto.DISPPARAMS; +import com.sun.jna.platform.win32.User32; +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.DWORDByReference; +import com.sun.jna.platform.win32.WinDef.LCID; +import com.sun.jna.platform.win32.WinDef.UINT; +import com.sun.jna.platform.win32.WinDef.UINTByReference; +import com.sun.jna.platform.win32.WinDef.WORD; +import com.sun.jna.platform.win32.WinError; +import com.sun.jna.platform.win32.WinNT.HRESULT; +import com.sun.jna.platform.win32.WinUser; +import com.sun.jna.ptr.IntByReference; +import com.sun.jna.ptr.PointerByReference; + +public class ComEventCallbacks_Test { + + final String WORD_APPLICATION_INTERFACE = "{00020970-0000-0000-C000-000000000046}"; + final String APPLICATION_EVENTS_4 = "{00020A01-0000-0000-C000-000000000046}"; + + @Before + public void before() { + HRESULT hr = Ole32.INSTANCE.CoInitializeEx(null, Ole32.COINIT_MULTITHREADED); + COMUtils.checkRC(hr); + } + + @After + public void after() { + Ole32.INSTANCE.CoUninitialize(); + } + + class Application_Events4 implements IDispatchCallback { + public DispatchListener listener = new DispatchListener(this); + + @Override + public Pointer getPointer() { + return this.listener.getPointer(); + } + + //------------------------ IDispatch ------------------------------ + @Override + public HRESULT GetTypeInfoCount(UINTByReference pctinfo) { + return new HRESULT(WinError.E_NOTIMPL); + } + + @Override + public HRESULT GetTypeInfo(UINT iTInfo, LCID lcid, PointerByReference ppTInfo) { + return new HRESULT(WinError.E_NOTIMPL); + } + + @Override + public HRESULT GetIDsOfNames(REFIID.ByValue riid, WString[] rgszNames, int cNames, LCID lcid, DISPIDByReference rgDispId) { + return new HRESULT(WinError.E_NOTIMPL); + } + + public boolean Invoke_called = false; + @Override + public HRESULT Invoke(DISPID dispIdMember, REFIID.ByValue riid, LCID lcid, + WORD wFlags, DISPPARAMS.ByReference pDispParams, + VARIANT.ByReference pVarResult, EXCEPINFO.ByReference pExcepInfo, + IntByReference puArgErr) { + this.Invoke_called = true; + + return new HRESULT(WinError.E_NOTIMPL); + } + + + //------------------------ IUnknown ------------------------------ + public boolean QueryInterface_called = false; + @Override + public HRESULT QueryInterface(REFIID.ByValue refid, PointerByReference ppvObject) { + this.QueryInterface_called = true; + if (null==ppvObject) { + return new HRESULT(WinError.E_POINTER); + } + + String s = refid.toGuidString(); + IID appEvnts4 = new IID(APPLICATION_EVENTS_4); + REFIID.ByValue riid = new REFIID.ByValue(appEvnts4.getPointer()); + + if (refid.equals(riid)) { + ppvObject.setValue(this.getPointer()); + return WinError.S_OK; + } + + if (new Guid.IID(refid.getPointer()).equals(Unknown.IID_IUNKNOWN)) { + ppvObject.setValue(this.getPointer()); + return WinError.S_OK; + } + + if (new Guid.IID(refid.getPointer()).equals(Dispatch.IID_IDISPATCH)) { + ppvObject.setValue(this.getPointer()); + return WinError.S_OK; + } + + return new HRESULT(WinError.E_NOINTERFACE); + } + + public int AddRef() { + return 0; + } + + public int Release() { + return 0; + } + + } + + @Test + public void cause_Quit_Event() { + // Create word object + CLSID clsid = new CLSID("{000209FF-0000-0000-C000-000000000046}"); + PointerByReference ppWordApp = new PointerByReference(); + HRESULT hr = Ole32.INSTANCE + .CoCreateInstance(clsid, null, WTypes.CLSCTX_SERVER, IDispatch.IID_IDISPATCH, ppWordApp); +// HRESULT hr =OleAuto.INSTANCE.GetActiveObject(clsid, null, ppWordApp); + COMUtils.checkRC(hr); + + // query for ConnectionPointContainer + Unknown unk = new Unknown(ppWordApp.getValue()); + PointerByReference ppCpc = new PointerByReference(); + IID cpcIID = new IID("{B196B284-BAB4-101A-B69C-00AA00341D07}"); + hr = unk.QueryInterface(new REFIID.ByValue(cpcIID), ppCpc); + COMUtils.checkRC(hr); + ConnectionPointContainer cpc = new ConnectionPointContainer(ppCpc.getValue()); + + // find connection point for Application_Events4 + IID appEvnts4 = new IID(APPLICATION_EVENTS_4); + REFIID riid = new REFIID(appEvnts4.getPointer()); + PointerByReference ppCp = new PointerByReference(); + hr = cpc.FindConnectionPoint(riid, ppCp); + COMUtils.checkRC(hr); + final ConnectionPoint cp = new ConnectionPoint(ppCp.getValue()); + IID cp_iid = new IID(); + hr = cp.GetConnectionInterface(cp_iid); + COMUtils.checkRC(hr); + + final Application_Events4 listener = new Application_Events4(); + final DWORDByReference pdwCookie = new DWORDByReference(); + HRESULT hr1 = cp.Advise(listener, pdwCookie); + COMUtils.checkRC(hr1); + +// Assert.assertTrue(listener.QueryInterface_called); +// + // Call Quit + Dispatch d = new Dispatch(ppWordApp.getValue()); + DISPID dispIdMember = new DISPID(1105); // Quit + REFIID.ByValue niid = new REFIID.ByValue(Guid.IID_NULL); + LCID lcid = Kernel32.INSTANCE.GetSystemDefaultLCID(); + WinDef.WORD wFlags = new WinDef.WORD(1); + DISPPARAMS.ByReference pDispParams = new DISPPARAMS.ByReference(); + VARIANT.ByReference pVarResult = new VARIANT.ByReference(); + IntByReference puArgErr = new IntByReference(); + EXCEPINFO.ByReference pExcepInfo = new EXCEPINFO.ByReference(); + hr = d.Invoke(dispIdMember, niid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); + COMUtils.checkRC(hr); + + //Wait for event to happen + try { + Thread.sleep(200); +// WinUser.MSG msg = new WinUser.MSG(); +// while (((User32.INSTANCE.GetMessage(msg, null, 0, 0)) != 0)) { +// User32.INSTANCE.TranslateMessage(msg); +// User32.INSTANCE.DispatchMessage(msg); +// } + } catch (Exception e) { + e.printStackTrace(); + } + + Assert.assertTrue(listener.Invoke_called); + } + +} diff --git a/contrib/platform/test/com/sun/jna/platform/win32/COM/ConnectionPointContainer_Test.java b/contrib/platform/test/com/sun/jna/platform/win32/COM/ConnectionPointContainer_Test.java new file mode 100644 index 0000000000..8b1ea575fa --- /dev/null +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/ConnectionPointContainer_Test.java @@ -0,0 +1,242 @@ +/* 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; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.sun.jna.Pointer; +import com.sun.jna.WString; +import com.sun.jna.platform.win32.Guid.CLSID; +import com.sun.jna.platform.win32.Guid.IID; +import com.sun.jna.platform.win32.Guid.REFIID; +import com.sun.jna.platform.win32.OaIdl; +import com.sun.jna.platform.win32.OaIdl.DISPID; +import com.sun.jna.platform.win32.OaIdl.DISPIDByReference; +import com.sun.jna.platform.win32.OaIdl.EXCEPINFO; +import com.sun.jna.platform.win32.OleAuto.DISPPARAMS; +import com.sun.jna.platform.win32.Guid; +import com.sun.jna.platform.win32.Kernel32; +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.WTypes; +import com.sun.jna.platform.win32.WinDef; +import com.sun.jna.platform.win32.WinError; +import com.sun.jna.platform.win32.Variant.VARIANT; +import com.sun.jna.platform.win32.WinDef.DWORDByReference; +import com.sun.jna.platform.win32.WinDef.LCID; +import com.sun.jna.platform.win32.WinDef.UINT; +import com.sun.jna.platform.win32.WinDef.UINTByReference; +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; + +public class ConnectionPointContainer_Test { + + PointerByReference ppWordApp; + + @Before + public void before() { + HRESULT hr = Ole32.INSTANCE.CoInitialize(null); + COMUtils.checkRC(hr); + + // Create word object + CLSID clsid = new CLSID("{000209FF-0000-0000-C000-000000000046}"); + this.ppWordApp = new PointerByReference(); + hr = Ole32.INSTANCE + .CoCreateInstance(clsid, null, WTypes.CLSCTX_SERVER, IDispatch.IID_IDISPATCH, this.ppWordApp); + COMUtils.checkRC(hr); + } + + @After + public void after() { + // Close Word + Dispatch d = new Dispatch(this.ppWordApp.getValue()); + DISPID dispIdMember = new DISPID(1105); // Quit + REFIID.ByValue riid = new REFIID.ByValue(Guid.IID_NULL); + LCID lcid = Kernel32.INSTANCE.GetSystemDefaultLCID(); + WinDef.WORD wFlags = new WinDef.WORD(1); + DISPPARAMS.ByReference pDispParams = new DISPPARAMS.ByReference(); + VARIANT.ByReference pVarResult = new VARIANT.ByReference(); + IntByReference puArgErr = new IntByReference(); + EXCEPINFO.ByReference pExcepInfo = new EXCEPINFO.ByReference(); + d.Invoke(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); + + Ole32.INSTANCE.CoUninitialize(); + } + + @Test + public void queryInterface_ConnectionPointContainer() { + Unknown unk = new Unknown(this.ppWordApp.getValue()); + PointerByReference ppCpc = new PointerByReference(); + IID cpcIID = new IID("{B196B284-BAB4-101A-B69C-00AA00341D07}"); + HRESULT hr = unk.QueryInterface(new REFIID.ByValue(cpcIID), ppCpc); + COMUtils.checkRC(hr); + ConnectionPointContainer cpc = new ConnectionPointContainer(ppCpc.getValue()); + } + + @Test + public void FindConnectionPoint() { + // query for ConnectionPointContainer + Unknown unk = new Unknown(this.ppWordApp.getValue()); + PointerByReference ppCpc = new PointerByReference(); + IID cpcIID = new IID("{B196B284-BAB4-101A-B69C-00AA00341D07}"); + HRESULT hr = unk.QueryInterface(new REFIID.ByValue(cpcIID), ppCpc); + COMUtils.checkRC(hr); + ConnectionPointContainer cpc = new ConnectionPointContainer(ppCpc.getValue()); + + // find connection point for Application_Events4 + IID appEvnts4 = new IID("{00020A01-0000-0000-C000-000000000046}"); + REFIID riid = new REFIID(appEvnts4.getPointer()); + PointerByReference ppCp = new PointerByReference(); + hr = cpc.FindConnectionPoint(riid, ppCp); + COMUtils.checkRC(hr); + ConnectionPoint cp = new ConnectionPoint(ppCp.getValue()); + } + + @Test + public void GetConnectionInterface() { + // query for ConnectionPointContainer + Unknown unk = new Unknown(this.ppWordApp.getValue()); + PointerByReference ppCpc = new PointerByReference(); + IID cpcIID = new IID("{B196B284-BAB4-101A-B69C-00AA00341D07}"); + HRESULT hr = unk.QueryInterface(new REFIID.ByValue(cpcIID), ppCpc); + COMUtils.checkRC(hr); + ConnectionPointContainer cpc = new ConnectionPointContainer(ppCpc.getValue()); + + // find connection point for Application_Events4 + IID appEvnts4 = new IID("{00020A01-0000-0000-C000-000000000046}"); + REFIID riid = new REFIID(appEvnts4.getPointer()); + PointerByReference ppCp = new PointerByReference(); + hr = cpc.FindConnectionPoint(riid, ppCp); + COMUtils.checkRC(hr); + ConnectionPoint cp = new ConnectionPoint(ppCp.getValue()); + + IID cp_iid = new IID(); + hr = cp.GetConnectionInterface(cp_iid); + COMUtils.checkRC(hr); + + Assert.assertEquals(appEvnts4, cp_iid); + } + + class Application_Events4 implements IDispatchCallback { + public DispatchListener listener = new DispatchListener(this); + + @Override + public Pointer getPointer() { + return this.listener.getPointer(); + } + + //------------------------ IDispatch ------------------------------ + @Override + public HRESULT GetTypeInfoCount(UINTByReference pctinfo) { + return new HRESULT(WinError.E_NOTIMPL); + } + + @Override + public HRESULT GetTypeInfo(UINT iTInfo, LCID lcid, PointerByReference ppTInfo) { + return new HRESULT(WinError.E_NOTIMPL); + } + + @Override + public HRESULT GetIDsOfNames(REFIID.ByValue riid, WString[] rgszNames, int cNames, LCID lcid, DISPIDByReference rgDispId) { + return new HRESULT(WinError.E_NOTIMPL); + } + + public boolean Invoke_called = false; + @Override + public HRESULT Invoke(DISPID dispIdMember, REFIID.ByValue riid, LCID lcid, WORD wFlags, + DISPPARAMS.ByReference pDispParams, VARIANT.ByReference pVarResult, EXCEPINFO.ByReference pExcepInfo, + IntByReference puArgErr) { + this.Invoke_called = true; + return new HRESULT(WinError.E_NOTIMPL); + } + + + //------------------------ IUnknown ------------------------------ + public boolean QueryInterface_called = false; + @Override + public HRESULT QueryInterface(REFIID.ByValue refid, PointerByReference ppvObject) { + this.QueryInterface_called = true; + if (null==ppvObject) { + return new HRESULT(WinError.E_POINTER); + } + + String s = refid.toGuidString(); + IID appEvnts4 = new IID("{00020A01-0000-0000-C000-000000000046}"); + REFIID.ByValue riid = new REFIID.ByValue(appEvnts4.getPointer()); + + if (refid.equals(riid)) { + return WinError.S_OK; + } + + if (new Guid.IID(refid.getPointer()).equals(Unknown.IID_IUNKNOWN)) { + ppvObject.setValue(this.getPointer()); + return WinError.S_OK; + } + + if (new Guid.IID(refid.getPointer()).equals(Dispatch.IID_IDISPATCH)) { + ppvObject.setValue(this.getPointer()); + return WinError.S_OK; + } + + return new HRESULT(WinError.E_NOINTERFACE); + } + + public int AddRef() { + return 0; + } + + public int Release() { + return 0; + } + + } + + @Test + public void Advise() { + + // query for ConnectionPointContainer + Unknown unk = new Unknown(this.ppWordApp.getValue()); + PointerByReference ppCpc = new PointerByReference(); + IID cpcIID = new IID("{B196B284-BAB4-101A-B69C-00AA00341D07}"); + HRESULT hr = unk.QueryInterface(new REFIID.ByValue(cpcIID), ppCpc); + COMUtils.checkRC(hr); + ConnectionPointContainer cpc = new ConnectionPointContainer(ppCpc.getValue()); + + // find connection point for Application_Events4 + IID appEvnts4 = new IID("{00020A01-0000-0000-C000-000000000046}"); + REFIID riid = new REFIID(appEvnts4.getPointer()); + PointerByReference ppCp = new PointerByReference(); + hr = cpc.FindConnectionPoint(riid, ppCp); + COMUtils.checkRC(hr); + ConnectionPoint cp = new ConnectionPoint(ppCp.getValue()); + IID cp_iid = new IID(); + hr = cp.GetConnectionInterface(cp_iid); + COMUtils.checkRC(hr); + + Application_Events4 listener = new Application_Events4(); + + DWORDByReference pdwCookie = new DWORDByReference(); + hr = cp.Advise(listener, pdwCookie); + COMUtils.checkRC(hr); + + Assert.assertTrue(listener.QueryInterface_called); + + } + +} 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 new file mode 100644 index 0000000000..102ccf9bca --- /dev/null +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/EnumMoniker_Test.java @@ -0,0 +1,233 @@ +/* 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; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.sun.jna.platform.win32.Ole32; +import com.sun.jna.platform.win32.WinNT; +import com.sun.jna.platform.win32.WinDef.DWORD; +import com.sun.jna.platform.win32.WinDef.ULONG; +import com.sun.jna.platform.win32.WinDef.ULONGByReference; +import com.sun.jna.platform.win32.WinNT.HRESULT; +import com.sun.jna.platform.win32.COM.util.Factory; +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.COM.util.annotation.ComProperty; +import com.sun.jna.ptr.PointerByReference; + +public class EnumMoniker_Test { + + @ComInterface(iid="{00020970-0000-0000-C000-000000000046}") + interface Application { + @ComProperty + boolean getVisible(); + + @ComProperty + void setVisible(boolean value); + + @ComMethod + void Quit(); + } + + @ComObject(progId="Word.Application") + interface MsWordApp extends Application { + } + + Factory factory; + MsWordApp ob1; + MsWordApp ob2; + + @Before + public void before() { + 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(); + Ole32.INSTANCE.CoUninitialize(); + } + + @Test + public void Reset() { + // GetRunningObjectTable + PointerByReference pprot = new PointerByReference(); + HRESULT hr = Ole32.INSTANCE.GetRunningObjectTable(new DWORD(0), pprot); + COMUtils.checkRC(hr); + IRunningObjectTable rot = new RunningObjectTable(pprot.getValue()); + + // EnumRunning + PointerByReference ppenumMoniker = new PointerByReference(); + hr = rot.EnumRunning(ppenumMoniker); + COMUtils.checkRC(hr); + IEnumMoniker iterator = new EnumMoniker(ppenumMoniker.getValue()); + + // Reset + hr = iterator.Reset(); + COMUtils.checkRC(hr); + + // Next + PointerByReference rgelt1 = new PointerByReference(); + ULONGByReference pceltFetched1 = new ULONGByReference(); + hr = iterator.Next(new ULONG(1), rgelt1, pceltFetched1); + COMUtils.checkRC(hr); + + // Reset + hr = iterator.Reset(); + COMUtils.checkRC(hr); + + // Next + PointerByReference rgelt2 = new PointerByReference(); + ULONGByReference pceltFetched2 = new ULONGByReference(); + hr = iterator.Next(new ULONG(1), rgelt2, pceltFetched2); + COMUtils.checkRC(hr); + + assertEquals(rgelt1.getValue(), rgelt2.getValue()); + } + + @Test + public void Next() { + // GetRunningObjectTable + PointerByReference pprot = new PointerByReference(); + HRESULT hr = Ole32.INSTANCE.GetRunningObjectTable(new DWORD(0), pprot); + COMUtils.checkRC(hr); + IRunningObjectTable rot = new RunningObjectTable(pprot.getValue()); + + // EnumRunning + PointerByReference ppenumMoniker = new PointerByReference(); + hr = rot.EnumRunning(ppenumMoniker); + COMUtils.checkRC(hr); + IEnumMoniker iterator = new EnumMoniker(ppenumMoniker.getValue()); + + // Reset + hr = iterator.Reset(); + COMUtils.checkRC(hr); + + // Next + PointerByReference rgelt1 = new PointerByReference(); + ULONGByReference pceltFetched1 = new ULONGByReference(); + hr = iterator.Next(new ULONG(1), rgelt1, pceltFetched1); + COMUtils.checkRC(hr); + + // Next + PointerByReference rgelt2 = new PointerByReference(); + ULONGByReference pceltFetched2 = new ULONGByReference(); + hr = iterator.Next(new ULONG(1), rgelt2, pceltFetched2); + COMUtils.checkRC(hr); + + assertNotEquals(rgelt1.getValue(), rgelt2.getValue()); + } + + @Test + public void Skip() { + // GetRunningObjectTable + PointerByReference pprot = new PointerByReference(); + HRESULT hr = Ole32.INSTANCE.GetRunningObjectTable(new DWORD(0), pprot); + COMUtils.checkRC(hr); + IRunningObjectTable rot = new RunningObjectTable(pprot.getValue()); + + // EnumRunning + PointerByReference ppenumMoniker = new PointerByReference(); + hr = rot.EnumRunning(ppenumMoniker); + COMUtils.checkRC(hr); + IEnumMoniker iterator = new EnumMoniker(ppenumMoniker.getValue()); + + // Reset + hr = iterator.Reset(); + COMUtils.checkRC(hr); + + // Next + PointerByReference rgelt1 = new PointerByReference(); + ULONGByReference pceltFetched1 = new ULONGByReference(); + hr = iterator.Next(new ULONG(1), rgelt1, pceltFetched1); + COMUtils.checkRC(hr); + + // Reset + hr = iterator.Reset(); + COMUtils.checkRC(hr); + + // Skip + hr = iterator.Skip(new ULONG(1)); + COMUtils.checkRC(hr); + + // Next + PointerByReference rgelt2 = new PointerByReference(); + ULONGByReference pceltFetched2 = new ULONGByReference(); + hr = iterator.Next(new ULONG(1), rgelt2, pceltFetched2); + COMUtils.checkRC(hr); + + assertNotEquals(rgelt1.getValue(), rgelt2.getValue()); + } + + @Test + public void Clone() { + // GetRunningObjectTable + PointerByReference pprot = new PointerByReference(); + HRESULT hr = Ole32.INSTANCE.GetRunningObjectTable(new DWORD(0), pprot); + COMUtils.checkRC(hr); + IRunningObjectTable rot = new RunningObjectTable(pprot.getValue()); + + // EnumRunning + PointerByReference ppenumMoniker = new PointerByReference(); + hr = rot.EnumRunning(ppenumMoniker); + COMUtils.checkRC(hr); + IEnumMoniker iterator1 = new EnumMoniker(ppenumMoniker.getValue()); + + // iterator1.Reset + hr = iterator1.Reset(); + COMUtils.checkRC(hr); + + // iterator1.Next + PointerByReference rgelt1 = new PointerByReference(); + ULONGByReference pceltFetched1 = new ULONGByReference(); + hr = iterator1.Next(new ULONG(1), rgelt1, pceltFetched1); + COMUtils.checkRC(hr); + + // iterator1.Clone + PointerByReference ppenum = new PointerByReference(); + hr = iterator1.Clone(ppenum); + COMUtils.checkRC(hr); + IEnumMoniker iterator2 = new EnumMoniker(ppenum.getValue()); + + // iterator2.Next + PointerByReference rgelt2 = new PointerByReference(); + ULONGByReference pceltFetched2 = new ULONGByReference(); + hr = iterator2.Next(new ULONG(1), rgelt2, pceltFetched2); + COMUtils.checkRC(hr); + + assertNotEquals(rgelt1.getValue(), rgelt2.getValue()); + + // iterator1.Next + rgelt1 = new PointerByReference(); + pceltFetched1 = new ULONGByReference(); + hr = iterator1.Next(new ULONG(1), rgelt1, pceltFetched1); + COMUtils.checkRC(hr); + + assertEquals(rgelt1.getValue(), rgelt2.getValue()); + } + +} 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 746a388643..6df3845f9a 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 @@ -16,6 +16,7 @@ import com.sun.jna.WString; import com.sun.jna.platform.win32.Guid.CLSID; +import com.sun.jna.platform.win32.Guid.REFIID; import com.sun.jna.platform.win32.OaIdl.DISPIDByReference; import com.sun.jna.platform.win32.OleAuto.DISPPARAMS; import com.sun.jna.platform.win32.Guid; @@ -101,7 +102,7 @@ public void testGetIDsOfNames() { WString[] ptName = new WString[] { new WString("Application") }; DISPIDByReference pdispID = new DISPIDByReference(); - HRESULT hr = dispatch.GetIDsOfNames(Guid.IID_NULL, ptName, 1, LOCALE_SYSTEM_DEFAULT, pdispID); + HRESULT hr = dispatch.GetIDsOfNames(new REFIID.ByValue(Guid.IID_NULL), ptName, 1, LOCALE_SYSTEM_DEFAULT, pdispID); COMUtils.checkRC(hr); assertEquals(0, hr.intValue()); } 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 5c8a6b6146..33d65e9456 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 @@ -15,6 +15,7 @@ import junit.framework.TestCase; import com.sun.jna.platform.win32.Guid.CLSID; +import com.sun.jna.platform.win32.Guid.REFIID; import com.sun.jna.platform.win32.Ole32; import com.sun.jna.platform.win32.W32Errors; import com.sun.jna.platform.win32.WTypes; @@ -65,7 +66,7 @@ protected void setUp() throws Exception { public void testQueryInterface() { Unknown iUnknown = this.createIUnknown(); PointerByReference ppvObject = new PointerByReference(); - iUnknown.QueryInterface(IUnknown.IID_IUNKNOWN, ppvObject); + iUnknown.QueryInterface(new REFIID.ByValue(IUnknown.IID_IUNKNOWN), ppvObject); assertTrue("ppvObject:" + ppvObject.toString(), ppvObject != null); } 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 new file mode 100644 index 0000000000..c3f17d3df0 --- /dev/null +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/RunningObjectTable_Test.java @@ -0,0 +1,182 @@ +/* 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; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.sun.jna.platform.win32.Ole32; +import com.sun.jna.platform.win32.Guid.REFIID; +import com.sun.jna.platform.win32.WTypes.BSTRByReference; +import com.sun.jna.platform.win32.WinDef.DWORD; +import com.sun.jna.platform.win32.WinDef.ULONG; +import com.sun.jna.platform.win32.WinDef.ULONGByReference; +import com.sun.jna.platform.win32.WinNT; +import com.sun.jna.platform.win32.WinNT.HRESULT; +import com.sun.jna.ptr.PointerByReference; + +public class RunningObjectTable_Test { + + @Before + public void before() { + HRESULT hr = Ole32.INSTANCE.CoInitialize(null); + COMUtils.checkRC(hr); + } + + @After + public void after() { + Ole32.INSTANCE.CoUninitialize(); + } + + @Test + public void GetRunningObjectTable() { + PointerByReference pprot = new PointerByReference(); + HRESULT hr = Ole32.INSTANCE.GetRunningObjectTable(new DWORD(0), pprot); + COMUtils.checkRC(hr); + + assertNotNull(pprot.getValue()); + } + + @Test + public void Register() { + PointerByReference pprot = new PointerByReference(); + HRESULT hr = Ole32.INSTANCE.GetRunningObjectTable(new DWORD(0), pprot); + COMUtils.checkRC(hr); + IRunningObjectTable rot = new RunningObjectTable(pprot.getValue()); + + //Can't yet be tested as IMoniker is not fully implemented + //rot.Register(grfFlags, punkObject, pmkObjectName, pdwRegister); + + } + + @Test + public void Revoke() { + PointerByReference pprot = new PointerByReference(); + HRESULT hr = Ole32.INSTANCE.GetRunningObjectTable(new DWORD(0), pprot); + COMUtils.checkRC(hr); + IRunningObjectTable rot = new RunningObjectTable(pprot.getValue()); + + //Can't yet be tested as IMoniker is not fully implemented, + // so we can't register an object, and hence can't get a registration key to Revoke one + //rot.Revoke(dwRegister); + + } + + @Test + public void IsRunning() { + PointerByReference pprot = new PointerByReference(); + HRESULT hr = Ole32.INSTANCE.GetRunningObjectTable(new DWORD(0), pprot); + COMUtils.checkRC(hr); + IRunningObjectTable rot = new RunningObjectTable(pprot.getValue()); + + //Can't yet be tested as IMoniker is not fully implemented, + //rot.IsRunning(pmkObjectName); + + } + + @Test + public void GetObject() { + PointerByReference pprot = new PointerByReference(); + HRESULT hr = Ole32.INSTANCE.GetRunningObjectTable(new DWORD(0), pprot); + COMUtils.checkRC(hr); + IRunningObjectTable rot = new RunningObjectTable(pprot.getValue()); + + PointerByReference ppenumMoniker = new PointerByReference(); + hr = rot.EnumRunning(ppenumMoniker); + COMUtils.checkRC(hr); + IEnumMoniker iterator = new EnumMoniker(ppenumMoniker.getValue()); + + iterator.Reset(); + + PointerByReference rgelt = new PointerByReference(); + ULONGByReference pceltFetched = new ULONGByReference(); + hr = iterator.Next(new ULONG(1), rgelt, pceltFetched); + + while (WinNT.S_OK.equals(hr) && pceltFetched.getValue().intValue() > 0) { + Moniker moniker = new Moniker(rgelt.getValue()); + + PointerByReference ppbc = new PointerByReference(); + Ole32.INSTANCE.CreateBindCtx(new DWORD(), ppbc); + //IBindCtx pbc = new BindCtx(ppbc.getValue()); + + 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)); + + PointerByReference ppunkObject = new PointerByReference(); + hr = rot.GetObject(moniker.getPointer(), ppunkObject); + COMUtils.checkRC(hr); + + IUnknown unk = new Unknown(ppunkObject.getValue()); + PointerByReference ppvObject = new PointerByReference(); + hr = unk.QueryInterface(new REFIID.ByValue(IUnknown.IID_IUNKNOWN), ppvObject); + assertEquals(0, hr.intValue()); + assertNotNull(ppvObject.getValue()); + + moniker.Release(); + + hr = iterator.Next(new ULONG(1), rgelt, pceltFetched); + } + + } + + @Test + public void NoteChangeTime() { + PointerByReference pprot = new PointerByReference(); + HRESULT hr = Ole32.INSTANCE.GetRunningObjectTable(new DWORD(0), pprot); + COMUtils.checkRC(hr); + IRunningObjectTable rot = new RunningObjectTable(pprot.getValue()); + + //Can't yet be tested as IMoniker is not fully implemented, + // so we can't register an object, and hence can't get a registration key + //rot.NoteChangeTime(dwRegister, pfiletime); + + } + + @Test + public void GetTimeOfLastChange() { + PointerByReference pprot = new PointerByReference(); + HRESULT hr = Ole32.INSTANCE.GetRunningObjectTable(new DWORD(0), pprot); + COMUtils.checkRC(hr); + IRunningObjectTable rot = new RunningObjectTable(pprot.getValue()); + + //Can't yet be tested as IMoniker is not fully implemented, + // so we can't register an object, and hence can't get a registration key + //rot.GetTimeOfLastChange(pmkObjectName, pfiletime); + + } + + @Test + public void EnumRunning() { + PointerByReference pprot = new PointerByReference(); + HRESULT hr = Ole32.INSTANCE.GetRunningObjectTable(new DWORD(0), pprot); + COMUtils.checkRC(hr); + IRunningObjectTable rot = new RunningObjectTable(pprot.getValue()); + + PointerByReference ppenumMoniker = new PointerByReference(); + hr = rot.EnumRunning(ppenumMoniker); + COMUtils.checkRC(hr); + + assertNotNull(ppenumMoniker.getValue()); + + } + + + +} 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 new file mode 100644 index 0000000000..cc099a13d1 --- /dev/null +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/util/ComEventCallbacks_Test.java @@ -0,0 +1,268 @@ +/* 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 org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.sun.jna.platform.win32.User32; +import com.sun.jna.platform.win32.WinDef.HWND; +import com.sun.jna.platform.win32.COM.util.annotation.ComEventCallback; +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.COM.util.annotation.ComProperty; + +public class ComEventCallbacks_Test { + + Factory factory; + + @Before + public void before() { + this.factory = new Factory(); + } + + @After + public void after() { + this.factory.disposeAll(); + this.factory.getComThread().terminate(100); + } + + + @ComObject(progId="Word.Application") + interface ComIMsWordApp extends ComIApplication { + } + + @ComInterface(iid="{00020970-0000-0000-C000-000000000046}") + interface ComIApplication extends IUnknown, IConnectionPoint { + @ComProperty + boolean getVisible(); + + @ComProperty + void setVisible(boolean value); + + @ComMethod + void Quit(boolean SaveChanges, Object OriginalFormat, Boolean RouteDocument); + + @ComProperty + ComIDocuments getDocuments(); + + } + + @ComInterface(iid="{0002096C-0000-0000-C000-000000000046}") + interface ComIDocuments { + @ComMethod + ComIDocument Open(String fileName); + @ComMethod + ComIDocument Add(); + } + + @ComInterface(iid="{0002096B-0000-0000-C000-000000000046}") + interface ComIDocument { + @ComProperty + String getFullName(); + + @ComMethod + void Select(); + } + + @ComInterface(iid="{00020962-0000-0000-C000-000000000046}") + interface ComIWindow {} + + @ComInterface(iid="{00020975-0000-0000-C000-000000000046}") + public interface ComISelection { + @ComProperty + String getText(); + } + + @ComInterface(iid="{00020A01-0000-0000-C000-000000000046}") + interface ApplicationEvents4_Event { + @ComEventCallback(dispid=10) + void WindowActivate(ComIDocument doc, ComIWindow win); + + @ComEventCallback(dispid=2) + void Quit(); + + @ComEventCallback(dispid=12) + void WindowSelectionChange(ComISelection sel); + } + + class ApplicationEvents4_EventListener extends AbstractComEventCallbackListener implements ApplicationEvents4_Event { + + @Override + public void errorReceivingCallbackEvent(String message, Exception exception) { + + } + + Boolean WindowActivate_called = null; + @Override + public void WindowActivate(ComIDocument doc, ComIWindow win) { + if (null!=doc && null !=win) { + String docName = doc.getFullName(); + WindowActivate_called = true; + } + } + + Boolean Quit_called = null; + @Override + public void Quit() { + Quit_called = true; + } + + Boolean WindowSelectionChange_called = null; + @Override + public void WindowSelectionChange(ComISelection sel) { + if (null!=sel) { + String t = sel.getText(); + WindowSelectionChange_called = true; + } + } + + } + + @Test + public void advise_Quit() { + // Create word object + ComIMsWordApp wordObj = factory.createObject(ComIMsWordApp.class); + ComIApplication wordApp = wordObj.queryInterface(ComIApplication.class); + wordApp.setVisible(true); + ApplicationEvents4_EventListener listener = new ApplicationEvents4_EventListener(); + wordApp.advise(ApplicationEvents4_Event.class, listener); + + wordApp.Quit(false, null, null); + + //Wait for event to happen + try { + Thread.sleep(200); + } catch (Exception e) { + e.printStackTrace(); + } + + Assert.assertNotNull(listener.Quit_called); + Assert.assertTrue(listener.Quit_called); + } + + @Test + public void unadvise_Quit() { + // Create word object + ComIMsWordApp wordObj = factory.createObject(ComIMsWordApp.class); + ComIApplication wordApp = wordObj.queryInterface(ComIApplication.class); + + ApplicationEvents4_EventListener listener = new ApplicationEvents4_EventListener(); + IComEventCallbackCookie cookie = wordApp.advise(ApplicationEvents4_Event.class, listener); + + wordApp.unadvise(ApplicationEvents4_Event.class, cookie); + listener.Quit_called=false; + wordApp.Quit(false, null, null); + + //Wait for event to happen + try { + Thread.sleep(200); + } catch (Exception e) { + e.printStackTrace(); + } + + Assert.assertNotNull(listener.Quit_called); + Assert.assertFalse(listener.Quit_called); + } + + @Test + public void WindowActivate() { + // Create word object + ComIMsWordApp wordObj = factory.createObject(ComIMsWordApp.class); + ComIApplication wordApp = wordObj.queryInterface(ComIApplication.class); + wordApp.setVisible(true); + ApplicationEvents4_EventListener listener = new ApplicationEvents4_EventListener(); + wordApp.advise(ApplicationEvents4_Event.class, listener); + wordApp.getDocuments().Add(); + + //bring word doc to front + HWND h = User32.INSTANCE.FindWindow("OpusApp", null); + if (h == null) + h = User32.INSTANCE.FindWindow("NetUIHWND", null); + User32.INSTANCE.ShowWindow(h, User32.SW_RESTORE); + User32.INSTANCE.SetForegroundWindow(h); + + //Wait for event to happen + try { + Thread.sleep(500); + } catch (Exception e) { + e.printStackTrace(); + } + + Assert.assertNotNull(listener.WindowActivate_called); + Assert.assertTrue(listener.WindowActivate_called); + + wordApp.Quit(false, null, null); + + } + + @Test + public void WindowSelectionChanged() { + // Create word object + ComIMsWordApp wordObj = factory.createObject(ComIMsWordApp.class); + ComIApplication wordApp = wordObj.queryInterface(ComIApplication.class); + wordApp.setVisible(true); + ApplicationEvents4_EventListener listener = new ApplicationEvents4_EventListener(); + wordApp.advise(ApplicationEvents4_Event.class, listener); + + ComIDocument doc = wordApp.getDocuments().Add(); + + doc.Select(); + + //Wait for event to happen + try { + Thread.sleep(200); + } catch (Exception e) { + e.printStackTrace(); + } + + Assert.assertNotNull(listener.WindowSelectionChange_called); + Assert.assertTrue(listener.WindowSelectionChange_called); + + wordApp.Quit(false, null, null); + + } + +// @Test +// public void WindowSelectionChanged_jvmCrash() { +// // Create word object +// ComIMsWordApp wordObj = factory.createObject(ComIMsWordApp.class); +// ComIApplication wordApp = wordObj.queryInterface(ComIApplication.class); +// wordApp.setVisible(true); +// ApplicationEvents4_EventListener listener = new ApplicationEvents4_EventListener(); +// wordApp.advise(ApplicationEvents4_Event.class, listener); +// +// +// +// ComIDocument doc = wordApp.getDocuments().Add(); +// +// doc.Select(); +// +// //Wait for event to happen +// try { +// Thread.sleep(2000000); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// +// Assert.assertNotNull(listener.WindowSelectionChange_called); +// Assert.assertTrue(listener.WindowSelectionChange_called); +// +// wordApp.Quit(false, null, null); +// +// } + +} 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 new file mode 100644 index 0000000000..30a55dc892 --- /dev/null +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/util/ProxyObject_Test.java @@ -0,0 +1,130 @@ +/* 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 static org.junit.Assert.*; + +import java.util.List; + +import javax.management.InvalidApplicationException; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.sun.jna.platform.win32.COM.COMException; +import com.sun.jna.platform.win32.COM.COMUtils; +import com.sun.jna.platform.win32.COM.util.annotation.ComInterface; +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.Guid.IID; +import com.sun.jna.platform.win32.Ole32; +import com.sun.jna.platform.win32.Ole32Util; +import com.sun.jna.platform.win32.OleAuto; +import com.sun.jna.platform.win32.Variant; +import com.sun.jna.platform.win32.WinDef; +import com.sun.jna.platform.win32.WinNT; +import com.sun.jna.ptr.PointerByReference; + +public class ProxyObject_Test { + + @ComInterface(iid="{00020970-0000-0000-C000-000000000046}") + interface Application extends IUnknown { + @ComProperty + boolean getVisible(); + + @ComProperty + void setVisible(boolean value); + + @ComMethod + void Quit(boolean SaveChanges, Object OriginalFormat, Boolean RouteDocument); + } + + @ComObject(progId="Word.Application") + interface MsWordApp extends Application { + } + + Factory factory; + + @Before + public void before() { + this.factory = new Factory(); + //ensure there are no word applications running. + while(true) { + try { + MsWordApp ao = this.factory.fetchObject(MsWordApp.class); + Application a = ao.queryInterface(Application.class); + try { + a.Quit(true, null, null); + try { + //wait for it to quit + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } catch (Exception e) { + e.printStackTrace();e.getCause().printStackTrace(); + } + } catch(Exception e) { + break; + } + } + } + + @After + public void after() { + try { + //wait for it to quit + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + + @Test + public void equals() { + MsWordApp comObj1 = this.factory.createObject(MsWordApp.class); + MsWordApp comObj2 = this.factory.fetchObject(MsWordApp.class); + + boolean res = comObj1.equals(comObj2); + + assertTrue(res); + + comObj1.Quit(false, null,null); + } + + @Test + public void notEquals() { + MsWordApp comObj1 = this.factory.createObject(MsWordApp.class); + MsWordApp comObj2 = this.factory.createObject(MsWordApp.class); + + boolean res = comObj1.equals(comObj2); + + assertFalse(res); + + comObj1.Quit(false, null,null); + } + + @Test + public void accessWhilstDisposing() { + MsWordApp comObj1 = this.factory.createObject(MsWordApp.class); + + //TODO: how to test this? + + this.factory.disposeAll(); + + } + +} 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 new file mode 100644 index 0000000000..544bec0365 --- /dev/null +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/util/RunningObjectTable_Test.java @@ -0,0 +1,133 @@ +/* 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 static org.junit.Assert.*; + +import java.util.List; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.sun.jna.platform.win32.COM.COMException; +import com.sun.jna.platform.win32.COM.COMUtils; +import com.sun.jna.platform.win32.COM.util.annotation.ComInterface; +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.Guid.IID; +import com.sun.jna.platform.win32.Ole32; +import com.sun.jna.platform.win32.Ole32Util; +import com.sun.jna.platform.win32.OleAuto; +import com.sun.jna.platform.win32.Variant; +import com.sun.jna.platform.win32.WinDef; +import com.sun.jna.platform.win32.WinNT; +import com.sun.jna.ptr.PointerByReference; + +public class RunningObjectTable_Test { + + @ComInterface(iid="{00020970-0000-0000-C000-000000000046}") + interface Application extends IUnknown { + @ComProperty + boolean getVisible(); + + @ComProperty + void setVisible(boolean value); + + @ComMethod + void Quit(boolean SaveChanges, Object OriginalFormat, Boolean RouteDocument); + } + + @ComObject(progId="Word.Application") + interface MsWordApp extends Application { + } + + Factory factory; + MsWordApp msWord; + + @Before + public void before() { + this.factory = new Factory(); + //ensure there is only one word application running. + while(true) { + try { + MsWordApp ao = this.factory.fetchObject(MsWordApp.class); + Application a = ao.queryInterface(Application.class); + try { + a.Quit(true, null, null); + try { + //wait for it to quit + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } catch (Exception e) { + e.printStackTrace();e.getCause().printStackTrace(); + } + } catch(Exception e) { + break; + } + } + + + this.msWord = this.factory.createObject(MsWordApp.class); + msWord.setVisible(true); + } + + @After + public void after() { + this.msWord.Quit(true, null, null); + try { + //wait for it to quit + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + @Test + public void getRunningObjectTable() { + IRunningObjectTable rot = this.factory.getRunningObjectTable(); + + assertNotNull(rot); + } + + @Test + public void enumRunning() { + IRunningObjectTable rot = this.factory.getRunningObjectTable(); + + for(IUnknown obj: rot.enumRunning()) { + try { + Application msw = obj.queryInterface(Application.class); + } catch(COMException ex) { + int i= 0; + } + } + } + + @Test + public void getActiveObjectsByInterface() { + IRunningObjectTable rot = this.factory.getRunningObjectTable(); + + List objs = rot.getActiveObjectsByInterface(Application.class); + assertTrue(objs.size() > 0); + + for(Application dobj: objs) { + msWord.setVisible(true); + boolean v2 = dobj.getVisible(); + assertEquals(true, v2); + } + + } +} diff --git a/contrib/platform/test/com/sun/jna/platform/win32/GuidTest.java b/contrib/platform/test/com/sun/jna/platform/win32/GuidTest.java index b5bb00b3b3..c474981348 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/GuidTest.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/GuidTest.java @@ -126,4 +126,18 @@ public void testNewGuid() { assertEquals(guidFromString.toGuidString(), guidString); } + + /** + * Tests the GUID.ByValue. + */ + public void testGuidByValue() { + GUID newGuid = GUID.newGuid(); + String guidString = newGuid.toGuidString(); + + GUID.ByValue bv = new GUID.ByValue(newGuid); + + String guidBV = bv.toGuidString(); + + assertEquals(guidBV, guidString); + } }