diff --git a/jacob/JacobComLifetime.html b/jacob/JacobComLifetime.html
new file mode 100644
index 0000000..7f1a3a7
--- /dev/null
+++ b/jacob/JacobComLifetime.html
@@ -0,0 +1,51 @@
+
COM Object Lifetime in JACOB
+
+
introduction
+
+JACOB Version 1.7 implements a new
+Threading Model that is more
+compatible with COM apartments. There is also an incompatibility
+between the Java object lifetime model and that of COM objects.
+COM Objects live and die by their reference count, whereas Java
+objects are collected by the Garbage Collector (GC) based on algortihms
+that are hidden from the user.
+
COM Object Lifetime in JACOB Prior to Version 1.7
+
+In version 1.6 and earlier, JACOB objects which wrapped COM objects
+had finalize()
methods that would call a native
+release
method which would call a COM Release
.
+
+This has many problems. For one thing, the GC may take a long time to
+kick in and resource consumption may grow. However, the more problematic
+issue is that finalizers are called from a separate thread, and, as was
+discussed in the Threading Model
+document, this can result in COM errors if the object is running in an
+STA. Even if the object is running in an MTA, the finalizer may decide
+to run after we have terminated the thread that holds the component, in
+which case we would get fatal errors and crashes.
+
COM Object Lifetime in JACOB in Version 1.7
+
+In Version 1.7, all JACOB objects which wrap COM objects extend
+com.jacob.com.JacobObject
. This object has some special
+code to register itself with a com.jacob.com.ROT
object
+which represents a Running Object Table (ROT). This table maps a
+Thread to the set of JacobObjects created in that thread. Therefore,
+when you call ComThread.Release()
, the ROT checks whether
+that thread has created any objects, and these objects are released
+by calling their native release
method (which is public).
+
+This lifetime management method ties the lifecycle to the thread's
+lifecycle rather than the GC. The JacobObject's still have finalizers,
+but they will typically not perform the native release
+since that has already been called. The native release
+methods were written such that you can call them multiple times without
+worrying - since they zero out the native pointer when called the first
+time.
+
+If you choose to call release
methods on your objects
+yourself, that is allowed. In that case, when the thread is released
+the release calls will be no-ops.
+
+It becomes important for you to call ComThread.Release()
+on any thread before you allow it to exit, otherwise you may get
+some random crashes later on in your code.
diff --git a/jacob/JacobThreading.html b/jacob/JacobThreading.html
new file mode 100644
index 0000000..7960551
--- /dev/null
+++ b/jacob/JacobThreading.html
@@ -0,0 +1,410 @@
+
COM Apartments in JACOB
+
+
introduction
+
+The COM model for Threading differs from the Java model.
+In COM, each component can declare whether or not it support
+multi-threading.
+
+You can find some basic information about COM threading at:
+
+
+http://www.execpc.com/~gopalan/com/com_threading.html
+
+
+www.microsoft.com/msj/0297/apartment/apartment.htm
+
+
+http://www.cswl.com/whiteppr/white/multithreading.html
+
+
+The term Single Threaded Apartment (STA) refers to a thread
+where all COM objects created in that thread are
+single-threaded. This can manifest itself in two ways:
+
+Either all calls into that component are made from the same thread
+that created the component
+
+OR any call that is made from another thread gets serialized by COM.
+This serialization of calls is done by using a Windows message loop and
+posting messages to a hidden window (I'm not kidding). The way COM
+achieves this is by requiring any other thread to make calls through
+a local Proxy object rather than the original object (more on this
+when we discuss the JACOB DispatchProxy class).
+
+What does this mean for a Java application? If you are using a component
+that declares itself as ThreadingModel "Apartment" (you can
+find this out by looking in the registry under its CLSID), and you plan
+to create, use and destroy this component in one thread - then you are
+following the rules of an STA and you can declare the thread as an
+STA thread.
+
+On the other hand, if you need to make method calls from another thread
+(e.g. in a servlet) then you have a few choices. Either you
+create the component in its own STA, by extending
+com.jacob.com.STA
, and use the
+com.jacob.com.DispatchProxy
class to pass the Dispatch
+pointer between threads, or you can declare your thread as an MTA
+thread. In that case, COM will make
+the cross-thread calls into the STA that is running your component.
+If you create an Apartment threaded component in the MTA,
+COM will automatically create an STA for you and put your
+component in there, and then marshall all the calls.
+
+This brings us to the notion of a Main STA. COM requires that
+if there is any Apartment threaded component in your application, then
+the first STA created is tagged as the Main STA. COM uses the
+Main STA to create all the Apartment threaded components that are
+created from an MTA thread. The problem is that if you have already
+created an STA, then COM will pick that as the Main STA, and if you
+ever exit that thread - the whole application will exit.
+
+
COM Threads in JACOB Prior to Version 1.7
+
+Up until version 1.7 of JACOB, there was only one model available
+in JACOB:
+
+-
+Before version 1.6: All threads were automatically initialized as STAs.
+
+-
+In version 1.6: All threads were automatically initialized as MTAs.
+
+
+
+The reason for the change in default was that tagging a Java thread
+as an STA can cause problems. Any Java Swing application, as well as
+servlets and applets need to be able to make calls from multiple
+threads. If you try to make COM method calls across STA threads - it
+will fail!
+
+In most cases, the default chosen by JACOB 1.6 (MTA) works fine, however
+there are some notable exceptions that have caused people grief. One
+such exception is in the case of MAPI. It turns out that if you try to
+create a MAPI object from an MTA thread - it simply fails and exits.
+This has caused some people to recompile JACOB 1.6 back with the STA
+default.
+
+There is another problem with MTA threads: when you are using Apartment
+threaded components, we already noted that COM will create the
+components in the Main STA. If one doesn't exist, COM will create it.
+However, this means that all Apartment threaded components will
+be created in the same STA. This creates a bottleneck, and a
+dependency between unrelated components. Also, if that STA exits, then
+all components are destroyed and the application will likely crash.
+
+
COM Threads in JACOB Version 1.7
+
+In Version 1.7 we have added finer grained control to allow the
+Java programmer to control how COM creates its components.
+Unfortunately, this means that you need to have a pretty good
+understanding of the dark and mystical subject of COM Apartments.
+There are a few different cases you need to consider:
+
Default
+
+If you simply run code that was created in Version 1.6 and ignore
+the COM threading issue, then you will get the same behavior as in 1.6:
+Each java thread will be an MTA thread, and all Apartment threaded
+components will be created by COM in its own Main STA. This typically
+works for most applications (exceptions noted above).
+
Create Your Own Apartment
+
+To declare an MTA thread use the following template:
+
+
+
+ComThread.InitMTA();
+...
+...
+ComThread.Release();
+
+
+
+If you want JACOB to create its own Main STA (rather than having COM
+choose an STA for you), then you should use:
+
+
+
+Thread 1:
+ComThread.InitMTA(true); // a true tells JACOB to create a Main STA
+...
+...
+ComThread.Release();
+...
+Thread 2:
+ComThread.InitMTA();
+...
+...
+ComThread.Release();
+...
+...
+ComThread.quitMainSTA();
+
+
+
+In this case, you can also create the Main STA explicitly:
+
+
+
+ComThread.startMainSTA();
+...
+...
+Thread 1:
+ComThread.InitMTA();
+...
+...
+ComThread.Release();
+...
+Thread 2:
+ComThread.InitMTA();
+...
+...
+ComThread.Release();
+...
+...
+ComThread.quitMainSTA();
+
+
+
+In the latter case, all Apartment threaded components will be created in
+JACOB's main STA. This still has all the problems of components
+sharing the same Main STA and creating a bottleneck. To avoid that,
+you can also create STA threads yourself:
+
+
+
+ComThread.startMainSTA();
+...
+...
+Thread 1:
+ComThread.InitSTA();
+...
+...
+ComThread.Release();
+...
+Thread 2:
+ComThread.InitMTA();
+...
+...
+ComThread.Release();
+...
+...
+ComThread.quitMainSTA();
+
+
+
+In this example, thread 1 is an STA and thread 2 is an MTA. You could
+omit the call to ComThread.startMainSTA(), but if you do, then COM will
+make the first STA your main one, and then if you exit that thread,
+the application will crash.
+
+Actually, Thread 1 is almost an STA. It's lacking a windows
+message loop. So, this type of STA is fine as long as you are creating
+a component and using it in the same thread, and not makind event
+callbacks.
+
JACOB's STA Class
+
+If you want to create an true STA where you can create a component and
+then let other threads call methods on it, then you need a windows
+message loop. JACOB provides a class called:
+com.jacob.com.STA
which does exactly this.
+
+
+public class com.jacob.com.STA extends java.lang.Thread
+{
+ public com.jacob.com.STA();
+ public boolean OnInit(); // you override this
+ public void OnQuit(); // you override this
+ public void quit(); // you can call this from ANY thread
+}
+
+
+
+The STA class extends
+java.lang.Thread
and it provides you with two methods
+that you can override: OnInit
and OnQuit
.
+These methods are called from the thread's run
method
+so they will execute in the new thread. These methods allow you to
+create COM components (Dispatch objects) and release them.
+To create an STA, you subclass it and override the OnInit.
+
+The quit
method is the only other method that
+can be called from any thread. This method uses the Win32 function
+PostThreadMessage
to force the STA's windows message loop
+to exit, thereby terminating the thread.
+
+You will then need to make calls into the component that is running
+in the STA thread. If you simply try to make calls from another thread
+on a Dispatch object created in the STA thread, you will get a COM
+Exception. For more details see:
+
+Don Box 'Effective COM' Rule 29: Don't Access raw
+interface pointers across apartment boundaries.
+
The DispatchProxy Class
+Since you cannot call methods directly on a Dispatch object created
+in another STA JACOB provides a method for the class that created
+the Dispatch object to marshal it to your thread. This is done via
+the com.jacob.com.DispatchProxy
class.
+
+
+public class DispatchProxy extends JacobObject {
+ public DispatchProxy(Dispatch);
+ public Dispatch toDispatch();
+
+ public native void release();
+ public void finalize();
+}
+
+
+
+This class works as follows: the thread that created the Dispatch
+object constructs an instance of DispatchProxy(Dispatch) with the
+Dispatch as a parameter. This instance can then be accessed from
+another thread, which will invoke its toDispatch
method
+proxy as if it were local to your thread. COM will do the inter-thread
+marshalling transparently.
+
+The following example is part of samples/test/ScriptTest2.java in the
+JACOB distribution. It shows how you can create the ScriptControl
+in one STA thread and make method calls on it from another:
+
+
+import com.jacob.com.*;
+import com.jacob.activeX.*;
+
+class ScriptTest2 extends STA
+{
+ public static ActiveXComponent sC;
+ public static Dispatch sControl = null;
+ public static DispatchProxy sCon = null;
+
+ public boolean OnInit()
+ {
+ try
+ {
+ System.out.println("OnInit");
+ System.out.println(Thread.currentThread());
+ String lang = "VBScript";
+
+ sC = new ActiveXComponent("ScriptControl");
+ sControl = (Dispatch)sC.getObject();
+
+ // sCon can be called from another thread
+ sCon = new DispatchProxy(sControl);
+
+ Dispatch.put(sControl, "Language", lang);
+ return true;
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ public void OnQuit()
+ {
+ System.out.println("OnQuit");
+ }
+
+ public static void main(String args[]) throws Exception
+ {
+ try {
+ ComThread.InitSTA();
+ ScriptTest2 script = new ScriptTest2();
+ Thread.sleep(1000);
+
+ // get a thread-local Dispatch from sCon
+ Dispatch sc = sCon.toDispatch();
+
+ // call a method on the thread-local Dispatch obtained
+ // from the DispatchProxy. If you try to make the same
+ // method call on the sControl object - you will get a
+ // ComException.
+ Variant result = Dispatch.call(sc, "Eval", args[0]);
+ System.out.println("eval("+args[0]+") = "+ result);
+ script.quit();
+ System.out.println("called quit");
+ } catch (ComException e) {
+ e.printStackTrace();
+ }
+ finally
+ {
+ ComThread.Release();
+ }
+ }
+}
+
+
+
+You can try to modify the Dispatch.call
invocation in
+the main thread to use sControl
directly, and you will see
+that it fails. Notice that once we construct the ScriptTest2 object
+in the main thread, we sleep for a second to allow the other thread
+time to initialize itself.
+
+The STA thread calls sCon = new DispatchProxy(sControl);
+to save a global reference to the DispatchProxy that represents the
+sControl
object. The main thread then calls:
+Dispatch sc = sCon.toDispatch();
to get a local Dispatch
+proxy out of the DispatchProxy object.
+
+At most one(!)
+thread can call toDispatch(), and the call can be made only once.
+This is because a IStream object is used to pass the proxy, and
+it is only written once and closed when you read it.
+If you need multiple threads to access a Dispatch pointer, then
+create that many DispatchProxy objects. For more details please
+refer to the Don Box reference above.
+
+
+
Recommended Procedure
+
+-
+It is recommended that you always allow JACOB to manage the main STA
+rather than letting COM create one on its own or tag one of yours.
+
+-
+Declare an STA thread using ComThread.InitSTA()
+if all your
+method calls for that component are going to come from the same thread.
+
+-
+If you want an STA thread that allows other threads to call into it,
+use the
com.jacob.com.STA
class as outlined above.
+
+-
+If you have a COM component that declares its ThreadingModel as
+"Free" or "Both", then use the MTA.
+
+-
+In most cases, if you need to make method calls from multiple threads,
+you can simply
+use MTA threads, and allow COM to create the components in
+the Main STA. You should only create your own STA's and DispatchProxy
+if you understand COM well enough to know when the MTA solution
+will fail or have other shortcomings.
+
+There are 3 examples in the samples/test directory that demonstrate
+these cases:
+
+ScriptTest.java - creates an STA for the ScriptControl component and
+runs all its method calls from that STA.
+
+ScriptTest2.java - creates a separate STA thread, and makes
+method calls into the component from another thread using DispatchProxy.
+
+ScriptTest3.java - creates a separate MTA thread, and makes method
+calls into the component from another MTA thread. This is simpler
+than ScriptTest2 for most applications.
+
+
Default Threading Model
+If you create a new thread, and don't call
+ComThread.InitSTA()
or ComThread.InitMTA()
+on it, then the first time your java code creates a JacobObject, it
+will try to register itself with the ROT, and when it sees that the
+current thread is not initialized, it will initialize it as MTA.
+This means that the code to do this is no longer inside the native
+jni code - it is now in the com.jacob.com.ROT
class.
+For more details on the ROT, see the
+Object Lifetime document.
diff --git a/jacob/LICENSE.TXT b/jacob/LICENSE.TXT
new file mode 100644
index 0000000..69a2eda
--- /dev/null
+++ b/jacob/LICENSE.TXT
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
diff --git a/jacob/META-INF/MANIFEST.MF b/jacob/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..90f14d9
--- /dev/null
+++ b/jacob/META-INF/MANIFEST.MF
@@ -0,0 +1,897 @@
+Manifest-Version: 1.0
+
+Name: ./com/jacob/activeX/ActiveXComponent.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: qqewKW8c2W7aSvB4Ob/bMbCPeFI=
+MD5-Digest: EZs0WpbDBV5Id5XRw2tbtg==
+
+Name: ./com/jacob/activeX/ActiveXComponent.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: IeJoOZ9U4LtHuqyqJGKG24nDTYw=
+MD5-Digest: Qqf2RAOc0xBTG8dGIyA2+w==
+
+Name: ./com/jacob/com/ComException.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: fuWzbhsBKLBjPtk5pvgVzskMFz4=
+MD5-Digest: vwLlwRM/J9NYONB/UVw1AA==
+
+Name: ./com/jacob/com/ComException.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: 9HsO+/DGzYdZtFDK+Yi6SyEo29I=
+MD5-Digest: tHiTxIfngQHjEXPzVC31pA==
+
+Name: ./com/jacob/com/ComFailException.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: dghV0kFmeXaebK73wRAyBNZsfeM=
+MD5-Digest: EmfTcOZd7lFdNX+ZZIGufA==
+
+Name: ./com/jacob/com/ComFailException.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: yIS8kOUyyl2ymTHxb/8Za4ktjsw=
+MD5-Digest: sdqsHsk9p4XXX5kfvQOQNg==
+
+Name: ./com/jacob/com/ComThread.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: J+KEmDJYSMA2VXg8smZpLFQYAuc=
+MD5-Digest: wnPiLbEgp7GC4sMVsQ1eWg==
+
+Name: ./com/jacob/com/ComThread.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: q0K2wuQ+be8Qrrai/Ui1BTMeFeo=
+MD5-Digest: eH6GkFkD3A3PrX1cZJWr6w==
+
+Name: ./com/jacob/com/Dispatch.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: tYSc84+VUMMWYt7hrLDtcnINNUI=
+MD5-Digest: etVQxCE1JEN1rYCc5ZA79A==
+
+Name: ./com/jacob/com/Dispatch.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: Q95eP1KW/Z/ICzzeaNDCFUIG408=
+MD5-Digest: IovIOD5G/XY7qFAHViNeng==
+
+Name: ./com/jacob/com/DispatchEvents.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: 7cgrmVJc18T/hRvT3931tQzVa5s=
+MD5-Digest: CtihQf0ka9OChKX+OnKucQ==
+
+Name: ./com/jacob/com/DispatchEvents.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: 5MwAZmktJFp7rq23Lz/VG1/ULk4=
+MD5-Digest: 2haKHCBa7UXfl8HCSPEyQQ==
+
+Name: ./com/jacob/com/DispatchProxy.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: xDGCGyw+8G/kxFFOQtQo3rbhDN8=
+MD5-Digest: +5n2WPrM0Jj0FauyuctPMQ==
+
+Name: ./com/jacob/com/DispatchProxy.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: 4NGdFabt0CZL8y56A1x/AEat6/o=
+MD5-Digest: Wd9zhjmACcUxZ3gqdWtB2w==
+
+Name: ./com/jacob/com/EnumVariant.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: ft/EfZ1xwI/J07yz6oxla2jKZFM=
+MD5-Digest: zRYy+0tuDsAQ7SCOJxgx5A==
+
+Name: ./com/jacob/com/EnumVariant.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: 3biekksAd50gb6GRfpefO2PpS6c=
+MD5-Digest: zlu6oH2HFI//sGTexAv9GQ==
+
+Name: ./com/jacob/com/JacobObject.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: 9uw+e0Wxha1A6tp6PFQE1JMJkvQ=
+MD5-Digest: D37EFI7kTv9NEnsyQcsXsA==
+
+Name: ./com/jacob/com/JacobObject.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: TqJDUM7Ujxt5/zAGSG9uCoKcJ4U=
+MD5-Digest: oD0tL8WPPCN3jF59jfd/yA==
+
+Name: ./com/jacob/com/MainSTA.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: 3WKAHdSq2yTa/lqHgyOTo6vqvnk=
+MD5-Digest: h0kY/3xCUs0uCyhWUL+DWQ==
+
+Name: ./com/jacob/com/MainSTA.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: pDIgNuK9H9KhKQEZIMIgM44nDo8=
+MD5-Digest: p/CDI6V3KgdOViQQ6/oR0g==
+
+Name: ./com/jacob/com/ROT.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: bEQuGPBbOn8HlXMmcLQCRh0BlYs=
+MD5-Digest: rCXiBlficXaJbCoFMCeoJg==
+
+Name: ./com/jacob/com/ROT.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: K6WVkJuFZNjgow/o4/1pTyKu2Tk=
+MD5-Digest: eOCwqvCPVk+haZ7WFzEJOg==
+
+Name: ./com/jacob/com/SafeArray.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: AIqtFq0miAVrMUY0HZUnXuhl284=
+MD5-Digest: TiPLaOJAMTzTVP2a2AsX0A==
+
+Name: ./com/jacob/com/SafeArray.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: CGBlCL952tC//MTG+XxqSOQh/hI=
+MD5-Digest: pf25bH4uo0LZOzz7utDa8Q==
+
+Name: ./com/jacob/com/STA.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: 6cqSEZm+8kVkAO4Vnc5G04qCrCE=
+MD5-Digest: 7O16Je2NaryCebJZ28U20A==
+
+Name: ./com/jacob/com/STA.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: S0EbhtSPEAv9fGOaTNBymxmZthM=
+MD5-Digest: 9fcj8YmMFCCfB8M5eF7lPA==
+
+Name: ./com/jacob/com/Variant.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: ea5nat308Pg7cxcJdywpqL++HiM=
+MD5-Digest: 6/TukZAwtC9UOUArjcpTXg==
+
+Name: ./com/jacob/com/Variant.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: psnbnw0M+2egeuqpbf2u1C7I/EY=
+MD5-Digest: iuuq5W1sFXeT269RJC7U6w==
+
+Name: ./com/jacob/com/WrongThreadException.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: 55DxaZjMfzYE9MTCKZ8VPgpjVLc=
+MD5-Digest: 9uygPT4WdJg8N6Yo/t0tkA==
+
+Name: ./com/jacob/com/WrongThreadException.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: PPQzELKIkTeQJfGTBUfUonPdSnc=
+MD5-Digest: bNwuGE+cW1Z9+pWnI3r/Bg==
+
+Name: ./jacob.dll
+Digest-Algorithms: SHA MD5
+SHA-Digest: 3LlRg0frUqmTW8HjSXm2tGZi9og=
+MD5-Digest: MgUWKEmjKUX4hFTLoSyeCA==
+
+Name: ./jacob.jar
+Digest-Algorithms: SHA MD5
+SHA-Digest: xLY8bhITrVUd+Ft+++piDVNh+lc=
+MD5-Digest: 5MOSXL4nEeEAdO40bNd3oA==
+
+Name: ./JacobComLifetime.html
+Digest-Algorithms: SHA MD5
+SHA-Digest: uGRYLP2xhOaPGbunFQ7cxZcUvaw=
+MD5-Digest: 3RU8RW+2/liuGpkyYbTPHg==
+
+Name: ./jacobSrc_18.zip
+Digest-Algorithms: SHA MD5
+SHA-Digest: 2jmj7l5rSw0yVb/vlWAYkK/YBwk=
+MD5-Digest: 1B2M2Y8AsgTpgAmY7PhCfg==
+
+Name: ./JacobThreading.html
+Digest-Algorithms: SHA MD5
+SHA-Digest: IQs2MYpplp8guNE7nFWcnsEJLt8=
+MD5-Digest: MuRQ3uXcEMeB5msQ/oYyTQ==
+
+Name: ./jni/ComThread.cpp
+Digest-Algorithms: SHA MD5
+SHA-Digest: pfEIKsR11Doq3+Dmwpyf6tscRCY=
+MD5-Digest: RDG15eEa+FxZtSmn1sadSg==
+
+Name: ./jni/ComThread.h
+Digest-Algorithms: SHA MD5
+SHA-Digest: JtBBBpPcOqjBm4o10ui48TOgkps=
+MD5-Digest: z3ocf5BOusRSSdB8madNlA==
+
+Name: ./jni/ComThread.obj
+Digest-Algorithms: SHA MD5
+SHA-Digest: Z05DKyL+S6GI3w0GhhkoeWRS+Ss=
+MD5-Digest: wUSJQhroulYl2cZ+eLnu7Q==
+
+Name: ./jni/Dispatch.cpp
+Digest-Algorithms: SHA MD5
+SHA-Digest: FH0YWD3RyD9CR1fHkGiIzJLh0tk=
+MD5-Digest: VAjOj5ZPrBCbqvd15um09w==
+
+Name: ./jni/Dispatch.h
+Digest-Algorithms: SHA MD5
+SHA-Digest: N74Cx8buqtuTUkLbg604pgcRGmE=
+MD5-Digest: bX1snnEyrNBwexgVNtasCg==
+
+Name: ./jni/Dispatch.obj
+Digest-Algorithms: SHA MD5
+SHA-Digest: saxklkHmLIdMVLdKj4vmYRtBHVo=
+MD5-Digest: 0Y6c1VfYLJuQWlm6MI9UuA==
+
+Name: ./jni/DispatchEvents.cpp
+Digest-Algorithms: SHA MD5
+SHA-Digest: UHLjKXAwbPlVN8hQoexl38jv1lM=
+MD5-Digest: lL07d5A5AIxqphOxetIiLg==
+
+Name: ./jni/DispatchEvents.h
+Digest-Algorithms: SHA MD5
+SHA-Digest: VKWhIhXOim7LLhyLGJclVlkilfI=
+MD5-Digest: s4huR7K3gZu5qfQQTTRcGg==
+
+Name: ./jni/DispatchEvents.obj
+Digest-Algorithms: SHA MD5
+SHA-Digest: 0I3opm1/14UCERfLZqUkoAnqObI=
+MD5-Digest: Kd6mTsrifhRCmOT2rUkLHw==
+
+Name: ./jni/DispatchProxy.cpp
+Digest-Algorithms: SHA MD5
+SHA-Digest: sEo5fo91hMQ0k+XVaZk5TCkC0NM=
+MD5-Digest: tsX0rWU+eL5pKaBRhANZIw==
+
+Name: ./jni/DispatchProxy.h
+Digest-Algorithms: SHA MD5
+SHA-Digest: FCqZSwrPy5rOPWeiioNcxz9ooj8=
+MD5-Digest: IfhrIzu/elu0CFTU/+FH0A==
+
+Name: ./jni/DispatchProxy.obj
+Digest-Algorithms: SHA MD5
+SHA-Digest: yN/dtGG4um+SuuQrTo5+1uLSiiY=
+MD5-Digest: FTdU29Tt31Zr+v/uF+Exlg==
+
+Name: ./jni/EnumVariant.cpp
+Digest-Algorithms: SHA MD5
+SHA-Digest: UqE3XEqyuSOqCey9y6NtgO56vlk=
+MD5-Digest: MjoER1irRaeyqAouQJLnaw==
+
+Name: ./jni/EnumVariant.h
+Digest-Algorithms: SHA MD5
+SHA-Digest: rHJQr1J+8v4371BuFvhLifmyXRg=
+MD5-Digest: 0ShO6APjAlzrxpL1VHtp4Q==
+
+Name: ./jni/EnumVariant.obj
+Digest-Algorithms: SHA MD5
+SHA-Digest: SBD1O7LN4s4xoYdYX8HMutBkIno=
+MD5-Digest: q05v4Kbf3xXr6TTKFSJh+g==
+
+Name: ./jni/EventProxy.cpp
+Digest-Algorithms: SHA MD5
+SHA-Digest: tQM4T5PxwKGiWIe7WAr7OUCZn88=
+MD5-Digest: xH3pvJqZW5utS9K2jPDkog==
+
+Name: ./jni/EventProxy.h
+Digest-Algorithms: SHA MD5
+SHA-Digest: 25r17CcIBLdEIoHXKp65NyTmVQk=
+MD5-Digest: 2CpIIkRfJSfZQpkvpbBenQ==
+
+Name: ./jni/EventProxy.obj
+Digest-Algorithms: SHA MD5
+SHA-Digest: gShJkleKBewW8MrzUC0/XvRQWNw=
+MD5-Digest: zpim8NXVV7RfD/xk2mJW6w==
+
+Name: ./jni/jacob.dll
+Digest-Algorithms: SHA MD5
+SHA-Digest: 3LlRg0frUqmTW8HjSXm2tGZi9og=
+MD5-Digest: MgUWKEmjKUX4hFTLoSyeCA==
+
+Name: ./jni/jacob.exp
+Digest-Algorithms: SHA MD5
+SHA-Digest: 72e/gQTKiE1r9Uslz4vYRQ0PHmQ=
+MD5-Digest: 5mklGz6sCKSgVrjey6YL5g==
+
+Name: ./jni/jacob.lib
+Digest-Algorithms: SHA MD5
+SHA-Digest: m8ZbuTExo3Un0O7MWBc5o9WJ6g8=
+MD5-Digest: ybxMyVrwSNUnuhbGLQnYkw==
+
+Name: ./jni/makefile
+Digest-Algorithms: SHA MD5
+SHA-Digest: n/Ol9YQ2klBEFhF8C7gM37Q85go=
+MD5-Digest: 5gkJFwMCbAAZAEyb/OWKPw==
+
+Name: ./jni/README.txt
+Digest-Algorithms: SHA MD5
+SHA-Digest: lHYa7laejzkdRZkjyk5hh01Nh70=
+MD5-Digest: 6YannUlp3XpNr7bZP6i5Bg==
+
+Name: ./jni/SafeArray.cpp
+Digest-Algorithms: SHA MD5
+SHA-Digest: +u64HvTcLPDEuGHsH7ydYMNmROI=
+MD5-Digest: 1C3cuqY05UZF4Kh28Vc3Bw==
+
+Name: ./jni/SafeArray.h
+Digest-Algorithms: SHA MD5
+SHA-Digest: g5KEynNNTCV/0+TtLSrgtBGIVB8=
+MD5-Digest: W6TK/CsQYfRRrCsn1vlf8A==
+
+Name: ./jni/SafeArray.obj
+Digest-Algorithms: SHA MD5
+SHA-Digest: HcWyMrmnhyYxKsIO8GfrtEFgHC0=
+MD5-Digest: saSZ5dtWYxMPDzN6svD+lg==
+
+Name: ./jni/STA.cpp
+Digest-Algorithms: SHA MD5
+SHA-Digest: nEJ3iujtVaHY41S00J/KQSp6MTc=
+MD5-Digest: N3O7B829ib75rCZgY1lifw==
+
+Name: ./jni/STA.h
+Digest-Algorithms: SHA MD5
+SHA-Digest: +VwuhNMGYzZ9aGjZX/YPppDdO1A=
+MD5-Digest: G+RltDyKn4lfuOR9XSQxUA==
+
+Name: ./jni/STA.obj
+Digest-Algorithms: SHA MD5
+SHA-Digest: KUDmvPyX3TI/FlQlk/7NLmZVHZs=
+MD5-Digest: kBJEBoZm/30B9aHP7jAxhg==
+
+Name: ./jni/StdAfx.cpp
+Digest-Algorithms: SHA MD5
+SHA-Digest: QXk1fqHJAYChd8X7CH73V6EJqgU=
+MD5-Digest: rkapC0u6Da9N3BzEShh5uA==
+
+Name: ./jni/StdAfx.h
+Digest-Algorithms: SHA MD5
+SHA-Digest: i9b1viSLE73TdBRHyEYqCQnHdok=
+MD5-Digest: O9mOBXwgjNSj0cF5bibF3g==
+
+Name: ./jni/stdafx.obj
+Digest-Algorithms: SHA MD5
+SHA-Digest: WY6n8VAjHD+D+8yfca65Lv2Yanc=
+MD5-Digest: 1ZNNwyP06I7kkDqF1oWmYA==
+
+Name: ./jni/util.cpp
+Digest-Algorithms: SHA MD5
+SHA-Digest: svps5GbrBIhBersEfXdVDaRxwdM=
+MD5-Digest: V3cYxfy/UdMYgPE4LU2jQw==
+
+Name: ./jni/util.h
+Digest-Algorithms: SHA MD5
+SHA-Digest: If9oIOxyhA0rL44GJlLkrc1IDPg=
+MD5-Digest: A7UlJkDnsxJEKCtn6G1UOw==
+
+Name: ./jni/util.obj
+Digest-Algorithms: SHA MD5
+SHA-Digest: Eycr3pdkbM6wpCusv6ppEtXavQQ=
+MD5-Digest: HiuPDNWBFDdn7X4DutL/mw==
+
+Name: ./jni/Variant.cpp
+Digest-Algorithms: SHA MD5
+SHA-Digest: ZVW7VPsmlHWKjuTpZKs08XlS320=
+MD5-Digest: faCR0N6dP5W+bxzgvblpsA==
+
+Name: ./jni/Variant.h
+Digest-Algorithms: SHA MD5
+SHA-Digest: xEKVgKNM1RnfDIKpP01mHj+3SqU=
+MD5-Digest: jeRydyEBbi2E+WLhuKANIg==
+
+Name: ./jni/Variant.obj
+Digest-Algorithms: SHA MD5
+SHA-Digest: VkpRSFzVd3DOh5l14/Ohhf3+FBM=
+MD5-Digest: 0A4By2V6SdUdFYoNaELkSA==
+
+Name: ./LICENSE.TXT
+Digest-Algorithms: SHA MD5
+SHA-Digest: f6pMV3+4WoA2adisGIy1Rax2W8o=
+MD5-Digest: fCYjCTNV8MYNNuW3i2aTFw==
+
+Name: ./makefile
+Digest-Algorithms: SHA MD5
+SHA-Digest: 8fbp+qFE+YwIwHcapQbHKyq6QE8=
+MD5-Digest: /37LTLMPhiaLolS1X1k1HQ==
+
+Name: ./README.TXT
+Digest-Algorithms: SHA MD5
+SHA-Digest: NCWTHs86RAcfK917rbotr81sExc=
+MD5-Digest: +KTt8W0TCJsei2AxVFpQFQ==
+
+Name: ./samples/ado/ADO_README.txt
+Digest-Algorithms: SHA MD5
+SHA-Digest: vyqm9URm65OyGqdOiWCuk67W94I=
+MD5-Digest: gP7U0PwFXCXojgEkzzXYIg==
+
+Name: ./samples/ado/Command.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: VYX5u7DXdbMzqsFPgv5yox5adKs=
+MD5-Digest: ZISCJalFcRGqxRX+172meg==
+
+Name: ./samples/ado/Command.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: u/GPTs8U4XUh8qsXCYrkGpmAq58=
+MD5-Digest: hru+Ns3kuh7ukNMEo7UYlw==
+
+Name: ./samples/ado/CommandTypeEnum.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: hegtG5C8KdUCTpjqfsU30otxd3Y=
+MD5-Digest: aBVcQnMQtpARZsSJcrxoPg==
+
+Name: ./samples/ado/CommandTypeEnum.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: 7fa7uxQ9WMUFB6ms7rEi3nKyM/s=
+MD5-Digest: Ey7VKrr+74MTFlyJRdK1WQ==
+
+Name: ./samples/ado/Connection.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: jmve106WOcmbLHhPKwQolgOEl0c=
+MD5-Digest: TGjR6vuVVJkepeC8Bkx0Mw==
+
+Name: ./samples/ado/Connection.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: aIz0OGEkKM5qhfqGPDaizgSQH6o=
+MD5-Digest: uKdIqNEb0fQW6/F54+ULyg==
+
+Name: ./samples/ado/Field.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: jxR9z2XYejS/LMekS66Slmc7/Wc=
+MD5-Digest: sGuUfiZ0YbwCsSmI6mrHCQ==
+
+Name: ./samples/ado/Field.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: yXzIXtij0oGqhOpZViy+2GzMqgA=
+MD5-Digest: gjaIquVdHvBcVczuTZjqMQ==
+
+Name: ./samples/ado/Fields.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: 1qWM9CqE5xj2nH7qFOJ6MGY8CjI=
+MD5-Digest: 9rkQ0Cdn32mX+NkIr6JiQg==
+
+Name: ./samples/ado/Fields.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: blVsEdbjJxuW4X4jO9CWgQirOm4=
+MD5-Digest: As+B/G3vm+k5pzQWXTAsdw==
+
+Name: ./samples/ado/ms/README
+Digest-Algorithms: SHA MD5
+SHA-Digest: WYL+bmWW1nkqEGoOHgf4E5+80Lw=
+MD5-Digest: VPd6NUQNQ5kJOgMbpyCd4A==
+
+Name: ./samples/ado/ms/testms.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: RoKESkqQJiR1k9PRG0VbhdjRChE=
+MD5-Digest: GHy6MwcQVWfuBMTWFX3tdg==
+
+Name: ./samples/ado/ms/testms.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: GW9uXFNDW4pTPSjZHo2D5lFc/zU=
+MD5-Digest: +6iJfY4I6HB/eA8LcgKB6A==
+
+Name: ./samples/ado/Recordset.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: 7DOBgOnKy6VMFm7V59fULgPEfio=
+MD5-Digest: M5HhfmAKFb/b/C6csy69wA==
+
+Name: ./samples/ado/Recordset.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: WSFzf787gED6BkN3vSVGhXxb/XU=
+MD5-Digest: aOk5BtJdTTJuJpGyWUpRIg==
+
+Name: ./samples/ado/test.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: AEXzmSw0nhniEgEgcHEqSAIY6cs=
+MD5-Digest: nQp4MdGvsHDnkVG1CzDRrA==
+
+Name: ./samples/ado/test.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: u59LMxRc+XIhuM/vHtznkCLC0IE=
+MD5-Digest: b4q8u/F+GYhyWIr1cM8EdA==
+
+Name: ./samples/applet/AppTest.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: n56Is99dBgC8tQ6K9IqwYnALkmI=
+MD5-Digest: FdQ7a7vx1CXpNinMKQEveQ==
+
+Name: ./samples/applet/AppTest.html
+Digest-Algorithms: SHA MD5
+SHA-Digest: 2pGYv1dUavvaMY+1b0hBhS9mv3Y=
+MD5-Digest: rZWQxtKOziVCquj5M6GFFw==
+
+Name: ./samples/applet/AppTest.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: pC2PW5TpOHZuAYJGm9B1Od/BRw4=
+MD5-Digest: qMKmotn7i7fzaPgoBD6gdQ==
+
+Name: ./samples/README.txt
+Digest-Algorithms: SHA MD5
+SHA-Digest: 9kyVx/ey8MxEfF1HATrDZlg9Rxk=
+MD5-Digest: gRXrNz3NEKFy7fasoujArg==
+
+Name: ./samples/servlet/JacobScript.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: NY4hemo3uGEIBCWTyyyzm7a0CzQ=
+MD5-Digest: MUuHIxHh6F98jE0YH7P+bg==
+
+Name: ./samples/servlet/JacobScript.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: dvp/KSXGqV6gC2s9NPzTvAbm0uc=
+MD5-Digest: JUP2vLcS7M4pe9uWJsIOWw==
+
+Name: ./samples/servlet/readme.txt
+Digest-Algorithms: SHA MD5
+SHA-Digest: GE4VxwDk3uAEQDBvvWBoOe4KKXw=
+MD5-Digest: 1MSy/NVW2EyTybpjuagEIQ==
+
+Name: ./samples/test/Access.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: YJ8ho+ID8ugfEDWCPxYbNoiNpsE=
+MD5-Digest: QInWVJKkR9hjDynEpHjVOQ==
+
+Name: ./samples/test/Access.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: uqv9slXCqv98mTceAxd95Y7Vrh0=
+MD5-Digest: fpK035MccuE2h/Z01omyOA==
+
+Name: ./samples/test/atl/MultiFace/dlldata.c
+Digest-Algorithms: SHA MD5
+SHA-Digest: HWTbDhfSULe5RQibEUEI830BLuE=
+MD5-Digest: 0+48R+h0ivE4WGRJFfPJDA==
+
+Name: ./samples/test/atl/MultiFace/Face.cpp
+Digest-Algorithms: SHA MD5
+SHA-Digest: OhddW2y86e39z4U0TPDtqmB+MmA=
+MD5-Digest: 4dTrCiRHhORZk4BnDf7z3w==
+
+Name: ./samples/test/atl/MultiFace/Face.h
+Digest-Algorithms: SHA MD5
+SHA-Digest: y0gekndtQPP58IyEFliYdG37qns=
+MD5-Digest: GTxFB6uT1X5vEGI0WcrL/Q==
+
+Name: ./samples/test/atl/MultiFace/Face.rgs
+Digest-Algorithms: SHA MD5
+SHA-Digest: F8u+qbVSCFIKnUMKvvy5UYQ+HLs=
+MD5-Digest: S4ANAdXVLXbCPN2x7uD5pQ==
+
+Name: ./samples/test/atl/MultiFace/MultiFace.aps
+Digest-Algorithms: SHA MD5
+SHA-Digest: lQbTvrX5Vvm9994+oYa+l9zCrMI=
+MD5-Digest: u2p9rqJFCAD8E0y/GBYa9w==
+
+Name: ./samples/test/atl/MultiFace/MultiFace.cpp
+Digest-Algorithms: SHA MD5
+SHA-Digest: k3Fh0X2Zf2P5HFYX0XBC3cr8F8U=
+MD5-Digest: dgadf5J+z2FmRkZrARoVhw==
+
+Name: ./samples/test/atl/MultiFace/MultiFace.def
+Digest-Algorithms: SHA MD5
+SHA-Digest: 2LcCcz80Nw99Cplvy56LVfKj4AQ=
+MD5-Digest: u/wev8ycCsOtBXjq4koWsA==
+
+Name: ./samples/test/atl/MultiFace/MultiFace.dsp
+Digest-Algorithms: SHA MD5
+SHA-Digest: EP934454nHfECg4uMbMpi2qSiBg=
+MD5-Digest: BpITlBALRWf1UnbtvqJ1tw==
+
+Name: ./samples/test/atl/MultiFace/MultiFace.dsw
+Digest-Algorithms: SHA MD5
+SHA-Digest: HPkFe3R5aG/7zdtwSpPIvCoJrX8=
+MD5-Digest: JwOWHmGnfAJWodLnqiA4ig==
+
+Name: ./samples/test/atl/MultiFace/MultiFace.h
+Digest-Algorithms: SHA MD5
+SHA-Digest: NzYDi990PqhD0pyW/XswKUHiQGI=
+MD5-Digest: I4SDltcfIyyBFfg71dSKoA==
+
+Name: ./samples/test/atl/MultiFace/MultiFace.idl
+Digest-Algorithms: SHA MD5
+SHA-Digest: rE8NyFJgJFgoxHYEFJRFTwIGTjA=
+MD5-Digest: Yf3mnqG5Jx/iSE5S/1N3QA==
+
+Name: ./samples/test/atl/MultiFace/MultiFace.ncb
+Digest-Algorithms: SHA MD5
+SHA-Digest: 7GDt/Nx4jef09B5ACmv+1xqcQt4=
+MD5-Digest: zyxbqfMC8PmDrMRA4VvVcA==
+
+Name: ./samples/test/atl/MultiFace/MultiFace.opt
+Digest-Algorithms: SHA MD5
+SHA-Digest: 9KOiwG4QxIFaNgVtYosl9rn4F5Q=
+MD5-Digest: Ai1X3ztSmyZneaivsOIhgA==
+
+Name: ./samples/test/atl/MultiFace/MultiFace.plg
+Digest-Algorithms: SHA MD5
+SHA-Digest: GgHEYrPCgoTvQJbLVkGSucuJI84=
+MD5-Digest: fzXVPatmqIW5BKWNn20x1w==
+
+Name: ./samples/test/atl/MultiFace/MultiFace.rc
+Digest-Algorithms: SHA MD5
+SHA-Digest: cKcPvkLwFvr2SpNabMVU4LRCHQQ=
+MD5-Digest: B81k6bAmMI8mY9pywHyQ9Q==
+
+Name: ./samples/test/atl/MultiFace/MultiFace.tlb
+Digest-Algorithms: SHA MD5
+SHA-Digest: 45izBsDG1ouPhqTvH8IDPK9oNlY=
+MD5-Digest: 5smfNJ6a5a/r3EBBmZN/Yw==
+
+Name: ./samples/test/atl/MultiFace/MultiFaceps.def
+Digest-Algorithms: SHA MD5
+SHA-Digest: BZnsV6gPHLCjBY1gkyjg/SCOw+4=
+MD5-Digest: nAyFg5jxyfxmfe2MD3C1vA==
+
+Name: ./samples/test/atl/MultiFace/MultiFaceps.mk
+Digest-Algorithms: SHA MD5
+SHA-Digest: bJNeboLTRvXTAOuiiEboGEW6s/8=
+MD5-Digest: L+Fei2KII1dnTm5Goszing==
+
+Name: ./samples/test/atl/MultiFace/MultiFace_i.c
+Digest-Algorithms: SHA MD5
+SHA-Digest: L+orpCaMGOQ+onrBja2eUcqCkZg=
+MD5-Digest: EMEes+f0GfZuWG1TY8iItg==
+
+Name: ./samples/test/atl/MultiFace/MultiFace_p.c
+Digest-Algorithms: SHA MD5
+SHA-Digest: qhXfLrVwc3+a2zQh3nqfuMMXJj4=
+MD5-Digest: PddZdwiG4GABL2pFOgRWjg==
+
+Name: ./samples/test/atl/MultiFace/resource.h
+Digest-Algorithms: SHA MD5
+SHA-Digest: ltVpL0yIoPqNP533PfXz0Mz3or0=
+MD5-Digest: 67snAuAXM2aTH3ZXCjkOsg==
+
+Name: ./samples/test/atl/MultiFace/StdAfx.cpp
+Digest-Algorithms: SHA MD5
+SHA-Digest: rRcr4BUiUcSuC9HT6rQc5MToiHk=
+MD5-Digest: I/3OLbvTOW7wzD1mshUuuQ==
+
+Name: ./samples/test/atl/MultiFace/StdAfx.h
+Digest-Algorithms: SHA MD5
+SHA-Digest: q4qcVRmFU7LYISdjJeW4CgEE9Xg=
+MD5-Digest: jPsHuOvPDPZYxq1xxcvLsg==
+
+Name: ./samples/test/atl/MultiFace.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: 68ZRr3nlrxp7xvgB8QtPLvBXkB0=
+MD5-Digest: +E/sNJRVhdK9DvCHDKyeKA==
+
+Name: ./samples/test/atl/MultiFace.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: RD5SVQAbELsukdxLSrAlVraY5Rw=
+MD5-Digest: O0/kAOqvz9Y1Gow65MmdJQ==
+
+Name: ./samples/test/atl/readme.txt
+Digest-Algorithms: SHA MD5
+SHA-Digest: EHBHwONmkXMZLgpTRc6m8pORye0=
+MD5-Digest: D+oj7h9BOskXCcBQuBSFdw==
+
+Name: ./samples/test/DispatchTest.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: b+R4oUyy/tugq7jgd+ZKEzqd5pI=
+MD5-Digest: Uf5nmYcYZrCNk/YSYyUpcA==
+
+Name: ./samples/test/DispatchTest.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: W0BY50++uyVxEmDh8soynVg6lwI=
+MD5-Digest: A6oIyzfJUCR1M6k3fQQz8Q==
+
+Name: ./samples/test/errEvents.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: EzYY0sXl18eP1HDctmCpgEWXxxI=
+MD5-Digest: 2ZH6Pcx49W7FYL9aF1qiPQ==
+
+Name: ./samples/test/foo.foo
+Digest-Algorithms: SHA MD5
+SHA-Digest: hKLRQFDind7Bt/el/UA0bOILVEc=
+MD5-Digest: LfWLkubtUd37afJ4Ctu48A==
+
+Name: ./samples/test/foo.ser
+Digest-Algorithms: SHA MD5
+SHA-Digest: lmeuI3I317iY2RKqZL40s3zMkZA=
+MD5-Digest: D73llNfjRNWi6/yEfqjcZg==
+
+Name: ./samples/test/IEEvents.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: MzKjQ9LnBvcLGqb4eIoYX3pbWro=
+MD5-Digest: rLvMvumb3zT+lmpnH12/0g==
+
+Name: ./samples/test/IETest.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: 7wOaFqd2TvqatunZ8cgjkuwvAmc=
+MD5-Digest: +Jlit06yZxTmsaTAGLjR8A==
+
+Name: ./samples/test/IETest.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: t3BKHw/pqw5198/fE3ttMMBijbE=
+MD5-Digest: oBRVGqLdSZSxD6Acpne9mA==
+
+Name: ./samples/test/jacobtest.xls
+Digest-Algorithms: SHA MD5
+SHA-Digest: iPakwQbwO78iKOXAnKi7J1vzvEs=
+MD5-Digest: n07pNBLHIG662l3KfsZWdg==
+
+Name: ./samples/test/math.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: Z4QCBzw8I8743G2bsANsMvYvQjU=
+MD5-Digest: oAuf3ElYdBR3Lmrq0+d9Og==
+
+Name: ./samples/test/math.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: n8YiT1GFbeaWXLMy+INu2Wfl7/k=
+MD5-Digest: h1G6CVTiAFjm7Re1f64NEA==
+
+Name: ./samples/test/MathProj/Math.cls
+Digest-Algorithms: SHA MD5
+SHA-Digest: CZJcmhZCs1+1p4NO71dggowWNc8=
+MD5-Digest: +gkN44UHyxn83JeQVf+E6Q==
+
+Name: ./samples/test/MathProj/MathTest.dll
+Digest-Algorithms: SHA MD5
+SHA-Digest: hoUwAKBHCK55cn7JdsA3wBf/Bn0=
+MD5-Digest: 3BcNgFO5perWuHx79V0mXg==
+
+Name: ./samples/test/MathProj/MathTest.exp
+Digest-Algorithms: SHA MD5
+SHA-Digest: ff9RS0k+cu2JO360qYqMoA1oJuA=
+MD5-Digest: FNmayjvq8mTjLcIUbX5Zkw==
+
+Name: ./samples/test/MathProj/MathTest.lib
+Digest-Algorithms: SHA MD5
+SHA-Digest: 62KdZxK15c8CLHZXYnJxbrjuBIc=
+MD5-Digest: Is8yCaURP4hrKCZbNWmW7Q==
+
+Name: ./samples/test/MathProj/MathTest.vbp
+Digest-Algorithms: SHA MD5
+SHA-Digest: I/k59CxSo5KBb/Mj0zLXnB/gpDU=
+MD5-Digest: Iil+Tidd/5EWFe5TnPwhiA==
+
+Name: ./samples/test/MathProj/MathTest.vbw
+Digest-Algorithms: SHA MD5
+SHA-Digest: h3dc5rr6p7aV45U26F4DyFTJM7I=
+MD5-Digest: LudpvbnfPRzD0GwfkSjRdg==
+
+Name: ./samples/test/MathProj/README
+Digest-Algorithms: SHA MD5
+SHA-Digest: nPVI0dpp+w5yLvy/p9le2e4BwiY=
+MD5-Digest: S8VlUENr3X79v9OFAUljyQ==
+
+Name: ./samples/test/Outlook.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: DbN+VE/zRE6P+R2qIph048KmCl8=
+MD5-Digest: Sxs8kOpskGsoOpwnSJxX2g==
+
+Name: ./samples/test/Outlook.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: OBV8N5rPxKJliq2DSDxLlJe8+2c=
+MD5-Digest: 1ZgPwE5lkgetta1TElh2Iw==
+
+Name: ./samples/test/safearray.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: C9m0td07CI3WCNqMvDgCReVBk4U=
+MD5-Digest: 3sWM1BZ/M6XrqeIJCSnIfw==
+
+Name: ./samples/test/safearray.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: /F4AvsA0zZN/I7cJAr1sHRsw+Fc=
+MD5-Digest: oKA2jfEuphjZf30RyxJsvQ==
+
+Name: ./samples/test/sample2.mdb
+Digest-Algorithms: SHA MD5
+SHA-Digest: Wp2D73waAFiEmDPw8ji7q+jZgFQ=
+MD5-Digest: ZKs2YBS5XVEK9iDtHnGUpw==
+
+Name: ./samples/test/sa_dispatch.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: nCuBxiPc21pt7CnmxD+TIV4x1FI=
+MD5-Digest: IhuUwtw0m6RfONvXtqvSAw==
+
+Name: ./samples/test/sa_dispatch.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: tIIx4FMZGe7k6+GH4ajRoWPJvyY=
+MD5-Digest: DWknkLquVVJKRyKYSfXSOA==
+
+Name: ./samples/test/sa_test.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: NhQ8ICD0BX3upJ3yhPox7D4OrYw=
+MD5-Digest: 2J2GkyWd+qfgf7Fjs8JnwA==
+
+Name: ./samples/test/sa_test.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: R682jIXe76aB9kJyNM0wtbZqtxU=
+MD5-Digest: qLpQzDlRNgHUMSNvW9F9Vw==
+
+Name: ./samples/test/ScriptTest.bat
+Digest-Algorithms: SHA MD5
+SHA-Digest: bxoaT2EWQv5FYtCWB0e9T89wJ2c=
+MD5-Digest: iQQJtrBB1MZ6ljtIXoqIxQ==
+
+Name: ./samples/test/ScriptTest.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: 9McitGPdEWuF+klNFu9Op2dcOuk=
+MD5-Digest: SzDmf+iH5s/E1EmYPh208w==
+
+Name: ./samples/test/ScriptTest.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: yo2azi6j2xgIDKymZGO5l4FEdjE=
+MD5-Digest: P/DSKEt74WRFIgJqRVHVtw==
+
+Name: ./samples/test/ScriptTest2.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: LktPbcouI60ec7wmvfmurGSFaT4=
+MD5-Digest: OygfOlXJlkqn1x4TM8eI7g==
+
+Name: ./samples/test/ScriptTest2.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: HTrcf7IR3Og5i0xIw1mB7F4i0AY=
+MD5-Digest: cyeOvZyeb0ZMjYFwAuCvRw==
+
+Name: ./samples/test/ScriptTest3.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: ZdD9Uar1kiYkiiOrOG5/Zs/gKHQ=
+MD5-Digest: JP8N1C1bKhlZUzjNWjtfMw==
+
+Name: ./samples/test/ScriptTest3.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: Q0QxUzUMaIEUiuSiCYFDh8tPWzk=
+MD5-Digest: 2JjocMlhddWcUXsKb3Arlw==
+
+Name: ./samples/test/speed.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: DdOhaT+V3Gz8lUFpTjkNHU8yUHI=
+MD5-Digest: 10C0cOv36ugsmjtRdWiYeQ==
+
+Name: ./samples/test/speed.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: VRRtx5ebOKZ9w9i7zr5tjiGHtSA=
+MD5-Digest: fW3+AiO4odk/dPP8QRwP7g==
+
+Name: ./samples/test/test.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: 0F3HoVHLRbxeIftBk5xSiayuruw=
+MD5-Digest: xmgAS3ZMreVcVetw+Emz6w==
+
+Name: ./samples/test/test.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: fDgQ7roF5yECQWDgqE/H7hMS9lY=
+MD5-Digest: C+R1qFuy0KYA6+NpE6lcMw==
+
+Name: ./samples/test/testEvents.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: VgQZMlTDKdXwHwnO+pg34FVxe+s=
+MD5-Digest: pxOGqcHhcNCgpLrq961CYA==
+
+Name: ./samples/test/variant_test.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: rhCKxgFsnz4DCR3V6ZCnGZMKHNc=
+MD5-Digest: U6IqRLGkVKIi6GYMVfQaJQ==
+
+Name: ./samples/test/variant_test.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: 7NFXoGskiCa/ZL7U8Acx/uZkdTE=
+MD5-Digest: xPiJ1/PwMsYlUPlAiR+wkg==
+
+Name: ./samples/test/varSerTest.class
+Digest-Algorithms: SHA MD5
+SHA-Digest: EyK1bvd0fQXevbJJfukQqFSTq+0=
+MD5-Digest: ceVxF+Oz7CJF5whitqs7IA==
+
+Name: ./samples/test/varSerTest.java
+Digest-Algorithms: SHA MD5
+SHA-Digest: 1kR1a6FqMGKYgazH8ZllBmTxWN4=
+MD5-Digest: E+9UQHIkQN/XII2libkWXw==
+
+Name: ./todo.txt
+Digest-Algorithms: SHA MD5
+SHA-Digest: GuE6XLByuSmPs4Q3TX8Qs2JRSro=
+MD5-Digest: KtiB8O69ft5CCxNs+T9zZQ==
+
+Name: ./vstudio/jacob/jacob.dsp
+Digest-Algorithms: SHA MD5
+SHA-Digest: nreCezgQ/DKa7TQ4Cj28cRzKQzM=
+MD5-Digest: GOjDddOu1ZU5r0iGcEZzaw==
+
+Name: ./vstudio/jacob/jacob.dsw
+Digest-Algorithms: SHA MD5
+SHA-Digest: yB8Hhn1M6jX7cOBloxUL2pAFf7Y=
+MD5-Digest: hGWX78QoGIXxJed6eeTbAQ==
+
+Name: ./vstudio/jacob/jacob.ncb
+Digest-Algorithms: SHA MD5
+SHA-Digest: xSDLS4QUbjm8RHNL/Qzq70zkYlk=
+MD5-Digest: PK8cmkqwvTT9ECgqFhpdVQ==
+
+Name: ./vstudio/jacob/jacob.opt
+Digest-Algorithms: SHA MD5
+SHA-Digest: ZI/dl8LS/Sp5vpLdODDNox8LfMc=
+MD5-Digest: 90HtjVn8YtapmRMC9MAp0g==
+
+Name: ./vstudio/jacob/jacob.plg
+Digest-Algorithms: SHA MD5
+SHA-Digest: 6D62etCgUdwooRVezsQCR5GG79M=
+MD5-Digest: FEkATqvQLJeVQzpfboND4A==
+
+Name: ./WhatsNew.html
+Digest-Algorithms: SHA MD5
+SHA-Digest: WZmYYAE5PedacDkqwqNPFlp4vSE=
+MD5-Digest: WVceOUyV6DUWlncvAuqzpw==
+
diff --git a/jacob/README.TXT b/jacob/README.TXT
new file mode 100644
index 0000000..c4a5c9c
--- /dev/null
+++ b/jacob/README.TXT
@@ -0,0 +1,28 @@
+For documentation see: http://users.rcn.com/danadler/jacob/
+
+The java code is in com\jacob\*.
+
+The C++ code is in .\jni.
+
+To build, run:
+
+nmake -f makefile
+
+That will first compile the JAVA files and build the JAR file, and
+then compile the C++ code and build the DLL.
+
+Building the jni:
+
+The following are hardcoded into the makefile, so you may have to
+change it. I developed this with the C++ compiler and ATL version
+that ship with VC++ 6.0, so I'm not sure if different versions will
+work.
+
+I have compiled this against JDK 1.1.6 and 1.2.2 as well as Microsoft
+SDK for Java 3.2 as the JDK setting.
+
+DEST_DIR is a destination directory into which to copy the final DLL.
+
+JDK = d:\j2sdk1.4.2_06
+DEST_DIR = d:\jacob
+MSDEVDIR = d:\apps\\"Microsoft Visual Studio"\VC98
diff --git a/jacob/WhatsNew.html b/jacob/WhatsNew.html
new file mode 100644
index 0000000..85c6bb3
--- /dev/null
+++ b/jacob/WhatsNew.html
@@ -0,0 +1,114 @@
+What's New in JACOB 1.8
+
+
+-
+Move To SourceForge
+The project is not housed at
+Sourceforge.net.
+
+
+-
+Licensing Change
+All limitations on commercial use of JACOB have been removed and it
+is now being developed under a BSD license at
+Sourceforge.net.
+
+
+-
+Compiled with Java 1.4.2
+Version 1.8 was compiled with JSEE 1.4.2 and fixes the compilation bug
+that was remnant of compilation with JDK 1.1.
+
+
+-
+Baseline For Change
+This version is the baseline for the first CVS checkin and we encourage
+people to start contributing to the project with this version.
+
+
+
+
+ -
+
What's New in JACOB 1.7
+
+
+-
+Explicit COM Threading Model Support:
+See a detailed discussion of
+COM Apartments in JACOB
+
+
+-
+New COM Object Lifetime model:
+See a detailed discussion of
+COM Object Lifetime in JACOB.
+
+
+-
+Improved Event Handling:
+Thanks to code contributed by
+
+Niels Olof Bouvin
+and Henning Jae JACOB 1.7 can
+read the type information of a Connection Point interface by looking
+it up in the registry. This makes it possible to use events with IE as
+well as office products.
+
+
+
+-
+Improved Dispatch:
+Error messages from Invoke failures are now printed out as well as
+allowing the passing in of arguments to a Get method.
+
+
+-
+EnumVariant Implementation:
+Makes it easier to iterate over COM collections. Thanks to code
+contributed by
+Thomas Hallgren.
+
+
+-
+SafeArray leaks:
+SafeArrays were not being properly freed prior to version 1.7, many
+other memory leaks were fixed as well.
+
+
+-
+Visual Studio Project:
+For those who want to debug: vstudio/jacob. At the moment all the
+native code is replicated there from the jni directory...
+
+
+
+Related Links
+
+-
+The JACOB mailing list is hosted at yahoo groups:
+
+http://groups.yahoo.com/group/jacob-project.
+This is the preferred way to get support for JACOB. It also
+includes an extensive archive. If you are doing any development with
+JACOB, please join the list.
+
-
+Massimiliano Bigatti has developed
+
+Jacobgen - a generator that automatically creates JACOB code from
+Type Libraries
+
+-
+Steven Lewis is developing a version of Java2Com that supports JACOB
+code generation. See:
+
+http://www.lordjoe.com/Java2Com/index.html.
+
-
+To find documentation on the com.ms.com package, go to:
+
+http://www.microsoft.com/java/download/dl_sdk40.htm
+and at the bottom of the page is a link that says:
+Microsoft SDK for Java 4.0 Documentation Only. You should download
+that file and install it. Then, view sdkdocs.chm and look for
+"Microsoft Packages Reference". Hopefully, the next release of
+JACOB will include full javadoc (volunteers?)...
+
diff --git a/jacob/com/jacob/activeX/ActiveXComponent.java b/jacob/com/jacob/activeX/ActiveXComponent.java
new file mode 100644
index 0000000..6835076
--- /dev/null
+++ b/jacob/com/jacob/activeX/ActiveXComponent.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jacob.activeX;
+
+import com.jacob.com.*;
+
+/**
+ * This class simulates com.ms.activeX.ActiveXComponent only as
+ * it used for creating Dispatch objects
+ */
+public class ActiveXComponent extends Dispatch
+{
+ public ActiveXComponent(String progid)
+ {
+ super(progid);
+ }
+
+ public Object getObject()
+ {
+ return this;
+ }
+
+ public Variant invoke(String name, Variant[] args)
+ {
+ return Dispatch.callN(this, name, args);
+ }
+
+ public Variant getProperty(String name)
+ {
+ return Dispatch.get(this, name);
+ }
+
+ public void setProperty(String name, Variant arg)
+ {
+ Dispatch.put(this, name, arg);
+ }
+
+ protected void finalize()
+ {
+ super.finalize();
+ }
+
+ static {
+ System.loadLibrary("jacob");
+ }
+}
diff --git a/jacob/com/jacob/com/ComException.java b/jacob/com/jacob/com/ComException.java
new file mode 100644
index 0000000..742d703
--- /dev/null
+++ b/jacob/com/jacob/com/ComException.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jacob.com;
+
+public abstract class ComException extends RuntimeException
+{
+ // Fields
+ protected int hr;
+ protected int m_helpContext;
+ protected String m_helpFile;
+ protected String m_source;
+
+ // Constructors
+ public ComException()
+ {
+ super();
+ }
+
+ public ComException(int hr)
+ {
+ super();
+ this.hr = hr;
+ }
+
+ public ComException(int hr, String description)
+ {
+ super(description);
+ this.hr = hr;
+ }
+
+ public ComException(int hr, String source, String helpFile,
+ int helpContext)
+ {
+ super();
+ this.hr = hr;
+ m_source = source;
+ m_helpFile = helpFile;
+ m_helpContext = helpContext;
+ }
+
+ public ComException(int hr, String description, String source,
+ String helpFile, int helpContext)
+ {
+ super(description);
+ this.hr = hr;
+ m_source = source;
+ m_helpFile = helpFile;
+ m_helpContext = helpContext;
+ }
+
+ public ComException(String description)
+ {
+ super(description);
+ }
+
+ // Methods
+ public int getHelpContext() { return m_helpContext; }
+ public String getHelpFile() { return m_helpFile; }
+ public int getHResult() { return hr; }
+ public String getSource() { return m_source; }
+}
diff --git a/jacob/com/jacob/com/ComFailException.java b/jacob/com/jacob/com/ComFailException.java
new file mode 100644
index 0000000..6f72140
--- /dev/null
+++ b/jacob/com/jacob/com/ComFailException.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jacob.com;
+
+public class ComFailException extends ComException
+{
+ // Constructors
+ public ComFailException(int hr)
+ {
+ super(hr);
+ }
+ public ComFailException(int hr, String message)
+ {
+ super(hr, message);
+ }
+
+ public ComFailException(int hr, String source, String helpFile,
+ int helpContext)
+ {
+ super(hr, source, helpFile, helpContext);
+ }
+
+ public ComFailException(int hr, String description,
+ String source, String helpFile, int helpContext)
+ {
+ super(hr, description, source, helpFile, helpContext);
+ }
+
+ public ComFailException()
+ {
+ super();
+ }
+
+ public ComFailException(String message)
+ {
+ super(message);
+ }
+}
diff --git a/jacob/com/jacob/com/ComThread.java b/jacob/com/jacob/com/ComThread.java
new file mode 100644
index 0000000..f375060
--- /dev/null
+++ b/jacob/com/jacob/com/ComThread.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jacob.com;
+import java.util.Hashtable;
+import java.util.Vector;
+
+public abstract class ComThread
+{
+ private static final int MTA = 0x0;
+ private static final int STA = 0x2;
+
+ public static boolean haveSTA = false;
+ public static MainSTA mainSTA = null;
+
+ /**
+ * Initialize the current java thread to be part of the
+ * Multi-threaded COM Apartment
+ */
+ public static synchronized void InitMTA()
+ {
+ InitMTA(false);
+ }
+
+ /**
+ * Initialize the current java thread to be an STA
+ */
+ public static synchronized void InitSTA()
+ {
+ InitSTA(false);
+ }
+
+ /**
+ * Initialize the current java thread to be part of the
+ * Multi-threaded COM Apartment, if createMainSTA is true,
+ * create a separate MainSTA
+ * thread that will house all Apartment Threaded components
+ */
+ public static synchronized void InitMTA(boolean createMainSTA)
+ {
+ Init(createMainSTA, MTA);
+ }
+
+ /**
+ * Initialize the current java thread to be an STA
+ * COM Apartment, if createMainSTA is true,
+ * create a separate MainSTA
+ * thread that will house all Apartment Threaded components
+ */
+ public static synchronized void InitSTA(boolean createMainSTA)
+ {
+ Init(createMainSTA, STA);
+ }
+
+ public static synchronized void startMainSTA()
+ {
+ mainSTA = new MainSTA();
+ haveSTA = true;
+ }
+
+ public static synchronized void quitMainSTA()
+ {
+ if (mainSTA != null) mainSTA.quit();
+ }
+
+ /**
+ * Initialize the current java thread to be part of the
+ * MTA/STA COM Apartment
+ */
+ public static synchronized void Init(boolean createMainSTA, int mode)
+ {
+ if (createMainSTA && !haveSTA)
+ {
+ // if the current thread is going to be in the MTA and there
+ // is no STA thread yet, then create a main STA thread
+ // to avoid COM creating its own
+ startMainSTA();
+ }
+ //System.out.println("before Init: "+mode);
+ doCoInitialize(mode);
+ //System.out.println("after Init");
+ ROT.addThread();
+ //System.out.println("after ROT.addThread");
+ }
+
+ /**
+ * Call CoUninitialize to release this java thread from COM
+ */
+ public static synchronized void Release()
+ {
+ //System.out.println("before clearObjects");
+ ROT.clearObjects();
+ //System.out.println("before UnInit");
+ doCoUninitialize();
+ //System.out.println("after UnInit");
+ }
+
+ public static native void doCoInitialize(int threadModel);
+ public static native void doCoUninitialize();
+
+ static {
+ System.loadLibrary("jacob");
+ }
+}
diff --git a/jacob/com/jacob/com/Dispatch.java b/jacob/com/jacob/com/Dispatch.java
new file mode 100644
index 0000000..2d351a8
--- /dev/null
+++ b/jacob/com/jacob/com/Dispatch.java
@@ -0,0 +1,546 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jacob.com;
+
+import java.lang.reflect.Array;
+
+public class Dispatch extends JacobObject
+{
+ public int m_pDispatch;
+ public static final int LOCALE_SYSTEM_DEFAULT = 2048;
+ public static final int Method = 1;
+ public static final int Get = 2;
+ public static final int Put = 4;
+ public static final int PutRef = 8;
+ public static final int fdexNameCaseSensitive = 1;
+ public static final int DISPID_UNKNOWN = -1;
+ public static final int DISPID_VALUE = 0;
+ public static final int DISPID_PROPERTYPUT = -3;
+ public static final int DISPID_NEWENUM = -4;
+ public static final int DISPID_EVALUATE = -5;
+ public static final int DISPID_CONSTRUCTOR = -6;
+ public static final int DISPID_DESTRUCTOR = -7;
+ public static final int DISPID_COLLECT = -8;
+ public static final int DISPID_AUTOSIZE = -500;
+ public static final int DISPID_BACKCOLOR = -501;
+ public static final int DISPID_BACKSTYLE = -502;
+ public static final int DISPID_BORDERCOLOR = -503;
+ public static final int DISPID_BORDERSTYLE = -504;
+ public static final int DISPID_BORDERWIDTH = -505;
+ public static final int DISPID_DRAWMODE = -507;
+ public static final int DISPID_DRAWSTYLE = -508;
+ public static final int DISPID_DRAWWIDTH = -509;
+ public static final int DISPID_FILLCOLOR = -510;
+ public static final int DISPID_FILLSTYLE = -511;
+ public static final int DISPID_FONT = -512;
+ public static final int DISPID_FORECOLOR = -513;
+ public static final int DISPID_ENABLED = -514;
+ public static final int DISPID_HWND = -515;
+ public static final int DISPID_TABSTOP = -516;
+ public static final int DISPID_TEXT = -517;
+ public static final int DISPID_CAPTION = -518;
+ public static final int DISPID_BORDERVISIBLE = -519;
+ public static final int DISPID_APPEARANCE = -520;
+ public static final int DISPID_MOUSEPOINTER = -521;
+ public static final int DISPID_MOUSEICON = -522;
+ public static final int DISPID_PICTURE = -523;
+ public static final int DISPID_VALID = -524;
+ public static final int DISPID_READYSTATE = -525;
+ public static final int DISPID_REFRESH = -550;
+ public static final int DISPID_DOCLICK = -551;
+ public static final int DISPID_ABOUTBOX = -552;
+ public static final int DISPID_CLICK = -600;
+ public static final int DISPID_DBLCLICK = -601;
+ public static final int DISPID_KEYDOWN = -602;
+ public static final int DISPID_KEYPRESS = -603;
+ public static final int DISPID_KEYUP = -604;
+ public static final int DISPID_MOUSEDOWN = -605;
+ public static final int DISPID_MOUSEMOVE = -606;
+ public static final int DISPID_MOUSEUP = -607;
+ public static final int DISPID_ERROREVENT = -608;
+ public static final int DISPID_READYSTATECHANGE = -609;
+ public static final int DISPID_AMBIENT_BACKCOLOR = -701;
+ public static final int DISPID_AMBIENT_DISPLAYNAME = -702;
+ public static final int DISPID_AMBIENT_FONT = -703;
+ public static final int DISPID_AMBIENT_FORECOLOR = -704;
+ public static final int DISPID_AMBIENT_LOCALEID = -705;
+ public static final int DISPID_AMBIENT_MESSAGEREFLECT = -706;
+ public static final int DISPID_AMBIENT_SCALEUNITS = -707;
+ public static final int DISPID_AMBIENT_TEXTALIGN = -708;
+ public static final int DISPID_AMBIENT_USERMODE = -709;
+ public static final int DISPID_AMBIENT_UIDEAD = -710;
+ public static final int DISPID_AMBIENT_SHOWGRABHANDLES = -711;
+ public static final int DISPID_AMBIENT_SHOWHATCHING = -712;
+ public static final int DISPID_AMBIENT_DISPLAYASDEFAULT = -713;
+ public static final int DISPID_AMBIENT_SUPPORTSMNEMONICS = -714;
+ public static final int DISPID_AMBIENT_AUTOCLIP = -715;
+ public static final int DISPID_AMBIENT_APPEARANCE = -716;
+ public static final int DISPID_AMBIENT_CODEPAGE = -725;
+ public static final int DISPID_AMBIENT_PALETTE = -726;
+ public static final int DISPID_AMBIENT_CHARSET = -727;
+ public static final int DISPID_AMBIENT_TRANSFERPRIORITY = -728;
+
+ // map args based on msdn doc
+ protected static Variant obj2variant(Object o)
+ {
+ if (o == null)
+ return new Variant();
+ if (o instanceof Variant)
+ return (Variant)o;
+ if (o instanceof Integer)
+ return new Variant(((Integer)o).intValue());
+ if (o instanceof String)
+ return new Variant((String)o);
+ if (o instanceof Boolean)
+ return new Variant(((Boolean)o).booleanValue());
+ if (o instanceof Double)
+ return new Variant(((Double)o).doubleValue());
+ if (o instanceof Float)
+ return new Variant(((Float)o).floatValue());
+ if (o instanceof SafeArray)
+ return new Variant((SafeArray)o);
+ if (o instanceof Dispatch) {
+ Variant v = new Variant();
+ v.putObject((Dispatch)o);
+ return v;
+ }
+ // automatically convert arrays using reflection
+ Class c1 = o.getClass();
+ SafeArray sa = null;
+ if (c1.isArray())
+ {
+ int len1 = Array.getLength(o);
+ Object first = Array.get(o, 0);
+ if (first.getClass().isArray())
+ {
+ int max = 0;
+ for (int i = 0; i < len1; i++)
+ {
+ Object e1 = Array.get(o, i);
+ int len2 = Array.getLength(e1);
+ if (max < len2)
+ {
+ max = len2;
+ }
+ }
+ sa = new SafeArray(Variant.VariantVariant, len1, max);
+ for (int i = 0; i < len1; i++)
+ {
+ Object e1 = Array.get(o, i);
+ for (int j = 0; j < Array.getLength(e1); j++)
+ {
+ sa.setVariant(i, j, obj2variant(Array.get(e1, j)));
+ }
+ }
+ } else {
+ sa = new SafeArray(Variant.VariantVariant, len1);
+ for (int i = 0; i < len1; i++)
+ {
+ sa.setVariant(i, obj2variant(Array.get(o, i)));
+ }
+ }
+ return new Variant(sa);
+ }
+ throw new ClassCastException("cannot convert to Variant");
+ }
+
+ // same as above, for an array
+ protected static Variant[] obj2variant(Object[] o)
+ {
+ Variant vArg[] = new Variant[o.length];
+ for(int i=0;i(Variant[] args)
+ protected native void init(Dispatch src, Object sink);
+ protected native void init2(Dispatch src, Object sink, String progId);
+
+ // call this to explicitly release the com object before gc
+ public native void release();
+
+ protected void finalize()
+ {
+ //System.out.println("DispatchEvents finalize start");
+ if (m_pConnPtProxy != 0) release();
+ //System.out.println("DispatchEvents finalize end");
+ }
+
+ static {
+ System.loadLibrary("jacob");
+ }
+}
diff --git a/jacob/com/jacob/com/DispatchProxy.java b/jacob/com/jacob/com/DispatchProxy.java
new file mode 100644
index 0000000..b384f39
--- /dev/null
+++ b/jacob/com/jacob/com/DispatchProxy.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jacob.com;
+
+/**
+ * If you need to pass a COM Dispatch object between STA threads, you
+ * have to marshall the interface.
+ * This class is used as follows: the STA that creates the Dispatch
+ * object must construct an instance of this class. Another thread
+ * can then call toDispatch() on that instance and get a Dispatch
+ * pointer which has been marshalled.
+ * WARNING: You can only call toDispatch() once! If you need to call
+ * it multiple times (or from multiple threads) you need to construct
+ * a separate DispatchProxy instance for each such case!
+ */
+public class DispatchProxy extends JacobObject
+{
+ public int m_pStream;
+
+ public DispatchProxy(Dispatch localDispatch)
+ {
+ MarshalIntoStream(localDispatch);
+ }
+
+ public Dispatch toDispatch()
+ {
+ return MarshalFromStream();
+ }
+
+ private native void MarshalIntoStream(Dispatch d);
+ private native Dispatch MarshalFromStream();
+ public native void release();
+
+ public void finalize()
+ {
+ if (m_pStream != 0) release();
+ }
+}
diff --git a/jacob/com/jacob/com/EnumVariant.java b/jacob/com/jacob/com/EnumVariant.java
new file mode 100644
index 0000000..07519e7
--- /dev/null
+++ b/jacob/com/jacob/com/EnumVariant.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jacob.com;
+
+/**
+ * An implementation of IEnumVariant based on code submitted by
+ * Thomas Hallgren (mailto:Thomas.Hallgren@eoncompany.com)
+ */
+public class EnumVariant extends JacobObject implements java.util.Enumeration
+{
+ private int m_pIEnumVARIANT;
+ private final Variant[] m_recBuf = new Variant[1];
+
+ // this only gets called from JNI
+ //
+ protected EnumVariant(int pIEnumVARIANT)
+ {
+ m_pIEnumVARIANT = pIEnumVARIANT;
+ }
+
+ public EnumVariant(Object disp)
+ {
+ int[] hres = new int[1];
+ Variant evv = Dispatch.invokev(
+ disp,
+ Dispatch.DISPID_NEWENUM,
+ Dispatch.Get,
+ new Variant[0],
+ hres);
+ if(evv.getvt() != Variant.VariantObject)
+ //
+ // The DISPID_NEWENUM did not result in a valid object
+ //
+ throw new ComFailException("Can't obtain EnumVARIANT");
+
+ EnumVariant tmp = evv.toEnumVariant();
+ m_pIEnumVARIANT = tmp.m_pIEnumVARIANT;
+ tmp.m_pIEnumVARIANT = 0;
+ }
+
+ /**
+ * Implements java.util.Enumeration
+ */
+ public boolean hasMoreElements()
+ {
+ {
+ if(m_recBuf[0] == null)
+ {
+ if(this.Next(m_recBuf) <= 0)
+ return false;
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Implements java.util.Enumeration
+ */
+ public Object nextElement()
+ {
+ Object last = m_recBuf[0];
+ if(last == null)
+ {
+ if(this.Next(m_recBuf) <= 0)
+ throw new java.util.NoSuchElementException();
+ last = m_recBuf[0];
+ }
+ m_recBuf[0] = null;
+ return last;
+ }
+
+ /**
+ * Get next element in collection or null if at end
+ */
+ public Variant Next()
+ {
+ if (hasMoreElements()) return (Variant)nextElement();
+ return null;
+ }
+
+ public native int Next(Variant[] receiverArray);
+
+ public native void Skip(int count);
+
+ public native void Reset();
+
+ public native void release();
+
+ protected void finalize()
+ {
+ //System.out.println("EnumVariant finalize start");
+ if (m_pIEnumVARIANT != 0) this.release();
+ //System.out.println("EnumVariant finalize end");
+ }
+}
diff --git a/jacob/com/jacob/com/JacobObject.java b/jacob/com/jacob/com/JacobObject.java
new file mode 100644
index 0000000..4685eb4
--- /dev/null
+++ b/jacob/com/jacob/com/JacobObject.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jacob.com;
+
+/**
+ * All COM object created by JACOB extend this class so that
+ * we can automatically release them when the thread is detached from
+ * COM - if we leave it to the finalizer it will call the release from
+ * another thread, which may result in a segmentation violation.
+ */
+public class JacobObject
+{
+ public JacobObject()
+ {
+ ROT.addObject(this);
+ }
+
+ public void release() {}
+}
diff --git a/jacob/com/jacob/com/MainSTA.java b/jacob/com/jacob/com/MainSTA.java
new file mode 100644
index 0000000..b1e4c79
--- /dev/null
+++ b/jacob/com/jacob/com/MainSTA.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jacob.com;
+
+/**
+ * We provide our own main sta thread to avoid COM tagging a random
+ * thread as the main STA - this is the thread in which all Apartment
+ * threaded components will be created if the client chooses an MTA
+ * threading model for the java side of the app.
+ */
+public class MainSTA extends STA
+{
+ static {
+ System.loadLibrary("jacob");
+ }
+}
diff --git a/jacob/com/jacob/com/ROT.java b/jacob/com/jacob/com/ROT.java
new file mode 100644
index 0000000..ac7704d
--- /dev/null
+++ b/jacob/com/jacob/com/ROT.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jacob.com;
+import java.util.Hashtable;
+import java.util.Vector;
+
+/**
+ * The Running Object Table (ROT) maps each thread to a vector of
+ * all the JacobObjects that were created in that thread. It always
+ * operates on the current thread so all the methods are static and
+ * they implicitly get the current thread.
+ * Conceptually, this is similar to the ThreadLocal class of Java 1.2
+ * but we are also supporting Java 1.6
+ * The clearObjects method is used to release all the COM objects
+ * created by Jacob in the current thread prior to uninitializing COM
+ * for that thread. If we leave this job to the garbage collector,
+ * then finalize might get called from a separate thread which is not
+ * initialized for COM, and also the component itself may have been
+ * freed.
+ */
+public abstract class ROT
+{
+ private static Hashtable rot = new Hashtable();
+
+ protected static void addThread()
+ {
+ String t_name = Thread.currentThread().getName();
+ if (rot.contains(t_name)) return;
+ Vector v = new Vector();
+ rot.put(t_name, v);
+ }
+
+ protected static void clearObjects()
+ {
+ String t_name = Thread.currentThread().getName();
+ Vector v = (Vector)rot.get(t_name);
+ if (v != null)
+ {
+ while (!v.isEmpty())
+ {
+ JacobObject o = (JacobObject)v.elementAt(0);
+ //System.out.println(t_name + " release:"+o+"->"+o.getClass().getName());
+ if (o != null) o.release();
+ v.removeElementAt(0);
+ }
+ rot.remove(t_name);
+ }
+ }
+
+ protected static void addObject(JacobObject o)
+ {
+ String t_name = Thread.currentThread().getName();
+ //System.out.println(t_name + " add:"+o+"->"+o.getClass().getName());
+ Vector v = (Vector)rot.get(t_name);
+ if (v == null)
+ {
+ // this thread has not been initialized as a COM thread
+ // so make it part of MTA for backwards compatibility
+ ComThread.InitMTA(false);
+ addThread();
+ v = (Vector)rot.get(t_name);
+ }
+ if (v != null)
+ {
+ v.addElement(o);
+ }
+ }
+
+ static {
+ System.loadLibrary("jacob");
+ }
+}
diff --git a/jacob/com/jacob/com/STA.java b/jacob/com/jacob/com/STA.java
new file mode 100644
index 0000000..08fb89d
--- /dev/null
+++ b/jacob/com/jacob/com/STA.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jacob.com;
+
+/**
+ * A class that implements a Single Threaded Apartment.
+ * Users will subclass this and override OnInit() and OnQuit()
+ * where they will create and destroy a COM component that wants to
+ * run in an STA other than the main STA.
+ */
+public class STA extends Thread
+{
+ public int threadID;
+
+ public STA()
+ {
+ start(); // start the thread
+ }
+
+ public void run()
+ {
+ // init COM
+ ComThread.InitSTA();
+ if (OnInit())
+ {
+ // this call blocks in the win32 message loop
+ // until quitMessagePump is called
+ doMessagePump();
+ }
+ OnQuit();
+ // uninit COM
+ ComThread.Release();
+ }
+
+ /**
+ * Override this method to create and initialize any COM
+ * component that you want to run in this thread. If anything
+ * fails, return false to terminate the thread.
+ */
+ public boolean OnInit()
+ {
+ return true;
+ }
+
+ /**
+ * Override this method to destroy any resource
+ * before the thread exits and COM in uninitialized
+ */
+ public void OnQuit()
+ {
+ }
+
+ public void quit()
+ {
+ quitMessagePump();
+ }
+
+ /**
+ * run a message pump for the main STA
+ */
+ public native void doMessagePump();
+
+ /**
+ * quit message pump for the main STA
+ */
+ public native void quitMessagePump();
+
+ static {
+ System.loadLibrary("jacob");
+ }
+}
diff --git a/jacob/com/jacob/com/SafeArray.java b/jacob/com/jacob/com/SafeArray.java
new file mode 100644
index 0000000..dc561aa
--- /dev/null
+++ b/jacob/com/jacob/com/SafeArray.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jacob.com;
+
+public class SafeArray extends JacobObject
+{
+ int m_pV = 0;
+
+ public SafeArray() {}
+
+ public SafeArray(int vt)
+ {
+ init(vt, new int[] {0}, new int[] {-1});
+ }
+
+ public SafeArray(int vt,int celems)
+ {
+ init(vt, new int[] {0}, new int[] {celems});
+ }
+
+ public SafeArray(int vt,int celems1,int celems2)
+ {
+ init(vt, new int[] {0,0}, new int[] {celems1, celems2});
+ }
+
+ public SafeArray(int vt,int lbounds[],int celems[])
+ {
+ init(vt, lbounds, celems);
+ }
+
+ // convert a string to a VT_UI1 array
+ public SafeArray(String s)
+ {
+ char[] ca = s.toCharArray();
+ init(Variant.VariantByte, new int[] {0}, new int[] {ca.length});
+ fromCharArray(ca);
+ }
+
+ protected native void init(int vt, int lbounds[], int celems[]);
+
+ // not impl
+ public int getNumLocks() { return 0; }
+
+ // convert a VT_UI1 array to string
+ public String asString()
+ {
+ if (getvt() != Variant.VariantByte) return null;
+ char ja[] = toCharArray();
+ return new String(ja);
+ }
+
+
+ public native Object clone();
+ // call this to explicitly release the com object before gc
+
+ public void release()
+ {
+ destroy();
+ }
+
+ public native void destroy();
+ public native int getvt();
+ protected void finalize()
+ {
+ //System.out.println("SafeArray finalize start");
+ if (m_pV != 0) release();
+ //System.out.println("SafeArray finalize end");
+ }
+ public native void reinit(SafeArray sa);
+ public native void reinterpretType(int vt);
+
+ public native int getLBound();
+ public native int getLBound(int dim);
+ public native int getUBound();
+ public native int getUBound(int dim);
+
+ public native int getNumDim();
+ public native int getFeatures();
+ public native int getElemSize();
+
+ public native void fromCharArray(char ja[]);
+ public native void fromIntArray(int ja[]);
+ public native void fromShortArray(short ja[]);
+ public native void fromDoubleArray(double ja[]);
+ public native void fromStringArray(String ja[]);
+ public native void fromByteArray(byte ja[]);
+ public native void fromFloatArray(float ja[]);
+ public native void fromBooleanArray(boolean ja[]);
+ public native void fromVariantArray(Variant ja[]);
+
+ public native char[] toCharArray();
+ public native int[] toIntArray();
+ public native short[] toShortArray();
+ public native double[] toDoubleArray();
+ public native String[] toStringArray();
+ public native byte[] toByteArray();
+ public native float[] toFloatArray();
+ public native boolean[] toBooleanArray();
+ public native Variant[] toVariantArray();
+
+ // char access
+ public native char getChar(int sa_idx);
+ public native char getChar(int sa_idx1, int sa_idx2);
+ public native void setChar(int sa_idx, char c);
+ public native void setChar(int sa_idx1, int sa_idx2, char c);
+ public native void getChars(int sa_idx, int nelems, char ja[], int ja_start);
+ public native void setChars(int sa_idx, int nelems, char ja[], int ja_start);
+
+ // int access
+ public native int getInt(int sa_idx);
+ public native int getInt(int sa_idx1, int sa_idx2);
+ public native void setInt(int sa_idx, int c);
+ public native void setInt(int sa_idx1, int sa_idx2, int c);
+ public native void getInts(int sa_idx, int nelems, int ja[], int ja_start);
+ public native void setInts(int sa_idx, int nelems, int ja[], int ja_start);
+
+ // short access
+ public native short getShort(int sa_idx);
+ public native short getShort(int sa_idx1, int sa_idx2);
+ public native void setShort(int sa_idx, short c);
+ public native void setShort(int sa_idx1, int sa_idx2, short c);
+ public native void getShorts(int sa_idx, int nelems, short ja[], int ja_start);
+ public native void setShorts(int sa_idx, int nelems, short ja[], int ja_start);
+
+ // double access
+ public native double getDouble(int sa_idx);
+ public native double getDouble(int sa_idx1, int sa_idx2);
+ public native void setDouble(int sa_idx, double c);
+ public native void setDouble(int sa_idx1, int sa_idx2, double c);
+ public native void getDoubles(int sa_idx, int nelems, double ja[], int ja_start);
+ public native void setDoubles(int sa_idx, int nelems, double ja[], int ja_start);
+
+ // string access
+ public native String getString(int sa_idx);
+ public native String getString(int sa_idx1, int sa_idx2);
+ public native void setString(int sa_idx, String c);
+ public native void setString(int sa_idx1, int sa_idx2, String c);
+ public native void getStrings(int sa_idx, int nelems, String ja[], int ja_start);
+ public native void setStrings(int sa_idx, int nelems, String ja[], int ja_start);
+
+ // byte access
+ public native byte getByte(int sa_idx);
+ public native byte getByte(int sa_idx1, int sa_idx2);
+ public native void setByte(int sa_idx, byte c);
+ public native void setByte(int sa_idx1, int sa_idx2, byte c);
+ public native void getBytes(int sa_idx, int nelems, byte ja[], int ja_start);
+ public native void setBytes(int sa_idx, int nelems, byte ja[], int ja_start);
+
+ // float access
+ public native float getFloat(int sa_idx);
+ public native float getFloat(int sa_idx1, int sa_idx2);
+ public native void setFloat(int sa_idx, float c);
+ public native void setFloat(int sa_idx1, int sa_idx2, float c);
+ public native void getFloats(int sa_idx, int nelems, float ja[], int ja_start);
+ public native void setFloats(int sa_idx, int nelems, float ja[], int ja_start);
+
+ // boolean access
+ public native boolean getBoolean(int sa_idx);
+ public native boolean getBoolean(int sa_idx1, int sa_idx2);
+ public native void setBoolean(int sa_idx, boolean c);
+ public native void setBoolean(int sa_idx1, int sa_idx2, boolean c);
+ public native void getBooleans(int sa_idx, int nelems, boolean ja[], int ja_start);
+ public native void setBooleans(int sa_idx, int nelems, boolean ja[], int ja_start);
+
+ // variant access
+ public native Variant getVariant(int sa_idx);
+ public native Variant getVariant(int sa_idx1, int sa_idx2);
+ public native void setVariant(int sa_idx, Variant c);
+ public native void setVariant(int sa_idx1, int sa_idx2, Variant c);
+ public native void getVariants(int sa_idx, int nelems, Variant ja[], int ja_start);
+ public native void setVariants(int sa_idx, int nelems, Variant ja[], int ja_start);
+
+ public String toString()
+ {
+ String s = "";
+ int ndim = getNumDim();
+ if (ndim == 1)
+ {
+ int ldim = getLBound();
+ int udim = getUBound();
+ for (int i = ldim; i <= udim; i++)
+ {
+ Variant v = getVariant(i);
+
+ if (((v.getvt() & Variant.VariantTypeMask) | Variant.VariantArray) == v.getvt())
+ {
+ return s + "[" + v.toSafeArray().toString() + "]";
+ }
+ else
+ {
+ s += " " + v.toString();
+ }
+ }
+ }
+ else if (ndim == 2)
+ {
+ int ldim1 = getLBound(1);
+ int udim1 = getUBound(1);
+
+ int ldim2 = getLBound(2);
+ int udim2 = getUBound(2);
+
+ for (int i = ldim1; i <= udim1; i++)
+ {
+ for (int j = ldim2; j <= udim2; j++)
+ {
+ Variant v = getVariant(i, j);
+ s += " " + v.toString();
+ }
+ s += "\n";
+ }
+ }
+ return s;
+ }
+
+ static {
+ System.loadLibrary("jacob");
+ }
+
+}
diff --git a/jacob/com/jacob/com/Variant.java b/jacob/com/jacob/com/Variant.java
new file mode 100644
index 0000000..d779fc7
--- /dev/null
+++ b/jacob/com/jacob/com/Variant.java
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jacob.com;
+
+public class Variant extends JacobObject implements java.io.Serializable
+{
+ int m_pVariant = 0;
+
+ public static final short VariantEmpty = 0;
+ public static final short VariantNull = 1;
+ public static final short VariantShort = 2;
+ public static final short VariantInt = 3;
+ public static final short VariantFloat = 4;
+ public static final short VariantDouble = 5;
+ public static final short VariantCurrency = 6;
+ public static final short VariantDate = 7;
+ public static final short VariantString = 8;
+ public static final short VariantDispatch = 9;
+ public static final short VariantError = 10;
+ public static final short VariantBoolean = 11;
+ public static final short VariantVariant = 12;
+ public static final short VariantObject = 13;
+ public static final short VariantByte = 17;
+ public static final short VariantTypeMask = 4095;
+ public static final short VariantArray = 8192;
+ public static final short VariantByref = 16384;
+
+ public native int toInt();
+ public native double toDate();
+ public native boolean toBoolean();
+ public native EnumVariant toEnumVariant();
+
+ public native void getNull();
+ public native void putNull();
+
+ public native Variant cloneIndirect();
+ public native double toDouble();
+ public native long toCurrency();
+
+ // superceded by SafeArray
+ public void putVariantArray(Variant[] in)
+ {
+ throw new ComFailException("Not implemented");
+ }
+
+ // superceded by SafeArray
+ public Variant[] getVariantArray()
+ {
+ throw new ComFailException("Not implemented");
+ }
+
+ // superceded by SafeArray
+ public void putByteArray(Object in)
+ {
+ throw new ComFailException("Not implemented");
+ }
+
+ public native void putShortRef(short in);
+ public native void putIntRef(int in);
+ public native void putDoubleRef(double in);
+ public native void putDateRef(double in);
+ public native void putStringRef(String in);
+ public native short getShortRef();
+ public native int getIntRef();
+ public native void putShort(short in);
+ public native short getShort();
+ public native double getDoubleRef();
+ public native double getDateRef();
+ public native String getStringRef();
+
+ // superceded by SafeArray
+ public Object toCharArray()
+ {
+ throw new ComFailException("Not implemented");
+ }
+
+ public native void VariantClear();
+ public native Dispatch toDispatch();
+ public native Object clone();
+ public native String toString();
+ public native int getInt();
+ public native double getDate();
+ public native void putInt(int in);
+ public native void putDate(double in);
+ public native byte toByte();
+
+ public Object getDispatch() { return toDispatch(); }
+ public void putDispatch(Object in) { putObject(in); }
+
+ public native boolean getBoolean();
+ public native byte getByte();
+ public native void putBoolean(boolean in);
+ public native void putByte(byte in);
+ public native int toError();
+
+ public Object toObject()
+ {
+ return toDispatch();
+ }
+
+ public native void getEmpty();
+ public native void putEmpty();
+ public native int getError();
+ public native void putError(int in);
+ public native double getDouble();
+ public Object getObject()
+ {
+ return toDispatch();
+ }
+
+ public native void putCurrency(long in);
+
+ public native void putObject(Object in);
+
+ public native void putDouble(double in);
+ public native long getCurrency();
+ public native void putFloatRef(float in);
+ public native void putCurrencyRef(long in);
+ public native void putErrorRef(int in);
+ public native void putBooleanRef(boolean in);
+
+ public void putObjectRef(Object in)
+ {
+ putObject(in);
+ }
+
+ public native void putByteRef(byte in);
+ public native String getString();
+ public native void putString(String in);
+ public native float getFloatRef();
+ public native long getCurrencyRef();
+ public native int getErrorRef();
+ public native boolean getBooleanRef();
+ public native Object getObjectRef();
+ public native byte getByteRef();
+ public native float toFloat();
+
+ /**
+ * By default toSafeArray makes a deep copy due to the fact
+ * that this Variant owns the embedded SafeArray and will
+ * destroy it when it gc's
+ */
+ public SafeArray toSafeArray()
+ {
+ return toSafeArray(true);
+ }
+
+ public native SafeArray toSafeArray(boolean deepCopy);
+ public native void putSafeArrayRef(SafeArray in);
+ public native void putSafeArray(SafeArray in);
+
+ public native void noParam();
+
+ // superceded by SafeArray
+ public void putCharArray(Object in)
+ {
+ throw new ComFailException("Not implemented");
+ }
+
+ public native float getFloat();
+ public native void putFloat(float in);
+
+ public void putDispatchRef(Object in) { putDispatch(in); }
+ public Object getDispatchRef() { return getDispatch(); }
+
+ // superceded by SafeArray
+ public void putVariantArrayRef(Variant[] in)
+ {
+ throw new ClassCastException("Not implemented");
+ }
+
+ // superceded by SafeArray
+ public Variant[] getVariantArrayRef()
+ {
+ throw new ClassCastException("Not implemented");
+ }
+
+ public native void changeType(short in);
+
+ public void changeType(int in)
+ {
+ changeType((short)in);
+ }
+
+ public Object toScriptObject() { return toDispatch(); }
+
+ public Variant()
+ {
+ init();
+ putEmpty();
+ }
+
+ public Variant(int in)
+ {
+ init();
+ putInt(in);
+ }
+
+ public Variant(double in)
+ {
+ init();
+ putDouble(in);
+ }
+
+ public Variant(boolean in)
+ {
+ init();
+ putBoolean(in);
+ }
+
+ public Variant(String in)
+ {
+ init();
+ putString(in);
+ }
+
+ public Variant(SafeArray in,boolean fByRef)
+ {
+ init();
+ if (fByRef) {
+ putSafeArrayRef(in);
+ } else {
+ putSafeArray(in);
+ }
+ }
+
+ public Variant(Object in)
+ {
+ this(in, false);
+ }
+
+ public Variant(Object o,boolean fByRef)
+ {
+ init();
+ if (o == null) {
+ putEmpty();
+ } else if (o instanceof Integer) {
+ if (fByRef) putIntRef(((Integer)o).intValue());
+ else putInt(((Integer)o).intValue());
+ } else if (o instanceof String) {
+ if (fByRef) putStringRef((String)o);
+ else putString((String)o);
+ } else if (o instanceof Boolean) {
+ if (fByRef) putBooleanRef(((Boolean)o).booleanValue());
+ else putBoolean(((Boolean)o).booleanValue());
+ } else if (o instanceof Double) {
+ if (fByRef) putDoubleRef(((Double)o).doubleValue());
+ else putDouble(((Double)o).doubleValue());
+ } else if (o instanceof Float) {
+ if (fByRef) putFloatRef(((Float)o).floatValue());
+ else putFloat(((Float)o).floatValue());
+ } else if (o instanceof SafeArray) {
+ if (fByRef) putSafeArrayRef((SafeArray)o);
+ else putSafeArray((SafeArray)o);
+ } else {
+ if (fByRef) putObjectRef(o); else putObject(o);
+ }
+ }
+
+ //weird constructors
+ public Variant(int in,int in1)
+ {
+ throw new ComFailException("Not implemented");
+ }
+
+ public Variant(int in,boolean in1)
+ {
+ throw new ComFailException("Not implemented");
+ }
+
+ public Variant(int in,double in1)
+ {
+ throw new ComFailException("Not implemented");
+ }
+
+ public Variant(int in,Object in1)
+ {
+ throw new ComFailException("Not implemented");
+ }
+
+ public native short getvt();
+ public native short toShort();
+
+ // call this to explicitly release the com object before gc
+ public native void release();
+
+ protected native void init();
+
+ protected void finalize()
+ {
+ //System.out.println("Variant finalize start:"+m_pVariant);
+ if (m_pVariant != 0) release();
+ //System.out.println("Variant finalize end");
+ }
+
+
+ // superceded by SafeArray
+ public Variant[] toVariantArray()
+ {
+ throw new ClassCastException("Not implemented");
+ }
+
+ // superceded by SafeArray
+ public Object toByteArray()
+ {
+ throw new ClassCastException("Not implemented");
+ }
+
+ static {
+ System.loadLibrary("jacob");
+ }
+
+ // serialization support
+ private void writeObject(java.io.ObjectOutputStream oos)
+ {
+ try {
+ Save(oos);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream ois)
+ {
+ try {
+ Load(ois);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ // is the variant null or empty or error or null disp
+ public native boolean isNull();
+
+ public native void Save(java.io.OutputStream os)
+ throws java.io.IOException;
+
+ public native void Load(java.io.InputStream is)
+ throws java.io.IOException;
+
+}
diff --git a/jacob/com/jacob/com/WrongThreadException.java b/jacob/com/jacob/com/WrongThreadException.java
new file mode 100644
index 0000000..4b79b7f
--- /dev/null
+++ b/jacob/com/jacob/com/WrongThreadException.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jacob.com;
+
+public class WrongThreadException extends RuntimeException
+{
+ // Constructors
+ public WrongThreadException() { super(); }
+ public WrongThreadException(String s) { super(s); }
+}
diff --git a/jacob/jacob.dll b/jacob/jacob.dll
new file mode 100644
index 0000000..1f539b9
Binary files /dev/null and b/jacob/jacob.dll differ
diff --git a/jacob/jacob.jar b/jacob/jacob.jar
new file mode 100644
index 0000000..46800c3
Binary files /dev/null and b/jacob/jacob.jar differ
diff --git a/jacob/jni/ComThread.cpp b/jacob/jni/ComThread.cpp
new file mode 100644
index 0000000..ce631ae
--- /dev/null
+++ b/jacob/jni/ComThread.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "stdafx.h"
+#include
+#include "ComThread.h"
+// Win32 support for Ole Automation
+#include
+#include
+#include
+#include
+#include
+#include "util.h"
+
+extern "C"
+{
+
+JNIEXPORT void JNICALL Java_com_jacob_com_ComThread_doCoInitialize
+ (JNIEnv *env, jclass cls, jint mode)
+{
+ int threadModel = mode;
+ CoInitializeEx(NULL, threadModel);
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_ComThread_doCoUninitialize
+ (JNIEnv *env, jclass cls)
+{
+ CoUninitialize();
+}
+
+}
diff --git a/jacob/jni/ComThread.h b/jacob/jni/ComThread.h
new file mode 100644
index 0000000..780064a
--- /dev/null
+++ b/jacob/jni/ComThread.h
@@ -0,0 +1,30 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include
+/* Header for class com_jacob_com_ComThread */
+
+#ifndef _Included_com_jacob_com_ComThread
+#define _Included_com_jacob_com_ComThread
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_jacob_com_ComThread
+ * Method: doCoInitialize
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_ComThread_doCoInitialize
+ (JNIEnv *, jclass, jint);
+
+/*
+ * Class: com_jacob_com_ComThread
+ * Method: doCoUninitialize
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_ComThread_doCoUninitialize
+ (JNIEnv *, jclass);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/jacob/jni/Dispatch.cpp b/jacob/jni/Dispatch.cpp
new file mode 100644
index 0000000..571a3af
--- /dev/null
+++ b/jacob/jni/Dispatch.cpp
@@ -0,0 +1,422 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "stdafx.h"
+#include
+#include "Dispatch.h"
+// Win32 support for Ole Automation
+#include
+#include
+#include
+#include
+#include
+#include "util.h"
+
+extern "C"
+{
+
+#define DISP_FLD "m_pDispatch"
+
+// extract a IDispatch from a jobject
+IDispatch *extractDispatch(JNIEnv *env, jobject arg)
+{
+ jclass argClass = env->GetObjectClass(arg);
+ jfieldID ajf = env->GetFieldID( argClass, DISP_FLD, "I");
+ jint anum = env->GetIntField(arg, ajf);
+ IDispatch *v = (IDispatch *)anum;
+ return v;
+}
+
+JNIEXPORT jobject JNICALL Java_com_jacob_com_Dispatch_QueryInterface
+ (JNIEnv *env, jobject _this, jstring _iid)
+{
+ // get the current IDispatch
+ IDispatch *pIDispatch = extractDispatch(env, _this);
+ if (!pIDispatch) return NULL;
+ const char *siid = env->GetStringUTFChars(_iid, NULL);
+ USES_CONVERSION;
+ LPOLESTR bsIID = A2W(siid);
+ env->ReleaseStringUTFChars(_iid, siid);
+ IID iid;
+ HRESULT hr = IIDFromString(bsIID, &iid);
+ if (FAILED(hr)) {
+ ThrowComFail(env, "Can't get IID from String", hr);
+ return NULL;
+ }
+
+ // try to call QI on the passed IID
+ IDispatch *disp;
+ hr = pIDispatch->QueryInterface(iid, (void **)&disp);
+ if (FAILED(hr)) {
+ ThrowComFail(env, "QI on IID from String Failed", hr);
+ return NULL;
+ }
+
+ jclass autoClass = env->FindClass("com/jacob/com/Dispatch");
+ jmethodID autoCons =
+ env->GetMethodID(autoClass, "", "(I)V");
+ // construct a Dispatch object to return
+ // I am copying the pointer to java
+ if (disp) disp->AddRef();
+ jobject newAuto = env->NewObject(autoClass, autoCons, disp);
+ return newAuto;
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Dispatch_createInstance
+ (JNIEnv *env, jobject _this, jstring _progid)
+{
+ jclass clazz = env->GetObjectClass(_this);
+ jfieldID jf = env->GetFieldID( clazz, DISP_FLD, "I");
+
+ const char *progid = env->GetStringUTFChars(_progid, NULL);
+ CLSID clsid;
+ HRESULT hr;
+ IUnknown *punk = NULL;
+ IDispatch *pIDispatch;
+ USES_CONVERSION;
+ LPOLESTR bsProgId = A2W(progid);
+ if (strchr(progid,':'))
+ {
+ env->ReleaseStringUTFChars(_progid, progid);
+ // it's a moniker
+ hr = CoGetObject(bsProgId, NULL, IID_IUnknown, (LPVOID *)&punk);
+ if (FAILED(hr)) {
+ ThrowComFail(env, "Can't find moniker", hr);
+ return;
+ }
+ IClassFactory *pIClass;
+ // if it was a clsid moniker, I may have a class factory
+ hr = punk->QueryInterface(IID_IClassFactory, (void **)&pIClass);
+ if (!SUCCEEDED(hr)) goto doDisp;
+ punk->Release();
+ // try to create an instance
+ hr = pIClass->CreateInstance(NULL, IID_IUnknown, (void **)&punk);
+ if (FAILED(hr)) {
+ ThrowComFail(env, "Can't create moniker class instance", hr);
+ return;
+ }
+ pIClass->Release();
+ goto doDisp;
+ }
+ env->ReleaseStringUTFChars(_progid, progid);
+ // Now, try to find an IDispatch interface for progid
+ hr = CLSIDFromProgID(bsProgId, &clsid);
+ if (FAILED(hr)) {
+ ThrowComFail(env, "Can't get object clsid from progid", hr);
+ return;
+ }
+ // standard creation
+ hr = CoCreateInstance(clsid,NULL,CLSCTX_LOCAL_SERVER|CLSCTX_INPROC_SERVER,IID_IUnknown, (void **)&punk);
+ if (!SUCCEEDED(hr)) {
+ ThrowComFail(env, "Can't co-create object", hr);
+ return;
+ }
+doDisp:
+
+ // now get an IDispatch pointer from the IUnknown
+ hr = punk->QueryInterface(IID_IDispatch, (void **)&pIDispatch);
+ if (!SUCCEEDED(hr)) {
+ ThrowComFail(env, "Can't QI object for IDispatch", hr);
+ return;
+ }
+ // CoCreateInstance called AddRef
+ punk->Release();
+ env->SetIntField(_this, jf, (unsigned int)pIDispatch);
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Dispatch_release
+ (JNIEnv *env, jobject _this)
+{
+ jclass clazz = env->GetObjectClass(_this);
+ jfieldID jf = env->GetFieldID( clazz, DISP_FLD, "I");
+ jint num = env->GetIntField(_this, jf);
+
+ IDispatch *disp = (IDispatch *)num;
+ if (disp) {
+ disp->Release();
+ env->SetIntField(_this, jf, (unsigned int)0);
+ }
+}
+
+static HRESULT
+name2ID(IDispatch *pIDispatch, const char *prop, DISPID *dispid, long lcid)
+{
+ HRESULT hresult;
+ USES_CONVERSION;
+ LPOLESTR propOle = A2W(prop);
+ hresult = pIDispatch->GetIDsOfNames(IID_NULL,(LPOLESTR*)&propOle,1,lcid,dispid);
+ return hresult;
+}
+
+JNIEXPORT jintArray JNICALL Java_com_jacob_com_Dispatch_getIDsOfNames
+ (JNIEnv *env, jclass clazz, jobject disp, jint lcid, jobjectArray names)
+{
+ IDispatch *pIDispatch = extractDispatch(env, disp);
+ if (!pIDispatch) return NULL;
+
+ int l = env->GetArrayLength(names);
+ int i;
+ LPOLESTR *lps = (LPOLESTR *)CoTaskMemAlloc(l * sizeof(LPOLESTR));
+ DISPID *dispid = (DISPID *)CoTaskMemAlloc(l * sizeof(DISPID));
+ for(i=0;iGetObjectArrayElement(names, i);
+ const char *nm = env->GetStringUTFChars(s, NULL);
+ LPOLESTR nmos = A2W(nm);
+ env->ReleaseStringUTFChars(s, nm);
+ lps[i] = nmos;
+ env->DeleteLocalRef(s);
+ }
+ HRESULT hr = pIDispatch->GetIDsOfNames(IID_NULL,lps,l,lcid,dispid);
+ if (FAILED(hr)) {
+ CoTaskMemFree(lps);
+ CoTaskMemFree(dispid);
+ char buf[1024];
+ strcpy(buf, "Can't map names to dispid:");
+ for(i=0;iGetObjectArrayElement(names, i);
+ const char *nm = env->GetStringUTFChars(s, NULL);
+ strcat(buf, nm);
+ env->ReleaseStringUTFChars(s, nm);
+ env->DeleteLocalRef(s);
+ }
+ ThrowComFail(env, buf, hr);
+ return NULL;
+ }
+ jintArray iarr = env->NewIntArray(l);
+ env->SetIntArrayRegion(iarr, i, l, dispid);
+ CoTaskMemFree(lps);
+ CoTaskMemFree(dispid);
+ return iarr;
+}
+
+static char* BasicToCharString(const BSTR inBasicString)
+{
+ char* charString = NULL;
+ const size_t charStrSize = ::SysStringLen(inBasicString) + 1;
+ if (charStrSize > 1)
+ {
+ charString = new char[charStrSize];
+ size_t len = ::wcstombs(charString, inBasicString, charStrSize);
+ }
+ else
+ charString = ::strdup("");
+
+ return charString;
+}
+
+static char* CreateErrorMsgFromResult(HRESULT inResult)
+{
+ char* msg = NULL;
+ ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM, NULL, inResult,MAKELANGID(LANG_NEUTRAL,
+ SUBLANG_DEFAULT), (LPTSTR) &msg, 0, NULL);
+ if (msg == NULL)
+ msg = ::strdup("An unknown COM error has occured.");
+
+ return msg;
+}
+
+static char* CreateErrorMsgFromInfo(HRESULT inResult, EXCEPINFO* ioInfo,
+ const char* methName)
+{
+ char* msg = NULL;
+
+ // If this is a dispatch exception (triggered by an Invoke message),
+ // then we have to take some additional steps to process the error
+ // message.
+ if (inResult == DISP_E_EXCEPTION)
+ {
+ // Check to see if the server deferred filling in the exception
+ // information. If so, make the call to populate the structure.
+ if (ioInfo->pfnDeferredFillIn != NULL)
+ (*(ioInfo->pfnDeferredFillIn))(ioInfo);
+
+ // Build the error message from exception information content.
+ char* source = ::BasicToCharString(ioInfo->bstrSource);
+ char* desc = ::BasicToCharString(ioInfo->bstrDescription);
+ const size_t MSG_LEN = ::strlen(methName) + ::strlen(source) + ::strlen(desc) + 128;
+ msg = new char[MSG_LEN];
+ ::strncpy(msg, "Invoke of: ", MSG_LEN);
+ ::strncat(msg, methName, MSG_LEN);
+ ::strncat(msg, "\nSource: ", MSG_LEN);
+ ::strncat(msg, source, MSG_LEN);
+ ::strncat(msg, "\nDescription: ", MSG_LEN);
+ ::strncat(msg, desc, MSG_LEN);
+ ::strncat(msg, "\n", MSG_LEN);
+ delete source;
+ delete desc;
+ }
+ else
+ {
+ char* msg2 = CreateErrorMsgFromResult(inResult);
+ const size_t MSG_LEN = ::strlen(methName) + ::strlen(msg2) + 128;
+ msg = new char[MSG_LEN];
+ ::strncpy(msg, "A COM exception has been encountered:\n"
+ "At Invoke of: ", MSG_LEN);
+ ::strncat(msg, methName, MSG_LEN);
+ ::strncat(msg, "\nDescription: ", MSG_LEN);
+ ::strncat(msg, msg2, MSG_LEN);
+ delete msg2;
+ }
+ return msg;
+}
+
+
+#define SETDISPPARAMS(dp, numArgs, pvArgs, numNamed, pNamed) \
+ {\
+ (dp).cArgs = numArgs; \
+ (dp).rgvarg = pvArgs; \
+ (dp).cNamedArgs = numNamed; \
+ (dp).rgdispidNamedArgs = pNamed; \
+ }
+
+#define SETNOPARAMS(dp) SETDISPPARAMS(dp, 0, NULL, 0, NULL)
+
+JNIEXPORT jobject JNICALL Java_com_jacob_com_Dispatch_invokev
+ (JNIEnv *env, jclass clazz,
+ jobject disp, jstring name, jint dispid,
+ jint lcid, jint wFlags, jobjectArray vArg, jintArray uArgErr)
+{
+ DISPPARAMS dispparams;
+ EXCEPINFO excepInfo;
+
+ IDispatch *pIDispatch = extractDispatch(env, disp);
+ if (!pIDispatch) return NULL;
+
+ int dispID = dispid;
+ if (name != NULL)
+ {
+ const char *nm = env->GetStringUTFChars(name, NULL);
+ HRESULT hr;
+ if (FAILED(hr = name2ID(pIDispatch, nm, (long *)&dispID, lcid))) {
+ char buf[1024];
+ sprintf(buf, "Can't map name to dispid: %s", nm);
+ ThrowComFail(env, buf, -1);
+ return NULL;
+ }
+ env->ReleaseStringUTFChars(name, nm);
+ }
+
+ int num_args = env->GetArrayLength(vArg);
+ int i, j;
+ VARIANT *varr = NULL;
+ if (num_args)
+ {
+ varr = (VARIANT *)CoTaskMemAlloc(num_args*sizeof(VARIANT));
+ /* reverse args for dispatch */
+ for(i=num_args-1,j=0;0<=i;i--,j++)
+ {
+ VariantInit(&varr[j]);
+ jobject arg = env->GetObjectArrayElement(vArg, i);
+ VARIANT *v = extractVariant(env, arg);
+ // no escape from copy?
+ VariantCopy(&varr[j], v);
+ env->DeleteLocalRef(arg);
+ }
+ }
+ // prepare a new return value
+ jclass variantClass = env->FindClass("com/jacob/com/Variant");
+ jmethodID variantCons =
+ env->GetMethodID(variantClass, "", "()V");
+ // construct a variant to return
+ jobject newVariant = env->NewObject(variantClass, variantCons);
+ // get the VARIANT from the newVariant
+ VARIANT *v = extractVariant(env, newVariant);
+ DISPID dispidPropertyPut = DISPID_PROPERTYPUT;
+
+ // determine how to dispatch
+ switch (wFlags)
+ {
+ case DISPATCH_PROPERTYGET: // GET
+ case DISPATCH_METHOD: // METHOD
+ case DISPATCH_METHOD|DISPATCH_PROPERTYGET:
+ {
+ SETDISPPARAMS(dispparams, num_args, varr, 0, NULL);
+ break;
+ }
+ case DISPATCH_PROPERTYPUT:
+ {
+ SETDISPPARAMS(dispparams, num_args, varr, 1, &dispidPropertyPut);
+ break;
+ }
+ }
+
+ HRESULT hr = 0;
+ jint count = env->GetArrayLength(uArgErr);
+ if ( count != 0 )
+ {
+ jint *uAE = env->GetIntArrayElements(uArgErr, NULL);
+ hr = pIDispatch->Invoke(dispID,IID_NULL,
+ lcid,wFlags,&dispparams,v,&excepInfo,(unsigned int *)uAE);
+ env->ReleaseIntArrayElements(uArgErr, uAE, 0);
+ }
+ else
+ {
+ hr = pIDispatch->Invoke(dispID,IID_NULL,
+ lcid,wFlags,&dispparams,v,&excepInfo, NULL);
+ }
+ if (num_args)
+ {
+ // to account for inouts, I need to copy the inputs back to
+ // the java array after the method returns
+ // this occurs, for example, in the ADO wrappers
+ for(i=num_args-1,j=0;0<=i;i--,j++)
+ {
+ jobject arg = env->GetObjectArrayElement(vArg, i);
+ VARIANT *v = extractVariant(env, arg);
+ // reverse copy
+ VariantCopy(v, &varr[j]);
+ // clear out the temporary variant
+ VariantClear(&varr[j]);
+ env->DeleteLocalRef(arg);
+ }
+ }
+
+ if (varr) CoTaskMemFree(varr);
+
+ // check for error and display a somewhat verbose error message
+ if (!SUCCEEDED(hr)) {
+ const char *nm = env->GetStringUTFChars(name, NULL);
+ char *buf = CreateErrorMsgFromInfo(hr, &excepInfo, nm);
+ env->ReleaseStringUTFChars(name, nm);
+ ThrowComFail(env, buf, hr);
+ if (buf) delete buf;
+ return NULL;
+ }
+
+ return newVariant;
+}
+
+}
+
+
diff --git a/jacob/jni/Dispatch.h b/jacob/jni/Dispatch.h
new file mode 100644
index 0000000..a6f7da6
--- /dev/null
+++ b/jacob/jni/Dispatch.h
@@ -0,0 +1,53 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include
+/* Header for class Dispatch */
+
+#ifndef _Included_Dispatch
+#define _Included_Dispatch
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_jacob_com_Dispatch
+ * Method: QueryInterface
+ * Signature: (Ljava/lang/String;)Lcom/jacob/com/Dispatch;
+ */
+JNIEXPORT jobject JNICALL Java_com_jacob_com_Dispatch_QueryInterface
+ (JNIEnv *, jobject, jstring);
+
+/*
+ * Class: Dispatch
+ * Method: createInstance
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Dispatch_createInstance
+ (JNIEnv *, jobject, jstring);
+
+/*
+ * Class: Dispatch
+ * Method: release
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Dispatch_release
+ (JNIEnv *, jobject);
+
+/*
+ * Class: Dispatch
+ * Method: getIDsOfNames
+ * Signature: (Ljava/lang/Object;I[Ljava/lang/String;)[I
+ */
+JNIEXPORT jintArray JNICALL Java_com_jacob_com_Dispatch_getIDsOfNames
+ (JNIEnv *, jclass, jobject, jint, jobjectArray);
+
+/*
+ * Class: Dispatch
+ * Method: invokev
+ * Signature: (Ljava/lang/Object;Ljava/lang/String;III[LVariant;[I)LVariant;
+ */
+JNIEXPORT jobject JNICALL Java_com_jacob_com_Dispatch_invokev
+ (JNIEnv *, jclass, jobject, jstring, jint, jint, jint, jobjectArray, jintArray);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/jacob/jni/DispatchEvents.cpp b/jacob/jni/DispatchEvents.cpp
new file mode 100644
index 0000000..493930b
--- /dev/null
+++ b/jacob/jni/DispatchEvents.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "DispatchEvents.h"
+#include "EventProxy.h"
+// Win32 support for Ole Automation
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "util.h"
+
+extern "C"
+{
+
+#define PROXY_FLD "m_pConnPtProxy"
+
+// defined below
+BOOL GetEventIID(IUnknown*, IID*, CComBSTR **, DISPID **, int *,LPOLESTR);
+BOOL getClassInfoFromProgId(LPOLESTR bsProgId,LPTYPEINFO *pClassInfo);
+
+// extract a EventProxy* from a jobject
+EventProxy *extractProxy(JNIEnv *env, jobject arg)
+{
+ jclass argClass = env->GetObjectClass(arg);
+ jfieldID ajf = env->GetFieldID( argClass, PROXY_FLD, "I");
+ jint anum = env->GetIntField(arg, ajf);
+ EventProxy *v = (EventProxy *)anum;
+ return v;
+}
+
+void putProxy(JNIEnv *env, jobject arg, EventProxy *ep)
+{
+ jclass argClass = env->GetObjectClass(arg);
+ jfieldID ajf = env->GetFieldID( argClass, PROXY_FLD, "I");
+ jint anum = env->GetIntField(arg, ajf);
+ env->SetIntField(arg, ajf, (jint)ep);
+}
+
+/*
+ * Class: DispatchEvents
+ * Method: init2
+ * Signature: (LDispatch;Ljava/lang/Object;Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_DispatchEvents_init2
+ (JNIEnv *env, jobject _this, jobject src, jobject sink, jstring _progid)
+{
+ USES_CONVERSION;
+ // find progid if any
+ LPOLESTR bsProgId = NULL;
+ if (_progid!=NULL) {
+ const char *progid = env->GetStringUTFChars(_progid, NULL);
+ bsProgId = A2W(progid);
+ }
+
+ // get the IDispatch for the source object
+ IDispatch *pDisp = extractDispatch(env, src);
+ CComQIPtr pUnk(pDisp);
+ // see if it implements connection points
+ CComQIPtr pCPC(pUnk);
+ if (!pCPC)
+ {
+ // no events, throw something
+ ThrowComFail(env, "Can't find IConnectionPointContainer", -1);
+ return;
+ }
+ // hook up to the default source iid
+ CComPtr pCP;
+ IID eventIID;
+ CComBSTR *mNames;
+ DISPID *mIDs;
+ int n_EventMethods;
+ if (!GetEventIID(pUnk, &eventIID, &mNames, &mIDs, &n_EventMethods,bsProgId)) {
+ ThrowComFail(env, "Can't find event iid", -1);
+ return;
+ }
+ HRESULT hr = pCPC->FindConnectionPoint(eventIID, &pCP);
+ DWORD dwEventCookie;
+ if (SUCCEEDED(hr))
+ {
+ EventProxy *ep = new EventProxy(env, sink, pCP, eventIID, mNames, mIDs, n_EventMethods);
+ // need to store ep on _this, in case it gets collected
+ putProxy(env, _this, ep);
+ } else {
+ ThrowComFail(env, "Can't FindConnectionPoint", hr);
+ }
+}
+
+/*
+ * Class: DispatchEvents
+ * Method: init
+ * Signature: (LDispatch;Ljava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_DispatchEvents_init
+ (JNIEnv *env, jobject _this, jobject src, jobject sink)
+{
+ Java_com_jacob_com_DispatchEvents_init2(env,_this,src,sink,NULL);
+}
+
+/*
+ * Class: DispatchEvents
+ * Method: release
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_DispatchEvents_release
+ (JNIEnv *env, jobject _this)
+{
+ EventProxy *ep = extractProxy(env, _this);
+ if (ep) {
+ ep->Release();
+ putProxy(env, _this, NULL);
+ }
+}
+
+/*
+ * I need a reverse map from the event interface's dispids to
+ * function names so that we can reflect them to java
+ */
+void
+LoadNameCache(LPTYPEINFO pTypeInfo, LPTYPEATTR pta,
+ CComBSTR **mNames, DISPID **mIDs, int *nmeth)
+{
+ CComBSTR *names = NULL;
+ DISPID *ids = NULL;
+ int m_nCount;
+
+ m_nCount = pta->cFuncs;
+ *nmeth = m_nCount;
+ names = m_nCount == 0 ? NULL : new CComBSTR[m_nCount];
+ ids = m_nCount == 0 ? NULL : new DISPID[m_nCount];
+ for (int i=0; iGetFuncDesc(i, &pfd)))
+ {
+ CComBSTR bstrName;
+ if (SUCCEEDED(pTypeInfo->GetDocumentation(pfd->memid, &bstrName, NULL, NULL, NULL)))
+ {
+ names[i].Attach(bstrName.Detach());
+ ids[i] = pfd->memid;
+ /*
+ USES_CONVERSION;
+ printf("map:%d -> %s\n", ids[i], W2A((OLECHAR *)names[i]));
+ */
+ }
+ pTypeInfo->ReleaseFuncDesc(pfd);
+ }
+ }
+ *mNames = names;
+ *mIDs = ids;
+}
+
+#define IMPLTYPE_MASK \
+ (IMPLTYPEFLAG_FDEFAULT | IMPLTYPEFLAG_FSOURCE | IMPLTYPEFLAG_FRESTRICTED)
+
+#define IMPLTYPE_DEFAULTSOURCE \
+ (IMPLTYPEFLAG_FDEFAULT | IMPLTYPEFLAG_FSOURCE)
+
+
+BOOL GetEventIID(IUnknown *m_pObject, IID* piid,
+ CComBSTR **mNames, DISPID **mIDs, int *nmeth,LPOLESTR bsProgId)
+{
+ *piid = GUID_NULL;
+ ATLASSERT(m_pObject != NULL);
+ // I Always use IProvideClassInfo rather than IProvideClassInfo2
+ // since I also need to create a mapping from dispid to name
+ LPPROVIDECLASSINFO pPCI = NULL;
+ LPTYPEINFO pClassInfo = NULL;
+ if (SUCCEEDED(m_pObject->QueryInterface(IID_IProvideClassInfo, (LPVOID*)&pPCI)))
+ {
+ //printf("got IProvideClassInfo\n");
+ ATLASSERT(pPCI != NULL);
+ HRESULT hr = pPCI->GetClassInfo(&pClassInfo);
+ pPCI->Release();
+ if (!SUCCEEDED(hr)) return false;
+ }
+ else if (getClassInfoFromProgId(bsProgId,&pClassInfo)) {
+ }
+ else {
+ printf("couldn't get IProvideClassInfo\n");
+ return false;
+ }
+
+
+ //printf("got ClassInfo\n");
+ ATLASSERT(pClassInfo != NULL);
+ LPTYPEATTR pClassAttr;
+ if (SUCCEEDED(pClassInfo->GetTypeAttr(&pClassAttr)))
+ {
+ //printf("got TypeAttr\n");
+ ATLASSERT(pClassAttr != NULL);
+ ATLASSERT(pClassAttr->typekind == TKIND_COCLASS);
+
+ // Search for typeinfo of the default events interface.
+ int nFlags;
+ HREFTYPE hRefType;
+
+ for (unsigned int i = 0; i < pClassAttr->cImplTypes; i++)
+ {
+ if (SUCCEEDED(pClassInfo->GetImplTypeFlags(i, &nFlags)) &&
+ ((nFlags & IMPLTYPE_MASK) == IMPLTYPE_DEFAULTSOURCE))
+ {
+ // Found it. Now look at its attributes to get IID.
+ LPTYPEINFO pEventInfo = NULL;
+ if (SUCCEEDED(pClassInfo->GetRefTypeOfImplType(i,
+ &hRefType)) &&
+ SUCCEEDED(pClassInfo->GetRefTypeInfo(hRefType,
+ &pEventInfo)))
+ {
+ ATLASSERT(pEventInfo != NULL);
+ LPTYPEATTR pEventAttr;
+ if (SUCCEEDED(pEventInfo->GetTypeAttr(&pEventAttr)))
+ {
+ ATLASSERT(pEventAttr != NULL);
+
+ // create a mapping from dispid to string
+ LoadNameCache(pEventInfo, pEventAttr,
+ mNames, mIDs, nmeth);
+
+ *piid = pEventAttr->guid;
+ pEventInfo->ReleaseTypeAttr(pEventAttr);
+ }
+ pEventInfo->Release();
+ }
+ break;
+ }
+ }
+ pClassInfo->ReleaseTypeAttr(pClassAttr);
+ }
+ pClassInfo->Release();
+
+ return (!IsEqualIID(*piid, GUID_NULL));
+}
+
+BOOL getClassInfoFromProgId(LPOLESTR bsProgId,LPTYPEINFO *pClassInfo)
+{
+ USES_CONVERSION;
+ CLSID clsid;
+ GUID libid;
+ if (FAILED(CLSIDFromProgID(bsProgId, &clsid))) return false;
+ if (FAILED(StringFromCLSID(clsid,&bsProgId))) return false;
+ HKEY keySoftware, keyClasses, keyCLSID, keyXXXX, keyTypeLib;
+ DWORD dwType, dwCountData=50;
+ BYTE abData[50];
+ LONG lVal;
+ lVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE,_T("SOFTWARE"),0,KEY_READ,&keySoftware);
+ if (lVal==ERROR_SUCCESS) {
+ lVal = RegOpenKeyEx(keySoftware,_T("Classes"),0,KEY_READ,&keyClasses);
+ if (lVal==ERROR_SUCCESS) {
+ lVal = RegOpenKeyEx(keyClasses,_T("CLSID"),0,KEY_READ,&keyCLSID);
+ if (lVal==ERROR_SUCCESS) {
+ _TCHAR *tsProgId = W2T(bsProgId);
+ lVal = RegOpenKeyEx(keyCLSID,tsProgId,0,KEY_READ,&keyXXXX);
+ if (lVal==ERROR_SUCCESS) {
+ lVal = RegOpenKeyEx(keyXXXX,_T("TypeLib"),0,KEY_READ,&keyTypeLib);
+ if (lVal==ERROR_SUCCESS) {
+ lVal = RegQueryValueEx(keyTypeLib,NULL,NULL,&dwType,abData,&dwCountData);
+ RegCloseKey(keyTypeLib);
+ }
+ RegCloseKey(keyXXXX);
+ }
+ RegCloseKey(keyCLSID);
+ }
+ RegCloseKey(keyClasses);
+ }
+ RegCloseKey(keySoftware);
+ }
+ if (lVal!=ERROR_SUCCESS) return false;
+ BSTR bsLibId = A2BSTR((char*)abData);
+ if (FAILED(CLSIDFromString(bsLibId,&libid))) return false;
+ //Try loading from registry information.
+ ITypeLib* pITypeLib;
+ if (FAILED(LoadRegTypeLib(libid,1,0, LANG_NEUTRAL, &pITypeLib))) return false;
+ //Find ITypeInfo for coclass.
+ pITypeLib->GetTypeInfoOfGuid(clsid, pClassInfo);
+ pITypeLib->Release();
+ return true;
+}
+
+}
+
+
diff --git a/jacob/jni/DispatchEvents.h b/jacob/jni/DispatchEvents.h
new file mode 100644
index 0000000..e8ca421
--- /dev/null
+++ b/jacob/jni/DispatchEvents.h
@@ -0,0 +1,39 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include
+/* Header for class DispatchEvents */
+
+#ifndef _Included_DispatchEvents
+#define _Included_DispatchEvents
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: DispatchEvents
+ * Method: init
+ * Signature: (LDispatch;Ljava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_DispatchEvents_init
+ (JNIEnv *, jobject, jobject, jobject);
+
+/*
+ * Class: DispatchEvents
+ * Method: init2
+ * Signature: (LDispatch;Ljava/lang/Object;Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_DispatchEvents_init2
+ (JNIEnv *, jobject, jobject, jobject, jstring);
+
+/*
+ * Class: DispatchEvents
+ * Method: release
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_DispatchEvents_release
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
diff --git a/jacob/jni/DispatchProxy.cpp b/jacob/jni/DispatchProxy.cpp
new file mode 100644
index 0000000..7cb78ca
--- /dev/null
+++ b/jacob/jni/DispatchProxy.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "stdafx.h"
+#include
+#include "ComThread.h"
+// Win32 support for Ole Automation
+#include
+#include
+#include
+#include
+#include
+#include "util.h"
+
+extern "C"
+{
+
+// extract a IStream from a jobject
+IStream *extractStream(JNIEnv *env, jobject arg)
+{
+ jclass argClass = env->GetObjectClass(arg);
+ jfieldID ajf = env->GetFieldID( argClass, "m_pStream", "I");
+ jint anum = env->GetIntField(arg, ajf);
+ IStream *v = (IStream *)anum;
+ return v;
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_DispatchProxy_MarshalIntoStream
+ (JNIEnv *env, jobject _this, jobject disp)
+{
+ IDispatch *pIDispatch = extractDispatch(env, disp);
+ if (!pIDispatch) return;
+ IStream *ps; // this is the stream we will marshall into
+ HRESULT hr = CoMarshalInterThreadInterfaceInStream(
+ IID_IDispatch, pIDispatch, &ps);
+ if (!SUCCEEDED(hr))
+ {
+ ThrowComFail(env, "Could not Marshal Dispatch into IStream", hr);
+ return;
+ }
+ // store the stream pointer on the object
+ jclass argClass = env->GetObjectClass(_this);
+ jfieldID ajf = env->GetFieldID( argClass, "m_pStream", "I");
+ env->SetIntField(_this, ajf, (jint)ps);
+}
+
+JNIEXPORT jobject JNICALL Java_com_jacob_com_DispatchProxy_MarshalFromStream
+ (JNIEnv *env, jobject _this)
+{
+ IStream *ps = extractStream(env, _this);
+ if (!ps)
+ {
+ ThrowComFail(env, "Could not get IStream from DispatchProxy", -1);
+ return NULL;
+ }
+ IDispatch *pD;
+ HRESULT hr = CoGetInterfaceAndReleaseStream(ps, IID_IDispatch, (void **)&pD);
+ // zero out the stream pointer on the object
+ // since the stream can only be read once
+ jclass argClass = env->GetObjectClass(_this);
+ jfieldID ajf = env->GetFieldID( argClass, "m_pStream", "I");
+ env->SetIntField(_this, ajf, (unsigned int)0);
+
+ if (!SUCCEEDED(hr))
+ {
+ ThrowComFail(env, "Could not Marshal Dispatch from IStream", hr);
+ return NULL;
+ }
+ jclass autoClass = env->FindClass("com/jacob/com/Dispatch");
+ jmethodID autoCons = env->GetMethodID(autoClass, "", "(I)V");
+ // construct a Dispatch object to return
+ // I am copying the pointer to java
+ if (pD) pD->AddRef();
+ jobject newAuto = env->NewObject(autoClass, autoCons, pD);
+ return newAuto;
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_DispatchProxy_release
+ (JNIEnv *env, jobject _this)
+{
+ IStream *ps = extractStream(env, _this);
+ if (ps) {
+ ps->Release();
+ jclass argClass = env->GetObjectClass(_this);
+ jfieldID ajf = env->GetFieldID( argClass, "m_pStream", "I");
+ env->SetIntField(_this, ajf, (unsigned int)0);
+ }
+}
+
+}
diff --git a/jacob/jni/DispatchProxy.h b/jacob/jni/DispatchProxy.h
new file mode 100644
index 0000000..211b81a
--- /dev/null
+++ b/jacob/jni/DispatchProxy.h
@@ -0,0 +1,37 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include
+/* Header for class com_jacob_com_DispatchProxy */
+
+#ifndef _Included_com_jacob_com_DispatchProxy
+#define _Included_com_jacob_com_DispatchProxy
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_jacob_com_DispatchProxy
+ * Method: MarshalIntoStream
+ * Signature: (Lcom/jacob/com/Dispatch;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_DispatchProxy_MarshalIntoStream
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: com_jacob_com_DispatchProxy
+ * Method: MarshalFromStream
+ * Signature: ()Lcom/jacob/com/Dispatch;
+ */
+JNIEXPORT jobject JNICALL Java_com_jacob_com_DispatchProxy_MarshalFromStream
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_DispatchProxy
+ * Method: release
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_DispatchProxy_release
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/jacob/jni/EnumVariant.cpp b/jacob/jni/EnumVariant.cpp
new file mode 100644
index 0000000..4785214
--- /dev/null
+++ b/jacob/jni/EnumVariant.cpp
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "stdafx.h"
+#include
+#include "Dispatch.h"
+// Win32 support for Ole Automation
+#include
+#include
+#include
+#include
+#include
+#include "util.h"
+
+/**
+ * An implementation of IEnumVariant based on code submitted by
+ * Thomas Hallgren (mailto:Thomas.Hallgren@eoncompany.com)
+ */
+extern "C"
+{
+
+// extract a IDispatch from a jobject
+IEnumVARIANT* extractEnumVariant(JNIEnv* env, jobject arg)
+{
+ jfieldID FID_pIEnumVARIANT = 0;
+ jclass clazz = env->GetObjectClass(arg);
+ FID_pIEnumVARIANT = env->GetFieldID(clazz, "m_pIEnumVARIANT", "I");
+ return (IEnumVARIANT*)env->GetIntField(arg, FID_pIEnumVARIANT);
+}
+
+JNIEXPORT jint JNICALL
+Java_com_jacob_com_EnumVariant_Next(JNIEnv* env, jobject _this, jobjectArray vars)
+{
+ IEnumVARIANT* self = extractEnumVariant(env, _this);
+ printf("self=%x\n", self);
+ if(self == NULL)
+ return 0;
+
+ ULONG count = (ULONG)env->GetArrayLength(vars);
+ if(count == 0)
+ return 0;
+
+ VARIANT* sink = (VARIANT*)CoTaskMemAlloc(count * sizeof(VARIANT));
+ ULONG fetchCount = 0;
+
+ HRESULT hr = self->Next(count, sink, &fetchCount);
+ if(FAILED(hr))
+ {
+ CoTaskMemFree(sink);
+ ThrowComFail(env, "IEnumVARIANT::Next", hr);
+ return 0;
+ }
+
+ // prepare a new return value array
+ //
+ jclass clazz = env->FindClass("com/jacob/com/Variant");
+ jmethodID ctor = env->GetMethodID(clazz, "", "()V");
+
+ for(ULONG idx = 0; idx < fetchCount; ++idx)
+ {
+ // construct a variant to return
+ //
+ jobject newVariant = env->NewObject(clazz, ctor);
+ VARIANT* v = extractVariant(env, newVariant);
+ VariantCopy(v, sink + idx);
+ env->SetObjectArrayElement(vars, idx, newVariant);
+ env->DeleteLocalRef(newVariant);
+ }
+ CoTaskMemFree(sink);
+ return (jint)fetchCount;
+}
+
+JNIEXPORT void JNICALL
+Java_com_jacob_com_EnumVariant_release(JNIEnv* env, jobject _this)
+{
+ IEnumVARIANT* self = extractEnumVariant(env, _this);
+ if(self != NULL)
+ {
+ self->Release();
+ jfieldID FID_pIEnumVARIANT = 0;
+ jclass clazz = env->GetObjectClass(_this);
+ FID_pIEnumVARIANT = env->GetFieldID(clazz, "m_pIEnumVARIANT", "I");
+ env->SetIntField(_this, FID_pIEnumVARIANT, (unsigned int)0);
+ }
+}
+
+JNIEXPORT void JNICALL
+Java_com_jacob_com_EnumVariant_Reset(JNIEnv* env, jobject _this)
+{
+ IEnumVARIANT* self = extractEnumVariant(env, _this);
+ if(self == NULL)
+ return;
+
+ HRESULT hr = self->Reset();
+ if(FAILED(hr))
+ ThrowComFail(env, "IEnumVARIANT::Reset", hr);
+}
+
+JNIEXPORT void JNICALL
+Java_com_jacob_com_EnumVariant_Skip(JNIEnv* env, jobject _this, jint count)
+{
+ IEnumVARIANT* self = extractEnumVariant(env, _this);
+ if(self == NULL)
+ return;
+
+ HRESULT hr = self->Skip((ULONG)count);
+ if(FAILED(hr))
+ ThrowComFail(env, "IEnumVARIANT::Skip", hr);
+}
+
+}
diff --git a/jacob/jni/EnumVariant.h b/jacob/jni/EnumVariant.h
new file mode 100644
index 0000000..902c453
--- /dev/null
+++ b/jacob/jni/EnumVariant.h
@@ -0,0 +1,46 @@
+/* Header for class EnumVariant
+ */
+#ifndef _Included_EnumVariant
+#define _Included_EnumVariant
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_jacob_com_EnumVariant
+ * Method: Next
+ * Signature: ([Lcom/jacob/com/Variant;)I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_EnumVariant_Next
+ (JNIEnv *, jobject, jobjectArray);
+
+/*
+ * Class: com_jacob_com_EnumVariant
+ * Method: Release
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_EnumVariant_release
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_EnumVariant
+ * Method: Reset
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_EnumVariant_Reset
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_EnumVariant
+ * Method: Skip
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_EnumVariant_Skip
+ (JNIEnv *, jobject, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/jacob/jni/EventProxy.cpp b/jacob/jni/EventProxy.cpp
new file mode 100644
index 0000000..b011d3b
--- /dev/null
+++ b/jacob/jni/EventProxy.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "EventProxy.h"
+
+// hook myself up as a listener for delegate
+EventProxy::EventProxy(JNIEnv *env, jobject aSinkObj,
+ CComPtr pConn,
+ IID eid, CComBSTR mName[], DISPID mID[], int mNum) :
+ m_cRef(0), pCP(pConn),
+ eventIID(eid), MethNum(mNum), MethName(mName),
+ MethID(mID), JMethID(NULL), javaSinkClass(NULL)
+{
+ javaSinkObj = env->NewGlobalRef(aSinkObj);
+ // we need this to attach to the event invocation thread
+ env->GetJavaVM(&jvm);
+ AddRef();
+ HRESULT hr = pCP->Advise(this, &dwEventCookie);
+ if (SUCCEEDED(hr)) {
+ // create a mapping from the DISPID's to jmethodID's by using
+ // the method names I extracted from the classinfo
+ JMethID = new jmethodID[MethNum];
+ javaSinkClass = env->GetObjectClass(javaSinkObj);
+ const char *method;
+ for(int i=0;iGetMethodID(javaSinkClass, method, "([Lcom/jacob/com/Variant;)V");
+ // need to clear exceptions because GetMethodID above may fail
+ // if the user didn't implement all the methods
+ env->ExceptionClear();
+ }
+ } else {
+ ThrowComFail(env, "Advise failed", hr);
+ }
+}
+
+// unhook myself up as a listener and get rid of delegate
+EventProxy::~EventProxy()
+{
+ pCP->Unadvise(dwEventCookie);
+ JNIEnv *env;
+ // attach to the current running thread
+ jvm->AttachCurrentThread((void **)&env, jvm);
+
+ env->DeleteGlobalRef(javaSinkObj);
+ if (MethNum) {
+ delete [] MethName;
+ delete [] MethID;
+ if (JMethID) delete [] JMethID;
+ }
+ // detach from thread
+ jvm->DetachCurrentThread();
+}
+
+// I only support the eventIID interface which was passed in
+// by the DispatchEvent wrapper who looked it up as the
+// source object's default source interface
+STDMETHODIMP EventProxy::QueryInterface(REFIID rid, void **ppv)
+{
+ if (rid == IID_IUnknown || rid == eventIID || rid == IID_IDispatch)
+ {
+ *ppv = this;
+ AddRef();
+ return S_OK;
+ }
+ return E_NOINTERFACE;
+}
+
+// This should never get called - the event source fires events
+// by dispid's, not by name
+STDMETHODIMP EventProxy::GetIDsOfNames(REFIID riid,
+ OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID *rgDispID)
+{
+ return E_UNEXPECTED;
+}
+
+// The actual callback from the connection point arrives here
+STDMETHODIMP EventProxy::Invoke(DISPID dispID, REFIID riid,
+ LCID lcid, unsigned short wFlags, DISPPARAMS *pDispParams,
+ VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
+{
+ HRESULT hr;
+ jmethodID meth = 0;
+ JNIEnv *env = NULL;
+
+
+ // map dispID to jmethodID
+ for(int i=0;iAttachCurrentThread((void**)&env, jvm);
+
+ // how many params
+ int num = pDispParams->cArgs;
+ // get variant class
+ jclass vClass = env->FindClass("com/jacob/com/Variant");
+ // and the constructor
+ jmethodID vCons = env->GetMethodID(vClass, "", "()V");
+ // make an array of them
+ jobjectArray varr = env->NewObjectArray(num, vClass, 0);
+ int i,j;
+ for(i=num-1,j=0;i>=0;i--,j++)
+ {
+ // construct a java variant holder
+ jobject arg = env->NewObject(vClass, vCons);
+ // get the empty variant from it
+ VARIANT *va = extractVariant(env, arg);
+ // copy the value
+ VariantCopy(va, &pDispParams->rgvarg[i]);
+ // put it in the array
+ env->SetObjectArrayElement(varr, j, arg);
+ env->DeleteLocalRef(arg);
+ }
+ // call the method
+ env->CallVoidMethod(javaSinkObj, meth, varr);
+
+ // detach from thread
+ jvm->DetachCurrentThread();
+ return S_OK;
+ }
+ return E_NOINTERFACE;
+}
diff --git a/jacob/jni/EventProxy.h b/jacob/jni/EventProxy.h
new file mode 100644
index 0000000..12b44b3
--- /dev/null
+++ b/jacob/jni/EventProxy.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 1999 Dan Adler, 315 E72 St. NY, NY, 10021, USA.
+ * mailto:danadler@rcn.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * Redistribution of the JACOB software is not permitted as part of any
+ * commercial product that is targeted primarily at Java developers.
+ * Such products include, but are not limited to: Java virtual machines,
+ * integrated development environments, code libraries, and application
+ * server products. Licensing terms for such distribution may be
+ * obtained from the copyright holder.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include
+#include
+#include
+#include
+#include
+#include "stdafx.h"
+#include "util.h"
+
+/*
+ * An instance of this class stands between a connection point
+ * and a java object. When it gets invoked from the cp, it reflects
+ * the call into the java object dynamically. The eventIID is passed
+ * in as are the valid dispids and the corresponding names. A map
+ * is created between the dispids and the java object's method in
+ * the constructor. For now, all the java event methods have to have
+ * the same signature: (Variant[])
+ */
+class EventProxy : public IDispatch
+{
+private:
+ LONG m_cRef;
+ CComPtr pCP; // the connection point
+ DWORD dwEventCookie; // connection point cookie
+ jobject javaSinkObj; // the java object to delegate calls
+ jclass javaSinkClass; // the java class of the object
+ IID eventIID; // the interface iid passed in
+ int MethNum;
+ CComBSTR *MethName; // Array of method names
+ DISPID *MethID; // Array of method ids
+ jmethodID *JMethID; // Array of java method ids
+ JavaVM *jvm; // The java vm we are running
+public:
+ // constuct with a global JNI ref to a sink object
+ // to which we will delegate event callbacks
+ EventProxy(JNIEnv *jenv, jobject aSinkObj,
+ CComPtr pConn,
+ IID eventIID, CComBSTR *mName, DISPID *mID, int mNum);
+ ~EventProxy();
+
+ // IUnknown methods
+ STDMETHODIMP_(ULONG) AddRef(void)
+ {
+ return InterlockedIncrement(&m_cRef);
+ }
+
+ STDMETHODIMP_(ULONG) Release(void)
+ {
+ LONG res = InterlockedDecrement(&m_cRef);
+ if (res == 0) delete this;
+ return res;
+ }
+
+ STDMETHODIMP QueryInterface(REFIID rid, void **ppv);
+
+ // IDispatch methods
+ STDMETHODIMP GetTypeInfoCount(UINT *num)
+ {
+ *num = 0;
+ return S_OK;
+ }
+
+ STDMETHODIMP GetTypeInfo(UINT, LCID, ITypeInfo **pptInfo)
+ {
+ *pptInfo=NULL;
+ return E_NOTIMPL;
+ }
+
+ // These are the actual supported methods
+ STDMETHODIMP GetIDsOfNames(REFIID, OLECHAR **, UINT, LCID , DISPID *);
+ STDMETHODIMP Invoke(DISPID, REFIID, LCID, WORD , DISPPARAMS *, VARIANT *, EXCEPINFO *, UINT *);
+};
diff --git a/jacob/jni/README.txt b/jacob/jni/README.txt
new file mode 100644
index 0000000..a6550c3
--- /dev/null
+++ b/jacob/jni/README.txt
@@ -0,0 +1,17 @@
+To build, run:
+
+nmake -f makefile
+
+The following are hardcoded into the makefile, so you may have to
+change it. I developed this with the C++ compiler and ATL version
+that ship with VC++ 6.0, so I'm not sure if different versions will
+work.
+
+I have compiled this against JDK 1.1.6 and 1.2.2 as well as Microsoft
+SDK for Java 3.2 as the JDK setting.
+
+DEST_DIR is a destination directory into which to copy the final DLL.
+
+JDK = d:\j2sdk1.4.2_06
+DEST_DIR = d:\jacob
+MSDEVDIR = d:\apps\\"Microsoft Visual Studio"\VC98
diff --git a/jacob/jni/STA.cpp b/jacob/jni/STA.cpp
new file mode 100644
index 0000000..37bdab3
--- /dev/null
+++ b/jacob/jni/STA.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "stdafx.h"
+#include
+#include "ComThread.h"
+// Win32 support for Ole Automation
+#include
+#include
+#include
+#include
+#include
+#include "util.h"
+
+extern "C"
+{
+
+JNIEXPORT void JNICALL Java_com_jacob_com_STA_doMessagePump
+ (JNIEnv *env, jobject obj)
+{
+ // store the current thread id so we can kill it
+ jclass argClass = env->GetObjectClass(obj);
+ jfieldID ajf = env->GetFieldID( argClass, "threadID", "I");
+ jint threadID = (jint)GetCurrentThreadId();
+ env->SetIntField(obj, ajf, threadID);
+
+ MSG msg;
+
+ ZeroMemory(&msg, sizeof(msg));
+ msg.wParam = S_OK;
+
+ while (GetMessage(&msg, NULL, 0, 0))
+ {
+ DispatchMessage(&msg);
+ }
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_STA_quitMessagePump
+ (JNIEnv *env, jobject obj)
+{
+ jclass argClass = env->GetObjectClass(obj);
+ jfieldID ajf = env->GetFieldID( argClass, "threadID", "I");
+ jint threadID = env->GetIntField(obj, ajf);
+ PostThreadMessage((DWORD)threadID, WM_QUIT, 0, 0);
+}
+
+}
diff --git a/jacob/jni/STA.h b/jacob/jni/STA.h
new file mode 100644
index 0000000..463cd13
--- /dev/null
+++ b/jacob/jni/STA.h
@@ -0,0 +1,29 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include
+/* Header for class STA */
+
+#ifndef _Included_com_jacob_com_STA
+#define _Included_com_jacob_com_STA
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_jacob_com_STA
+ * Method: doMessagePump
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_STA_doMessagePump
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_STA
+ * Method: quitMessagePump
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_STA_quitMessagePump
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/jacob/jni/SafeArray.cpp b/jacob/jni/SafeArray.cpp
new file mode 100644
index 0000000..d6839a7
--- /dev/null
+++ b/jacob/jni/SafeArray.cpp
@@ -0,0 +1,2438 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "SafeArray.h"
+// Win32 support for Ole Automation
+#include
+#include
+#include
+#include
+#include
+#include
+#include "util.h"
+
+extern "C"
+{
+
+#define V_FLD "m_pV"
+
+static SAFEARRAY *makeArray(int vt, int nDims, long *lb, long *cel)
+{
+ if (nDims == 1) {
+ // no need to alloc
+ SAFEARRAYBOUND sab;
+ sab.lLbound = lb[0];
+ sab.cElements = cel[0];
+ SAFEARRAY *sa = SafeArrayCreate(vt,1,&sab);
+ return sa;
+ } else {
+ SAFEARRAYBOUND* rgsaBounds = new SAFEARRAYBOUND[nDims];
+ for(int i=0;iGetObjectClass(arg);
+ jfieldID vf = env->GetFieldID( argClass, V_FLD, "I");
+ jint vnum = env->GetIntField(arg, vf);
+ if (vnum != NULL)
+ {
+ // if vnum is not NULL, then there is a Variant wrapper present
+ VARIANT *v = (VARIANT *)vnum;
+ return v;
+ }
+ return NULL;
+}
+
+// extract a SAFEARRAY from a SafeArray object
+SAFEARRAY *extractSA(JNIEnv *env, jobject arg)
+{
+ VARIANT *v = extractWrapper(env, arg);
+ if (v != NULL)
+ {
+ SAFEARRAY *sa = V_ARRAY(v);
+ return sa;
+ }
+ return NULL;
+}
+
+// deep copy a SAFEARRAY
+SAFEARRAY *copySA(SAFEARRAY *psa)
+{
+ // easiest way to make a deep copy is to use VariantCopy
+ VARTYPE vt;
+ SafeArrayGetVartype(psa, &vt);
+ VARIANT v1, v2;
+
+ VariantClear(&v1);
+ VariantClear(&v2);
+ V_VT(&v1) = VT_ARRAY | vt;
+ V_ARRAY(&v1) = psa;
+ VariantCopy(&v2, &v1);
+ SAFEARRAY *sa = V_ARRAY(&v2);
+ VariantInit(&v2); // make sure it's not owned by this variant
+ return sa;
+}
+
+// create a VARIANT wrapper for the safearray
+void setSA(JNIEnv *env, jobject arg, SAFEARRAY *sa, int copy)
+{
+ // construct a variant to hold the result
+ // the variant then owns the array
+ jclass argClass = env->GetObjectClass(arg);
+ jfieldID ajf = env->GetFieldID( argClass, V_FLD, "I");
+ jint vnum = env->GetIntField(arg, ajf);
+ VARIANT *v = (VARIANT *)vnum;
+ if (v == NULL)
+ {
+ v = new VARIANT();
+ VariantInit(v);
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(sa, &vt);
+ V_VT(v) = VT_ARRAY | vt;
+ V_ARRAY(v) = copy ? copySA(sa) : sa;
+ env->SetIntField(arg, ajf, (unsigned int)v);
+}
+
+/*
+ * Class: SafeArray
+ * Method: init
+ * Signature: (I[I[I)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_init
+ (JNIEnv *env, jobject _this, jint vt, jintArray lb, jintArray cel)
+{
+ jint *lbounds = env->GetIntArrayElements(lb, NULL);
+ jint *celems = env->GetIntArrayElements(cel, NULL);
+ int nDims = env->GetArrayLength(lb);
+ // array lengths must match
+ if (nDims != env->GetArrayLength(cel)) return;
+ // build the sa according to params
+ if ( nDims > 0 )
+ {
+ SAFEARRAY *sa = makeArray(vt, nDims, lbounds, celems);
+ env->ReleaseIntArrayElements(lb, lbounds, 0);
+ env->ReleaseIntArrayElements(cel, celems, 0);
+ jclass clazz = env->GetObjectClass(_this);
+ setSA(env, _this, sa, 0);
+ }
+}
+
+/*
+ * Class: SafeArray
+ * Method: clone
+ * Signature: ()Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_com_jacob_com_SafeArray_clone
+ (JNIEnv *env, jobject _this)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (psa)
+ {
+ // prepare a new return value
+ jclass saClass = env->GetObjectClass(_this);
+ jmethodID saCons = env->GetMethodID(saClass, "", "()V");
+ // construct an SA to return
+ jobject newSA = env->NewObject(saClass, saCons);
+ // wrap in a Variant
+ setSA(env, newSA, psa, 1);
+ return newSA;
+ }
+ return NULL;
+}
+
+/*
+ * Class: SafeArray
+ * Method: destroy
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_destroy
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractWrapper(env, _this);
+ if (v) {
+ // this is the case where a Variant wrapper exists, in that
+ // case free the variant, but if there is just a raw SA, then
+ // the owning variant will free it
+ jclass saClass = env->GetObjectClass(_this);
+ jfieldID jf = env->GetFieldID(saClass, V_FLD, "I");
+ VariantClear(v);
+ delete v;
+ env->SetIntField(_this, jf, (unsigned int)0);
+ }
+}
+
+/*
+ * Class: SafeArray
+ * Method: getvt
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getvt
+ (JNIEnv *env, jobject _this)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (psa) {
+ VARTYPE vt;
+ SafeArrayGetVartype(psa, &vt);
+ return (jint)vt;
+ }
+ return NULL;
+}
+
+/*
+ * Class: SafeArray
+ * Method: reinit
+ * Signature: (LSafeArray;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_reinit
+ (JNIEnv *env, jobject _this, jobject sa)
+{
+ // what to do here?
+}
+
+/*
+ * Class: SafeArray
+ * Method: reinterpretType
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_reinterpretType
+ (JNIEnv *env, jobject _this, jint vt)
+{
+}
+
+/*
+ * Class: SafeArray
+ * Method: getLBound
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getLBound__
+ (JNIEnv *env, jobject _this)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (psa) {
+ jint lb;
+ SafeArrayGetLBound(psa, 1, &lb);
+ return lb;
+ }
+ return NULL;
+}
+
+/*
+ * Class: SafeArray
+ * Method: getLBound
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getLBound__I
+ (JNIEnv *env, jobject _this, jint dim)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (psa) {
+ jint lb;
+ SafeArrayGetLBound(psa, dim, &lb);
+ return lb;
+ }
+ return NULL;
+}
+
+/*
+ * Class: SafeArray
+ * Method: getUBound
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getUBound__
+ (JNIEnv *env, jobject _this)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (psa) {
+ jint lb;
+ SafeArrayGetUBound(psa, 1, &lb);
+ return lb;
+ }
+ return NULL;
+}
+
+/*
+ * Class: SafeArray
+ * Method: getUBound
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getUBound__I
+ (JNIEnv *env, jobject _this, jint dim)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (psa) {
+ jint lb;
+ SafeArrayGetUBound(psa, dim, &lb);
+ return lb;
+ }
+ return NULL;
+}
+
+/*
+ * Class: SafeArray
+ * Method: getNumDim
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getNumDim
+ (JNIEnv *env, jobject _this)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (psa) {
+ return SafeArrayGetDim(psa);
+ }
+ return NULL;
+}
+
+/*
+ * Class: SafeArray
+ * Method: getFeatures
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getFeatures
+ (JNIEnv *env, jobject _this)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (psa) {
+ SafeArrayLock(psa);
+ jint features = psa->fFeatures;
+ SafeArrayUnlock(psa);
+ return features;
+ }
+ return NULL;
+}
+
+/*
+ * Class: SafeArray
+ * Method: getElemSize
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getElemSize
+ (JNIEnv *env, jobject _this)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (psa) {
+ jint siz = SafeArrayGetElemsize(psa);
+ return siz;
+ }
+ return NULL;
+}
+
+static int numElements(SAFEARRAY *psa)
+{
+ int nDims = SafeArrayGetDim(psa);
+ int elems = 0;
+ for(int i=1;i<=nDims;i++) {
+ long lb, ub;
+ SafeArrayGetLBound(psa, i, &lb);
+ SafeArrayGetUBound(psa, i, &ub);
+ elems += ub - lb + 1;
+ }
+ return elems;
+}
+
+/*
+ * Class: SafeArray
+ * Method: fromCharArray
+ * Signature: ([C)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromCharArray
+ (JNIEnv *env, jobject _this, jcharArray a)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (!psa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(psa, &vt);
+ int len = env->GetArrayLength(a);
+ if (len > numElements(psa))
+ {
+ // max size of memcpy
+ len = numElements(psa);
+ }
+ // get the double array - don't make a copy
+ jchar *iarr = env->GetCharArrayElements(a, 0);
+ if (vt == VT_VARIANT) {
+ VARIANT v;
+ VariantInit(&v);
+ V_VT(&v) = VT_UI2;
+ for(int i=0;iReleaseCharArrayElements(a, iarr, 0);
+}
+
+/*
+ * Class: SafeArray
+ * Method: fromIntArray
+ * Signature: ([I)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromIntArray
+ (JNIEnv *env, jobject _this, jintArray a)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (!psa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(psa, &vt);
+ int len = env->GetArrayLength(a);
+ if (len > numElements(psa))
+ {
+ // max size of memcpy
+ len = numElements(psa);
+ }
+ // get the int array - don't make a copy
+ jint *iarr = env->GetIntArrayElements(a, 0);
+ if (vt == VT_VARIANT) {
+ VARIANT v;
+ VariantInit(&v);
+ V_VT(&v) = VT_I4;
+ for(int i=0;iReleaseIntArrayElements(a, iarr, 0);
+}
+
+/*
+ * Class: SafeArray
+ * Method: fromShortArray
+ * Signature: ([S)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromShortArray
+ (JNIEnv *env, jobject _this, jshortArray a)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (!psa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(psa, &vt);
+ int len = env->GetArrayLength(a);
+ if (len > numElements(psa))
+ {
+ // max size of memcpy
+ len = numElements(psa);
+ }
+ // get the short array - don't make a copy
+ jshort *iarr = env->GetShortArrayElements(a, 0);
+ if (vt == VT_VARIANT) {
+ VARIANT v;
+ VariantInit(&v);
+ V_VT(&v) = VT_I2;
+ for(int i=0;iReleaseShortArrayElements(a, iarr, 0);
+}
+
+/*
+ * Class: SafeArray
+ * Method: fromDoubleArray
+ * Signature: ([D)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromDoubleArray
+ (JNIEnv *env, jobject _this, jdoubleArray a)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (!psa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(psa, &vt);
+ int len = env->GetArrayLength(a);
+ if (len > numElements(psa))
+ {
+ // max size of memcpy
+ len = numElements(psa);
+ }
+ // get the double array - don't make a copy
+ jdouble *iarr = env->GetDoubleArrayElements(a, 0);
+ if (vt == VT_VARIANT) {
+ VARIANT v;
+ VariantInit(&v);
+ V_VT(&v) = VT_R8;
+ for(int i=0;iReleaseDoubleArrayElements(a, iarr, 0);
+}
+
+/*
+ * Class: SafeArray
+ * Method: fromStringArray
+ * Signature: ([Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromStringArray
+ (JNIEnv *env, jobject _this, jobjectArray a)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (!psa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(psa, &vt);
+ int len = env->GetArrayLength(a);
+ if (len > numElements(psa))
+ {
+ // max size of memcpy
+ len = numElements(psa);
+ }
+ if (vt == VT_VARIANT) {
+ VARIANT v;
+ VariantInit(&v);
+ V_VT(&v) = VT_BSTR;
+ for(int i=0;iGetObjectArrayElement(a, i);
+ const char *str = env->GetStringUTFChars(s, NULL);
+ CComBSTR bs(str);
+ V_VT(&v) = VT_BSTR;
+ V_BSTR(&v) = bs.Copy();
+ long x = i;
+ SafeArrayPutElement(psa,&x,&v);
+ env->ReleaseStringUTFChars(s, str);
+ VariantClear(&v);
+ }
+ } else if (vt == VT_BSTR) {
+ for(int i=0;iGetObjectArrayElement(a, i);
+ const char *str = env->GetStringUTFChars(s, NULL);
+ CComBSTR bs(str);
+ BSTR bstr = bs.Detach();
+ long x = i;
+ SafeArrayPutElement(psa,&x,bstr);
+ env->ReleaseStringUTFChars(s, str);
+ }
+ } else {
+ ThrowComFail(env, "safearray cannot be assigned from string\n", 0);
+ }
+}
+
+/*
+ * Class: SafeArray
+ * Method: fromByteArray
+ * Signature: ([B)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromByteArray
+ (JNIEnv *env, jobject _this, jbyteArray a)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (!psa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(psa, &vt);
+ int len = env->GetArrayLength(a);
+ if (len > numElements(psa))
+ {
+ // max size of memcpy
+ len = numElements(psa);
+ }
+ // get the byte array - don't make a copy
+ jbyte *iarr = env->GetByteArrayElements(a, 0);
+ if (vt == VT_VARIANT) {
+ VARIANT v;
+ VariantInit(&v);
+ V_VT(&v) = VT_UI1;
+ for(int i=0;iReleaseByteArrayElements(a, iarr, 0);
+}
+
+/*
+ * Class: SafeArray
+ * Method: fromFloatArray
+ * Signature: ([F)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromFloatArray
+ (JNIEnv *env, jobject _this, jfloatArray a)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (!psa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(psa, &vt);
+ int len = env->GetArrayLength(a);
+ if (len > numElements(psa))
+ {
+ // max size of memcpy
+ len = numElements(psa);
+ }
+ // get the float array - don't make a copy
+ jfloat *iarr = env->GetFloatArrayElements(a, 0);
+ if (vt == VT_VARIANT) {
+ VARIANT v;
+ VariantInit(&v);
+ V_VT(&v) = VT_R4;
+ for(int i=0;iReleaseFloatArrayElements(a, iarr, 0);
+}
+
+/*
+ * Class: SafeArray
+ * Method: fromBooleanArray
+ * Signature: ([Z)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromBooleanArray
+ (JNIEnv *env, jobject _this, jbooleanArray a)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (!psa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(psa, &vt);
+ int len = env->GetArrayLength(a);
+ if (len > numElements(psa))
+ {
+ // max size of memcpy
+ len = numElements(psa);
+ }
+ // get the boolean array - don't make a copy
+ jboolean *iarr = env->GetBooleanArrayElements(a, 0);
+ if (vt == VT_VARIANT) {
+ VARIANT v;
+ VariantInit(&v);
+ V_VT(&v) = VT_BOOL;
+ for(int i=0;iReleaseBooleanArrayElements(a, iarr, 0);
+}
+
+/*
+ * Class: SafeArray
+ * Method: fromVariantArray
+ * Signature: ([LVariant;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromVariantArray
+ (JNIEnv *env, jobject _this, jobjectArray a)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (!psa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(psa, &vt);
+ int len = env->GetArrayLength(a);
+ if (len > numElements(psa))
+ {
+ // max size of memcpy
+ len = numElements(psa);
+ }
+ if (vt == VT_VARIANT) {
+ for(int i=0;iGetObjectArrayElement(a, i);
+ VARIANT *v = extractVariant(env, var);
+ long x = i;
+ if (v) SafeArrayPutElement(psa,&x,v);
+ }
+ } else {
+ ThrowComFail(env, "safearray cannot be assigned from variant", -1);
+ }
+}
+
+/*
+ * Class: SafeArray
+ * Method: toCharArray
+ * Signature: ()[C
+ */
+JNIEXPORT jcharArray JNICALL Java_com_jacob_com_SafeArray_toCharArray
+ (JNIEnv *env, jobject _this)
+{
+ SAFEARRAY *sa = extractSA(env, _this);
+ if (!sa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return NULL;
+ }
+ long lb, ub;
+ SafeArrayGetLBound(sa, 1, &lb);
+ SafeArrayGetUBound(sa, 1, &ub);
+ int num = ub - lb + 1;
+ VARTYPE vt;
+ SafeArrayGetVartype(sa, &vt);
+ if (vt == VT_UI2 || vt == VT_I2) {
+ jcharArray iarr = env->NewCharArray(num);
+ void *pData;
+ SafeArrayAccessData(sa, &pData);
+ env->SetCharArrayRegion(iarr, 0, num, (jchar *)pData);
+ SafeArrayUnaccessData(sa);
+ return iarr;
+ } else if (vt == VT_VARIANT) {
+ jcharArray iarr = env->NewCharArray(num);
+ VARIANT v;
+ VariantInit(&v);
+ for(int i=lb;i<=ub;i++) {
+ long ix = i;
+ SafeArrayGetElement(sa, &ix, (void*) &v);
+ if (FAILED(VariantChangeType(&v, &v, 0, VT_UI2))) {
+ return NULL;
+ }
+ jchar val = V_UI2(&v);
+ env->SetCharArrayRegion(iarr, i, 1, &val);
+ }
+ return iarr;
+ }
+ return NULL;
+}
+
+/*
+ * Class: SafeArray
+ * Method: toIntArray
+ * Signature: ()[I
+ */
+JNIEXPORT jintArray JNICALL Java_com_jacob_com_SafeArray_toIntArray
+ (JNIEnv *env, jobject _this)
+{
+ SAFEARRAY *sa = extractSA(env, _this);
+ if (!sa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return NULL;
+ }
+ long lb, ub;
+ SafeArrayGetLBound(sa, 1, &lb);
+ SafeArrayGetUBound(sa, 1, &ub);
+ int num = ub - lb + 1;
+ VARTYPE vt;
+ SafeArrayGetVartype(sa, &vt);
+ if (vt == VT_I4) {
+ jintArray iarr = env->NewIntArray(num);
+ void *pData;
+ SafeArrayAccessData(sa, &pData);
+ env->SetIntArrayRegion(iarr, 0, num, (jint *)pData);
+ SafeArrayUnaccessData(sa);
+ return iarr;
+ } else if (vt == VT_VARIANT) {
+ jintArray iarr = env->NewIntArray(num);
+ VARIANT v;
+ VariantInit(&v);
+ for(int i=lb;i<=ub;i++) {
+ long ix = i;
+ SafeArrayGetElement(sa, &ix, (void*) &v);
+ if (FAILED(VariantChangeType(&v, &v, 0, VT_I4))) {
+ return NULL;
+ }
+ jint val = V_I4(&v);
+ env->SetIntArrayRegion(iarr, i, 1, &val);
+ }
+ return iarr;
+ }
+ return NULL;
+}
+
+
+/*
+ * Class: SafeArray
+ * Method: toShortArray
+ * Signature: ()[S
+ */
+JNIEXPORT jshortArray JNICALL Java_com_jacob_com_SafeArray_toShortArray
+ (JNIEnv *env, jobject _this)
+{
+ SAFEARRAY *sa = extractSA(env, _this);
+ if (!sa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return NULL;
+ }
+ long lb, ub;
+ SafeArrayGetLBound(sa, 1, &lb);
+ SafeArrayGetUBound(sa, 1, &ub);
+ int num = ub - lb + 1;
+ VARTYPE vt;
+ SafeArrayGetVartype(sa, &vt);
+ if (vt == VT_I2) {
+ jshortArray iarr = env->NewShortArray(num);
+ void *pData;
+ SafeArrayAccessData(sa, &pData);
+ env->SetShortArrayRegion(iarr, 0, num, (jshort *)pData);
+ SafeArrayUnaccessData(sa);
+ return iarr;
+ } else if (vt == VT_VARIANT) {
+ jshortArray iarr = env->NewShortArray(num);
+ VARIANT v;
+ VariantInit(&v);
+ for(int i=lb;i<=ub;i++) {
+ long ix = i;
+ SafeArrayGetElement(sa, &ix, (void*) &v);
+ if (FAILED(VariantChangeType(&v, &v, 0, VT_I2))) {
+ return NULL;
+ }
+ jshort val = V_I2(&v);
+ env->SetShortArrayRegion(iarr, i, 1, &val);
+ }
+ return iarr;
+ }
+ return NULL;
+}
+
+/*
+ * Class: SafeArray
+ * Method: toDoubleArray
+ * Signature: ()[D
+ */
+JNIEXPORT jdoubleArray JNICALL Java_com_jacob_com_SafeArray_toDoubleArray
+ (JNIEnv *env, jobject _this)
+{
+ SAFEARRAY *sa = extractSA(env, _this);
+ if (!sa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return NULL;
+ }
+ long lb, ub;
+ SafeArrayGetLBound(sa, 1, &lb);
+ SafeArrayGetUBound(sa, 1, &ub);
+ int num = ub - lb + 1;
+ VARTYPE vt;
+ SafeArrayGetVartype(sa, &vt);
+ if (vt == VT_R8) {
+ jdoubleArray iarr = env->NewDoubleArray(num);
+ void *pData;
+ SafeArrayAccessData(sa, &pData);
+ env->SetDoubleArrayRegion(iarr, 0, num, (jdouble *)pData);
+ SafeArrayUnaccessData(sa);
+ return iarr;
+ } else if (vt == VT_VARIANT) {
+ jdoubleArray iarr = env->NewDoubleArray(num);
+ VARIANT v;
+ VariantInit(&v);
+ for(int i=lb;i<=ub;i++) {
+ long ix = i;
+ SafeArrayGetElement(sa, &ix, (void*) &v);
+ if (FAILED(VariantChangeType(&v, &v, 0, VT_R8))) {
+ return NULL;
+ }
+ jdouble val = V_R8(&v);
+ env->SetDoubleArrayRegion(iarr, i, 1, &val);
+ }
+ return iarr;
+ }
+ return NULL;
+}
+
+/*
+ * Class: SafeArray
+ * Method: toStringArray
+ * Signature: ()[Ljava/lang/String;
+ */
+JNIEXPORT jobjectArray JNICALL Java_com_jacob_com_SafeArray_toStringArray
+ (JNIEnv *env, jobject _this)
+{
+ SAFEARRAY *sa = extractSA(env, _this);
+ if (!sa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return NULL;
+ }
+ long lb, ub;
+ SafeArrayGetLBound(sa, 1, &lb);
+ SafeArrayGetUBound(sa, 1, &ub);
+ int num = ub - lb + 1;
+ VARTYPE vt;
+ SafeArrayGetVartype(sa, &vt);
+ if (vt == VT_VARIANT)
+ {
+ jclass sClass = env->FindClass("java/lang/String");
+ jobjectArray iarr = env->NewObjectArray(num, sClass, NULL);
+ VARIANT v;
+ VariantInit(&v);
+ for(int i=lb;i<=ub;i++) {
+ long ix = i;
+ SafeArrayGetElement(sa, &ix, (void*) &v);
+ if (FAILED(VariantChangeType(&v, &v, 0, VT_BSTR))) {
+ return NULL;
+ }
+ BSTR bs = V_BSTR(&v);
+ jstring js = env->NewString(bs, SysStringLen(bs));
+ env->SetObjectArrayElement(iarr, i, js);
+ }
+ return iarr;
+ } else if (vt == VT_BSTR) {
+ jclass sClass = env->FindClass("java/lang/String");
+ jobjectArray iarr = env->NewObjectArray(num, sClass, NULL);
+ for(int i=lb;i<=ub;i++) {
+ BSTR bs = NULL;
+ long ix = i;
+ SafeArrayGetElement(sa, &ix, (void*) &bs);
+ jstring js = env->NewString(bs, SysStringLen(bs));
+ env->SetObjectArrayElement(iarr, i, js);
+ }
+ return iarr;
+ }
+ ThrowComFail(env, "safearray cannot be converted to string[]", 0);
+ return NULL;
+}
+
+/*
+ * Class: SafeArray
+ * Method: toByteArray
+ * Signature: ()[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_com_jacob_com_SafeArray_toByteArray
+ (JNIEnv *env, jobject _this)
+{
+ SAFEARRAY *sa = extractSA(env, _this);
+ if (!sa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return NULL;
+ }
+ long lb, ub;
+ SafeArrayGetLBound(sa, 1, &lb);
+ SafeArrayGetUBound(sa, 1, &ub);
+ int num = ub - lb + 1;
+ VARTYPE vt;
+ SafeArrayGetVartype(sa, &vt);
+ if (vt == VT_I1 || vt == VT_UI1) {
+ jbyteArray iarr = env->NewByteArray(num);
+ jbyte *pData;
+ SafeArrayAccessData(sa, (void **)&pData);
+ env->SetByteArrayRegion(iarr, 0, num, pData);
+ SafeArrayUnaccessData(sa);
+ return iarr;
+ } else if (vt == VT_VARIANT) {
+ jbyteArray iarr = env->NewByteArray(num);
+ VARIANT v;
+ VariantInit(&v);
+ for(int i=lb,j=0;i<=ub;i++,j++) {
+ long ix = i;
+ SafeArrayGetElement(sa, &ix, (void*) &v);
+ if (FAILED(VariantChangeType(&v, &v, 0, VT_UI1))) {
+ return NULL;
+ }
+ jbyte val = V_UI1(&v);
+ env->SetByteArrayRegion(iarr, j, 1, &val);
+ }
+ return iarr;
+ }
+ return NULL;
+}
+
+/*
+ * Class: SafeArray
+ * Method: toFloatArray
+ * Signature: ()[F
+ */
+JNIEXPORT jfloatArray JNICALL Java_com_jacob_com_SafeArray_toFloatArray
+ (JNIEnv *env, jobject _this)
+{
+ SAFEARRAY *sa = extractSA(env, _this);
+ if (!sa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return NULL;
+ }
+ long lb, ub;
+ SafeArrayGetLBound(sa, 1, &lb);
+ SafeArrayGetUBound(sa, 1, &ub);
+ int num = ub - lb + 1;
+ VARTYPE vt;
+ SafeArrayGetVartype(sa, &vt);
+ if (vt == VT_R4) {
+ jfloatArray iarr = env->NewFloatArray(num);
+ void *pData;
+ SafeArrayAccessData(sa, &pData);
+ env->SetFloatArrayRegion(iarr, 0, num, (jfloat *)pData);
+ SafeArrayUnaccessData(sa);
+ return iarr;
+ } else if (vt == VT_VARIANT) {
+ jfloatArray iarr = env->NewFloatArray(num);
+ VARIANT v;
+ VariantInit(&v);
+ for(int i=lb;i<=ub;i++) {
+ long ix = i;
+ SafeArrayGetElement(sa, &ix, (void*) &v);
+ if (FAILED(VariantChangeType(&v, &v, 0, VT_R4))) {
+ return NULL;
+ }
+ jfloat val = V_R4(&v);
+ env->SetFloatArrayRegion(iarr, i, 1, &val);
+ }
+ return iarr;
+ }
+ return NULL;
+}
+
+/*
+ * Class: SafeArray
+ * Method: toBooleanArray
+ * Signature: ()[Z
+ */
+JNIEXPORT jbooleanArray JNICALL Java_com_jacob_com_SafeArray_toBooleanArray
+ (JNIEnv *env, jobject _this)
+{
+ SAFEARRAY *sa = extractSA(env, _this);
+ if (!sa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return NULL;
+ }
+ long lb, ub;
+ SafeArrayGetLBound(sa, 1, &lb);
+ SafeArrayGetUBound(sa, 1, &ub);
+ int num = ub - lb + 1;
+ VARTYPE vt;
+ SafeArrayGetVartype(sa, &vt);
+ if (vt == VT_BOOL) {
+ // need to loop because jboolean=1 byte and VARIANT_BOOL=2 bytes
+ jbooleanArray iarr = env->NewBooleanArray(num);
+ VARIANT_BOOL v;
+ for(int i=lb,j=0;i<=ub;i++,j++) {
+ long ix = i;
+ SafeArrayGetElement(sa, &ix, (void*) &v);
+ jboolean val = v == VARIANT_TRUE ? JNI_TRUE : JNI_FALSE;
+ env->SetBooleanArrayRegion(iarr, j, 1, &val);
+ }
+ return iarr;
+ } else if (vt == VT_VARIANT) {
+ jbooleanArray iarr = env->NewBooleanArray(num);
+ VARIANT v;
+ VariantInit(&v);
+ for(int i=lb;i<=ub;i++) {
+ long ix = i;
+ SafeArrayGetElement(sa, &ix, (void*) &v);
+ if (FAILED(VariantChangeType(&v, &v, 0, VT_BOOL))) {
+ return NULL;
+ }
+ jboolean val = V_BOOL(&v) == VARIANT_TRUE ? JNI_TRUE : JNI_FALSE;
+ env->SetBooleanArrayRegion(iarr, i, 1, &val);
+ }
+ return iarr;
+ }
+ return NULL;
+}
+
+/*
+ * Class: SafeArray
+ * Method: toVariantArray
+ * Signature: ()[LVariant;
+ */
+JNIEXPORT jobjectArray JNICALL Java_com_jacob_com_SafeArray_toVariantArray
+ (JNIEnv *env, jobject _this)
+{
+ SAFEARRAY *sa = extractSA(env, _this);
+ if (!sa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return NULL;
+ }
+ long lb, ub;
+ SafeArrayGetLBound(sa, 1, &lb);
+ SafeArrayGetUBound(sa, 1, &ub);
+ int num = ub - lb + 1;
+ jclass vClass = env->FindClass("com/jacob/com/Variant");
+ // create an array of Variant's
+ jobjectArray varr = env->NewObjectArray(num, vClass, 0);
+ // fill them in
+ jmethodID variantCons =
+ env->GetMethodID(vClass, "", "()V");
+ for(int i=lb;i<=ub;i++) {
+ long ix = i;
+ // construct a variant to return
+ jobject newVariant = env->NewObject(vClass, variantCons);
+ // get the VARIANT from the newVariant
+ VARIANT *v = extractVariant(env, newVariant);
+ SafeArrayGetElement(sa, &ix, (void*) v);
+ // put in object array
+ env->SetObjectArrayElement(varr, i, newVariant);
+ }
+ return varr;
+}
+
+// this is an ugly way to avoid copy/pasting the same code
+
+#define GET1DCODE(varType, varAccess, jtyp) \
+ SAFEARRAY *sa = extractSA(env, _this); \
+ if (!sa) { \
+ ThrowComFail(env, "safearray object corrupted", -1); \
+ return NULL; \
+ } \
+ if (SafeArrayGetDim(sa) != 1) { \
+ ThrowComFail(env, "safearray is not 1D", -1); \
+ return NULL; \
+ } \
+ VARTYPE vt; \
+ SafeArrayGetVartype(sa, &vt); \
+ if (vt == VT_VARIANT) { \
+ VARIANT v; \
+ VariantInit(&v); \
+ SafeArrayGetElement(sa, &idx, (void*) &v); \
+ if (FAILED(VariantChangeType(&v, &v, 0, varType))) { \
+ ThrowComFail(env, "VariantChangeType failed", -1); \
+ return NULL; \
+ } \
+ return (jtyp)varAccess(&v); \
+ } else if (vt == varType) { \
+ jtyp jc; \
+ SafeArrayGetElement(sa, &idx, (void*) &jc); \
+ return jc; \
+ } else { \
+ return NULL; \
+ }
+
+#define GET2DCODE(varType, varAccess, jtyp) \
+ SAFEARRAY *sa = extractSA(env, _this); \
+ if (!sa) { \
+ ThrowComFail(env, "safearray object corrupted", -1); \
+ return NULL; \
+ } \
+ if (SafeArrayGetDim(sa) != 2) { \
+ ThrowComFail(env, "safearray is not 2D", -1); \
+ return NULL; \
+ } \
+ long idx[2] = {i, j}; \
+ VARTYPE vt; \
+ SafeArrayGetVartype(sa, &vt); \
+ if (vt == VT_VARIANT) { \
+ VARIANT v; \
+ VariantInit(&v); \
+ SafeArrayGetElement(sa, idx, (void*) &v); \
+ if (FAILED(VariantChangeType(&v, &v, 0, varType))) { \
+ ThrowComFail(env, "VariantChangeType failed", -1); \
+ return NULL; \
+ } \
+ return (jtyp)varAccess(&v); \
+ } else if (vt == varType) { \
+ jtyp jc; \
+ SafeArrayGetElement(sa, idx, (void*) &jc); \
+ return jc; \
+ } else { \
+ return NULL; \
+ }
+
+
+#define SET1DCODE(varType, varAccess) \
+ SAFEARRAY *sa = extractSA(env, _this); \
+ if (!sa) { \
+ ThrowComFail(env, "safearray object corrupted", -1); \
+ return; \
+ } \
+ if (SafeArrayGetDim(sa) != 1) { \
+ ThrowComFail(env, "safearray is not 1D", -1); \
+ return; \
+ } \
+ VARTYPE vt; \
+ SafeArrayGetVartype(sa, &vt); \
+ if (vt == VT_VARIANT) { \
+ VARIANT v; \
+ VariantInit(&v); \
+ V_VT(&v) = varType; \
+ varAccess(&v) = c; \
+ SafeArrayPutElement(sa,&idx,&v); \
+ } else if (vt == varType) { \
+ SafeArrayPutElement(sa,&idx,&c); \
+ } else { \
+ ThrowComFail(env, "safearray type mismatch", -1); \
+ } \
+
+#define SET2DCODE(varType, varAccess) \
+ SAFEARRAY *sa = extractSA(env, _this); \
+ if (!sa) { \
+ ThrowComFail(env, "safearray object corrupted", -1); \
+ return; \
+ } \
+ if (SafeArrayGetDim(sa) != 2) { \
+ ThrowComFail(env, "safearray is not 2D", -1); \
+ return; \
+ } \
+ VARTYPE vt; \
+ SafeArrayGetVartype(sa, &vt); \
+ long idx[2] = {i,j}; \
+ if (vt == VT_VARIANT) { \
+ VARIANT v; \
+ VariantInit(&v); \
+ V_VT(&v) = varType; \
+ varAccess(&v) = c; \
+ SafeArrayPutElement(sa,idx,&v); \
+ } else if (vt == varType) { \
+ SafeArrayPutElement(sa,idx,&c); \
+ } else { \
+ ThrowComFail(env, "safearray type mismatch", -1); \
+ }
+
+#define GETARRAYCODE(varType, varType2, varAccess, jtyp, jsetArr) \
+ SAFEARRAY *sa = extractSA(env, _this); \
+ if (!sa) { \
+ ThrowComFail(env, "safearray object corrupted", -1); \
+ return; \
+ } \
+ VARTYPE vt; \
+ SafeArrayGetVartype(sa, &vt); \
+ if (vt == varType || vt == varType2) { \
+ jtyp *pData; \
+ SafeArrayAccessData(sa, (void **)&pData); \
+ env->jsetArr(ja, ja_start, nelem, &pData[idx]); \
+ SafeArrayUnaccessData(sa); \
+ return; \
+ } else if (vt == VT_VARIANT) { \
+ VARIANT v; \
+ VariantInit(&v); \
+ for(int i=idx, j=ja_start;ijsetArr(ja, j, 1, &val); \
+ } \
+ }
+
+#define SETARRAYCODE(varType, varType2, varAccess, jtyp, jgetArr, jrelArr) \
+ SAFEARRAY *psa = extractSA(env, _this); \
+ if (!psa) { \
+ ThrowComFail(env, "safearray object corrupted", -1); \
+ return; \
+ } \
+ VARTYPE vt; \
+ SafeArrayGetVartype(psa, &vt); \
+ jtyp *iarr = env->jgetArr(ja, 0); \
+ if (vt == VT_VARIANT) { \
+ VARIANT v; \
+ VariantInit(&v); \
+ V_VT(&v) = varType; \
+ for(int i=ja_start,j=idx;ijrelArr(ja, iarr, 0);
+
+/*
+ * Class: SafeArray
+ * Method: getChar
+ * Signature: (I)C
+ */
+JNIEXPORT jchar JNICALL Java_com_jacob_com_SafeArray_getChar__I
+ (JNIEnv *env, jobject _this, jint idx)
+{
+ GET1DCODE(VT_UI2, V_UI2, jchar)
+}
+
+/*
+ * Class: SafeArray
+ * Method: getChar
+ * Signature: (II)C
+ */
+JNIEXPORT jchar JNICALL Java_com_jacob_com_SafeArray_getChar__II
+ (JNIEnv *env, jobject _this, jint i, jint j)
+{
+ GET2DCODE(VT_UI2, V_UI2, jchar)
+}
+
+
+/*
+ * Class: SafeArray
+ * Method: setChar
+ * Signature: (IC)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setChar__IC
+ (JNIEnv *env, jobject _this, jint idx, jchar c)
+{
+ SET1DCODE(VT_UI2, V_UI2);
+}
+
+/*
+ * Class: SafeArray
+ * Method: setChar
+ * Signature: (IIC)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setChar__IIC
+ (JNIEnv *env, jobject _this, jint i, jint j, jchar c)
+{
+ SET2DCODE(VT_UI2, V_UI2);
+}
+
+/*
+ * Class: SafeArray
+ * Method: getChars
+ * Signature: (II[CI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getChars
+ (JNIEnv *env, jobject _this, jint idx, jint nelem, jcharArray ja, jint ja_start)
+{
+ GETARRAYCODE(VT_UI2, VT_I2, V_UI2, jchar, SetCharArrayRegion);
+}
+
+/*
+ * Class: SafeArray
+ * Method: setChars
+ * Signature: (II[CI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setChars
+ (JNIEnv *env, jobject _this, jint idx, jint nelem, jcharArray ja, jint ja_start)
+{
+ SETARRAYCODE(VT_UI2, VT_I2, V_UI2, jchar,
+ GetCharArrayElements, ReleaseCharArrayElements);
+}
+
+/*
+ * Class: SafeArray
+ * Method: getInt
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getInt__I
+ (JNIEnv *env, jobject _this, jint idx)
+{
+ GET1DCODE(VT_I4, V_I4, jint)
+}
+
+/*
+ * Class: SafeArray
+ * Method: getInt
+ * Signature: (II)I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getInt__II
+ (JNIEnv *env, jobject _this, jint i, jint j)
+{
+ GET2DCODE(VT_I4, V_I4, jint)
+}
+
+/*
+ * Class: SafeArray
+ * Method: setInt
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInt__II
+ (JNIEnv *env, jobject _this, jint idx, jint c)
+{
+ SET1DCODE(VT_I4, V_I4);
+}
+
+/*
+ * Class: SafeArray
+ * Method: setInt
+ * Signature: (III)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInt__III
+ (JNIEnv *env, jobject _this, jint i, jint j, jint c)
+{
+ SET2DCODE(VT_I4, V_I4);
+}
+
+/*
+ * Class: SafeArray
+ * Method: getInts
+ * Signature: (II[II)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getInts
+ (JNIEnv *env, jobject _this, jint idx, jint nelem, jintArray ja, jint ja_start)
+{
+ GETARRAYCODE(VT_I4, VT_I4, V_I4, jint, SetIntArrayRegion);
+}
+
+/*
+ * Class: SafeArray
+ * Method: setInts
+ * Signature: (II[II)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInts
+ (JNIEnv *env, jobject _this, jint idx, jint nelem, jintArray ja, jint ja_start)
+{
+ SETARRAYCODE(VT_I4, VT_I4, V_I4, jint,
+ GetIntArrayElements, ReleaseIntArrayElements);
+}
+
+/*
+ * Class: SafeArray
+ * Method: getShort
+ * Signature: (I)S
+ */
+JNIEXPORT jshort JNICALL Java_com_jacob_com_SafeArray_getShort__I
+ (JNIEnv *env, jobject _this, jint idx)
+{
+ GET1DCODE(VT_I2, V_I2, jshort)
+}
+
+/*
+ * Class: SafeArray
+ * Method: getShort
+ * Signature: (II)S
+ */
+JNIEXPORT jshort JNICALL Java_com_jacob_com_SafeArray_getShort__II
+ (JNIEnv *env, jobject _this, jint i, jint j)
+{
+ GET2DCODE(VT_I2, V_I2, jshort)
+}
+
+/*
+ * Class: SafeArray
+ * Method: setShort
+ * Signature: (IS)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setShort__IS
+ (JNIEnv *env, jobject _this, jint idx, jshort c)
+{
+ SET1DCODE(VT_I2, V_I2);
+}
+
+/*
+ * Class: SafeArray
+ * Method: setShort
+ * Signature: (IIS)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setShort__IIS
+ (JNIEnv *env, jobject _this, jint i, jint j, jshort c)
+{
+ SET2DCODE(VT_I2, V_I2);
+}
+
+/*
+ * Class: SafeArray
+ * Method: getShorts
+ * Signature: (II[SI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getShorts
+ (JNIEnv *env, jobject _this, jint idx, jint nelem, jshortArray ja, jint ja_start)
+{
+ GETARRAYCODE(VT_I2, VT_I2, V_I2, jshort, SetShortArrayRegion);
+}
+
+/*
+ * Class: SafeArray
+ * Method: setShorts
+ * Signature: (II[SI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setShorts
+ (JNIEnv *env, jobject _this, jint idx, jint nelem, jshortArray ja, jint ja_start)
+{
+ SETARRAYCODE(VT_I2, VT_I2, V_I2, jshort,
+ GetShortArrayElements, ReleaseShortArrayElements);
+}
+
+/*
+ * Class: SafeArray
+ * Method: getDouble
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_jacob_com_SafeArray_getDouble__I
+ (JNIEnv *env, jobject _this, jint idx)
+{
+ GET1DCODE(VT_R8, V_R8, jdouble)
+}
+
+/*
+ * Class: SafeArray
+ * Method: getDouble
+ * Signature: (II)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_jacob_com_SafeArray_getDouble__II
+ (JNIEnv *env, jobject _this, jint i, jint j)
+{
+ GET2DCODE(VT_R8, V_R8, jdouble)
+}
+
+/*
+ * Class: SafeArray
+ * Method: setDouble
+ * Signature: (ID)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setDouble__ID
+ (JNIEnv *env, jobject _this, jint idx, jdouble c)
+{
+ SET1DCODE(VT_R8, V_R8);
+}
+
+/*
+ * Class: SafeArray
+ * Method: setDouble
+ * Signature: (IID)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setDouble__IID
+ (JNIEnv *env, jobject _this, jint i, jint j, jdouble c)
+{
+ SET2DCODE(VT_R8, V_R8);
+}
+
+/*
+ * Class: SafeArray
+ * Method: getDoubles
+ * Signature: (II[DI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getDoubles
+ (JNIEnv *env, jobject _this, jint idx, jint nelem, jdoubleArray ja, jint ja_start)
+{
+ GETARRAYCODE(VT_R8, VT_R8, V_R8, jdouble, SetDoubleArrayRegion);
+}
+
+/*
+ * Class: SafeArray
+ * Method: setDoubles
+ * Signature: (II[DI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setDoubles
+ (JNIEnv *env, jobject _this, jint idx, jint nelem, jdoubleArray ja, jint ja_start)
+{
+ SETARRAYCODE(VT_R8, VT_R8, V_R8, jdouble,
+ GetDoubleArrayElements, ReleaseDoubleArrayElements);
+}
+
+/*
+ * Class: SafeArray
+ * Method: getString
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_jacob_com_SafeArray_getString__I
+ (JNIEnv *env, jobject _this, jint idx)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (!psa) {
+ ThrowComFail(env, "safearray object corrupted", -1); \
+ return NULL;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(psa, &vt);
+ if (vt == VT_VARIANT) {
+ VARIANT v;
+ VariantInit(&v);
+ SafeArrayGetElement(psa, &idx, &v);
+ if (FAILED(VariantChangeType(&v, &v, 0, VT_BSTR))) {
+ return NULL;
+ }
+ BSTR bs = V_BSTR(&v);
+ jstring js = env->NewString(bs, SysStringLen(bs));
+ return js;
+ } else if (vt == VT_BSTR) {
+ BSTR bs = NULL;
+ SafeArrayGetElement(psa, &idx, &bs);
+ jstring js = env->NewString(bs, SysStringLen(bs));
+ return js;
+ }
+ ThrowComFail(env, "safearray cannot get string", 0);
+ return NULL;
+}
+
+/*
+ * Class: SafeArray
+ * Method: getString
+ * Signature: (II)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_jacob_com_SafeArray_getString__II
+ (JNIEnv *env, jobject _this, jint i, jint j)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (!psa) {
+ ThrowComFail(env, "safearray object corrupted", -1); \
+ return NULL;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(psa, &vt);
+ if (vt == VT_VARIANT) {
+ VARIANT v;
+ VariantInit(&v);
+ long idx[2] = {i, j};
+ SafeArrayGetElement(psa, idx, &v);
+ if (FAILED(VariantChangeType(&v, &v, 0, VT_BSTR))) {
+ return NULL;
+ }
+ BSTR bs = V_BSTR(&v);
+ jstring js = env->NewString(bs, SysStringLen(bs));
+ return js;
+ } else if (vt == VT_BSTR) {
+ long idx[2] = {i, j};
+ BSTR bs = NULL;
+ SafeArrayGetElement(psa, idx, &bs);
+ jstring js = env->NewString(bs, SysStringLen(bs));
+ return js;
+ }
+ ThrowComFail(env, "safearray cannot get string", 0);
+ return NULL;
+}
+
+/*
+ * Class: SafeArray
+ * Method: setString
+ * Signature: (ILjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setString__ILjava_lang_String_2
+ (JNIEnv *env, jobject _this, jint idx, jstring s)
+{
+ SAFEARRAY *sa = extractSA(env, _this);
+ if (!sa) {
+ ThrowComFail(env, "safearray object corrupted", -1); \
+ return;
+ }
+ if (SafeArrayGetDim(sa) != 1) {
+ ThrowComFail(env, "safearray not 1D", -1); \
+ return;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(sa, &vt);
+ if (vt == VT_VARIANT) {
+ VARIANT v;
+ VariantInit(&v);
+ const char *str = env->GetStringUTFChars(s, NULL);
+ CComBSTR bs(str);
+ V_VT(&v) = VT_BSTR;
+ V_BSTR(&v) = bs.Copy();
+ SafeArrayPutElement(sa,&idx,&v); \
+ env->ReleaseStringUTFChars(s, str);
+ VariantClear(&v);
+ } else if (vt == VT_BSTR) {
+ const char *str = env->GetStringUTFChars(s, NULL);
+ CComBSTR bs(str);
+ SafeArrayPutElement(sa,&idx,bs.Detach());
+ env->ReleaseStringUTFChars(s, str);
+ } else {
+ ThrowComFail(env, "safearray cannot set string", 0);
+ }
+}
+
+/*
+ * Class: SafeArray
+ * Method: setString
+ * Signature: (IILjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setString__IILjava_lang_String_2
+ (JNIEnv *env, jobject _this, jint i, jint j, jstring s)
+{
+ SAFEARRAY *sa = extractSA(env, _this);
+ if (!sa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return;
+ }
+ if (SafeArrayGetDim(sa) != 1) {
+ ThrowComFail(env, "safearray is not 1D", -1);
+ return;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(sa, &vt);
+ if (vt == VT_VARIANT) {
+ VARIANT v;
+ VariantInit(&v);
+ const char *str = env->GetStringUTFChars(s, NULL);
+ CComBSTR bs(str);
+ V_VT(&v) = VT_BSTR;
+ V_BSTR(&v) = bs.Copy();
+ long idx[2] = {i,j};
+ SafeArrayPutElement(sa,idx,&v);
+ env->ReleaseStringUTFChars(s, str);
+ VariantClear(&v);
+ } else if (vt == VT_BSTR) {
+ long idx[2] = {i,j};
+ const char *str = env->GetStringUTFChars(s, NULL);
+ CComBSTR bs(str);
+ SafeArrayPutElement(sa,idx,bs.Detach());
+ env->ReleaseStringUTFChars(s, str);
+ } else {
+ ThrowComFail(env, "safearray cannot set string", 0);
+ }
+}
+
+/*
+ * Class: SafeArray
+ * Method: getStrings
+ * Signature: (II[Ljava/lang/String;I)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getStrings
+ (JNIEnv *env, jobject _this, jint idx, jint nelem, jobjectArray ja, jint ja_start)
+{
+ SAFEARRAY *sa = extractSA(env, _this);
+ if (!sa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return;
+ }
+ long lb, ub;
+ SafeArrayGetLBound(sa, 1, &lb);
+ SafeArrayGetUBound(sa, 1, &ub);
+ int num = ub - lb + 1;
+ VARTYPE vt;
+ SafeArrayGetVartype(sa, &vt);
+ if (vt == VT_VARIANT)
+ {
+ VARIANT v;
+ for(int i=idx, j=ja_start;iNewString(bs, SysStringLen(bs));
+ env->SetObjectArrayElement(ja, j, js);
+ VariantClear(&v);
+ }
+ }
+ else if (vt == VT_BSTR)
+ {
+ BSTR bs = NULL;
+ for(int i=idx, j=ja_start;iNewString(bs, SysStringLen(bs));
+ env->SetObjectArrayElement(ja, j, js);
+ }
+ } else {
+ ThrowComFail(env, "safearray cannot get strings", 0);
+ }
+}
+
+/*
+ * Class: SafeArray
+ * Method: setStrings
+ * Signature: (II[Ljava/lang/String;I)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setStrings
+ (JNIEnv *env, jobject _this, jint idx, jint nelem, jobjectArray ja, jint ja_start)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (!psa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(psa, &vt);
+ int len = env->GetArrayLength(ja);
+ if (len > numElements(psa))
+ {
+ len = numElements(psa);
+ }
+ if (vt == VT_VARIANT) {
+ VARIANT v;
+ VariantInit(&v);
+ for(int i=ja_start,j=idx;iGetObjectArrayElement(ja, i);
+ const char *str = env->GetStringUTFChars(s, NULL);
+ CComBSTR bs(str);
+ V_VT(&v) = VT_BSTR;
+ V_BSTR(&v) = bs.Copy();
+ long x = j;
+ SafeArrayPutElement(psa,&x,&v);
+ VariantClear(&v);
+ env->ReleaseStringUTFChars(s, str);
+ }
+ } else if (vt == VT_BSTR) {
+ for(int i=ja_start,j=idx;iGetObjectArrayElement(ja, i);
+ const char *str = env->GetStringUTFChars(s, NULL);
+ CComBSTR bs(str);
+ long x = j;
+ SafeArrayPutElement(psa,&x,bs.Detach());
+ env->ReleaseStringUTFChars(s, str);
+ }
+ } else {
+ ThrowComFail(env, "safearray cannot set strings", 0);
+ }
+}
+
+/*
+ * Class: SafeArray
+ * Method: getByte
+ * Signature: (I)B
+ */
+JNIEXPORT jbyte JNICALL Java_com_jacob_com_SafeArray_getByte__I
+ (JNIEnv *env, jobject _this, jint idx)
+{
+ GET1DCODE(VT_UI1, V_UI1, jbyte)
+}
+
+/*
+ * Class: SafeArray
+ * Method: getByte
+ * Signature: (II)B
+ */
+JNIEXPORT jbyte JNICALL Java_com_jacob_com_SafeArray_getByte__II
+ (JNIEnv *env, jobject _this, jint i, jint j)
+{
+ GET2DCODE(VT_UI1, V_UI1, jbyte)
+}
+
+/*
+ * Class: SafeArray
+ * Method: setByte
+ * Signature: (IB)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setByte__IB
+ (JNIEnv *env, jobject _this, jint idx, jbyte c)
+{
+ SET1DCODE(VT_UI1, V_UI1);
+}
+
+/*
+ * Class: SafeArray
+ * Method: setByte
+ * Signature: (IIB)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setByte__IIB
+ (JNIEnv *env, jobject _this, jint i, jint j, jbyte c)
+{
+ SET2DCODE(VT_UI1, V_UI1);
+}
+
+/*
+ * Class: SafeArray
+ * Method: getBytes
+ * Signature: (II[BI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getBytes
+ (JNIEnv *env, jobject _this, jint idx, jint nelem, jbyteArray ja, jint ja_start)
+{
+ GETARRAYCODE(VT_UI1, VT_I1, V_UI1, jbyte, SetByteArrayRegion);
+}
+
+/*
+ * Class: SafeArray
+ * Method: setBytes
+ * Signature: (II[BI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setBytes
+ (JNIEnv *env, jobject _this, jint idx, jint nelem, jbyteArray ja, jint ja_start)
+{
+ SETARRAYCODE(VT_UI1, VT_I1, V_UI1, jbyte,
+ GetByteArrayElements, ReleaseByteArrayElements);
+}
+
+/*
+ * Class: SafeArray
+ * Method: getFloat
+ * Signature: (I)F
+ */
+JNIEXPORT jfloat JNICALL Java_com_jacob_com_SafeArray_getFloat__I
+ (JNIEnv *env, jobject _this, jint idx)
+{
+ GET1DCODE(VT_R4, V_R4, jfloat)
+}
+
+/*
+ * Class: SafeArray
+ * Method: getFloat
+ * Signature: (II)F
+ */
+JNIEXPORT jfloat JNICALL Java_com_jacob_com_SafeArray_getFloat__II
+ (JNIEnv *env, jobject _this, jint i, jint j)
+{
+ GET2DCODE(VT_R4, V_R4, jfloat)
+}
+
+/*
+ * Class: SafeArray
+ * Method: setFloat
+ * Signature: (IF)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setFloat__IF
+ (JNIEnv *env, jobject _this, jint idx, jfloat c)
+{
+ SET1DCODE(VT_R4, V_R4);
+}
+
+/*
+ * Class: SafeArray
+ * Method: setFloat
+ * Signature: (IIF)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setFloat__IIF
+ (JNIEnv *env, jobject _this, jint i, jint j, jfloat c)
+{
+ SET2DCODE(VT_R4, V_R4);
+}
+
+/*
+ * Class: SafeArray
+ * Method: getFloats
+ * Signature: (II[FI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getFloats
+ (JNIEnv *env, jobject _this, jint idx, jint nelem, jfloatArray ja, jint ja_start)
+{
+ GETARRAYCODE(VT_R4, VT_R4, V_R4, jfloat, SetFloatArrayRegion);
+}
+
+/*
+ * Class: SafeArray
+ * Method: setFloats
+ * Signature: (II[FI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setFloats
+ (JNIEnv *env, jobject _this, jint idx, jint nelem, jfloatArray ja, jint ja_start)
+{
+ SETARRAYCODE(VT_R4, VT_R4, V_R4, jfloat,
+ GetFloatArrayElements, ReleaseFloatArrayElements);
+}
+
+/*
+ * Class: SafeArray
+ * Method: getBoolean
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_jacob_com_SafeArray_getBoolean__I
+ (JNIEnv *env, jobject _this, jint idx)
+{
+ // code is inline because of size mismatch
+ SAFEARRAY *sa = extractSA(env, _this);
+ if (!sa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return NULL;
+ }
+ if (SafeArrayGetDim(sa) != 1) {
+ ThrowComFail(env, "safearray not 1D", -1); \
+ return NULL;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(sa, &vt);
+ if (vt == VT_VARIANT) {
+ VARIANT v;
+ VariantInit(&v);
+ SafeArrayGetElement(sa, &idx, (void*) &v);
+ if (FAILED(VariantChangeType(&v, &v, 0, VT_BOOL))) {
+ ThrowComFail(env, "safearray change type failed", -1); \
+ return NULL;
+ }
+ jboolean jb = V_BOOL(&v) == VARIANT_TRUE ? JNI_TRUE: JNI_FALSE;
+ return jb;
+ } else if (vt == VT_BOOL) {
+ VARIANT_BOOL vb;
+ SafeArrayGetElement(sa, &idx, (void*) &vb);
+ jboolean jb = vb == VARIANT_TRUE ? JNI_TRUE: JNI_FALSE;
+ return jb;
+ } else {
+ return NULL;
+ }
+}
+
+/*
+ * Class: SafeArray
+ * Method: getBoolean
+ * Signature: (II)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_jacob_com_SafeArray_getBoolean__II
+ (JNIEnv *env, jobject _this, jint i, jint j)
+{
+ // code is inline because of size mismatch
+ SAFEARRAY *sa = extractSA(env, _this);
+ if (!sa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return NULL;
+ }
+ if (SafeArrayGetDim(sa) != 1) {
+ ThrowComFail(env, "safearray is not 1D", -1);
+ return NULL;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(sa, &vt);
+ long idx[2] = {i,j};
+ if (vt == VT_VARIANT) {
+ VARIANT v;
+ VariantInit(&v);
+ SafeArrayGetElement(sa, idx, (void*) &v);
+ if (FAILED(VariantChangeType(&v, &v, 0, VT_BOOL))) {
+ ThrowComFail(env, "safearray change type failed", -1);
+ return NULL;
+ }
+ jboolean jb = V_BOOL(&v) == VARIANT_TRUE ? JNI_TRUE: JNI_FALSE;
+ return jb;
+ } else if (vt == VT_BOOL) {
+ VARIANT_BOOL vb;
+ SafeArrayGetElement(sa, idx, (void*) &vb);
+ jboolean jb = vb == VARIANT_TRUE ? JNI_TRUE: JNI_FALSE;
+ return jb;
+ } else {
+ return NULL;
+ }
+}
+
+/*
+ * Class: SafeArray
+ * Method: setBoolean
+ * Signature: (IZ)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setBoolean__IZ
+ (JNIEnv *env, jobject _this, jint idx, jboolean c)
+{
+ // code is inline because of size mismatch
+ SAFEARRAY *sa = extractSA(env, _this);
+ if (!sa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return;
+ }
+ if (SafeArrayGetDim(sa) != 1) {
+ ThrowComFail(env, "safearray is not 1D", -1);
+ return;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(sa, &vt);
+ if (vt == VT_VARIANT) {
+ VARIANT v;
+ VariantInit(&v);
+ V_VT(&v) = VT_BOOL;
+ V_BOOL(&v) = c == JNI_TRUE ? VARIANT_TRUE : VARIANT_FALSE;
+ SafeArrayPutElement(sa,&idx,&v);
+ } else if (vt == VT_BOOL) {
+ VARIANT_BOOL vb = c == JNI_TRUE ? VARIANT_TRUE : VARIANT_FALSE;
+ SafeArrayPutElement(sa,&idx,&vb);
+ } else {
+ ThrowComFail(env, "safearray type mismatch", -1);
+ }
+}
+
+/*
+ * Class: SafeArray
+ * Method: setBoolean
+ * Signature: (IIZ)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setBoolean__IIZ
+ (JNIEnv *env, jobject _this, jint i, jint j, jboolean c)
+{
+ // code is inline because of size mismatch
+ SAFEARRAY *sa = extractSA(env, _this);
+ if (!sa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return;
+ }
+ if (SafeArrayGetDim(sa) != 1) {
+ ThrowComFail(env, "safearray is not 1D", -1);
+ return;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(sa, &vt);
+ long idx[2] = {i,j};
+ if (vt == VT_VARIANT) {
+ VARIANT v;
+ VariantInit(&v);
+ V_VT(&v) = VT_BOOL;
+ V_BOOL(&v) = c == JNI_TRUE ? VARIANT_TRUE : VARIANT_FALSE;
+ SafeArrayPutElement(sa,idx,&v);
+ } else if (vt == VT_BOOL) {
+ VARIANT_BOOL vb = c == JNI_TRUE ? VARIANT_TRUE : VARIANT_FALSE;
+ SafeArrayPutElement(sa,idx,&vb);
+ } else {
+ ThrowComFail(env, "safearray type mismatch", -1);
+ }
+}
+
+/*
+ * Class: SafeArray
+ * Method: getBooleans
+ * Signature: (II[ZI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getBooleans
+ (JNIEnv *env, jobject _this, jint idx, jint nelem, jbooleanArray ja, jint ja_start)
+{
+ SAFEARRAY *sa = extractSA(env, _this);
+ if (!sa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return;
+ }
+ long lb, ub;
+ SafeArrayGetLBound(sa, 1, &lb);
+ SafeArrayGetUBound(sa, 1, &ub);
+ int num = ub - lb + 1;
+ VARTYPE vt;
+ SafeArrayGetVartype(sa, &vt);
+ if (vt == VT_BOOL) {
+ VARIANT_BOOL v;
+ for(int i=idx, j=ja_start;iSetBooleanArrayRegion(ja, j, 1, &val);
+ }
+ } else if (vt == VT_VARIANT) {
+ VARIANT v;
+ VariantInit(&v);
+ for(int i=idx, j=ja_start;iSetBooleanArrayRegion(ja, j, 1, &val);
+ }
+ }
+}
+
+/*
+ * Class: SafeArray
+ * Method: setBooleans
+ * Signature: (II[ZI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setBooleans
+ (JNIEnv *env, jobject _this, jint idx, jint nelem, jbooleanArray ja, jint ja_start)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (!psa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(psa, &vt);
+ int len = env->GetArrayLength(ja);
+ if (len > numElements(psa))
+ {
+ len = numElements(psa);
+ }
+ jboolean *iarr = env->GetBooleanArrayElements(ja, 0);
+ if (vt == VT_VARIANT) {
+ VARIANT v;
+ VariantInit(&v);
+ V_VT(&v) = VT_BOOL;
+ for(int i=ja_start,j=idx;iReleaseBooleanArrayElements(ja, iarr, 0);
+}
+
+/*
+ * Class: SafeArray
+ * Method: getVariant
+ * Signature: (I)LVariant;
+ */
+JNIEXPORT jobject JNICALL Java_com_jacob_com_SafeArray_getVariant__I
+ (JNIEnv *env, jobject _this, jint idx)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (!psa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return NULL;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(psa, &vt);
+ // prepare a new return value
+ jclass variantClass = env->FindClass("com/jacob/com/Variant");
+ jmethodID variantCons =
+ env->GetMethodID(variantClass, "", "()V");
+ // construct a variant to return
+ jobject newVariant = env->NewObject(variantClass, variantCons);
+ // get the VARIANT from the newVariant
+ VARIANT *v = extractVariant(env, newVariant);
+ if (vt == VT_VARIANT) {
+ SafeArrayGetElement(psa, &idx, v);
+ } else if (vt == VT_DISPATCH || vt == VT_UNKNOWN) {
+ IDispatch *disp;
+ SafeArrayGetElement(psa, &idx, (void *)&disp);
+ VariantClear(v); // whatever was there before
+ V_VT(v) = VT_DISPATCH;
+ V_DISPATCH(v) = disp;
+ // I am handing the pointer to COM
+ disp->AddRef();
+ } else {
+ ThrowComFail(env, "safearray type is not variant/dispatch", -1);
+ }
+ return newVariant;
+}
+
+/*
+ * Class: SafeArray
+ * Method: getVariant
+ * Signature: (II)LVariant;
+ */
+JNIEXPORT jobject JNICALL Java_com_jacob_com_SafeArray_getVariant__II
+ (JNIEnv *env, jobject _this, jint i, jint j)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (!psa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return NULL;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(psa, &vt);
+ // prepare a new return value
+ jclass variantClass = env->FindClass("com/jacob/com/Variant");
+ jmethodID variantCons =
+ env->GetMethodID(variantClass, "", "()V");
+ // construct a variant to return
+ jobject newVariant = env->NewObject(variantClass, variantCons);
+ // get the VARIANT from the newVariant
+ VARIANT *v = extractVariant(env, newVariant);
+ long idx[2] = {i,j};
+ if (vt == VT_VARIANT) {
+ SafeArrayGetElement(psa, idx, v);
+ } else if (vt == VT_DISPATCH || vt == VT_UNKNOWN) {
+ IDispatch *disp;
+ SafeArrayGetElement(psa, idx, (void *)&disp);
+ VariantClear(v); // whatever was there before
+ V_VT(v) = VT_DISPATCH;
+ V_DISPATCH(v) = disp;
+ // I am handing the pointer to COM
+ disp->AddRef();
+ } else {
+ ThrowComFail(env, "safearray type is not variant/dispatch", -1);
+ }
+ return newVariant;
+}
+
+/*
+ * Class: SafeArray
+ * Method: setVariant
+ * Signature: (ILVariant;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setVariant__ILcom_jacob_com_Variant_2
+ (JNIEnv *env, jobject _this, jint idx, jobject s)
+{
+ SAFEARRAY *sa = extractSA(env, _this);
+ if (!sa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return;
+ }
+ if (SafeArrayGetDim(sa) != 1) {
+ ThrowComFail(env, "safearray is not 1D", -1);
+ return;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(sa, &vt);
+ VARIANT *v = extractVariant(env, s);
+ if (vt == VT_VARIANT) {
+ SafeArrayPutElement(sa,&idx,v);
+ } else if (vt == VT_DISPATCH || vt == VT_UNKNOWN) {
+ if (V_VT(v) != VT_DISPATCH) {
+ ThrowComFail(env, "variant is not dispatch", -1);
+ return;
+ }
+ IDispatch *disp = V_DISPATCH(v);
+ disp->AddRef();
+ SafeArrayPutElement(sa,&idx,disp);
+ } else {
+ ThrowComFail(env, "safearray type is not variant/dispatch", -1);
+ }
+}
+
+/*
+ * Class: SafeArray
+ * Method: setVariant
+ * Signature: (IILVariant;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setVariant__IILcom_jacob_com_Variant_2
+ (JNIEnv *env, jobject _this, jint i, jint j, jobject s)
+{
+ SAFEARRAY *sa = extractSA(env, _this);
+ if (!sa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return;
+ }
+ if (SafeArrayGetDim(sa) != 2) {
+ ThrowComFail(env, "safearray is not 2D", -1);
+ return;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(sa, &vt);
+ long idx[2] = {i, j};
+ if (vt == VT_VARIANT) {
+ VARIANT *v = extractVariant(env, s);
+ SafeArrayPutElement(sa,idx,v);
+ } else if (vt == VT_DISPATCH || vt == VT_UNKNOWN) {
+ VARIANT *v = extractVariant(env, s);
+ if (V_VT(v) != VT_DISPATCH) {
+ ThrowComFail(env, "variant is not dispatch", -1);
+ return;
+ }
+ IDispatch *disp = V_DISPATCH(v);
+ SafeArrayPutElement(sa,idx,disp);
+ } else {
+ ThrowComFail(env, "safearray type is not variant/dispatch", -1);
+ }
+}
+
+/*
+ * Class: SafeArray
+ * Method: getVariants
+ * Signature: (II[LVariant;I)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getVariants
+ (JNIEnv *env, jobject _this, jint idx, jint nelem, jobjectArray ja, jint ja_start)
+{
+ SAFEARRAY *sa = extractSA(env, _this);
+ if (!sa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return;
+ }
+ long lb, ub;
+ SafeArrayGetLBound(sa, 1, &lb);
+ SafeArrayGetUBound(sa, 1, &ub);
+ int num = ub - lb + 1;
+ VARTYPE vt;
+ SafeArrayGetVartype(sa, &vt);
+ if (vt == VT_VARIANT)
+ {
+ jclass variantClass = env->FindClass("com/jacob/com/Variant");
+ jmethodID variantCons =
+ env->GetMethodID(variantClass, "", "()V");
+ for(int i=idx, j=ja_start;iNewObject(variantClass, variantCons);
+ // get the VARIANT from the newVariant
+ VARIANT *v = extractVariant(env, newVariant);
+ SafeArrayGetElement(sa, &ix, (void*) v);
+ env->SetObjectArrayElement(ja, j, newVariant);
+ }
+ } else {
+ ThrowComFail(env, "safearray type is not variant", -1);
+ }
+}
+
+/*
+ * Class: SafeArray
+ * Method: setVariants
+ * Signature: (II[LVariant;I)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setVariants
+ (JNIEnv *env, jobject _this, jint idx, jint nelem, jobjectArray ja, jint ja_start)
+{
+ SAFEARRAY *psa = extractSA(env, _this);
+ if (!psa) {
+ ThrowComFail(env, "safearray object corrupted", -1);
+ return;
+ }
+ VARTYPE vt;
+ SafeArrayGetVartype(psa, &vt);
+ int len = env->GetArrayLength(ja);
+ if (len > numElements(psa))
+ {
+ len = numElements(psa);
+ }
+ if (vt == VT_VARIANT) {
+ VARIANT v;
+ VariantInit(&v);
+ for(int i=ja_start,j=idx;iGetObjectArrayElement(ja, i);
+ VARIANT *v = extractVariant(env, var);
+ long x = j;
+ SafeArrayPutElement(psa,&x,v);
+ }
+ } else {
+ ThrowComFail(env, "safearray type is not variant", -1);
+ }
+}
+
+}
diff --git a/jacob/jni/SafeArray.h b/jacob/jni/SafeArray.h
new file mode 100644
index 0000000..94d7203
--- /dev/null
+++ b/jacob/jni/SafeArray.h
@@ -0,0 +1,693 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include
+/* Header for class com_jacob_com_SafeArray */
+
+#ifndef _Included_com_jacob_com_SafeArray
+#define _Included_com_jacob_com_SafeArray
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: init
+ * Signature: (I[I[I)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_init
+ (JNIEnv *, jobject, jint, jintArray, jintArray);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: clone
+ * Signature: ()Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_com_jacob_com_SafeArray_clone
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: destroy
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_destroy
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getvt
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getvt
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: reinit
+ * Signature: (Lcom_jacob_com_SafeArray;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_reinit
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: reinterpretType
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_reinterpretType
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getLBound
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getLBound__
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getLBound
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getLBound__I
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getUBound
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getUBound__
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getUBound
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getUBound__I
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getNumDim
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getNumDim
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getFeatures
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getFeatures
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getElemSize
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getElemSize
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: fromCharArray
+ * Signature: ([C)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromCharArray
+ (JNIEnv *, jobject, jcharArray);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: fromIntArray
+ * Signature: ([I)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromIntArray
+ (JNIEnv *, jobject, jintArray);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: fromShortArray
+ * Signature: ([S)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromShortArray
+ (JNIEnv *, jobject, jshortArray);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: fromDoubleArray
+ * Signature: ([D)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromDoubleArray
+ (JNIEnv *, jobject, jdoubleArray);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: fromStringArray
+ * Signature: ([Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromStringArray
+ (JNIEnv *, jobject, jobjectArray);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: fromByteArray
+ * Signature: ([B)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromByteArray
+ (JNIEnv *, jobject, jbyteArray);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: fromFloatArray
+ * Signature: ([F)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromFloatArray
+ (JNIEnv *, jobject, jfloatArray);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: fromBooleanArray
+ * Signature: ([Z)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromBooleanArray
+ (JNIEnv *, jobject, jbooleanArray);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: fromVariantArray
+ * Signature: ([LVariant;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromVariantArray
+ (JNIEnv *, jobject, jobjectArray);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: toCharArray
+ * Signature: ()[C
+ */
+JNIEXPORT jcharArray JNICALL Java_com_jacob_com_SafeArray_toCharArray
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: toIntArray
+ * Signature: ()[I
+ */
+JNIEXPORT jintArray JNICALL Java_com_jacob_com_SafeArray_toIntArray
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: toShortArray
+ * Signature: ()[S
+ */
+JNIEXPORT jshortArray JNICALL Java_com_jacob_com_SafeArray_toShortArray
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: toDoubleArray
+ * Signature: ()[D
+ */
+JNIEXPORT jdoubleArray JNICALL Java_com_jacob_com_SafeArray_toDoubleArray
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: toStringArray
+ * Signature: ()[Ljava/lang/String;
+ */
+JNIEXPORT jobjectArray JNICALL Java_com_jacob_com_SafeArray_toStringArray
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: toByteArray
+ * Signature: ()[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_com_jacob_com_SafeArray_toByteArray
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: toFloatArray
+ * Signature: ()[F
+ */
+JNIEXPORT jfloatArray JNICALL Java_com_jacob_com_SafeArray_toFloatArray
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: toBooleanArray
+ * Signature: ()[Z
+ */
+JNIEXPORT jbooleanArray JNICALL Java_com_jacob_com_SafeArray_toBooleanArray
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: toVariantArray
+ * Signature: ()[LVariant;
+ */
+JNIEXPORT jobjectArray JNICALL Java_com_jacob_com_SafeArray_toVariantArray
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getChar
+ * Signature: (I)C
+ */
+JNIEXPORT jchar JNICALL Java_com_jacob_com_SafeArray_getChar__I
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getChar
+ * Signature: (II)C
+ */
+JNIEXPORT jchar JNICALL Java_com_jacob_com_SafeArray_getChar__II
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setChar
+ * Signature: (IC)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setChar__IC
+ (JNIEnv *, jobject, jint, jchar);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setChar
+ * Signature: (IIC)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setChar__IIC
+ (JNIEnv *, jobject, jint, jint, jchar);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getChars
+ * Signature: (II[CI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getChars
+ (JNIEnv *, jobject, jint, jint, jcharArray, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setChars
+ * Signature: (II[CI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setChars
+ (JNIEnv *, jobject, jint, jint, jcharArray, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getInt
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getInt__I
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getInt
+ * Signature: (II)I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getInt__II
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setInt
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInt__II
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setInt
+ * Signature: (III)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInt__III
+ (JNIEnv *, jobject, jint, jint, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getInts
+ * Signature: (II[II)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getInts
+ (JNIEnv *, jobject, jint, jint, jintArray, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setInts
+ * Signature: (II[II)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInts
+ (JNIEnv *, jobject, jint, jint, jintArray, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getShort
+ * Signature: (I)S
+ */
+JNIEXPORT jshort JNICALL Java_com_jacob_com_SafeArray_getShort__I
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getShort
+ * Signature: (II)S
+ */
+JNIEXPORT jshort JNICALL Java_com_jacob_com_SafeArray_getShort__II
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setShort
+ * Signature: (IS)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setShort__IS
+ (JNIEnv *, jobject, jint, jshort);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setShort
+ * Signature: (IIS)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setShort__IIS
+ (JNIEnv *, jobject, jint, jint, jshort);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getShorts
+ * Signature: (II[SI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getShorts
+ (JNIEnv *, jobject, jint, jint, jshortArray, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setShorts
+ * Signature: (II[SI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setShorts
+ (JNIEnv *, jobject, jint, jint, jshortArray, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getDouble
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_jacob_com_SafeArray_getDouble__I
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getDouble
+ * Signature: (II)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_jacob_com_SafeArray_getDouble__II
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setDouble
+ * Signature: (ID)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setDouble__ID
+ (JNIEnv *, jobject, jint, jdouble);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setDouble
+ * Signature: (IID)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setDouble__IID
+ (JNIEnv *, jobject, jint, jint, jdouble);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getDoubles
+ * Signature: (II[DI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getDoubles
+ (JNIEnv *, jobject, jint, jint, jdoubleArray, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setDoubles
+ * Signature: (II[DI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setDoubles
+ (JNIEnv *, jobject, jint, jint, jdoubleArray, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getString
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_jacob_com_SafeArray_getString__I
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getString
+ * Signature: (II)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_jacob_com_SafeArray_getString__II
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setString
+ * Signature: (ILjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setString__ILjava_lang_String_2
+ (JNIEnv *, jobject, jint, jstring);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setString
+ * Signature: (IILjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setString__IILjava_lang_String_2
+ (JNIEnv *, jobject, jint, jint, jstring);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getStrings
+ * Signature: (II[Ljava/lang/String;I)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getStrings
+ (JNIEnv *, jobject, jint, jint, jobjectArray, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setStrings
+ * Signature: (II[Ljava/lang/String;I)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setStrings
+ (JNIEnv *, jobject, jint, jint, jobjectArray, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getByte
+ * Signature: (I)B
+ */
+JNIEXPORT jbyte JNICALL Java_com_jacob_com_SafeArray_getByte__I
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getByte
+ * Signature: (II)B
+ */
+JNIEXPORT jbyte JNICALL Java_com_jacob_com_SafeArray_getByte__II
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setByte
+ * Signature: (IB)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setByte__IB
+ (JNIEnv *, jobject, jint, jbyte);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setByte
+ * Signature: (IIB)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setByte__IIB
+ (JNIEnv *, jobject, jint, jint, jbyte);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getBytes
+ * Signature: (II[BI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getBytes
+ (JNIEnv *, jobject, jint, jint, jbyteArray, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setBytes
+ * Signature: (II[BI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setBytes
+ (JNIEnv *, jobject, jint, jint, jbyteArray, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getFloat
+ * Signature: (I)F
+ */
+JNIEXPORT jfloat JNICALL Java_com_jacob_com_SafeArray_getFloat__I
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getFloat
+ * Signature: (II)F
+ */
+JNIEXPORT jfloat JNICALL Java_com_jacob_com_SafeArray_getFloat__II
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setFloat
+ * Signature: (IF)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setFloat__IF
+ (JNIEnv *, jobject, jint, jfloat);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setFloat
+ * Signature: (IIF)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setFloat__IIF
+ (JNIEnv *, jobject, jint, jint, jfloat);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getFloats
+ * Signature: (II[FI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getFloats
+ (JNIEnv *, jobject, jint, jint, jfloatArray, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setFloats
+ * Signature: (II[FI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setFloats
+ (JNIEnv *, jobject, jint, jint, jfloatArray, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getBoolean
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_jacob_com_SafeArray_getBoolean__I
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getBoolean
+ * Signature: (II)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_jacob_com_SafeArray_getBoolean__II
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setBoolean
+ * Signature: (IZ)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setBoolean__IZ
+ (JNIEnv *, jobject, jint, jboolean);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setBoolean
+ * Signature: (IIZ)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setBoolean__IIZ
+ (JNIEnv *, jobject, jint, jint, jboolean);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getBooleans
+ * Signature: (II[ZI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getBooleans
+ (JNIEnv *, jobject, jint, jint, jbooleanArray, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setBooleans
+ * Signature: (II[ZI)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setBooleans
+ (JNIEnv *, jobject, jint, jint, jbooleanArray, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getVariant
+ * Signature: (I)LVariant;
+ */
+JNIEXPORT jobject JNICALL Java_com_jacob_com_SafeArray_getVariant__I
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getVariant
+ * Signature: (II)LVariant;
+ */
+JNIEXPORT jobject JNICALL Java_com_jacob_com_SafeArray_getVariant__II
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setVariant
+ * Signature: (ILcom/jacob/com/Variant;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setVariant__ILcom_jacob_com_Variant_2
+ (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setVariant
+ * Signature: (IILcom/jacob/com/Variant;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setVariant__IILcom_jacob_com_Variant_2
+ (JNIEnv *, jobject, jint, jint, jobject);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: getVariants
+ * Signature: (II[LVariant;I)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getVariants
+ (JNIEnv *, jobject, jint, jint, jobjectArray, jint);
+
+/*
+ * Class: com_jacob_com_SafeArray
+ * Method: setVariants
+ * Signature: (II[LVariant;I)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setVariants
+ (JNIEnv *, jobject, jint, jint, jobjectArray, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/jacob/jni/StdAfx.cpp b/jacob/jni/StdAfx.cpp
new file mode 100644
index 0000000..e71783f
--- /dev/null
+++ b/jacob/jni/StdAfx.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// stdafx.cpp : source file that includes just the standard includes
+// stdafx.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+#ifdef _ATL_STATIC_REGISTRY
+#include
+#include
+#endif
+
+#include
diff --git a/jacob/jni/StdAfx.h b/jacob/jni/StdAfx.h
new file mode 100644
index 0000000..92eb401
--- /dev/null
+++ b/jacob/jni/StdAfx.h
@@ -0,0 +1,32 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently,
+// but are changed infrequently
+
+#if !defined(AFX_STDAFX_H__9988E984_6789_11D3_A646_000000000000__INCLUDED_)
+#define AFX_STDAFX_H__9988E984_6789_11D3_A646_000000000000__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#ifndef STRICT
+#define STRICT
+#endif
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0400
+#endif
+//#define _ATL_APARTMENT_THREADED
+#include
+#include
+#include
+#include
+//You may derive a class from CComModule and use it if you want to override
+//something, but do not change the name of _Module
+extern CComModule _Module;
+#include
+
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__9988E984_6789_11D3_A646_000000000000__INCLUDED)
diff --git a/jacob/jni/Variant.cpp b/jacob/jni/Variant.cpp
new file mode 100644
index 0000000..be2c338
--- /dev/null
+++ b/jacob/jni/Variant.cpp
@@ -0,0 +1,1145 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "stdafx.h"
+#include "Variant.h"
+// Win32 support for Ole Automation
+#include
+#include
+#include
+#include
+#include
+#include
+#include "util.h"
+
+extern "C"
+{
+
+#define VARIANT_FLD "m_pVariant"
+
+// extract a VARIANT from a Variant object
+VARIANT *extractVariant(JNIEnv *env, jobject arg)
+{
+ jclass argClass = env->GetObjectClass(arg);
+ jfieldID ajf = env->GetFieldID( argClass, VARIANT_FLD, "I");
+ jint anum = env->GetIntField(arg, ajf);
+ VARIANT *v = (VARIANT *)anum;
+ return v;
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_release
+ (JNIEnv *env, jobject _this)
+{
+ jclass clazz = env->GetObjectClass(_this);
+ jfieldID jf = env->GetFieldID(clazz, VARIANT_FLD, "I");
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ // fix byref leak
+ if (V_VT(v) & VT_BYREF) // is this a reference
+ {
+ void *pMem = V_BSTRREF(v); // get allocated memory
+ if (pMem)
+ {
+ if (V_VT(v) == (VT_BYREF|VT_BSTR))
+ {
+ BSTR *pBstr = (BSTR*)pMem;
+ if (*pBstr)
+ SysFreeString(*pBstr);// release bstr
+ }
+ CoTaskMemFree(pMem);
+ }
+ }
+ VariantClear(v);
+ delete v;
+ env->SetIntField(_this, jf, (unsigned int)0);
+ }
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_init
+ (JNIEnv *env, jobject _this)
+{
+ jclass clazz = env->GetObjectClass(_this);
+ jfieldID jf = env->GetFieldID( clazz, VARIANT_FLD, "I");
+ VARIANT *v = new VARIANT();
+ VariantInit(v);
+ env->SetIntField(_this, jf, (unsigned int)v);
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_Save
+ (JNIEnv *env, jobject _this, jobject outStream)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v)
+ {
+ DWORD flags = MSHCTX_LOCAL;
+ jint size = VARIANT_UserSize(&flags, 0L, v);
+ // allocate a byte array of the right length
+ jbyte* pBuf = new jbyte[size];
+ // clear it out
+ ZeroMemory(pBuf, size);
+ // marshall the Variant into the buffer
+ VARIANT_UserMarshal(&flags, (unsigned char *)pBuf, v);
+ // need to convert the buffer to a java byte ba[]
+ jbyteArray ba = env->NewByteArray(size);
+ env->SetByteArrayRegion(ba, 0, size, pBuf);
+ // and delete the original memory
+ delete [] pBuf;
+
+ //java code: DataOutputStream dos = new DataOutputStream(outStream);
+ jclass dosCls = env->FindClass("java/io/DataOutputStream");
+ jmethodID dosCons =
+ env->GetMethodID(dosCls, "", "(Ljava/io/OutputStream;)V");
+ jmethodID dosWriteInt =
+ env->GetMethodID(dosCls, "writeInt", "(I)V");
+ jmethodID dosWriteBytes =
+ env->GetMethodID(dosCls, "write", "([B)V");
+ jobject dos = env->NewObject(dosCls, dosCons, outStream);
+ // write the size into the stream
+ env->CallVoidMethod(dos, dosWriteInt, size);
+ // write the buffer into the stream
+ env->CallVoidMethod(dos, dosWriteBytes, ba);
+ }
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_Load
+ (JNIEnv *env, jobject _this, jobject inStream)
+{
+
+ VARIANT *v = extractVariant(env, _this);
+ if (!v)
+ {
+ // since the default constructor is not called when serializing in
+ // I need to init the underlying VARIANT
+ jclass clazz = env->GetObjectClass(_this);
+ jfieldID jf = env->GetFieldID( clazz, VARIANT_FLD, "I");
+ v = new VARIANT();
+ VariantInit(v);
+ env->SetIntField(_this, jf, (unsigned int)v);
+ }
+ if (v)
+ {
+ //java code: DataInputStream dis = new DataInputStream(outStream);
+ jclass disCls = env->FindClass("java/io/DataInputStream");
+ jmethodID disCons =
+ env->GetMethodID(disCls, "", "(Ljava/io/InputStream;)V");
+ jmethodID disReadInt =
+ env->GetMethodID(disCls, "readInt", "()I");
+ jmethodID disReadBytes =
+ env->GetMethodID(disCls, "readFully", "([B)V");
+ jobject dis = env->NewObject(disCls, disCons, inStream);
+
+ // read in the size from the input stream
+ jint size = env->CallIntMethod(dis, disReadInt);
+ // allocate a byte array of this size
+ jbyteArray ba = env->NewByteArray(size);
+ // read it in from the input stream
+ env->CallVoidMethod(dis, disReadBytes, ba);
+ if ( size > 0 )
+ {
+ // get a buffer from it
+ jbyte *pBuf = env->GetByteArrayElements(ba, 0);
+ // unmarshall the Variant from the buffer
+ DWORD flags = MSHCTX_LOCAL;
+ VARIANT_UserUnmarshal(&flags, (unsigned char *)pBuf, v);
+ // release the byte array
+ env->ReleaseByteArrayElements(ba, pBuf, 0);
+ }
+ }
+}
+
+JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_toInt
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ HRESULT hr;
+ if (FAILED(hr = VariantChangeType(v, v, 0, VT_I4))) {
+ ThrowComFail(env, "VariantChangeType failed", hr);
+ return NULL;
+ }
+ return (jint)V_I4(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_toDate
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ HRESULT hr;
+ if (FAILED(hr = VariantChangeType(v, v, 0, VT_DATE))) {
+ ThrowComFail(env, "VariantChangeType failed", hr);
+ return NULL;
+ }
+ return (jdouble)V_DATE(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT jboolean JNICALL Java_com_jacob_com_Variant_toBoolean
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ HRESULT hr;
+ if (FAILED(hr = VariantChangeType(v, v, 0, VT_BOOL))) {
+ ThrowComFail(env, "VariantChangeType failed", hr);
+ return NULL;
+ }
+ return (jboolean)V_BOOL(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_toEnumVariant
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v)
+ {
+ HRESULT hr;
+ if (FAILED(hr = VariantChangeType(v, v, 0, VT_UNKNOWN))) {
+ ThrowComFail(env, "VariantChangeType failed", hr);
+ return NULL;
+ }
+ jclass autoClass = env->FindClass("com/jacob/com/EnumVariant");
+ jmethodID autoCons =
+ env->GetMethodID(autoClass, "", "(I)V");
+ // construct an Unknown object to return
+ IUnknown *unk = V_UNKNOWN(v);
+ IEnumVARIANT *ie;
+ hr = unk->QueryInterface(IID_IEnumVARIANT, (void **)&ie);
+ if (FAILED(hr)) {
+ ThrowComFail(env, "[toEnumVariant]: Object does not implement IEnumVariant", hr);
+ return NULL;
+ }
+ // I am copying the pointer to java
+ if (ie) ie->AddRef();
+ jobject newAuto = env->NewObject(autoClass, autoCons, ie);
+ return newAuto;
+ }
+ return NULL;
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_getNull
+ (JNIEnv *env, jobject _this)
+{
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putNull
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+ V_VT(v) = VT_NULL;
+ }
+}
+
+JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_cloneIndirect
+ (JNIEnv *env, jobject _this)
+{
+ return NULL;
+}
+
+JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_toDouble
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ HRESULT hr;
+ if (FAILED(hr = VariantChangeType(v, v, 0, VT_R8))) {
+ ThrowComFail(env, "VariantChangeType failed", hr);
+ return NULL;
+ }
+ return (jdouble)V_R8(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_toCurrency
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ HRESULT hr;
+ if (FAILED(hr = VariantChangeType(v, v, 0, VT_CY))) {
+ ThrowComFail(env, "VariantChangeType failed", hr);
+ return NULL;
+ }
+ CY cy = V_CY(v);
+ return (jlong)cy.int64;
+ }
+ return NULL;
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putShortRef
+ (JNIEnv *env, jobject _this, jshort s)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+ short *ps = (short *)CoTaskMemAlloc(sizeof(short));
+ *ps = s;
+ V_VT(v) = VT_I2|VT_BYREF;
+ V_I2REF(v) = ps;
+ }
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putIntRef
+ (JNIEnv *env, jobject _this, jint s)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+ long *ps = (long *)CoTaskMemAlloc(sizeof(long));
+ *ps = s;
+ V_VT(v) = VT_I4|VT_BYREF;
+ V_I4REF(v) = ps;
+ }
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putDoubleRef
+ (JNIEnv *env, jobject _this, jdouble s)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ double *ps = (double *)CoTaskMemAlloc(sizeof(double));
+ *ps = s;
+ V_VT(v) = VT_R8|VT_BYREF;
+ V_R8REF(v) = ps;
+ }
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putDateRef
+ (JNIEnv *env, jobject _this, jdouble s)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+ double *ps = (double *)CoTaskMemAlloc(sizeof(double));
+ *ps = s;
+ V_VT(v) = VT_DATE|VT_BYREF;
+ V_DATEREF(v) = ps;
+ }
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putStringRef
+ (JNIEnv *env, jobject _this, jstring s)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+
+ // need to convert to C-style char buffer
+ jclass strcls = env->FindClass("java/lang/String");
+ jmethodID getBytes = env->GetMethodID(strcls, "getBytes", "()[B");
+ jbyteArray ba = (jbyteArray)env->CallObjectMethod(s, getBytes);
+ int len = env->GetArrayLength(ba);
+ jbyte* buf = (jbyte*)alloca(len + 1);
+ env->GetByteArrayRegion(ba, 0, len, buf);
+ buf[len] = '\0';
+ CComBSTR bs((char*)buf);
+
+ BSTR *pbs = (BSTR *)CoTaskMemAlloc(sizeof(BSTR));
+ bs.CopyTo(pbs);
+ V_VT(v) = VT_BSTR|VT_BYREF;
+ V_BSTRREF(v) = pbs;
+ }
+}
+
+JNIEXPORT jshort JNICALL Java_com_jacob_com_Variant_getShortRef
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ if (V_VT(v) != (VT_I2|VT_BYREF)) {
+ return NULL;
+ }
+ return (jshort)*V_I2REF(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getIntRef
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ if (V_VT(v) != (VT_I4|VT_BYREF)) {
+ return NULL;
+ }
+ return (jint)*V_I4REF(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putShort
+ (JNIEnv *env, jobject _this, jshort s)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+ V_VT(v) = VT_I2;
+ V_I2(v) = (short)s;
+ }
+}
+
+JNIEXPORT jshort JNICALL Java_com_jacob_com_Variant_getShort
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ if (V_VT(v) != VT_I2) {
+ return NULL;
+ }
+ return (jshort)V_I2(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getDoubleRef
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ if (V_VT(v) != (VT_R8|VT_BYREF)) {
+ return NULL;
+ }
+ return (jdouble)*V_R8REF(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getDateRef
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ if (V_VT(v) != (VT_DATE|VT_BYREF)) {
+ return NULL;
+ }
+ return (jdouble)*V_DATEREF(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT jstring JNICALL Java_com_jacob_com_Variant_getStringRef
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ if (V_VT(v) != (VT_BSTR|VT_BYREF)) {
+ return NULL;
+ }
+ BSTR *bs = V_BSTRREF(v);
+ jstring js = env->NewString(*bs, SysStringLen(*bs));
+ return js;
+ }
+ return NULL;
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_VariantClear
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v);
+ }
+}
+
+JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_toDispatch
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ HRESULT hr;
+ if (FAILED(hr = VariantChangeType(v, v, 0, VT_DISPATCH))) {
+ ThrowComFail(env, "VariantChangeType failed", hr);
+ return NULL;
+ }
+ jclass autoClass = env->FindClass("com/jacob/com/Dispatch");
+ jmethodID autoCons =
+ env->GetMethodID(autoClass, "", "(I)V");
+ // construct a Dispatch object to return
+ IDispatch *disp = V_DISPATCH(v);
+ // I am copying the pointer to java
+ if (disp) disp->AddRef();
+ jobject newAuto = env->NewObject(autoClass, autoCons, disp);
+ return newAuto;
+ }
+ return NULL;
+}
+
+JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_clone
+ (JNIEnv *env, jobject _this)
+{
+ return NULL;
+}
+
+JNIEXPORT jstring JNICALL Java_com_jacob_com_Variant_toString
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ switch (V_VT(v))
+ {
+ case VT_EMPTY:
+ case VT_NULL:
+ case VT_ERROR:
+ // causes VariantChangeType to bomb
+ return env->NewStringUTF("null");
+ }
+ HRESULT hr;
+ if (FAILED(hr = VariantChangeType(v, v, 0, VT_BSTR))) {
+ // cannot change type to a string
+ return env->NewStringUTF("???");
+ }
+ BSTR bs = V_BSTR(v);
+ jstring js = env->NewString(bs, SysStringLen(bs));
+ return js;
+ }
+ return NULL;
+}
+
+JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getInt
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ if (V_VT(v) != VT_I4) {
+ return NULL;
+ }
+ return (jint)V_I4(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getDate
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ if (V_VT(v) != VT_DATE) {
+ return NULL;
+ }
+ return (jdouble)V_DATE(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putInt
+ (JNIEnv *env, jobject _this, jint i)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+ V_VT(v) = VT_I4;
+ V_I4(v) = (int)i;
+ }
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putDate
+ (JNIEnv *env, jobject _this, jdouble date)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+ V_VT(v) = VT_DATE;
+ V_DATE(v) = date;
+ }
+}
+
+JNIEXPORT jbyte JNICALL Java_com_jacob_com_Variant_toByte
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ HRESULT hr;
+ if (FAILED(hr = VariantChangeType(v, v, 0, VT_UI1))) {
+ ThrowComFail(env, "VariantChangeType failed", hr);
+ return NULL;
+ }
+ return (jbyte)V_UI1(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT jboolean JNICALL Java_com_jacob_com_Variant_getBoolean
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ if (V_VT(v) != (VT_BOOL)) {
+ return NULL;
+ }
+ return (jboolean)V_BOOL(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT jbyte JNICALL Java_com_jacob_com_Variant_getByte
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ if (V_VT(v) != (VT_UI1)) {
+ return NULL;
+ }
+ return (jbyte)V_UI1(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putBoolean
+ (JNIEnv *env, jobject _this, jboolean b)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+ V_VT(v) = VT_BOOL;
+ V_BOOL(v) = b == JNI_TRUE ? VARIANT_TRUE : VARIANT_FALSE;
+ }
+ else ThrowComFail(env, "putBoolean failed", -1);
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putByte
+ (JNIEnv *env, jobject _this, jbyte b)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+ V_VT(v) = VT_UI1;
+ V_UI1(v) = b;
+ }
+ else ThrowComFail(env, "putByte failed", -1);
+}
+
+JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_toError
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ HRESULT hr;
+ if (FAILED(hr = VariantChangeType(v, v, 0, VT_ERROR))) {
+ ThrowComFail(env, "VariantChangeType failed", hr);
+ return NULL;
+ }
+ return (jint)V_ERROR(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_toObject
+ (JNIEnv *env, jobject _this)
+{
+ // not supported
+ return NULL;
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_getEmpty
+ (JNIEnv *env, jobject _this)
+{
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putEmpty
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+ V_VT(v) = VT_EMPTY;
+ }
+}
+
+JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getError
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ if (V_VT(v) != VT_ERROR) {
+ return NULL;
+ }
+ return (jint)V_ERROR(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putError
+ (JNIEnv *env, jobject _this, jint i)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+ V_VT(v) = VT_ERROR;
+ V_ERROR(v) = (int)i;
+ }
+}
+
+
+JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getDouble
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ if (V_VT(v) != VT_R8) {
+ return NULL;
+ }
+ return (jdouble)V_R8(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_getObject
+ (JNIEnv *env, jobject _this)
+{
+ // not supported
+ return NULL;
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putCurrency
+ (JNIEnv *env, jobject _this, jlong cur)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+ CY pf;
+ pf.int64 = (LONGLONG)cur;
+ V_VT(v) = VT_CY;
+ V_CY(v) = pf;
+ } else ThrowComFail(env, "putCurrency failed", -1);
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putObject
+ (JNIEnv *env, jobject _this, jobject _that)
+{
+ VARIANT *v = extractVariant(env, _this);
+ IDispatch *disp = extractDispatch(env, _that);
+ if (disp && v) {
+ VariantClear(v); // whatever was there before
+ V_VT(v) = VT_DISPATCH;
+ V_DISPATCH(v) = disp;
+ // I am handing the pointer to COM
+ disp->AddRef();
+ } else ThrowComFail(env, "putObject failed", -1);
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putDouble
+ (JNIEnv *env, jobject _this, jdouble d)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+ V_VT(v) = VT_R8;
+ V_R8(v) = (double)d;
+ }
+}
+
+JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getCurrency
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ if (V_VT(v) != VT_CY) {
+ return NULL;
+ }
+ CY cy;
+ cy = V_CY(v);
+ jlong jl;
+ memcpy(&jl, &cy, 64);
+ return jl;
+ }
+ return NULL;
+}
+
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putFloatRef
+ (JNIEnv *env, jobject _this, jfloat val)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+ float *pf = (float *)CoTaskMemAlloc(sizeof(float));
+ *pf = val;
+ V_VT(v) = VT_R4|VT_BYREF;
+ V_R4REF(v) = pf;
+ }
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putCurrencyRef
+ (JNIEnv *env, jobject _this, jlong cur)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+ CY *pf = (CY *)CoTaskMemAlloc(sizeof(CY));
+ memcpy(pf, &cur, 64);
+ V_VT(v) = VT_BYREF|VT_CY;
+ V_CYREF(v) = pf;
+ }
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putErrorRef
+ (JNIEnv *env, jobject _this, jint i)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+ V_VT(v) = VT_ERROR|VT_BYREF;
+ V_ERROR(v) = (int)i;
+ }
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putBooleanRef
+ (JNIEnv *env, jobject _this, jboolean b)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+ VARIANT_BOOL *br = (VARIANT_BOOL *)CoTaskMemAlloc(sizeof(VARIANT_BOOL));
+ *br = b ? VARIANT_TRUE : VARIANT_FALSE;
+ V_VT(v) = VT_BOOL|VT_BYREF;
+ V_BOOLREF(v) = br;
+ }
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putByteRef
+ (JNIEnv *env, jobject _this, jbyte b)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+ unsigned char *br = (unsigned char *)CoTaskMemAlloc(sizeof(char));
+ *br = b;
+ V_VT(v) = VT_UI1|VT_BYREF;
+ V_UI1REF(v) = br;
+ }
+}
+
+JNIEXPORT jstring JNICALL Java_com_jacob_com_Variant_getString
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ if (V_VT(v) != VT_BSTR) {
+ return NULL;
+ }
+ BSTR bs = V_BSTR(v);
+ jstring js = env->NewString(bs, SysStringLen(bs));
+ return js;
+ }
+ return NULL;
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putString
+ (JNIEnv *env, jobject _this, jstring s)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+ V_VT(v) = VT_BSTR;
+
+ // get C-style byte array
+ jclass strcls = env->FindClass("java/lang/String");
+ jmethodID getBytes = env->GetMethodID(strcls, "getBytes", "()[B");
+ jbyteArray ba = (jbyteArray)env->CallObjectMethod(s, getBytes);
+ int len = env->GetArrayLength(ba);
+ jbyte* buf = (jbyte*)alloca(len + 1);
+ env->GetByteArrayRegion(ba, 0, len, buf);
+ buf[len] = '\0';
+
+ CComBSTR bs((char*)buf);
+ V_VT(v) = VT_BSTR;
+ V_BSTR(v) = bs.Copy();
+ }
+}
+
+JNIEXPORT jfloat JNICALL Java_com_jacob_com_Variant_getFloatRef
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ if (V_VT(v) != (VT_R4|VT_BYREF)) {
+ return NULL;
+ }
+ return (jfloat)*V_R4REF(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getCurrencyRef
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ if (V_VT(v) != (VT_CY|VT_BYREF)) {
+ return NULL;
+ }
+ CY *cy;
+ cy = V_CYREF(v);
+ jlong jl;
+ memcpy(&jl, cy, 64);
+ return jl;
+ }
+ return NULL;
+}
+
+JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getErrorRef
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ if (V_VT(v) != (VT_ERROR|VT_BYREF)) {
+ return NULL;
+ }
+ return (jint)V_ERROR(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT jboolean JNICALL Java_com_jacob_com_Variant_getBooleanRef
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ if (V_VT(v) != (VT_BOOL|VT_BYREF)) {
+ return NULL;
+ }
+ return (jboolean)*V_BOOLREF(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_getObjectRef
+ (JNIEnv *env, jobject _this)
+{
+ return NULL;
+}
+
+
+JNIEXPORT jbyte JNICALL Java_com_jacob_com_Variant_getByteRef
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ if (V_VT(v) != (VT_UI1|VT_BYREF)) {
+ return NULL;
+ }
+ return (jbyte)*V_UI1REF(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT jfloat JNICALL Java_com_jacob_com_Variant_toFloat
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ HRESULT hr;
+ if (FAILED(hr = VariantChangeType(v, v, 0, VT_R4))) {
+ ThrowComFail(env, "VariantChangeType failed", hr);
+ return NULL;
+ }
+ return (jfloat)V_R4(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_toSafeArray
+ (JNIEnv *env, jobject _this, jboolean deepCopy)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ if ((V_VT(v) & VT_ARRAY) == 0)
+ {
+ ThrowComFail(env, "Variant not array", -1);
+ return NULL;
+ }
+ // prepare a new sa obj
+ jclass saClass = env->FindClass("com/jacob/com/SafeArray");
+ jmethodID saCons = env->GetMethodID(saClass, "", "()V");
+ // construct an SA to return
+ jobject newSA = env->NewObject(saClass, saCons);
+ // pass in the deep copy indicator
+ setSA(env, newSA, V_ARRAY(v), deepCopy == JNI_TRUE ? 1 : 0);
+ return newSA;
+ }
+ return NULL;
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putSafeArrayRef
+ (JNIEnv *env, jobject _this, jobject sa)
+{
+ SAFEARRAY *psa = extractSA(env, sa);
+ if (psa)
+ {
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VARTYPE vt;
+ SAFEARRAY **sa = (SAFEARRAY **)CoTaskMemAlloc(sizeof(SAFEARRAY*));
+ *sa = psa;
+ SafeArrayGetVartype(psa, &vt);
+ V_VT(v) = VT_ARRAY | vt | VT_BYREF;
+ V_ARRAYREF(v) = sa;
+ return;
+ }
+ ThrowComFail(env, "Can't get variant pointer", -1);
+ return;
+ }
+ ThrowComFail(env, "Can't get sa pointer", -1);
+ return;
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putSafeArray
+ (JNIEnv *env, jobject _this, jobject sa)
+{
+ SAFEARRAY *psa = extractSA(env, sa);
+ if (psa)
+ {
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VARTYPE vt;
+ SafeArrayGetVartype(psa, &vt);
+ V_VT(v) = VT_ARRAY | vt;
+ V_ARRAY(v) = psa;
+ return;
+ }
+ ThrowComFail(env, "Can't get variant pointer", -1);
+ return;
+ }
+ ThrowComFail(env, "Can't get sa pointer", -1);
+ return;
+}
+
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_noParam
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ V_VT(v) = VT_ERROR;
+ V_ERROR(v) = DISP_E_PARAMNOTFOUND;
+ }
+}
+
+JNIEXPORT jfloat JNICALL Java_com_jacob_com_Variant_getFloat
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ if (V_VT(v) != (VT_R4)) {
+ return NULL;
+ }
+ return (jfloat)V_R4(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putFloat
+ (JNIEnv *env, jobject _this, jfloat val)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+ V_VT(v) = VT_R4;
+ V_R4(v) = val;
+ }
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_changeType
+ (JNIEnv *env, jobject _this, jshort t)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantChangeType(v, v, 0, t);
+ }
+}
+
+JNIEXPORT jshort JNICALL Java_com_jacob_com_Variant_getvt
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ return (jshort)V_VT(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT jshort JNICALL Java_com_jacob_com_Variant_toShort
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ HRESULT hr;
+ if (FAILED(hr = VariantChangeType(v, v, 0, VT_I2))) {
+ ThrowComFail(env, "VariantChangeType failed", hr);
+ return NULL;
+ }
+ return (jshort)V_I2(v);
+ }
+ return NULL;
+}
+
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putSafeArrayRefHelper
+ (JNIEnv *env, jobject _this, jint pSA)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (v) {
+ VariantClear(v); // whatever was there before
+ }
+}
+
+JNIEXPORT jboolean JNICALL Java_com_jacob_com_Variant_isNull
+ (JNIEnv *env, jobject _this)
+{
+ VARIANT *v = extractVariant(env, _this);
+ if (!v) return JNI_TRUE;
+ if ((V_VT(v) & VT_ARRAY))
+ {
+ // is it a null safearray
+ if ((V_VT(v) & VT_BYREF))
+ if (!V_ARRAYREF(v)) return JNI_TRUE;
+ else
+ if (!V_ARRAY(v)) return JNI_TRUE;
+ }
+ switch (V_VT(v))
+ {
+ case VT_EMPTY:
+ case VT_NULL:
+ case VT_ERROR:
+ return JNI_TRUE;
+ // is it a null dispatch (Nothing in VB)
+ case VT_DISPATCH:
+ if (!V_DISPATCH(v)) return JNI_TRUE;
+ }
+ return JNI_FALSE;
+}
+
+}
diff --git a/jacob/jni/Variant.h b/jacob/jni/Variant.h
new file mode 100644
index 0000000..09f1288
--- /dev/null
+++ b/jacob/jni/Variant.h
@@ -0,0 +1,613 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include
+/* Header for class com_jacob_com_Variant */
+
+#ifndef _Included_com_jacob_com_Variant
+#define _Included_com_jacob_com_Variant
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_jacob_com_Variant
+ * Method: toInt
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_toInt
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: toDate
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_toDate
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: toBoolean
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_jacob_com_Variant_toBoolean
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: toEnumVariant
+ * Signature: ()Lcom/jacob/com/EnumVariant;
+ */
+JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_toEnumVariant
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getNull
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_getNull
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putNull
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putNull
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: cloneIndirect
+ * Signature: ()Lcom_jacob_com_Variant;
+ */
+JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_cloneIndirect
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: toDouble
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_toDouble
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: toCurrency
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_toCurrency
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putShortRef
+ * Signature: (S)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putShortRef
+ (JNIEnv *, jobject, jshort);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putIntRef
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putIntRef
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putDoubleRef
+ * Signature: (D)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putDoubleRef
+ (JNIEnv *, jobject, jdouble);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putDateRef
+ * Signature: (D)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putDateRef
+ (JNIEnv *, jobject, jdouble);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putStringRef
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putStringRef
+ (JNIEnv *, jobject, jstring);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getShortRef
+ * Signature: ()S
+ */
+JNIEXPORT jshort JNICALL Java_com_jacob_com_Variant_getShortRef
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getIntRef
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getIntRef
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putShort
+ * Signature: (S)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putShort
+ (JNIEnv *, jobject, jshort);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getShort
+ * Signature: ()S
+ */
+JNIEXPORT jshort JNICALL Java_com_jacob_com_Variant_getShort
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getDoubleRef
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getDoubleRef
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getDateRef
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getDateRef
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getStringRef
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_jacob_com_Variant_getStringRef
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: com_jacob_com_VariantClear
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_com_jacob_com_VariantClear
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: toDispatch
+ * Signature: ()LDispatch;
+ */
+JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_toDispatch
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: clone
+ * Signature: ()Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_clone
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: toString
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_jacob_com_Variant_toString
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getInt
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getInt
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getDate
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getDate
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putInt
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putInt
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putDate
+ * Signature: (D)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putDate
+ (JNIEnv *, jobject, jdouble);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: toByte
+ * Signature: ()B
+ */
+JNIEXPORT jbyte JNICALL Java_com_jacob_com_Variant_toByte
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getBoolean
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_jacob_com_Variant_getBoolean
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getByte
+ * Signature: ()B
+ */
+JNIEXPORT jbyte JNICALL Java_com_jacob_com_Variant_getByte
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putBoolean
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putBoolean
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putByte
+ * Signature: (B)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putByte
+ (JNIEnv *, jobject, jbyte);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: toError
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_toError
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: toObject
+ * Signature: ()Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_toObject
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getEmpty
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_getEmpty
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putEmpty
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putEmpty
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getError
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getError
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putError
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putError
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getDouble
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getDouble
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getObject
+ * Signature: ()Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_getObject
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putCurrency
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putCurrency
+ (JNIEnv *, jobject, jlong);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putObject
+ * Signature: (Ljava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putObject
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putDouble
+ * Signature: (D)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putDouble
+ (JNIEnv *, jobject, jdouble);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getCurrency
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getCurrency
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putFloatRef
+ * Signature: (F)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putFloatRef
+ (JNIEnv *, jobject, jfloat);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putCurrencyRef
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putCurrencyRef
+ (JNIEnv *, jobject, jlong);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putErrorRef
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putErrorRef
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putBooleanRef
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putBooleanRef
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putObjectRef
+ * Signature: (Ljava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putObjectRef
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putByteRef
+ * Signature: (B)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putByteRef
+ (JNIEnv *, jobject, jbyte);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getString
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_jacob_com_Variant_getString
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putString
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putString
+ (JNIEnv *, jobject, jstring);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getFloatRef
+ * Signature: ()F
+ */
+JNIEXPORT jfloat JNICALL Java_com_jacob_com_Variant_getFloatRef
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getCurrencyRef
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getCurrencyRef
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getErrorRef
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getErrorRef
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getBooleanRef
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_jacob_com_Variant_getBooleanRef
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getObjectRef
+ * Signature: ()Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_getObjectRef
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getByteRef
+ * Signature: ()B
+ */
+JNIEXPORT jbyte JNICALL Java_com_jacob_com_Variant_getByteRef
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: toFloat
+ * Signature: ()F
+ */
+JNIEXPORT jfloat JNICALL Java_com_jacob_com_Variant_toFloat
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: toSafeArray
+ * Signature: (Z)Lcom/jacob/com/SafeArray;
+ */
+JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_toSafeArray
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putSafeArrayRef
+ * Signature: (LSafeArray;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putSafeArrayRef
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putSafeArray
+ * Signature: (LSafeArray;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putSafeArray
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: noParam
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_noParam
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getFloat
+ * Signature: ()F
+ */
+JNIEXPORT jfloat JNICALL Java_com_jacob_com_Variant_getFloat
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: putFloat
+ * Signature: (F)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putFloat
+ (JNIEnv *, jobject, jfloat);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: changeType
+ * Signature: (S)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_changeType
+ (JNIEnv *, jobject, jshort);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: getvt
+ * Signature: ()S
+ */
+JNIEXPORT jshort JNICALL Java_com_jacob_com_Variant_getvt
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: toShort
+ * Signature: ()S
+ */
+JNIEXPORT jshort JNICALL Java_com_jacob_com_Variant_toShort
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: release
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_release
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_init
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: Save
+ * Signature: (Ljava/io/OutputStream;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_Save
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: Load
+ * Signature: (Ljava/io/InputStream;)V
+ */
+JNIEXPORT void JNICALL Java_com_jacob_com_Variant_Load
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: com_jacob_com_Variant
+ * Method: isNull
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_jacob_com_Variant_isNull
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/jacob/jni/jacob.dll b/jacob/jni/jacob.dll
new file mode 100644
index 0000000..1f539b9
Binary files /dev/null and b/jacob/jni/jacob.dll differ
diff --git a/jacob/jni/jacob.exp b/jacob/jni/jacob.exp
new file mode 100644
index 0000000..e7a56f7
Binary files /dev/null and b/jacob/jni/jacob.exp differ
diff --git a/jacob/jni/jacob.lib b/jacob/jni/jacob.lib
new file mode 100644
index 0000000..18b632f
Binary files /dev/null and b/jacob/jni/jacob.lib differ
diff --git a/jacob/jni/makefile b/jacob/jni/makefile
new file mode 100644
index 0000000..82bec7a
--- /dev/null
+++ b/jacob/jni/makefile
@@ -0,0 +1,51 @@
+JDK = d:\j2sdk1.4.2_06
+DEST_DIR = d:\jacob_18
+MSDEVDIR = d:\apps\\"Microsoft Visual Studio"\VC98
+
+JDK_INC = -I$(JDK)\include -I$(JDK)\include\win32
+JDK_LIB = $(JDK)\lib\jvm.lib
+MS_INC = -I$(MSDEVDIR)\Include -I$(MSDEVDIR)\ATL\Include
+SYS_LIB = oleaut32.lib ole32.lib uuid.lib kernel32.lib shell32.lib user32.lib
+OPT = /O2
+CC = cl $(OPT) $(JDK_INC) $(MS_INC)
+
+OBJFILES = stdafx.obj util.obj EventProxy.obj Variant.obj Dispatch.obj SafeArray.obj DispatchEvents.obj ComThread.obj EnumVariant.obj STA.obj DispatchProxy.obj
+
+all: jacob.dll
+ cp jacob.dll $(DEST_DIR)
+
+jacob.dll: $(OBJFILES)
+ link /dll /out:jacob.dll $(OBJFILES) $(JDK_LIB) $(SYS_LIB)
+
+stdafx.obj: stdafx.cpp *.h
+ $(CC) -c stdafx.cpp
+
+util.obj: util.cpp *.h
+ $(CC) -c util.cpp
+
+EventProxy.obj: EventProxy.cpp *.h
+ $(CC) -c EventProxy.cpp
+
+Variant.obj: Variant.cpp *.h
+ $(CC) -c Variant.cpp
+
+Dispatch.obj: Dispatch.cpp *.h
+ $(CC) -c Dispatch.cpp
+
+SafeArray.obj: SafeArray.cpp *.h
+ $(CC) -c SafeArray.cpp
+
+DispatchEvents.obj: DispatchEvents.cpp *.h
+ $(CC) -c DispatchEvents.cpp
+
+ComThread.obj: ComThread.cpp *.h
+ $(CC) -c ComThread.cpp
+
+EnumVariant.obj: EnumVariant.cpp *.h
+ $(CC) -c EnumVariant.cpp
+
+STA.obj: STA.cpp *.h
+ $(CC) -c STA.cpp
+
+DispatchProxy.obj: DispatchProxy.cpp *.h
+ $(CC) -c DispatchProxy.cpp
diff --git a/jacob/jni/util.cpp b/jacob/jni/util.cpp
new file mode 100644
index 0000000..fcbaaba
--- /dev/null
+++ b/jacob/jni/util.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the JACOB software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "Dispatch.h"
+// Win32 support for Ole Automation
+#include
+#include
+#include
+#include
+#include
+#include
+#include "util.h"
+
+extern "C"
+{
+
+void ThrowComFail(JNIEnv *env, const char* desc, jint hr)
+{
+ jclass failClass = env->FindClass("com/jacob/com/ComFailException");
+ // call the constructor that takes hr and message
+ jmethodID failCons =
+ env->GetMethodID(failClass, "", "(ILjava/lang/String;)V");
+ if (!desc) desc = "Java/COM Error";
+ jstring js = env->NewStringUTF(desc);
+ jthrowable fail = (jthrowable)env->NewObject(failClass, failCons, hr, js);
+ env->Throw(fail);
+}
+
+// if env's are different throw on the 1st env
+int CheckEnv(JNIEnv *env1, JNIEnv *env2)
+{
+ if (env1 != env2) {
+ jclass failClass = env1->FindClass("com/jacob/com/WrongThreadException");
+ // call the constructor that takes hr and message
+ jmethodID failCons =
+ env1->GetMethodID(failClass, "", "()V");
+ env1->ThrowNew(failClass, "Wrong Thread");
+ return 0;
+ }
+ return 1;
+}
+
+}
diff --git a/jacob/jni/util.h b/jacob/jni/util.h
new file mode 100644
index 0000000..6595374
--- /dev/null
+++ b/jacob/jni/util.h
@@ -0,0 +1,8 @@
+#include
+extern "C" {
+ VARIANT *extractVariant(JNIEnv *env, jobject arg);
+ void ThrowComFail(JNIEnv *env, const char* desc, jint hr);
+ IDispatch *extractDispatch(JNIEnv *env, jobject arg);
+ SAFEARRAY *extractSA(JNIEnv *env, jobject arg);
+ void setSA(JNIEnv *env, jobject arg, SAFEARRAY *sa, int copy);
+}
diff --git a/jacob/makefile b/jacob/makefile
new file mode 100644
index 0000000..cc7538d
--- /dev/null
+++ b/jacob/makefile
@@ -0,0 +1,18 @@
+JAVAC = d:\j2sdk1.4.2_06\bin\javac -O
+JAR = d:\j2sdk1.4.2_06\bin\jar -cvf jacob.jar
+COM_DIR = com\jacob\com
+ACX_DIR = com\jacob\activeX
+
+all: java jni
+ rm -f jacobSrc_18.zip jacobBin_18.zip
+ jar -cvf jacobSrc_18.zip .
+ jar -cvf jacobBin_18.zip jacob.dll jacob.jar LICENSE.TXT README.TXT samples
+
+java: jacob.jar
+ $(JAVAC) $(COM_DIR)\*.java $(ACX_DIR)\*.java
+ $(JAR) $(COM_DIR)\*.class $(ACX_DIR)\*.class
+
+jni: jni\jacob.dll
+ cd jni
+ nmake -f makefile all
+ cd ..\
diff --git a/jacob/samples/README.txt b/jacob/samples/README.txt
new file mode 100644
index 0000000..e546231
--- /dev/null
+++ b/jacob/samples/README.txt
@@ -0,0 +1,8 @@
+The ADO sample is a wrapper for the ADO classes. This demonstrates how
+to write JACOB wrappers.
+
+The applet sample shows how to use JACOB in an applet. The trick is to
+initialize and use the COM object in the same thread.
+
+The test directory has numerous tests that test various features
+of the JACOB functionality.
diff --git a/jacob/samples/ado/ADO_README.txt b/jacob/samples/ado/ADO_README.txt
new file mode 100644
index 0000000..f33b065
--- /dev/null
+++ b/jacob/samples/ado/ADO_README.txt
@@ -0,0 +1,88 @@
+- ADO Wrapper for JACOB - Copyright 1999, Dan Adler
+
+This sample shows how to generate more strongly typed wrapper classes
+for the JACOB automation classes. These are pure java classes which
+extend com.jacob.com.Dispatch and delegate all the methods to the
+unedrlying IDispatch pointer. This methodology is similar to the way
+MFC does automation wrappers, rather than using the @com directives
+to invisibly delegate the calls, as the Microsoft VM does.
+
+The ADO wrappers in this directory are not a part of the JACOB
+distribution, however, they demonstrate the preferred way to create
+wrappers around the core functionality. The wrappers included here are
+not a complete set, but they could easily be extended to provide all
+the functionality of the com.ms.wfc.data classes.
+
+The code in test.java demonstrates two ways to get a Recordset
+from SQL Server. In this case, I query for the authors in the 'pubs'
+database once by opening a Recordset object directly, and once by
+using the Command and Connection objects. The same code, using the WFC
+wrappers can be found in ms\testms.java in case you want to compare
+the performace. You can run the test.java demo in the MS VM as well.
+
+The constructor of the wrapper is used to create an instance.
+For example, the user can write:
+
+ Connection c = new Connection();
+
+The code for the Connection constructor is shown here:
+
+ public Connection()
+ {
+ super("ADODB.Connection");
+ }
+
+it simply delegates to the com.jacob.com.Dispatch constructor which
+takes a ProgID.
+
+Since I don't have a tool like JACTIVEX yet to create the wrappers
+automatically from the type library, I created them by hand by using
+the JACTIVEX'ed version as a starting point, and replacing the @com
+calls with delegated calls to JACOB classes. A simple PERL program
+could probably be used to automate this step.
+
+In order to return strongly typed wrappers from method calls, I had to
+create a special constructor which constructs the wrapper class instance
+and copies over the IDispatch pointer. This is because I can't cast a
+java Dispatch object to a super class object.
+
+For example, the Command class has a method like this:
+
+ public Connection getActiveConnection();
+
+Ideally, I would like the wrapper code to say:
+
+ public Connection getActiveConnection()
+ {
+ // this doesn't work
+ return (Connection)Dispatch.get(this, "ActiveConnection").toDispatch());
+ }
+
+Thereby wrapping the returned Dispatch pointer in a Connection object.
+But, since I can't cast in this way, I use the following construct:
+
+ public Connection getActiveConnection()
+ {
+ // this works
+ return new Connection(Dispatch.get(this, "ActiveConnection").toDispatch());
+ }
+
+Which uses a special constructor inserted into the Connection class:
+
+ /**
+ * This constructor is used instead of a case operation to
+ * turn a Dispatch object into a wider object - it must exist
+ * in every wrapper class whose instances may be returned from
+ * method calls wrapped in VT_DISPATCH Variants.
+ */
+ public Connection(Dispatch d)
+ {
+ // take over the IDispatch pointer
+ m_pDispatch = d.m_pDispatch;
+ // null out the input's pointer
+ d.m_pDispatch = 0;
+ }
+
+I have to add this constructor to any class whose instances I want
+to return from wrapped calls.
+
diff --git a/jacob/samples/ado/Command.java b/jacob/samples/ado/Command.java
new file mode 100644
index 0000000..b7618a8
--- /dev/null
+++ b/jacob/samples/ado/Command.java
@@ -0,0 +1,120 @@
+import com.jacob.com.*;
+
+public class Command extends Dispatch
+{
+ public Command()
+ {
+ super("ADODB.Command");
+ }
+
+ /**
+ * This constructor is used instead of a case operation to
+ * turn a Dispatch object into a wider object - it must exist
+ * in every wrapper class whose instances may be returned from
+ * method calls wrapped in VT_DISPATCH Variants.
+ */
+ public Command(Dispatch d)
+ {
+ // take over the IDispatch pointer
+ m_pDispatch = d.m_pDispatch;
+ // null out the input's pointer
+ d.m_pDispatch = 0;
+ }
+
+ public Variant getProperties()
+ {
+ return Dispatch.get(this, "Properties");
+ }
+
+ public Connection getActiveConnection()
+ {
+ return new Connection(Dispatch.get(this, "ActiveConnection").toDispatch());
+ }
+
+ public void setActiveConnection(Connection ppvObject)
+ {
+ Dispatch.put(this, "ActiveConnection", ppvObject);
+ }
+
+ public String getCommandText()
+ {
+ return Dispatch.get(this, "CommandText").toString();
+ }
+
+ public void setCommandText(String pbstr)
+ {
+ Dispatch.put(this, "CommandText", pbstr);
+ }
+
+ public int getCommandTimeout()
+ {
+ return Dispatch.get(this, "CommandTimeout").toInt();
+ }
+
+ public void setCommandTimeout(int plTimeout)
+ {
+ Dispatch.put(this, "CommandTimeout", new Variant(plTimeout));
+ }
+
+ public boolean getPrepared()
+ {
+ return Dispatch.get(this, "Prepared").toBoolean();
+ }
+
+ public void setPrepared(boolean pfPrepared)
+ {
+ Dispatch.put(this, "Prepared", new Variant(pfPrepared));
+ }
+
+ public Recordset Execute(Variant RecordsAffected, Variant Parameters, int Options)
+ {
+ return (Recordset)Dispatch.call(this, "Execute", RecordsAffected, Parameters, new Variant(Options)).toDispatch();
+ }
+
+ public Recordset Execute()
+ {
+ Variant dummy = new Variant();
+ return new Recordset(Dispatch.call(this, "Execute", dummy).toDispatch());
+ }
+
+ public Variant CreateParameter(String Name, int Type, int Direction, int Size, Variant Value)
+ {
+ return Dispatch.call(this, "CreateParameter", Name, new Variant(Type), new Variant(Direction), new Variant(Size), Value);
+ }
+
+ // need to wrap Parameters
+ public Variant getParameters()
+ {
+ return Dispatch.get(this, "Parameters");
+ }
+
+ public void setCommandType(int plCmdType)
+ {
+ Dispatch.put(this, "CommandType", new Variant(plCmdType));
+ }
+
+ public int getCommandType()
+ {
+ return Dispatch.get(this, "CommandType").toInt();
+ }
+
+ public String getName()
+ {
+ return Dispatch.get(this, "Name").toString();
+ }
+
+ public void setName(String pbstrName)
+ {
+ Dispatch.put(this, "Name", pbstrName);
+ }
+
+ public int getState()
+ {
+ return Dispatch.get(this, "State").toInt();
+ }
+
+ public void Cancel()
+ {
+ Dispatch.call(this, "Cancel");
+ }
+}
diff --git a/jacob/samples/ado/CommandTypeEnum.java b/jacob/samples/ado/CommandTypeEnum.java
new file mode 100644
index 0000000..69720ce
--- /dev/null
+++ b/jacob/samples/ado/CommandTypeEnum.java
@@ -0,0 +1,12 @@
+// Enum: CommandTypeEnum
+
+public interface CommandTypeEnum
+{
+ public static final int adCmdUnspecified = -1;
+ public static final int adCmdUnknown = 8;
+ public static final int adCmdText = 1;
+ public static final int adCmdTable = 2;
+ public static final int adCmdStoredProc = 4;
+ public static final int adCmdFile = 256;
+ public static final int adCmdTableDirect = 512;
+}
diff --git a/jacob/samples/ado/Connection.java b/jacob/samples/ado/Connection.java
new file mode 100644
index 0000000..2e42ff9
--- /dev/null
+++ b/jacob/samples/ado/Connection.java
@@ -0,0 +1,180 @@
+import com.jacob.com.*;
+
+public class Connection extends Dispatch
+{
+ public Connection()
+ {
+ super("ADODB.Connection");
+ }
+
+ /**
+ * This constructor is used instead of a case operation to
+ * turn a Dispatch object into a wider object - it must exist
+ * in every wrapper class whose instances may be returned from
+ * method calls wrapped in VT_DISPATCH Variants.
+ */
+ public Connection(Dispatch d)
+ {
+ // take over the IDispatch pointer
+ m_pDispatch = d.m_pDispatch;
+ // null out the input's pointer
+ d.m_pDispatch = 0;
+ }
+
+ // need to wrap Properties
+ public Variant getProperties()
+ {
+ return Dispatch.get(this, "Properties");
+ }
+
+ public String getConnectionString()
+ {
+ return Dispatch.get(this, "ConnectionString").toString();
+ }
+
+ public void setConnectionString(String pbstr)
+ {
+ Dispatch.put(this, "ConnectionString", pbstr);
+ }
+
+ public int getCommandTimeout()
+ {
+ return Dispatch.get(this, "CommandTimeout").toInt();
+ }
+
+ public void setCommandTimeout(int plTimeout)
+ {
+ Dispatch.put(this, "CommandTimeout", new Variant(plTimeout));
+ }
+
+ public int getConnectionTimeout()
+ {
+ return Dispatch.get(this, "ConnectionTimeout").toInt();
+ }
+
+ public void setConnectionTimeout(int plTimeout)
+ {
+ Dispatch.put(this, "ConnectionTimeout", new Variant(plTimeout));
+ }
+
+ public String getVersion()
+ {
+ return Dispatch.get(this, "Version").toString();
+ }
+
+ public void Close()
+ {
+ Dispatch.call(this, "Close");
+ }
+
+ // how to deal with RecordsAffected being output?
+ public Variant Execute(String CommandText, Variant RecordsAffected, int Options)
+ {
+ return Dispatch.call(this, CommandText, RecordsAffected, new Variant(Options));
+ }
+
+ public int BeginTrans()
+ {
+ return Dispatch.call(this, "BeginTrans").toInt();
+ }
+
+ public void CommitTrans()
+ {
+ Dispatch.call(this, "CommitTrans");
+ }
+
+ public void RollbackTrans()
+ {
+ Dispatch.call(this, "RollbackTrans");
+ }
+
+ public void Open(String ConnectionString, String UserID, String Password, int Options)
+ {
+ Dispatch.call(this, "Open", ConnectionString, UserID, Password, new Variant(Options));
+ }
+
+ public void Open()
+ {
+ Dispatch.call(this, "Open");
+ }
+
+ public Variant getErrors()
+ {
+ return Dispatch.get(this, "Errors");
+ }
+
+ public String getDefaultDatabase()
+ {
+ return Dispatch.get(this, "DefaultDatabase").toString();
+ }
+
+ public void setDefaultDatabase(String pbstr)
+ {
+ Dispatch.put(this, "DefaultDatabase", pbstr);
+ }
+
+ public int getIsolationLevel()
+ {
+ return Dispatch.get(this, "IsolationLevel").toInt();
+ }
+
+ public void setIsolationLevel(int Level)
+ {
+ Dispatch.put(this, "IsolationLevel", new Variant(Level));
+ }
+
+ public int getAttributes()
+ {
+ return Dispatch.get(this, "Attributes").toInt();
+ }
+
+ public void setAttributes(int plAttr)
+ {
+ Dispatch.put(this, "Attributes", new Variant(plAttr));
+ }
+
+ public int getCursorLocation()
+ {
+ return Dispatch.get(this, "CursorLocation").toInt();
+ }
+
+ public void setCursorLocation(int plCursorLoc)
+ {
+ Dispatch.put(this, "CursorLocation", new Variant(plCursorLoc));
+ }
+
+ public int getMode()
+ {
+ return Dispatch.get(this, "Mode").toInt();
+ }
+
+ public void setMode(int plMode)
+ {
+ Dispatch.put(this, "Mode", new Variant(plMode));
+ }
+
+ public String getProvider()
+ {
+ return Dispatch.get(this, "Provider").toString();
+ }
+
+ public void setProvider(String pbstr)
+ {
+ Dispatch.put(this, "Provider", pbstr);
+ }
+
+ public int getState()
+ {
+ return Dispatch.get(this, "State").toInt();
+ }
+
+ public Variant OpenSchema(int Schema, Variant Restrictions, Variant SchemaID)
+ {
+ return Dispatch.call(this, "OpenSchema", new Variant(Schema), Restrictions, SchemaID);
+ }
+
+ public void Cancel()
+ {
+ Dispatch.call(this, "Cancel");
+ }
+}
diff --git a/jacob/samples/ado/Field.java b/jacob/samples/ado/Field.java
new file mode 100644
index 0000000..345d137
--- /dev/null
+++ b/jacob/samples/ado/Field.java
@@ -0,0 +1,124 @@
+import com.jacob.com.*;
+
+public class Field extends Dispatch
+{
+ /**
+ * This constructor is used instead of a case operation to
+ * turn a Dispatch object into a wider object - it must exist
+ * in every wrapper class whose instances may be returned from
+ * method calls wrapped in VT_DISPATCH Variants.
+ */
+ public Field(Dispatch d)
+ {
+ // take over the IDispatch pointer
+ m_pDispatch = d.m_pDispatch;
+ // null out the input's pointer
+ d.m_pDispatch = 0;
+ }
+
+ public Variant getProperties()
+ {
+ return Dispatch.get(this, "Properties");
+ }
+
+ public int getActualSize()
+ {
+ return Dispatch.get(this, "ActualSize").toInt();
+ }
+
+ public int getAttributes()
+ {
+ return Dispatch.get(this, "Attributes").toInt();
+ }
+
+ public int getDefinedSize()
+ {
+ return Dispatch.get(this, "DefinedSize").toInt();
+ }
+
+ public String getName()
+ {
+ return Dispatch.get(this, "Name").toString();
+ }
+
+ public int getType()
+ {
+ return Dispatch.get(this, "Type").toInt();
+ }
+
+ public Variant getValue()
+ {
+ return Dispatch.get(this, "Value");
+ }
+
+ public void setValue(Variant pvar)
+ {
+ Dispatch.put(this, "Value", pvar);
+ }
+
+ public byte getPrecision()
+ {
+ return Dispatch.get(this, "Precision").toByte();
+ }
+
+ public byte getNumericScale()
+ {
+ return Dispatch.get(this, "NumericScale").toByte();
+ }
+
+ public void AppendChunk(Variant Data)
+ {
+ Dispatch.call(this, "AppendChunk", Data);
+ }
+
+ public Variant GetChunk(int Length)
+ {
+ return Dispatch.call(this, "GetChunk", new Variant(Length));
+ }
+
+ public Variant getOriginalValue()
+ {
+ return Dispatch.get(this, "OriginalValue");
+ }
+
+ public Variant getUnderlyingValue()
+ {
+ return Dispatch.get(this, "UnderlyingValue");
+ }
+
+ public Variant getDataFormat()
+ {
+ return Dispatch.get(this, "DataFormat");
+ }
+
+ public void setDataFormat(Variant ppiDF)
+ {
+ Dispatch.put(this, "DataFormat", ppiDF);
+ }
+
+ public void setPrecision(byte pb)
+ {
+ Dispatch.put(this, "Precision", new Variant(pb));
+ }
+
+ public void setNumericScale(byte pb)
+ {
+ Dispatch.put(this, "NumericScale", new Variant(pb));
+ }
+
+ public void setType(int pDataType)
+ {
+ Dispatch.put(this, "Type", new Variant(pDataType));
+ }
+
+ public void setDefinedSize(int pl)
+ {
+ Dispatch.put(this, "DefinedSize", new Variant(pl));
+ }
+
+ public void setAttributes(int pl)
+ {
+ Dispatch.put(this, "Attributes", new Variant(pl));
+ }
+
+}
diff --git a/jacob/samples/ado/Fields.java b/jacob/samples/ado/Fields.java
new file mode 100644
index 0000000..c8fd6cb
--- /dev/null
+++ b/jacob/samples/ado/Fields.java
@@ -0,0 +1,50 @@
+import com.jacob.com.*;
+
+public class Fields extends Dispatch
+{
+ /**
+ * This constructor is used instead of a case operation to
+ * turn a Dispatch object into a wider object - it must exist
+ * in every wrapper class whose instances may be returned from
+ * method calls wrapped in VT_DISPATCH Variants.
+ */
+ public Fields(Dispatch d)
+ {
+ // take over the IDispatch pointer
+ m_pDispatch = d.m_pDispatch;
+ // null out the input's pointer
+ d.m_pDispatch = 0;
+ }
+
+ public int getCount()
+ {
+ return Dispatch.get(this, "Count").toInt();
+ }
+
+ public Variant _NewEnum()
+ {
+ return Dispatch.call(this, "_NewEnum");
+ }
+
+ public void Refresh()
+ {
+ Dispatch.call(this, "Refresh");
+ }
+
+ public Field getItem(int Index)
+ {
+ return new Field(Dispatch.call(this, "Item", new Variant(Index)).toDispatch());
+ }
+
+ public void Append(String Name, int Type, int DefinedSize, int Attrib)
+ {
+ Dispatch.call(this, "Append", Name, new Variant(Type),
+ new Variant(DefinedSize), new Variant(Attrib));
+ }
+
+ public void Delete(Variant Index)
+ {
+ Dispatch.call(this, "Delete", Index);
+ }
+
+}
diff --git a/jacob/samples/ado/Recordset.java b/jacob/samples/ado/Recordset.java
new file mode 100644
index 0000000..fbedc51
--- /dev/null
+++ b/jacob/samples/ado/Recordset.java
@@ -0,0 +1,411 @@
+import com.jacob.com.*;
+
+public class Recordset extends Dispatch
+{
+ public Recordset()
+ {
+ super("ADODB.Recordset");
+ }
+
+ /**
+ * This constructor is used instead of a case operation to
+ * turn a Dispatch object into a wider object - it must exist
+ * in every wrapper class whose instances may be returned from
+ * method calls wrapped in VT_DISPATCH Variants.
+ */
+ public Recordset(Dispatch d)
+ {
+ // take over the IDispatch pointer
+ m_pDispatch = d.m_pDispatch;
+ // null out the input's pointer
+ d.m_pDispatch = 0;
+ }
+
+ public Variant getProperties()
+ {
+ return Dispatch.get(this, "Properties");
+ }
+
+ public int getAbsolutePosition()
+ {
+ return Dispatch.get(this, "AbsolutePosition").toInt();
+ }
+
+ public void setAbsolutePosition(int pl)
+ {
+ Dispatch.put(this, "AbsolutePosition", new Variant(pl));
+ }
+
+ public Connection getActiveConnection()
+ {
+ return new Connection(Dispatch.get(this, "ActiveConnection").toDispatch());
+ }
+
+ public void setActiveConnection(Connection ppvObject)
+ {
+ Dispatch.put(this, "ActiveConnection", ppvObject);
+ }
+
+ public void setActiveConnection(Variant ppvObject)
+ {
+ Dispatch.put(this, "ActiveConnection", ppvObject);
+ }
+
+ public boolean getBOF()
+ {
+ return Dispatch.get(this, "BOF").toBoolean();
+ }
+
+ public Variant getBookmark()
+ {
+ return Dispatch.get(this, "Bookmark");
+ }
+
+ public void setBookmark(Variant pvBookmark)
+ {
+ Dispatch.put(this, "Bookmark", pvBookmark);
+ }
+
+ public int getCacheSize()
+ {
+ return Dispatch.get(this, "CacheSize").toInt();
+ }
+
+ public void setCacheSize(int pl)
+ {
+ Dispatch.put(this, "CacheSize", new Variant(pl));
+ }
+
+ public int getCursorType()
+ {
+ return Dispatch.get(this, "CursorType").toInt();
+ }
+
+ public void setCursorType(int pl)
+ {
+ Dispatch.put(this, "CursorType", new Variant(pl));
+ }
+
+ public boolean getEOF()
+ {
+ return Dispatch.get(this, "EOF").toBoolean();
+ }
+
+ public Fields getFields()
+ {
+ return new Fields(Dispatch.get(this, "Fields").toDispatch());
+ }
+
+ public int getLockType()
+ {
+ return Dispatch.get(this, "LockType").toInt();
+ }
+
+ public void setLockType(int plLockType)
+ {
+ Dispatch.put(this, "LockType", new Variant(plLockType));
+ }
+
+ public int getMaxRecords()
+ {
+ return Dispatch.get(this, "MaxRecords").toInt();
+ }
+
+ public void setMaxRecords(int pl)
+ {
+ Dispatch.put(this, "MaxRecords", new Variant(pl));
+ }
+
+ public int getRecordCount()
+ {
+ return Dispatch.get(this, "RecordCount").toInt();
+ }
+
+ public void setSource(Object pvSource)
+ {
+ Dispatch.put(this, "Source", pvSource);
+ }
+
+ public void setSource(String pvSource)
+ {
+ Dispatch.put(this, "Source", pvSource);
+ }
+
+ public Variant getSource()
+ {
+ return Dispatch.get(this, "Source");
+ }
+
+ public void AddNew(Variant FieldList, Variant Values)
+ {
+ Dispatch.call(this, "AddNew", FieldList, Values);
+ }
+
+ public void CancelUpdate()
+ {
+ Dispatch.call(this, "CancelUpdate");
+ }
+
+ public void Close()
+ {
+ Dispatch.call(this, "Close");
+ }
+
+ public void Delete(int AffectRecords)
+ {
+ Dispatch.call(this, "Delete", new Variant(AffectRecords));
+ }
+
+ public Variant GetRows(int Rows, Variant Start, Variant Fields)
+ {
+ return Dispatch.call(this, "GetRows", new Variant(Rows), Start, Fields);
+ }
+
+ // get all rows
+ public Variant GetRows()
+ {
+ return Dispatch.call(this, "GetRows");
+ }
+
+ public void Move(int NumRecords, Variant Start)
+ {
+ Dispatch.call(this, "Move", new Variant(NumRecords), Start);
+ }
+
+ public void MoveNext()
+ {
+ Dispatch.call(this, "MoveNext");
+ }
+
+ public void MovePrevious()
+ {
+ Dispatch.call(this, "MovePrevious");
+ }
+
+ public void MoveFirst()
+ {
+ Dispatch.call(this, "MoveFirst");
+ }
+
+ public void MoveLast()
+ {
+ Dispatch.call(this, "MoveLast");
+ }
+
+ public void Open(Variant Source, Variant ActiveConnection, int CursorType, int LockType, int Options)
+ {
+ Dispatch.call(this, "Open", Source, ActiveConnection, new Variant(CursorType), new Variant(LockType), new Variant(Options));
+ }
+
+ public void Open(Variant Source, Variant ActiveConnection)
+ {
+ Dispatch.call(this, "Open", Source, ActiveConnection);
+ }
+
+ public void Requery(int Options)
+ {
+ Dispatch.call(this, "Requery", new Variant(Options));
+ }
+
+ public void Update(Variant Fields, Variant Values)
+ {
+ Dispatch.call(this, "Update", Fields, Values);
+ }
+
+ public int getAbsolutePage()
+ {
+ return Dispatch.get(this, "AbsolutePage").toInt();
+ }
+
+ public void setAbsolutePage(int pl)
+ {
+ Dispatch.put(this, "AbsolutePage", new Variant(pl));
+ }
+
+ public int getEditMode()
+ {
+ return Dispatch.get(this, "EditMode").toInt();
+ }
+
+ public Variant getFilter()
+ {
+ return Dispatch.get(this, "Filter");
+ }
+
+ public void setFilter(Variant Criteria)
+ {
+ Dispatch.put(this, "Filter", Criteria);
+ }
+
+ public int getPageCount()
+ {
+ return Dispatch.get(this, "PageCount").toInt();
+ }
+
+ public int getPageSize()
+ {
+ return Dispatch.get(this, "PageSize").toInt();
+ }
+
+ public void setPageSize(int pl)
+ {
+ Dispatch.put(this, "PageSize", new Variant(pl));
+ }
+
+ public String getSort()
+ {
+ return Dispatch.get(this, "Sort").toString();
+ }
+
+ public void setSort(String Criteria)
+ {
+ Dispatch.put(this, "Sort", Criteria);
+ }
+
+ public int getStatus()
+ {
+ return Dispatch.get(this, "Status").toInt();
+ }
+
+ public int getState()
+ {
+ return Dispatch.get(this, "State").toInt();
+ }
+
+ public void UpdateBatch(int AffectRecords)
+ {
+ Dispatch.call(this, "UpdateBatch", new Variant(AffectRecords));
+ }
+
+ public void CancelBatch(int AffectRecords)
+ {
+ Dispatch.call(this, "CancelBatch", new Variant(AffectRecords));
+ }
+
+ public int getCursorLocation()
+ {
+ return Dispatch.get(this, "CursorLocation").toInt();
+ }
+
+ public void setCursorLocation(int pl)
+ {
+ Dispatch.put(this, "CursorLocation", new Variant(pl));
+ }
+
+ public Recordset NextRecordset(Variant RecordsAffected)
+ {
+ return new Recordset(Dispatch.call(this, "NextRecordset", RecordsAffected).toDispatch());
+ }
+
+ public boolean Supports(int CursorOptions)
+ {
+ return Dispatch.call(this, "Supports", new Variant(CursorOptions)).toBoolean();
+ }
+
+ public Variant getCollect(Variant Index)
+ {
+ return Dispatch.get(this, "Collect");
+ }
+
+ public void setCollect(Variant Index, Variant pvar)
+ {
+ Dispatch.call(this, "Collect", Index, pvar);
+ }
+
+ public int getMarshalOptions()
+ {
+ return Dispatch.get(this, "MarshalOptions").toInt();
+ }
+
+ public void setMarshalOptions(int pl)
+ {
+ Dispatch.put(this, "MarshalOptions", new Variant(pl));
+ }
+
+ public void Find(String Criteria, int SkipRecords, int SearchDirection, Variant Start)
+ {
+ Dispatch.call(this, "Find", Criteria, new Variant(SkipRecords), new Variant(SearchDirection), Start);
+ }
+
+ public void Cancel()
+ {
+ Dispatch.call(this, "Cancel");
+ }
+
+ public Variant getDataSource()
+ {
+ return Dispatch.get(this, "DataSource");
+ }
+
+ public void setDataSource(Variant ppunkDataSource)
+ {
+ Dispatch.put(this, "DataSource", ppunkDataSource);
+ }
+
+ public void Save(String FileName, int PersistFormat)
+ {
+ Dispatch.call(this, "Save", FileName, new Variant(PersistFormat));
+ }
+
+ public Variant getActiveCommand()
+ {
+ return Dispatch.get(this, "ActiveCommand");
+ }
+
+ public void setStayInSync(boolean pb)
+ {
+ Dispatch.put(this, "StayInSync", new Variant(pb));
+ }
+
+ public boolean getStayInSync()
+ {
+ return Dispatch.get(this, "StayInSync").toBoolean();
+ }
+
+ public String GetString(int StringFormat, int NumRows, String ColumnDelimeter, String RowDelimeter, String NullExpr)
+ {
+ return Dispatch.call(this, "GetString", new Variant(StringFormat),
+ new Variant(NumRows), ColumnDelimeter, RowDelimeter, NullExpr).toString();
+ }
+
+ public String getDataMember()
+ {
+ return Dispatch.get(this, "DataMember").toString();
+ }
+
+ public void setDataMember(String pl)
+ {
+ Dispatch.put(this, "DataMember", new Variant(pl));
+ }
+
+ public int CompareBookmarks(Variant Bookmark1, Variant Bookmark2)
+ {
+ return Dispatch.call(this, "CompareBookmarks", Bookmark1, Bookmark2).toInt();
+ }
+
+ public Recordset Clone(int LockType)
+ {
+ return new Recordset(Dispatch.call(this, "Clone",
+ new Variant(LockType)).toDispatch());
+ }
+
+ public void Resync(int AffectRecords, int ResyncValues)
+ {
+ Dispatch.call(this, "Resync", new Variant(AffectRecords), new Variant(ResyncValues));
+ }
+
+ public void Seek(Variant KeyValues, int SeekOption)
+ {
+ Dispatch.call(this, "Seek", KeyValues, new Variant(SeekOption));
+ }
+
+ public void setIndex(String pl)
+ {
+ Dispatch.put(this, "Index", new Variant(pl));
+ }
+
+ public String getIndex()
+ {
+ return Dispatch.get(this, "Index)").toString();
+ }
+}
diff --git a/jacob/samples/ado/ms/README b/jacob/samples/ado/ms/README
new file mode 100644
index 0000000..ba754f0
--- /dev/null
+++ b/jacob/samples/ado/ms/README
@@ -0,0 +1,3 @@
+This is the WFC equivalent of the JACOB ADO example.
+
+This code must be compiled with JVC and run with JVIEW.
diff --git a/jacob/samples/ado/ms/testms.java b/jacob/samples/ado/ms/testms.java
new file mode 100644
index 0000000..49ee06e
--- /dev/null
+++ b/jacob/samples/ado/ms/testms.java
@@ -0,0 +1,64 @@
+import com.ms.com.*;
+import com.ms.wfc.data.*;
+
+// an ms-only version of test.java
+public class testms
+{
+ public static void printRS(Recordset rs)
+ {
+ Fields fs = rs.getFields();
+
+ for (int i=0;i Recordset");
+ Connection c = new Connection();
+ c.setConnectionString(con);
+ c.open();
+ Command comm = new Command();
+ comm.setActiveConnection(c);
+ comm.setCommandType(AdoEnums.CommandType.TEXT);
+ comm.setCommandText(query);
+ Recordset rs = comm.execute();
+ printRS(rs);
+ c.close();
+ }
+
+ public static void main(String[] args)
+ {
+ String connectStr = "DRIVER=SQL Server;SERVER=DANADLER;UID=sa;PWD=;WSID=DANADLER;DATABASE=pubs";
+ String queryStr = "select * from authors";
+ getCommand(connectStr, queryStr);
+ getRS(connectStr, queryStr);
+ }
+}
diff --git a/jacob/samples/ado/test.java b/jacob/samples/ado/test.java
new file mode 100644
index 0000000..decdac4
--- /dev/null
+++ b/jacob/samples/ado/test.java
@@ -0,0 +1,62 @@
+import com.jacob.com.*;
+
+public class test
+{
+ public static void printRS(Recordset rs)
+ {
+ Fields fs = rs.getFields();
+
+ for (int i=0;i Recordset");
+ Connection c = new Connection();
+ c.setConnectionString(con);
+ c.Open();
+ Command comm = new Command();
+ comm.setActiveConnection(c);
+ comm.setCommandType(CommandTypeEnum.adCmdText);
+ comm.setCommandText(query);
+ Recordset rs = comm.Execute();
+ printRS(rs);
+ c.Close();
+ }
+
+ public static void main(String[] args)
+ {
+ String connectStr = "DRIVER=SQL Server;SERVER=DANADLER;UID=sa;PWD=;WSID=DANADLER;DATABASE=pubs";
+ String queryStr = "select * from authors";
+ getCommand(connectStr, queryStr);
+ getRS(connectStr, queryStr);
+ }
+}
diff --git a/jacob/samples/applet/AppTest.html b/jacob/samples/applet/AppTest.html
new file mode 100644
index 0000000..c62a55c
--- /dev/null
+++ b/jacob/samples/applet/AppTest.html
@@ -0,0 +1,8 @@
+Applet Test (1.1)
+Applet Test (1.1)
+
+
+
+The source.
+
diff --git a/jacob/samples/applet/AppTest.java b/jacob/samples/applet/AppTest.java
new file mode 100644
index 0000000..ec0febf
--- /dev/null
+++ b/jacob/samples/applet/AppTest.java
@@ -0,0 +1,37 @@
+import java.awt.*;
+import java.awt.event.*;
+import java.applet.*;
+
+import com.jacob.com.*;
+import com.jacob.activeX.*;
+
+public class AppTest extends Applet implements ActionListener
+{
+ TextField in;
+ TextField out;
+ Button calc;
+ ActiveXComponent sC = null;
+ Object sControl = null;
+
+ public void init()
+ {
+ setLayout(new FlowLayout());
+ add(in = new TextField("1+1", 16));
+ add(out = new TextField("?", 16));
+ add(calc = new Button("Calculate"));
+ calc.addActionListener(this);
+
+ }
+
+ public void actionPerformed(ActionEvent ev)
+ {
+ if (sC == null) {
+ String lang = "VBScript";
+ sC = new ActiveXComponent("ScriptControl");
+ sControl = sC.getObject();
+ Dispatch.put(sControl, "Language", lang);
+ }
+ Variant v = Dispatch.call(sControl, "Eval", in.getText());
+ out.setText(v.toString());
+ }
+}
diff --git a/jacob/samples/servlet/JacobScript.java b/jacob/samples/servlet/JacobScript.java
new file mode 100644
index 0000000..452f456
--- /dev/null
+++ b/jacob/samples/servlet/JacobScript.java
@@ -0,0 +1,73 @@
+import javax.servlet.*;
+import javax.servlet.http.*;
+import java.io.*;
+
+import com.jacob.com.*;
+import com.jacob.activeX.*;
+
+public class JacobScript extends javax.servlet.http.HttpServlet
+{
+ public void doGet(HttpServletRequest req,
+ HttpServletResponse res)
+ throws ServletException
+ {
+ PrintWriter out = null;
+ try
+ {
+ res.setContentType("text/html");
+ out = res.getWriter();
+ // display a form
+ out.println("Enter a VBScript Expression
");
+ out.println("");
+ } catch (Exception e) {
+ e.printStackTrace();
+ out.println("Error:"+e+"
");
+ }
+ }
+
+ public void doPost(HttpServletRequest req,
+ HttpServletResponse res)
+ throws ServletException
+ {
+ PrintWriter out = null;
+
+ try
+ {
+ res.setContentType("text/html");
+ out = res.getWriter();
+ // get what they typed in
+ String expr = (String)req.getParameter("expr");
+ // make sure we have a session
+ HttpSession session = req.getSession(true);
+ Object sControl = null;
+ if (session.isNew())
+ {
+ // initialize the control and store it on the session
+ String lang = "VBScript";
+ ActiveXComponent sC = new ActiveXComponent("ScriptControl");
+ sControl = sC.getObject();
+ Dispatch.put(sControl, "Language", lang);
+ session.putValue("control", sControl);
+ }
+ else
+ {
+ sControl = session.getValue("control");
+ }
+ Variant result = Dispatch.call(sControl, "Eval", expr);
+ // display a form
+ out.println("Enter a VBScript Expression
");
+ out.println("");
+ out.println("Jacob Response:
");
+ out.println(""+result+"
");
+ } catch (Exception e) {
+ e.printStackTrace();
+ out.println("Error:"+e+"
");
+ }
+ }
+}
diff --git a/jacob/samples/servlet/readme.txt b/jacob/samples/servlet/readme.txt
new file mode 100644
index 0000000..708b6eb
--- /dev/null
+++ b/jacob/samples/servlet/readme.txt
@@ -0,0 +1,44 @@
+This sample runs in Weblogic 5.1 as a servlet.
+
+1. Compile this file (make sure you have jdk1.2 installed or the
+ javax.servlet.* classes in your classpath).
+2. Make sure the weblogic policy file allows native access. The easiest
+ way is to replace the contents with this:
+
+grant codeBase "file:d:/weblogic/-" {
+ permission java.security.AllPermission;
+};
+
+grant codeBase "file:/c:/classes/-" {
+ permission java.security.AllPermission;
+};
+
+
+grant codeBase "file:${java.home}/lib/ext/-" {
+ permission java.security.AllPermission;
+};
+
+grant {
+ permission java.security.AllPermission;
+};
+
+3. Add the servlet to the weblogic.properties file:
+
+weblogic.httpd.register.JacobScript=JacobScript
+
+4. Either add your CLASSPATH to weblogic.classpath in startWebLogic.cmd
+ or copy the com directory into weblogic/myserver/servletclasses
+
+5. Copy the jacob/samples/servlet/* into weblogic/myserver/servletclasses
+6. Start weblogic
+
+7. Type the url: http://localhost:7001/JacobScript into the browser
+ (If you run on port 7001)
+
+8. Enter a VBScript expression like:
+ 1+2
+ Now
+ "hello" & " world"
+ etc.
+ and watch the MS Script control (which you must have installed)
+ evaluate and return the result.
diff --git a/jacob/samples/test/Access.java b/jacob/samples/test/Access.java
new file mode 100644
index 0000000..88d1206
--- /dev/null
+++ b/jacob/samples/test/Access.java
@@ -0,0 +1,89 @@
+package samples.test;
+
+import com.jacob.com.*;
+import com.jacob.activeX.*;
+
+class Access
+{
+ public static void main(String[] args) throws Exception
+ {
+ ComThread.InitSTA();
+ ActiveXComponent ax = new ActiveXComponent("DAO.PrivateDBEngine");
+ // this only works for access files pre-access-2000
+ Dispatch db = open(ax, ".\\sample2.mdb");
+ String sql = "select * from MainTable";
+ // make a temporary querydef
+ Dispatch qd = Dispatch.call(db, "CreateQueryDef","").toDispatch();
+ // set the SQL string on it
+ Dispatch.put(qd, "SQL", sql);
+ Variant result = getByQueryDef(qd);
+ // the 2-d safearray is transposed from what you might expect
+ System.out.println(result.toSafeArray());
+ close(db);
+ ComThread.Release();
+ }
+
+ /**
+ * Open a database
+ */
+ public static Dispatch open(ActiveXComponent ax, String fileName)
+ {
+ Variant f = new Variant(false);
+ // open the file in read-only mode
+ Variant[] args = new Variant[] {new Variant(fileName), f, f};
+ Dispatch openDB = ax.invoke("OpenDatabase", args).toDispatch();
+ return openDB;
+ }
+
+ /**
+ * Close a database
+ */
+ public static void close(Dispatch openDB)
+ {
+ Dispatch.call(openDB, "Close");
+ }
+
+ /**
+ * Extract the values from the recordset
+ */
+ public static Variant getValues(Dispatch recset)
+ {
+ Dispatch.callSub(recset,"moveFirst");
+ Variant vi = new Variant(4096);
+ Variant v = Dispatch.call(recset,"GetRows", vi);
+ return v;
+ }
+
+ public static Variant getByQueryDef(Dispatch qd)
+ {
+ // get a reference to the recordset
+ Dispatch recset = Dispatch.call(qd, "OpenRecordset").toDispatch();
+ // get the values as a safe array
+ String[] cols = getColumns(recset);
+ for(int i=0;i
+ */
+
+import com.jacob.com.*;
+import com.jacob.activeX.*;
+
+
+public class Outlook {
+
+ private static String pad(int i) {
+ StringBuffer sb = new StringBuffer();
+
+ while(sb.length() < i) {
+ sb.append(' ');
+ }
+
+ return sb.toString();
+ }
+
+
+ private static void recurseFolders(int iIndent, Object o) {
+
+ if (o == null) return;
+ Object oFolders = Dispatch.get(o, "Folders").toDispatch();
+ // System.out.println("oFolders=" + oFolders);
+ if (oFolders == null) return;
+
+ Object oFolder = Dispatch.get(oFolders, "GetFirst").toDispatch();
+ do {
+ Object oFolderName = Dispatch.get(oFolder, "Name");
+ if (null == oFolderName) {
+ break;
+ }
+
+ System.out.println(pad(iIndent) + oFolderName);
+ recurseFolders(iIndent + 3, oFolder);
+
+ oFolder = Dispatch.get(oFolders, "GetNext").toDispatch();
+ } while(true);
+
+ }
+
+
+ public static void main(String asArgs[]) throws Exception {
+ System.out.println("Outlook: IN");
+
+ ActiveXComponent axOutlook = new ActiveXComponent("Outlook.Application");
+ try {
+ System.out.println("version="+axOutlook.getProperty("Version"));
+
+ Object oOutlook = axOutlook.getObject();
+ System.out.println("version="+Dispatch.get(oOutlook, "Version"));
+
+ Object oNameSpace = axOutlook.getProperty("Session").toDispatch();
+ System.out.println("oNameSpace=" + oNameSpace);
+
+ recurseFolders(0, oNameSpace);
+
+ } finally {
+ axOutlook.invoke("Quit", new Variant[] {});
+ }
+ }
+
+}
+
diff --git a/jacob/samples/test/ScriptTest.bat b/jacob/samples/test/ScriptTest.bat
new file mode 100644
index 0000000..f0316c2
--- /dev/null
+++ b/jacob/samples/test/ScriptTest.bat
@@ -0,0 +1,2 @@
+java ScriptTest "1+2"
+java ScriptTest "()1+2"
diff --git a/jacob/samples/test/ScriptTest.java b/jacob/samples/test/ScriptTest.java
new file mode 100644
index 0000000..6e4c06c
--- /dev/null
+++ b/jacob/samples/test/ScriptTest.java
@@ -0,0 +1,57 @@
+package samples.test;
+
+import com.jacob.com.*;
+import com.jacob.activeX.*;
+
+/**
+ * In this case the component is created and used in the same thread
+ * and it's an Apartment Threaded component, so we call InitSTA.
+ */
+class ScriptTest
+{
+ public static void main(String args[]) throws Exception
+ {
+ ComThread.InitSTA(true);
+ DispatchEvents de = null;
+ Dispatch sControl = null;
+
+ try {
+ String lang = "VBScript";
+ ActiveXComponent sC = new ActiveXComponent("ScriptControl");
+ sControl = (Dispatch)sC.getObject();
+ Dispatch.put(sControl, "Language", lang);
+ errEvents te = new errEvents();
+ de = new DispatchEvents(sControl, te);
+ Variant result = Dispatch.call(sControl, "Eval", args[0]);
+ // call it twice to see the objects reused
+ result = Dispatch.call(sControl, "Eval", args[0]);
+ // call it 3 times to see the objects reused
+ result = Dispatch.call(sControl, "Eval", args[0]);
+ System.out.println("eval("+args[0]+") = "+ result);
+ } catch (ComException e) {
+ e.printStackTrace();
+ }
+ finally
+ {
+ Integer I = null;
+ for(int i=1;i<1000000;i++)
+ {
+ I = new Integer(i);
+ }
+ System.out.println(I);
+ ComThread.Release();
+ ComThread.quitMainSTA();
+ }
+ }
+}
+
+class errEvents {
+ public void Error(Variant[] args)
+ {
+ System.out.println("java callback for error!");
+ }
+ public void Timeout(Variant[] args)
+ {
+ System.out.println("java callback for error!");
+ }
+}
diff --git a/jacob/samples/test/ScriptTest2.java b/jacob/samples/test/ScriptTest2.java
new file mode 100644
index 0000000..ec907b5
--- /dev/null
+++ b/jacob/samples/test/ScriptTest2.java
@@ -0,0 +1,98 @@
+package samples.test;
+
+import com.jacob.com.*;
+import com.jacob.activeX.*;
+
+/**
+ * This example demonstrates how to make calls between
+ * two different STA's.
+ * First, to create an STA, you need to extend the STA class
+ * and override its OnInit() method. This method will be called
+ * in the STA's thread so you can use it to create your COM
+ * components that will run in that STA.
+ * If you then try to call methods on those components from other
+ * threads (STA or MTA) - this will fail.
+ * You cannot create a component in an STA and call its methods
+ * from another thread.
+ * You can use the DispatchProxy to get a proxy to any Dispatch
+ * that lives in another STA. This object has to be created in the
+ * STA that houses the Dispatch (in this case it's created in the
+ * OnInit method). Then, another thread can call the toDispatch()
+ * method of DispatchProxy to get a local proxy. At most ONE (!)
+ * thread can call toDispatch(), and the call can be made only once.
+ * This is because a IStream object is used to pass the proxy, and
+ * it is only written once and closed when you read it.
+ * If you need multiple threads to access a Dispatch pointer, then
+ * create that many DispatchProxy objects.
+ */
+class ScriptTest2 extends STA
+{
+ public static ActiveXComponent sC;
+ public static DispatchEvents de = null;
+ public static Dispatch sControl = null;
+ public static DispatchProxy sCon = null;
+
+ public boolean OnInit()
+ {
+ try
+ {
+ System.out.println("OnInit");
+ System.out.println(Thread.currentThread());
+ String lang = "VBScript";
+ sC = new ActiveXComponent("ScriptControl");
+ sControl = (Dispatch)sC.getObject();
+
+ // sCon can be called from another thread
+ sCon = new DispatchProxy(sControl);
+
+ Dispatch.put(sControl, "Language", lang);
+ errEvents te = new errEvents();
+ de = new DispatchEvents(sControl, te);
+ return true;
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ public void OnQuit()
+ {
+ System.out.println("OnQuit");
+ }
+
+ public static void main(String args[]) throws Exception
+ {
+ try {
+ ComThread.InitSTA();
+ ScriptTest2 script = new ScriptTest2();
+ Thread.sleep(1000);
+
+ // get a thread-local Dispatch from sCon
+ Dispatch sc = sCon.toDispatch();
+
+ // call a method on the thread-local Dispatch obtained
+ // from the DispatchProxy. If you try to make the same
+ // method call on the sControl object - you will get a
+ // ComException.
+ Variant result = Dispatch.call(sc, "Eval", args[0]);
+ System.out.println("eval("+args[0]+") = "+ result);
+ script.quit();
+ System.out.println("called quit");
+ } catch (ComException e) {
+ e.printStackTrace();
+ }
+ finally
+ {
+ Integer I = null;
+ for(int i=1;i<1000000;i++)
+ {
+ I = new Integer(i);
+ }
+ System.out.println(I);
+ ComThread.Release();
+ }
+ }
+}
+
diff --git a/jacob/samples/test/ScriptTest3.java b/jacob/samples/test/ScriptTest3.java
new file mode 100644
index 0000000..6d8dbfb
--- /dev/null
+++ b/jacob/samples/test/ScriptTest3.java
@@ -0,0 +1,68 @@
+package samples.test;
+
+import com.jacob.com.*;
+import com.jacob.activeX.*;
+
+/**
+ * Here we create the ScriptControl component in a separate MTA thread
+ * and then call the Eval method from the main thread. The main thread
+ * must also be an MTA thread. If you try to create it as an STA
+ * then you will not be able to make calls into a component running
+ * in another thread.
+ */
+class ScriptTest3 extends Thread
+{
+ public static ActiveXComponent sC;
+ public static DispatchEvents de = null;
+ public static Dispatch sControl = null;
+ public static boolean quit = false;
+
+ public void run()
+ {
+ try
+ {
+ ComThread.InitMTA();
+ System.out.println("OnInit");
+ String lang = "VBScript";
+ sC = new ActiveXComponent("ScriptControl");
+ sControl = (Dispatch)sC.getObject();
+ Dispatch.put(sControl, "Language", lang);
+ errEvents te = new errEvents();
+ de = new DispatchEvents(sControl, te);
+ System.out.println("sControl="+sControl);
+ while (!quit) sleep(100);
+ ComThread.Release();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ finally
+ {
+ System.out.println("worker thread exits");
+ }
+ }
+
+ public static void main(String args[]) throws Exception
+ {
+ try {
+ ComThread.InitMTA();
+ ScriptTest3 script = new ScriptTest3();
+ script.start();
+ Thread.sleep(1000);
+
+ Variant result = Dispatch.call(sControl, "Eval", args[0]);
+ System.out.println("eval("+args[0]+") = "+ result);
+ System.out.println("setting quit");
+ script.quit = true;
+ } catch (ComException e) {
+ e.printStackTrace();
+ }
+ finally
+ {
+ System.out.println("main done");
+ ComThread.Release();
+ }
+ }
+}
+
diff --git a/jacob/samples/test/atl/MultiFace.java b/jacob/samples/test/atl/MultiFace.java
new file mode 100644
index 0000000..7647466
--- /dev/null
+++ b/jacob/samples/test/atl/MultiFace.java
@@ -0,0 +1,32 @@
+import com.jacob.com.*;
+import com.jacob.activeX.*;
+
+class MultiFace
+{
+ public static void main(String[] args)
+ {
+ System.runFinalizersOnExit(true);
+
+ ActiveXComponent mf = new ActiveXComponent("MultiFace.Face");
+ try {
+ // I am now dealing with the default interface (IFace1)
+ Dispatch.put(mf, "Face1Name", new Variant("Hello Face1"));
+ System.out.println(Dispatch.get(mf, "Face1Name"));
+
+ // get to IFace2 through the IID
+ Dispatch f2 = mf.QueryInterface("{9BF24410-B2E0-11D4-A695-00104BFF3241}");
+ // I am now dealing with IFace2
+ Dispatch.put(f2, "Face2Nam", new Variant("Hello Face2"));
+ System.out.println(Dispatch.get(f2, "Face2Nam"));
+
+ // get to IFace3 through the IID
+ Dispatch f3 = mf.QueryInterface("{9BF24411-B2E0-11D4-A695-00104BFF3241}");
+ // I am now dealing with IFace3
+ Dispatch.put(f3, "Face3Name", new Variant("Hello Face3"));
+ System.out.println(Dispatch.get(f3, "Face3Name"));
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/jacob/samples/test/atl/MultiFace/Face.cpp b/jacob/samples/test/atl/MultiFace/Face.cpp
new file mode 100644
index 0000000..83cdad3
--- /dev/null
+++ b/jacob/samples/test/atl/MultiFace/Face.cpp
@@ -0,0 +1,67 @@
+// Face.cpp : Implementation of CMultiFaceApp and DLL registration.
+
+#include "stdafx.h"
+#include "MultiFace.h"
+#include "Face.h"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+
+STDMETHODIMP Face::InterfaceSupportsErrorInfo(REFIID riid)
+{
+ static const IID* arr[] =
+ {
+ &IID_IFace1,
+ &IID_IFace2,
+ &IID_IFace3,
+ };
+
+ for (int i=0;i 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "resource.h" // main symbols
+
+/////////////////////////////////////////////////////////////////////////////
+// Face
+
+class Face :
+ public IDispatchImpl,
+ public IDispatchImpl,
+ public IDispatchImpl,
+ public ISupportErrorInfo,
+ public CComObjectRoot,
+ public CComCoClass
+{
+// IFace1
+private:
+ CComBSTR name1;
+
+// IFace2
+ CComBSTR name2;
+
+// IFace3
+ CComBSTR name3;
+
+public:
+ Face() {}
+BEGIN_COM_MAP(Face)
+ COM_INTERFACE_ENTRY2(IDispatch, IFace1)
+ COM_INTERFACE_ENTRY(IFace1)
+ COM_INTERFACE_ENTRY(IFace2)
+ COM_INTERFACE_ENTRY(IFace3)
+ COM_INTERFACE_ENTRY(ISupportErrorInfo)
+END_COM_MAP()
+//DECLARE_NOT_AGGREGATABLE(Face)
+// Remove the comment from the line above if you don't want your object to
+// support aggregation.
+
+DECLARE_REGISTRY_RESOURCEID(IDR_Face)
+// ISupportsErrorInfo
+ STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
+
+
+
+public:
+ STDMETHOD(get_Face3Name)(/*[out, retval]*/ BSTR *pVal);
+ STDMETHOD(put_Face3Name)(/*[in]*/ BSTR newVal);
+ STDMETHOD(get_Face2Nam)(/*[out, retval]*/ BSTR *pVal);
+ STDMETHOD(put_Face2Nam)(/*[in]*/ BSTR newVal);
+ STDMETHOD(get_Face1Name)(/*[out, retval]*/ BSTR *pVal);
+ STDMETHOD(put_Face1Name)(/*[in]*/ BSTR newVal);
+};
+
+#endif // !defined(AFX_FACE_H__9BF24413_B2E0_11D4_A695_00104BFF3241__INCLUDED_)
diff --git a/jacob/samples/test/atl/MultiFace/Face.rgs b/jacob/samples/test/atl/MultiFace/Face.rgs
new file mode 100644
index 0000000..70682d3
--- /dev/null
+++ b/jacob/samples/test/atl/MultiFace/Face.rgs
@@ -0,0 +1,23 @@
+HKCR
+{
+ MultiFace.Face.1 = s 'Face Class'
+ {
+ CLSID = s '{9BF24412-B2E0-11D4-A695-00104BFF3241}'
+ }
+ MultiFace.Face = s 'Face Class'
+ {
+ CLSID = s '{9BF24412-B2E0-11D4-A695-00104BFF3241}'
+ }
+ NoRemove CLSID
+ {
+ ForceRemove {9BF24412-B2E0-11D4-A695-00104BFF3241} = s 'Face Class'
+ {
+ ProgID = s 'MultiFace.Face.1'
+ VersionIndependentProgID = s 'MultiFace.Face'
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'both'
+ }
+ }
+ }
+}
diff --git a/jacob/samples/test/atl/MultiFace/MultiFace.aps b/jacob/samples/test/atl/MultiFace/MultiFace.aps
new file mode 100644
index 0000000..cb604ec
Binary files /dev/null and b/jacob/samples/test/atl/MultiFace/MultiFace.aps differ
diff --git a/jacob/samples/test/atl/MultiFace/MultiFace.cpp b/jacob/samples/test/atl/MultiFace/MultiFace.cpp
new file mode 100644
index 0000000..432544a
--- /dev/null
+++ b/jacob/samples/test/atl/MultiFace/MultiFace.cpp
@@ -0,0 +1,72 @@
+// MultiFace.cpp : Implementation of DLL Exports.
+
+
+// Note: Proxy/Stub Information
+// To build a separate proxy/stub DLL,
+// run nmake -f MultiFaceps.mk in the project directory.
+
+#include "stdafx.h"
+#include "resource.h"
+#include
+#include "MultiFace.h"
+
+#include "MultiFace_i.c"
+#include "Face.h"
+
+
+CComModule _Module;
+
+BEGIN_OBJECT_MAP(ObjectMap)
+OBJECT_ENTRY(CLSID_Face, Face)
+END_OBJECT_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// DLL Entry Point
+
+extern "C"
+BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
+{
+ if (dwReason == DLL_PROCESS_ATTACH)
+ {
+ _Module.Init(ObjectMap, hInstance, &LIBID_MULTIFACELib);
+ DisableThreadLibraryCalls(hInstance);
+ }
+ else if (dwReason == DLL_PROCESS_DETACH)
+ _Module.Term();
+ return TRUE; // ok
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Used to determine whether the DLL can be unloaded by OLE
+
+STDAPI DllCanUnloadNow(void)
+{
+ return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Returns a class factory to create an object of the requested type
+
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
+{
+ return _Module.GetClassObject(rclsid, riid, ppv);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// DllRegisterServer - Adds entries to the system registry
+
+STDAPI DllRegisterServer(void)
+{
+ // registers object, typelib and all interfaces in typelib
+ return _Module.RegisterServer(TRUE);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// DllUnregisterServer - Removes entries from the system registry
+
+STDAPI DllUnregisterServer(void)
+{
+ return _Module.UnregisterServer(TRUE);
+}
+
+
diff --git a/jacob/samples/test/atl/MultiFace/MultiFace.def b/jacob/samples/test/atl/MultiFace/MultiFace.def
new file mode 100644
index 0000000..3a720ec
--- /dev/null
+++ b/jacob/samples/test/atl/MultiFace/MultiFace.def
@@ -0,0 +1,9 @@
+; MultiFace.def : Declares the module parameters.
+
+LIBRARY "MultiFace.DLL"
+
+EXPORTS
+ DllCanUnloadNow @1 PRIVATE
+ DllGetClassObject @2 PRIVATE
+ DllRegisterServer @3 PRIVATE
+ DllUnregisterServer @4 PRIVATE
diff --git a/jacob/samples/test/atl/MultiFace/MultiFace.dsp b/jacob/samples/test/atl/MultiFace/MultiFace.dsp
new file mode 100644
index 0000000..8bf5a50
--- /dev/null
+++ b/jacob/samples/test/atl/MultiFace/MultiFace.dsp
@@ -0,0 +1,323 @@
+# Microsoft Developer Studio Project File - Name="MultiFace" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=MultiFace - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "MultiFace.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "MultiFace.mak" CFG="MultiFace - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "MultiFace - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "MultiFace - Win32 Unicode Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "MultiFace - Win32 Release MinSize" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "MultiFace - Win32 Release MinDependency" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "MultiFace - Win32 Unicode Release MinSize" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "MultiFace - Win32 Unicode Release MinDependency" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "MultiFace - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /Yu"stdafx.h" /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+# Begin Custom Build - Performing registration
+OutDir=.\Debug
+TargetPath=.\Debug\MultiFace.dll
+InputPath=.\Debug\MultiFace.dll
+SOURCE="$(InputPath)"
+
+"$(OutDir)\regsvr32.trg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ regsvr32 /s /c "$(TargetPath)"
+ echo regsvr32 exec. time > "$(OutDir)\regsvr32.trg"
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "MultiFace - Win32 Unicode Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "DebugU"
+# PROP BASE Intermediate_Dir "DebugU"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "DebugU"
+# PROP Intermediate_Dir "DebugU"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" /D "_UNICODE" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" /D "_UNICODE" /Yu"stdafx.h" /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+# Begin Custom Build - Performing registration
+OutDir=.\DebugU
+TargetPath=.\DebugU\MultiFace.dll
+InputPath=.\DebugU\MultiFace.dll
+SOURCE="$(InputPath)"
+
+"$(OutDir)\regsvr32.trg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ if "%OS%"=="" goto NOTNT
+ if not "%OS%"=="Windows_NT" goto NOTNT
+ regsvr32 /s /c "$(TargetPath)"
+ echo regsvr32 exec. time > "$(OutDir)\regsvr32.trg"
+ goto end
+ :NOTNT
+ echo Warning : Cannot register Unicode DLL on Windows 95
+ :end
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "MultiFace - Win32 Release MinSize"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ReleaseMinSize"
+# PROP BASE Intermediate_Dir "ReleaseMinSize"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ReleaseMinSize"
+# PROP Intermediate_Dir "ReleaseMinSize"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_ATL_DLL" /D "_ATL_MIN_CRT" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MT /W3 /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_ATL_DLL" /D "_ATL_MIN_CRT" /Yu"stdafx.h" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# Begin Custom Build - Performing registration
+OutDir=.\ReleaseMinSize
+TargetPath=.\ReleaseMinSize\MultiFace.dll
+InputPath=.\ReleaseMinSize\MultiFace.dll
+SOURCE="$(InputPath)"
+
+"$(OutDir)\regsvr32.trg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ regsvr32 /s /c "$(TargetPath)"
+ echo regsvr32 exec. time > "$(OutDir)\regsvr32.trg"
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "MultiFace - Win32 Release MinDependency"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ReleaseMinDependency"
+# PROP BASE Intermediate_Dir "ReleaseMinDependency"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ReleaseMinDependency"
+# PROP Intermediate_Dir "ReleaseMinDependency"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_ATL_STATIC_REGISTRY" /D "_ATL_MIN_CRT" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MT /W3 /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_ATL_STATIC_REGISTRY" /D "_ATL_MIN_CRT" /Yu"stdafx.h" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# Begin Custom Build - Performing registration
+OutDir=.\ReleaseMinDependency
+TargetPath=.\ReleaseMinDependency\MultiFace.dll
+InputPath=.\ReleaseMinDependency\MultiFace.dll
+SOURCE="$(InputPath)"
+
+"$(OutDir)\regsvr32.trg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ regsvr32 /s /c "$(TargetPath)"
+ echo regsvr32 exec. time > "$(OutDir)\regsvr32.trg"
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "MultiFace - Win32 Unicode Release MinSize"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ReleaseUMinSize"
+# PROP BASE Intermediate_Dir "ReleaseUMinSize"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ReleaseUMinSize"
+# PROP Intermediate_Dir "ReleaseUMinSize"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "_UNICODE" /D "_ATL_DLL" /D "_ATL_MIN_CRT" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MT /W3 /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "_UNICODE" /D "_ATL_DLL" /D "_ATL_MIN_CRT" /Yu"stdafx.h" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# Begin Custom Build - Performing registration
+OutDir=.\ReleaseUMinSize
+TargetPath=.\ReleaseUMinSize\MultiFace.dll
+InputPath=.\ReleaseUMinSize\MultiFace.dll
+SOURCE="$(InputPath)"
+
+"$(OutDir)\regsvr32.trg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ if "%OS%"=="" goto NOTNT
+ if not "%OS%"=="Windows_NT" goto NOTNT
+ regsvr32 /s /c "$(TargetPath)"
+ echo regsvr32 exec. time > "$(OutDir)\regsvr32.trg"
+ goto end
+ :NOTNT
+ echo Warning : Cannot register Unicode DLL on Windows 95
+ :end
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "MultiFace - Win32 Unicode Release MinDependency"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ReleaseUMinDependency"
+# PROP BASE Intermediate_Dir "ReleaseUMinDependency"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ReleaseUMinDependency"
+# PROP Intermediate_Dir "ReleaseUMinDependency"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "_UNICODE" /D "_ATL_STATIC_REGISTRY" /D "_ATL_MIN_CRT" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MT /W3 /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "_UNICODE" /D "_ATL_STATIC_REGISTRY" /D "_ATL_MIN_CRT" /Yu"stdafx.h" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# Begin Custom Build - Performing registration
+OutDir=.\ReleaseUMinDependency
+TargetPath=.\ReleaseUMinDependency\MultiFace.dll
+InputPath=.\ReleaseUMinDependency\MultiFace.dll
+SOURCE="$(InputPath)"
+
+"$(OutDir)\regsvr32.trg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ if "%OS%"=="" goto NOTNT
+ if not "%OS%"=="Windows_NT" goto NOTNT
+ regsvr32 /s /c "$(TargetPath)"
+ echo regsvr32 exec. time > "$(OutDir)\regsvr32.trg"
+ goto end
+ :NOTNT
+ echo Warning : Cannot register Unicode DLL on Windows 95
+ :end
+
+# End Custom Build
+
+!ENDIF
+
+# Begin Target
+
+# Name "MultiFace - Win32 Debug"
+# Name "MultiFace - Win32 Unicode Debug"
+# Name "MultiFace - Win32 Release MinSize"
+# Name "MultiFace - Win32 Release MinDependency"
+# Name "MultiFace - Win32 Unicode Release MinSize"
+# Name "MultiFace - Win32 Unicode Release MinDependency"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\Face.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MultiFace.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MultiFace.def
+# End Source File
+# Begin Source File
+
+SOURCE=.\MultiFace.idl
+# ADD MTL /tlb ".\MultiFace.tlb" /h "MultiFace.h" /iid "MultiFace_i.c" /Oicf
+# End Source File
+# Begin Source File
+
+SOURCE=.\MultiFace.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"stdafx.h"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\Face.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\Face.rgs
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/jacob/samples/test/atl/MultiFace/MultiFace.dsw b/jacob/samples/test/atl/MultiFace/MultiFace.dsw
new file mode 100644
index 0000000..4d6beb1
--- /dev/null
+++ b/jacob/samples/test/atl/MultiFace/MultiFace.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "MultiFace"=.\MultiFace.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/jacob/samples/test/atl/MultiFace/MultiFace.h b/jacob/samples/test/atl/MultiFace/MultiFace.h
new file mode 100644
index 0000000..9e0dffd
--- /dev/null
+++ b/jacob/samples/test/atl/MultiFace/MultiFace.h
@@ -0,0 +1,571 @@
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+/* File created by MIDL compiler version 5.01.0164 */
+/* at Sun Nov 05 01:12:47 2000
+ */
+/* Compiler settings for D:\jacob_15\samples\test\atl\MultiFace\MultiFace.idl:
+ Oicf (OptLev=i2), W1, Zp8, env=Win32, ms_ext, c_ext
+ error checks: allocation ref bounds_check enum stub_data
+*/
+//@@MIDL_FILE_HEADING( )
+
+
+/* verify that the version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 440
+#endif
+
+#include "rpc.h"
+#include "rpcndr.h"
+
+#ifndef __RPCNDR_H_VERSION__
+#error this stub requires an updated version of
+#endif // __RPCNDR_H_VERSION__
+
+#ifndef COM_NO_WINDOWS_H
+#include "windows.h"
+#include "ole2.h"
+#endif /*COM_NO_WINDOWS_H*/
+
+#ifndef __MultiFace_h__
+#define __MultiFace_h__
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+/* Forward Declarations */
+
+#ifndef __IFace1_FWD_DEFINED__
+#define __IFace1_FWD_DEFINED__
+typedef interface IFace1 IFace1;
+#endif /* __IFace1_FWD_DEFINED__ */
+
+
+#ifndef __IFace2_FWD_DEFINED__
+#define __IFace2_FWD_DEFINED__
+typedef interface IFace2 IFace2;
+#endif /* __IFace2_FWD_DEFINED__ */
+
+
+#ifndef __IFace3_FWD_DEFINED__
+#define __IFace3_FWD_DEFINED__
+typedef interface IFace3 IFace3;
+#endif /* __IFace3_FWD_DEFINED__ */
+
+
+#ifndef __Face_FWD_DEFINED__
+#define __Face_FWD_DEFINED__
+
+#ifdef __cplusplus
+typedef class Face Face;
+#else
+typedef struct Face Face;
+#endif /* __cplusplus */
+
+#endif /* __Face_FWD_DEFINED__ */
+
+
+/* header files for imported files */
+#include "oaidl.h"
+#include "ocidl.h"
+
+void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t);
+void __RPC_USER MIDL_user_free( void __RPC_FAR * );
+
+#ifndef __IFace1_INTERFACE_DEFINED__
+#define __IFace1_INTERFACE_DEFINED__
+
+/* interface IFace1 */
+/* [unique][helpstring][dual][uuid][object] */
+
+
+EXTERN_C const IID IID_IFace1;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("9BF2440F-B2E0-11D4-A695-00104BFF3241")
+ IFace1 : public IDispatch
+ {
+ public:
+ virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Face1Name(
+ /* [retval][out] */ BSTR __RPC_FAR *pVal) = 0;
+
+ virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_Face1Name(
+ /* [in] */ BSTR newVal) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IFace1Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )(
+ IFace1 __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )(
+ IFace1 __RPC_FAR * This);
+
+ ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )(
+ IFace1 __RPC_FAR * This);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfoCount )(
+ IFace1 __RPC_FAR * This,
+ /* [out] */ UINT __RPC_FAR *pctinfo);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfo )(
+ IFace1 __RPC_FAR * This,
+ /* [in] */ UINT iTInfo,
+ /* [in] */ LCID lcid,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetIDsOfNames )(
+ IFace1 __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
+ /* [in] */ UINT cNames,
+ /* [in] */ LCID lcid,
+ /* [size_is][out] */ DISPID __RPC_FAR *rgDispId);
+
+ /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Invoke )(
+ IFace1 __RPC_FAR * This,
+ /* [in] */ DISPID dispIdMember,
+ /* [in] */ REFIID riid,
+ /* [in] */ LCID lcid,
+ /* [in] */ WORD wFlags,
+ /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
+ /* [out] */ VARIANT __RPC_FAR *pVarResult,
+ /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
+ /* [out] */ UINT __RPC_FAR *puArgErr);
+
+ /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_Face1Name )(
+ IFace1 __RPC_FAR * This,
+ /* [retval][out] */ BSTR __RPC_FAR *pVal);
+
+ /* [helpstring][id][propput] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *put_Face1Name )(
+ IFace1 __RPC_FAR * This,
+ /* [in] */ BSTR newVal);
+
+ END_INTERFACE
+ } IFace1Vtbl;
+
+ interface IFace1
+ {
+ CONST_VTBL struct IFace1Vtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IFace1_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IFace1_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IFace1_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IFace1_GetTypeInfoCount(This,pctinfo) \
+ (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo)
+
+#define IFace1_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \
+ (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo)
+
+#define IFace1_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \
+ (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)
+
+#define IFace1_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \
+ (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)
+
+
+#define IFace1_get_Face1Name(This,pVal) \
+ (This)->lpVtbl -> get_Face1Name(This,pVal)
+
+#define IFace1_put_Face1Name(This,newVal) \
+ (This)->lpVtbl -> put_Face1Name(This,newVal)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IFace1_get_Face1Name_Proxy(
+ IFace1 __RPC_FAR * This,
+ /* [retval][out] */ BSTR __RPC_FAR *pVal);
+
+
+void __RPC_STUB IFace1_get_Face1Name_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE IFace1_put_Face1Name_Proxy(
+ IFace1 __RPC_FAR * This,
+ /* [in] */ BSTR newVal);
+
+
+void __RPC_STUB IFace1_put_Face1Name_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+
+#endif /* __IFace1_INTERFACE_DEFINED__ */
+
+
+#ifndef __IFace2_INTERFACE_DEFINED__
+#define __IFace2_INTERFACE_DEFINED__
+
+/* interface IFace2 */
+/* [unique][helpstring][dual][uuid][object] */
+
+
+EXTERN_C const IID IID_IFace2;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("9BF24410-B2E0-11D4-A695-00104BFF3241")
+ IFace2 : public IDispatch
+ {
+ public:
+ virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Face2Nam(
+ /* [retval][out] */ BSTR __RPC_FAR *pVal) = 0;
+
+ virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_Face2Nam(
+ /* [in] */ BSTR newVal) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IFace2Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )(
+ IFace2 __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )(
+ IFace2 __RPC_FAR * This);
+
+ ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )(
+ IFace2 __RPC_FAR * This);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfoCount )(
+ IFace2 __RPC_FAR * This,
+ /* [out] */ UINT __RPC_FAR *pctinfo);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfo )(
+ IFace2 __RPC_FAR * This,
+ /* [in] */ UINT iTInfo,
+ /* [in] */ LCID lcid,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetIDsOfNames )(
+ IFace2 __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
+ /* [in] */ UINT cNames,
+ /* [in] */ LCID lcid,
+ /* [size_is][out] */ DISPID __RPC_FAR *rgDispId);
+
+ /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Invoke )(
+ IFace2 __RPC_FAR * This,
+ /* [in] */ DISPID dispIdMember,
+ /* [in] */ REFIID riid,
+ /* [in] */ LCID lcid,
+ /* [in] */ WORD wFlags,
+ /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
+ /* [out] */ VARIANT __RPC_FAR *pVarResult,
+ /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
+ /* [out] */ UINT __RPC_FAR *puArgErr);
+
+ /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_Face2Nam )(
+ IFace2 __RPC_FAR * This,
+ /* [retval][out] */ BSTR __RPC_FAR *pVal);
+
+ /* [helpstring][id][propput] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *put_Face2Nam )(
+ IFace2 __RPC_FAR * This,
+ /* [in] */ BSTR newVal);
+
+ END_INTERFACE
+ } IFace2Vtbl;
+
+ interface IFace2
+ {
+ CONST_VTBL struct IFace2Vtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IFace2_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IFace2_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IFace2_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IFace2_GetTypeInfoCount(This,pctinfo) \
+ (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo)
+
+#define IFace2_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \
+ (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo)
+
+#define IFace2_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \
+ (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)
+
+#define IFace2_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \
+ (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)
+
+
+#define IFace2_get_Face2Nam(This,pVal) \
+ (This)->lpVtbl -> get_Face2Nam(This,pVal)
+
+#define IFace2_put_Face2Nam(This,newVal) \
+ (This)->lpVtbl -> put_Face2Nam(This,newVal)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IFace2_get_Face2Nam_Proxy(
+ IFace2 __RPC_FAR * This,
+ /* [retval][out] */ BSTR __RPC_FAR *pVal);
+
+
+void __RPC_STUB IFace2_get_Face2Nam_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE IFace2_put_Face2Nam_Proxy(
+ IFace2 __RPC_FAR * This,
+ /* [in] */ BSTR newVal);
+
+
+void __RPC_STUB IFace2_put_Face2Nam_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+
+#endif /* __IFace2_INTERFACE_DEFINED__ */
+
+
+#ifndef __IFace3_INTERFACE_DEFINED__
+#define __IFace3_INTERFACE_DEFINED__
+
+/* interface IFace3 */
+/* [unique][helpstring][dual][uuid][object] */
+
+
+EXTERN_C const IID IID_IFace3;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("9BF24411-B2E0-11D4-A695-00104BFF3241")
+ IFace3 : public IDispatch
+ {
+ public:
+ virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Face3Name(
+ /* [retval][out] */ BSTR __RPC_FAR *pVal) = 0;
+
+ virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_Face3Name(
+ /* [in] */ BSTR newVal) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IFace3Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )(
+ IFace3 __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )(
+ IFace3 __RPC_FAR * This);
+
+ ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )(
+ IFace3 __RPC_FAR * This);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfoCount )(
+ IFace3 __RPC_FAR * This,
+ /* [out] */ UINT __RPC_FAR *pctinfo);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfo )(
+ IFace3 __RPC_FAR * This,
+ /* [in] */ UINT iTInfo,
+ /* [in] */ LCID lcid,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetIDsOfNames )(
+ IFace3 __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
+ /* [in] */ UINT cNames,
+ /* [in] */ LCID lcid,
+ /* [size_is][out] */ DISPID __RPC_FAR *rgDispId);
+
+ /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Invoke )(
+ IFace3 __RPC_FAR * This,
+ /* [in] */ DISPID dispIdMember,
+ /* [in] */ REFIID riid,
+ /* [in] */ LCID lcid,
+ /* [in] */ WORD wFlags,
+ /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
+ /* [out] */ VARIANT __RPC_FAR *pVarResult,
+ /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
+ /* [out] */ UINT __RPC_FAR *puArgErr);
+
+ /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_Face3Name )(
+ IFace3 __RPC_FAR * This,
+ /* [retval][out] */ BSTR __RPC_FAR *pVal);
+
+ /* [helpstring][id][propput] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *put_Face3Name )(
+ IFace3 __RPC_FAR * This,
+ /* [in] */ BSTR newVal);
+
+ END_INTERFACE
+ } IFace3Vtbl;
+
+ interface IFace3
+ {
+ CONST_VTBL struct IFace3Vtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IFace3_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IFace3_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IFace3_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IFace3_GetTypeInfoCount(This,pctinfo) \
+ (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo)
+
+#define IFace3_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \
+ (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo)
+
+#define IFace3_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \
+ (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)
+
+#define IFace3_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \
+ (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)
+
+
+#define IFace3_get_Face3Name(This,pVal) \
+ (This)->lpVtbl -> get_Face3Name(This,pVal)
+
+#define IFace3_put_Face3Name(This,newVal) \
+ (This)->lpVtbl -> put_Face3Name(This,newVal)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IFace3_get_Face3Name_Proxy(
+ IFace3 __RPC_FAR * This,
+ /* [retval][out] */ BSTR __RPC_FAR *pVal);
+
+
+void __RPC_STUB IFace3_get_Face3Name_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE IFace3_put_Face3Name_Proxy(
+ IFace3 __RPC_FAR * This,
+ /* [in] */ BSTR newVal);
+
+
+void __RPC_STUB IFace3_put_Face3Name_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+
+#endif /* __IFace3_INTERFACE_DEFINED__ */
+
+
+
+#ifndef __MULTIFACELib_LIBRARY_DEFINED__
+#define __MULTIFACELib_LIBRARY_DEFINED__
+
+/* library MULTIFACELib */
+/* [helpstring][version][uuid] */
+
+
+EXTERN_C const IID LIBID_MULTIFACELib;
+
+EXTERN_C const CLSID CLSID_Face;
+
+#ifdef __cplusplus
+
+class DECLSPEC_UUID("9BF24412-B2E0-11D4-A695-00104BFF3241")
+Face;
+#endif
+#endif /* __MULTIFACELib_LIBRARY_DEFINED__ */
+
+/* Additional Prototypes for ALL interfaces */
+
+unsigned long __RPC_USER BSTR_UserSize( unsigned long __RPC_FAR *, unsigned long , BSTR __RPC_FAR * );
+unsigned char __RPC_FAR * __RPC_USER BSTR_UserMarshal( unsigned long __RPC_FAR *, unsigned char __RPC_FAR *, BSTR __RPC_FAR * );
+unsigned char __RPC_FAR * __RPC_USER BSTR_UserUnmarshal(unsigned long __RPC_FAR *, unsigned char __RPC_FAR *, BSTR __RPC_FAR * );
+void __RPC_USER BSTR_UserFree( unsigned long __RPC_FAR *, BSTR __RPC_FAR * );
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/jacob/samples/test/atl/MultiFace/MultiFace.idl b/jacob/samples/test/atl/MultiFace/MultiFace.idl
new file mode 100644
index 0000000..37b07aa
--- /dev/null
+++ b/jacob/samples/test/atl/MultiFace/MultiFace.idl
@@ -0,0 +1,70 @@
+// MultiFace.idl : IDL source for MultiFace.dll
+//
+
+// This file will be processed by the MIDL tool to
+// produce the type library (MultiFace.tlb) and marshalling code.
+
+import "oaidl.idl";
+import "ocidl.idl";
+
+ [
+ object,
+ uuid(9BF2440F-B2E0-11D4-A695-00104BFF3241),
+ dual,
+ helpstring("IFace1 Interface"),
+ pointer_default(unique)
+ ]
+ interface IFace1 : IDispatch
+ {
+ [propget, id(1), helpstring("property Face1Name")] HRESULT Face1Name([out, retval] BSTR *pVal);
+ [propput, id(1), helpstring("property Face1Name")] HRESULT Face1Name([in] BSTR newVal);
+ };
+
+ [
+ object,
+ uuid(9BF24410-B2E0-11D4-A695-00104BFF3241),
+ dual,
+ helpstring("IFace2 Interface"),
+ pointer_default(unique)
+ ]
+ interface IFace2 : IDispatch
+ {
+ [propget, id(1), helpstring("property Face2Nam")] HRESULT Face2Nam([out, retval] BSTR *pVal);
+ [propput, id(1), helpstring("property Face2Nam")] HRESULT Face2Nam([in] BSTR newVal);
+ };
+
+ [
+ object,
+ uuid(9BF24411-B2E0-11D4-A695-00104BFF3241),
+ dual,
+ helpstring("IFace3 Interface"),
+ pointer_default(unique)
+ ]
+ interface IFace3 : IDispatch
+ {
+ [propget, id(1), helpstring("property Face3Name")] HRESULT Face3Name([out, retval] BSTR *pVal);
+ [propput, id(1), helpstring("property Face3Name")] HRESULT Face3Name([in] BSTR newVal);
+ };
+
+[
+ uuid(9BF24403-B2E0-11D4-A695-00104BFF3241),
+ version(1.0),
+ helpstring("MultiFace 1.0 Type Library")
+]
+library MULTIFACELib
+{
+ importlib("stdole32.tlb");
+ importlib("stdole2.tlb");
+
+
+ [
+ uuid(9BF24412-B2E0-11D4-A695-00104BFF3241),
+ helpstring("Face Class")
+ ]
+ coclass Face
+ {
+ [default] interface IFace1;
+ interface IFace2;
+ interface IFace3;
+ };
+};
diff --git a/jacob/samples/test/atl/MultiFace/MultiFace.ncb b/jacob/samples/test/atl/MultiFace/MultiFace.ncb
new file mode 100644
index 0000000..2e46496
Binary files /dev/null and b/jacob/samples/test/atl/MultiFace/MultiFace.ncb differ
diff --git a/jacob/samples/test/atl/MultiFace/MultiFace.opt b/jacob/samples/test/atl/MultiFace/MultiFace.opt
new file mode 100644
index 0000000..38ebdd2
Binary files /dev/null and b/jacob/samples/test/atl/MultiFace/MultiFace.opt differ
diff --git a/jacob/samples/test/atl/MultiFace/MultiFace.plg b/jacob/samples/test/atl/MultiFace/MultiFace.plg
new file mode 100644
index 0000000..5ade7bc
--- /dev/null
+++ b/jacob/samples/test/atl/MultiFace/MultiFace.plg
@@ -0,0 +1,48 @@
+
+
+
+Build Log
+
+--------------------Configuration: MultiFace - Win32 Debug--------------------
+
+Command Lines
+Creating temporary file "C:\TEMP\RSP335.tmp" with contents
+[
+/nologo /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /Fp"Debug/MultiFace.pch" /Yu"stdafx.h" /Fo"Debug/" /Fd"Debug/" /FD /GZ /c
+"D:\jacob_15\samples\test\atl\MultiFace\MultiFace.cpp"
+"D:\jacob_15\samples\test\atl\MultiFace\Face.cpp"
+]
+Creating command line "cl.exe @C:\TEMP\RSP335.tmp"
+Creating temporary file "C:\TEMP\RSP336.tmp" with contents
+[
+kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /incremental:yes /pdb:"Debug/MultiFace.pdb" /debug /machine:I386 /def:".\MultiFace.def" /out:"Debug/MultiFace.dll" /implib:"Debug/MultiFace.lib" /pdbtype:sept
+.\Debug\StdAfx.obj
+.\Debug\MultiFace.obj
+.\Debug\MultiFace.res
+.\Debug\Face.obj
+]
+Creating command line "link.exe @C:\TEMP\RSP336.tmp"
+Creating temporary file "C:\TEMP\RSP337.bat" with contents
+[
+@echo off
+regsvr32 /s /c ".\Debug\MultiFace.dll"
+echo regsvr32 exec. time > ".\Debug\regsvr32.trg"
+]
+Creating command line "C:\TEMP\RSP337.bat"
+Compiling...
+MultiFace.cpp
+Face.cpp
+Generating Code...
+Linking...
+Output Window
+Performing registration
+RegSvr32: DllRegisterServer in .\Debug\MultiFace.dll succeeded.
+
+
+
+
+Results
+MultiFace.dll - 0 error(s), 0 warning(s)
+
+
+
diff --git a/jacob/samples/test/atl/MultiFace/MultiFace.rc b/jacob/samples/test/atl/MultiFace/MultiFace.rc
new file mode 100644
index 0000000..db11272
--- /dev/null
+++ b/jacob/samples/test/atl/MultiFace/MultiFace.rc
@@ -0,0 +1,125 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""winres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "1 TYPELIB ""MultiFace.tlb""\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0"
+ BEGIN
+ VALUE "CompanyName", "\0"
+ VALUE "FileDescription", "MultiFace Module\0"
+ VALUE "FileVersion", "1, 0, 0, 1\0"
+ VALUE "InternalName", "MultiFace\0"
+ VALUE "LegalCopyright", "Copyright 2000\0"
+ VALUE "OriginalFilename", "MultiFace.DLL\0"
+ VALUE "ProductName", "MultiFace Module\0"
+ VALUE "ProductVersion", "1, 0, 0, 1\0"
+ VALUE "OLESelfRegister", "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// REGISTRY
+//
+
+IDR_Face REGISTRY DISCARDABLE "Face.rgs"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_PROJNAME "MultiFace"
+ IDS_FACE_DESC "Face Class"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+1 TYPELIB "MultiFace.tlb"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/jacob/samples/test/atl/MultiFace/MultiFace.tlb b/jacob/samples/test/atl/MultiFace/MultiFace.tlb
new file mode 100644
index 0000000..6186694
Binary files /dev/null and b/jacob/samples/test/atl/MultiFace/MultiFace.tlb differ
diff --git a/jacob/samples/test/atl/MultiFace/MultiFace_i.c b/jacob/samples/test/atl/MultiFace/MultiFace_i.c
new file mode 100644
index 0000000..afa8b14
--- /dev/null
+++ b/jacob/samples/test/atl/MultiFace/MultiFace_i.c
@@ -0,0 +1,56 @@
+/* this file contains the actual definitions of */
+/* the IIDs and CLSIDs */
+
+/* link this file in with the server and any clients */
+
+
+/* File created by MIDL compiler version 5.01.0164 */
+/* at Sun Nov 05 01:12:47 2000
+ */
+/* Compiler settings for D:\jacob_15\samples\test\atl\MultiFace\MultiFace.idl:
+ Oicf (OptLev=i2), W1, Zp8, env=Win32, ms_ext, c_ext
+ error checks: allocation ref bounds_check enum stub_data
+*/
+//@@MIDL_FILE_HEADING( )
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+#ifndef __IID_DEFINED__
+#define __IID_DEFINED__
+
+typedef struct _IID
+{
+ unsigned long x;
+ unsigned short s1;
+ unsigned short s2;
+ unsigned char c[8];
+} IID;
+
+#endif // __IID_DEFINED__
+
+#ifndef CLSID_DEFINED
+#define CLSID_DEFINED
+typedef IID CLSID;
+#endif // CLSID_DEFINED
+
+const IID IID_IFace1 = {0x9BF2440F,0xB2E0,0x11D4,{0xA6,0x95,0x00,0x10,0x4B,0xFF,0x32,0x41}};
+
+
+const IID IID_IFace2 = {0x9BF24410,0xB2E0,0x11D4,{0xA6,0x95,0x00,0x10,0x4B,0xFF,0x32,0x41}};
+
+
+const IID IID_IFace3 = {0x9BF24411,0xB2E0,0x11D4,{0xA6,0x95,0x00,0x10,0x4B,0xFF,0x32,0x41}};
+
+
+const IID LIBID_MULTIFACELib = {0x9BF24403,0xB2E0,0x11D4,{0xA6,0x95,0x00,0x10,0x4B,0xFF,0x32,0x41}};
+
+
+const CLSID CLSID_Face = {0x9BF24412,0xB2E0,0x11D4,{0xA6,0x95,0x00,0x10,0x4B,0xFF,0x32,0x41}};
+
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/jacob/samples/test/atl/MultiFace/MultiFace_p.c b/jacob/samples/test/atl/MultiFace/MultiFace_p.c
new file mode 100644
index 0000000..e83ec80
--- /dev/null
+++ b/jacob/samples/test/atl/MultiFace/MultiFace_p.c
@@ -0,0 +1,570 @@
+/* this ALWAYS GENERATED file contains the proxy stub code */
+
+
+/* File created by MIDL compiler version 5.01.0164 */
+/* at Sun Nov 05 01:12:47 2000
+ */
+/* Compiler settings for D:\jacob_15\samples\test\atl\MultiFace\MultiFace.idl:
+ Oicf (OptLev=i2), W1, Zp8, env=Win32, ms_ext, c_ext
+ error checks: allocation ref bounds_check enum stub_data
+*/
+//@@MIDL_FILE_HEADING( )
+
+#define USE_STUBLESS_PROXY
+
+
+/* verify that the version is high enough to compile this file*/
+#ifndef __REDQ_RPCPROXY_H_VERSION__
+#define __REQUIRED_RPCPROXY_H_VERSION__ 440
+#endif
+
+
+#include "rpcproxy.h"
+#ifndef __RPCPROXY_H_VERSION__
+#error this stub requires an updated version of
+#endif // __RPCPROXY_H_VERSION__
+
+
+#include "MultiFace.h"
+
+#define TYPE_FORMAT_STRING_SIZE 55
+#define PROC_FORMAT_STRING_SIZE 57
+
+typedef struct _MIDL_TYPE_FORMAT_STRING
+ {
+ short Pad;
+ unsigned char Format[ TYPE_FORMAT_STRING_SIZE ];
+ } MIDL_TYPE_FORMAT_STRING;
+
+typedef struct _MIDL_PROC_FORMAT_STRING
+ {
+ short Pad;
+ unsigned char Format[ PROC_FORMAT_STRING_SIZE ];
+ } MIDL_PROC_FORMAT_STRING;
+
+
+extern const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;
+extern const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;
+
+
+/* Object interface: IUnknown, ver. 0.0,
+ GUID={0x00000000,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}} */
+
+
+/* Object interface: IDispatch, ver. 0.0,
+ GUID={0x00020400,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}} */
+
+
+/* Object interface: IFace1, ver. 0.0,
+ GUID={0x9BF2440F,0xB2E0,0x11D4,{0xA6,0x95,0x00,0x10,0x4B,0xFF,0x32,0x41}} */
+
+
+extern const MIDL_STUB_DESC Object_StubDesc;
+
+
+extern const MIDL_SERVER_INFO IFace1_ServerInfo;
+
+#pragma code_seg(".orpc")
+static const unsigned short IFace1_FormatStringOffsetTable[] =
+ {
+ (unsigned short) -1,
+ (unsigned short) -1,
+ (unsigned short) -1,
+ (unsigned short) -1,
+ 0,
+ 28
+ };
+
+static const MIDL_SERVER_INFO IFace1_ServerInfo =
+ {
+ &Object_StubDesc,
+ 0,
+ __MIDL_ProcFormatString.Format,
+ &IFace1_FormatStringOffsetTable[-3],
+ 0,
+ 0,
+ 0,
+ 0
+ };
+
+static const MIDL_STUBLESS_PROXY_INFO IFace1_ProxyInfo =
+ {
+ &Object_StubDesc,
+ __MIDL_ProcFormatString.Format,
+ &IFace1_FormatStringOffsetTable[-3],
+ 0,
+ 0,
+ 0
+ };
+
+CINTERFACE_PROXY_VTABLE(9) _IFace1ProxyVtbl =
+{
+ &IFace1_ProxyInfo,
+ &IID_IFace1,
+ IUnknown_QueryInterface_Proxy,
+ IUnknown_AddRef_Proxy,
+ IUnknown_Release_Proxy ,
+ 0 /* (void *)-1 /* IDispatch::GetTypeInfoCount */ ,
+ 0 /* (void *)-1 /* IDispatch::GetTypeInfo */ ,
+ 0 /* (void *)-1 /* IDispatch::GetIDsOfNames */ ,
+ 0 /* IDispatch_Invoke_Proxy */ ,
+ (void *)-1 /* IFace1::get_Face1Name */ ,
+ (void *)-1 /* IFace1::put_Face1Name */
+};
+
+
+static const PRPC_STUB_FUNCTION IFace1_table[] =
+{
+ STUB_FORWARDING_FUNCTION,
+ STUB_FORWARDING_FUNCTION,
+ STUB_FORWARDING_FUNCTION,
+ STUB_FORWARDING_FUNCTION,
+ NdrStubCall2,
+ NdrStubCall2
+};
+
+CInterfaceStubVtbl _IFace1StubVtbl =
+{
+ &IID_IFace1,
+ &IFace1_ServerInfo,
+ 9,
+ &IFace1_table[-3],
+ CStdStubBuffer_DELEGATING_METHODS
+};
+
+
+/* Object interface: IFace2, ver. 0.0,
+ GUID={0x9BF24410,0xB2E0,0x11D4,{0xA6,0x95,0x00,0x10,0x4B,0xFF,0x32,0x41}} */
+
+
+extern const MIDL_STUB_DESC Object_StubDesc;
+
+
+extern const MIDL_SERVER_INFO IFace2_ServerInfo;
+
+#pragma code_seg(".orpc")
+static const unsigned short IFace2_FormatStringOffsetTable[] =
+ {
+ (unsigned short) -1,
+ (unsigned short) -1,
+ (unsigned short) -1,
+ (unsigned short) -1,
+ 0,
+ 28
+ };
+
+static const MIDL_SERVER_INFO IFace2_ServerInfo =
+ {
+ &Object_StubDesc,
+ 0,
+ __MIDL_ProcFormatString.Format,
+ &IFace2_FormatStringOffsetTable[-3],
+ 0,
+ 0,
+ 0,
+ 0
+ };
+
+static const MIDL_STUBLESS_PROXY_INFO IFace2_ProxyInfo =
+ {
+ &Object_StubDesc,
+ __MIDL_ProcFormatString.Format,
+ &IFace2_FormatStringOffsetTable[-3],
+ 0,
+ 0,
+ 0
+ };
+
+CINTERFACE_PROXY_VTABLE(9) _IFace2ProxyVtbl =
+{
+ &IFace2_ProxyInfo,
+ &IID_IFace2,
+ IUnknown_QueryInterface_Proxy,
+ IUnknown_AddRef_Proxy,
+ IUnknown_Release_Proxy ,
+ 0 /* (void *)-1 /* IDispatch::GetTypeInfoCount */ ,
+ 0 /* (void *)-1 /* IDispatch::GetTypeInfo */ ,
+ 0 /* (void *)-1 /* IDispatch::GetIDsOfNames */ ,
+ 0 /* IDispatch_Invoke_Proxy */ ,
+ (void *)-1 /* IFace2::get_Face2Nam */ ,
+ (void *)-1 /* IFace2::put_Face2Nam */
+};
+
+
+static const PRPC_STUB_FUNCTION IFace2_table[] =
+{
+ STUB_FORWARDING_FUNCTION,
+ STUB_FORWARDING_FUNCTION,
+ STUB_FORWARDING_FUNCTION,
+ STUB_FORWARDING_FUNCTION,
+ NdrStubCall2,
+ NdrStubCall2
+};
+
+CInterfaceStubVtbl _IFace2StubVtbl =
+{
+ &IID_IFace2,
+ &IFace2_ServerInfo,
+ 9,
+ &IFace2_table[-3],
+ CStdStubBuffer_DELEGATING_METHODS
+};
+
+
+/* Object interface: IFace3, ver. 0.0,
+ GUID={0x9BF24411,0xB2E0,0x11D4,{0xA6,0x95,0x00,0x10,0x4B,0xFF,0x32,0x41}} */
+
+
+extern const MIDL_STUB_DESC Object_StubDesc;
+
+
+extern const MIDL_SERVER_INFO IFace3_ServerInfo;
+
+#pragma code_seg(".orpc")
+extern const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[1];
+
+static const MIDL_STUB_DESC Object_StubDesc =
+ {
+ 0,
+ NdrOleAllocate,
+ NdrOleFree,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ __MIDL_TypeFormatString.Format,
+ 1, /* -error bounds_check flag */
+ 0x20000, /* Ndr library version */
+ 0,
+ 0x50100a4, /* MIDL Version 5.1.164 */
+ 0,
+ UserMarshalRoutines,
+ 0, /* notify & notify_flag routine table */
+ 1, /* Flags */
+ 0, /* Reserved3 */
+ 0, /* Reserved4 */
+ 0 /* Reserved5 */
+ };
+
+static const unsigned short IFace3_FormatStringOffsetTable[] =
+ {
+ (unsigned short) -1,
+ (unsigned short) -1,
+ (unsigned short) -1,
+ (unsigned short) -1,
+ 0,
+ 28
+ };
+
+static const MIDL_SERVER_INFO IFace3_ServerInfo =
+ {
+ &Object_StubDesc,
+ 0,
+ __MIDL_ProcFormatString.Format,
+ &IFace3_FormatStringOffsetTable[-3],
+ 0,
+ 0,
+ 0,
+ 0
+ };
+
+static const MIDL_STUBLESS_PROXY_INFO IFace3_ProxyInfo =
+ {
+ &Object_StubDesc,
+ __MIDL_ProcFormatString.Format,
+ &IFace3_FormatStringOffsetTable[-3],
+ 0,
+ 0,
+ 0
+ };
+
+CINTERFACE_PROXY_VTABLE(9) _IFace3ProxyVtbl =
+{
+ &IFace3_ProxyInfo,
+ &IID_IFace3,
+ IUnknown_QueryInterface_Proxy,
+ IUnknown_AddRef_Proxy,
+ IUnknown_Release_Proxy ,
+ 0 /* (void *)-1 /* IDispatch::GetTypeInfoCount */ ,
+ 0 /* (void *)-1 /* IDispatch::GetTypeInfo */ ,
+ 0 /* (void *)-1 /* IDispatch::GetIDsOfNames */ ,
+ 0 /* IDispatch_Invoke_Proxy */ ,
+ (void *)-1 /* IFace3::get_Face3Name */ ,
+ (void *)-1 /* IFace3::put_Face3Name */
+};
+
+
+static const PRPC_STUB_FUNCTION IFace3_table[] =
+{
+ STUB_FORWARDING_FUNCTION,
+ STUB_FORWARDING_FUNCTION,
+ STUB_FORWARDING_FUNCTION,
+ STUB_FORWARDING_FUNCTION,
+ NdrStubCall2,
+ NdrStubCall2
+};
+
+CInterfaceStubVtbl _IFace3StubVtbl =
+{
+ &IID_IFace3,
+ &IFace3_ServerInfo,
+ 9,
+ &IFace3_table[-3],
+ CStdStubBuffer_DELEGATING_METHODS
+};
+
+#pragma data_seg(".rdata")
+
+static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[1] =
+ {
+
+ {
+ BSTR_UserSize
+ ,BSTR_UserMarshal
+ ,BSTR_UserUnmarshal
+ ,BSTR_UserFree
+ }
+
+ };
+
+
+#if !defined(__RPC_WIN32__)
+#error Invalid build platform for this stub.
+#endif
+
+#if !(TARGET_IS_NT40_OR_LATER)
+#error You need a Windows NT 4.0 or later to run this stub because it uses these features:
+#error -Oif or -Oicf, [wire_marshal] or [user_marshal] attribute, more than 32 methods in the interface.
+#error However, your C/C++ compilation flags indicate you intend to run this app on earlier systems.
+#error This app will die there with the RPC_X_WRONG_STUB_VERSION error.
+#endif
+
+
+static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =
+ {
+ 0,
+ {
+
+ /* Procedure get_Face3Name */
+
+
+ /* Procedure get_Face2Nam */
+
+
+ /* Procedure get_Face1Name */
+
+ 0x33, /* FC_AUTO_HANDLE */
+ 0x6c, /* Old Flags: object, Oi2 */
+/* 2 */ NdrFcLong( 0x0 ), /* 0 */
+/* 6 */ NdrFcShort( 0x7 ), /* 7 */
+#ifndef _ALPHA_
+/* 8 */ NdrFcShort( 0xc ), /* x86, MIPS, PPC Stack size/offset = 12 */
+#else
+ NdrFcShort( 0x18 ), /* Alpha Stack size/offset = 24 */
+#endif
+/* 10 */ NdrFcShort( 0x0 ), /* 0 */
+/* 12 */ NdrFcShort( 0x8 ), /* 8 */
+/* 14 */ 0x5, /* Oi2 Flags: srv must size, has return, */
+ 0x2, /* 2 */
+
+ /* Parameter pVal */
+
+
+ /* Parameter pVal */
+
+
+ /* Parameter pVal */
+
+/* 16 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */
+#ifndef _ALPHA_
+/* 18 */ NdrFcShort( 0x4 ), /* x86, MIPS, PPC Stack size/offset = 4 */
+#else
+ NdrFcShort( 0x8 ), /* Alpha Stack size/offset = 8 */
+#endif
+/* 20 */ NdrFcShort( 0x1e ), /* Type Offset=30 */
+
+ /* Return value */
+
+
+ /* Return value */
+
+
+ /* Return value */
+
+/* 22 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+#ifndef _ALPHA_
+/* 24 */ NdrFcShort( 0x8 ), /* x86, MIPS, PPC Stack size/offset = 8 */
+#else
+ NdrFcShort( 0x10 ), /* Alpha Stack size/offset = 16 */
+#endif
+/* 26 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Procedure put_Face3Name */
+
+
+ /* Procedure put_Face2Nam */
+
+
+ /* Procedure put_Face1Name */
+
+/* 28 */ 0x33, /* FC_AUTO_HANDLE */
+ 0x6c, /* Old Flags: object, Oi2 */
+/* 30 */ NdrFcLong( 0x0 ), /* 0 */
+/* 34 */ NdrFcShort( 0x8 ), /* 8 */
+#ifndef _ALPHA_
+/* 36 */ NdrFcShort( 0xc ), /* x86, MIPS, PPC Stack size/offset = 12 */
+#else
+ NdrFcShort( 0x18 ), /* Alpha Stack size/offset = 24 */
+#endif
+/* 38 */ NdrFcShort( 0x0 ), /* 0 */
+/* 40 */ NdrFcShort( 0x8 ), /* 8 */
+/* 42 */ 0x6, /* Oi2 Flags: clt must size, has return, */
+ 0x2, /* 2 */
+
+ /* Parameter newVal */
+
+
+ /* Parameter newVal */
+
+
+ /* Parameter newVal */
+
+/* 44 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */
+#ifndef _ALPHA_
+/* 46 */ NdrFcShort( 0x4 ), /* x86, MIPS, PPC Stack size/offset = 4 */
+#else
+ NdrFcShort( 0x8 ), /* Alpha Stack size/offset = 8 */
+#endif
+/* 48 */ NdrFcShort( 0x2c ), /* Type Offset=44 */
+
+ /* Return value */
+
+
+ /* Return value */
+
+
+ /* Return value */
+
+/* 50 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+#ifndef _ALPHA_
+/* 52 */ NdrFcShort( 0x8 ), /* x86, MIPS, PPC Stack size/offset = 8 */
+#else
+ NdrFcShort( 0x10 ), /* Alpha Stack size/offset = 16 */
+#endif
+/* 54 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ 0x0
+ }
+ };
+
+static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =
+ {
+ 0,
+ {
+ NdrFcShort( 0x0 ), /* 0 */
+/* 2 */
+ 0x11, 0x4, /* FC_RP [alloced_on_stack] */
+/* 4 */ NdrFcShort( 0x1a ), /* Offset= 26 (30) */
+/* 6 */
+ 0x13, 0x0, /* FC_OP */
+/* 8 */ NdrFcShort( 0xc ), /* Offset= 12 (20) */
+/* 10 */
+ 0x1b, /* FC_CARRAY */
+ 0x1, /* 1 */
+/* 12 */ NdrFcShort( 0x2 ), /* 2 */
+/* 14 */ 0x9, /* Corr desc: FC_ULONG */
+ 0x0, /* */
+/* 16 */ NdrFcShort( 0xfffc ), /* -4 */
+/* 18 */ 0x6, /* FC_SHORT */
+ 0x5b, /* FC_END */
+/* 20 */
+ 0x17, /* FC_CSTRUCT */
+ 0x3, /* 3 */
+/* 22 */ NdrFcShort( 0x8 ), /* 8 */
+/* 24 */ NdrFcShort( 0xfffffff2 ), /* Offset= -14 (10) */
+/* 26 */ 0x8, /* FC_LONG */
+ 0x8, /* FC_LONG */
+/* 28 */ 0x5c, /* FC_PAD */
+ 0x5b, /* FC_END */
+/* 30 */ 0xb4, /* FC_USER_MARSHAL */
+ 0x83, /* 131 */
+/* 32 */ NdrFcShort( 0x0 ), /* 0 */
+/* 34 */ NdrFcShort( 0x4 ), /* 4 */
+/* 36 */ NdrFcShort( 0x0 ), /* 0 */
+/* 38 */ NdrFcShort( 0xffffffe0 ), /* Offset= -32 (6) */
+/* 40 */
+ 0x12, 0x0, /* FC_UP */
+/* 42 */ NdrFcShort( 0xffffffea ), /* Offset= -22 (20) */
+/* 44 */ 0xb4, /* FC_USER_MARSHAL */
+ 0x83, /* 131 */
+/* 46 */ NdrFcShort( 0x0 ), /* 0 */
+/* 48 */ NdrFcShort( 0x4 ), /* 4 */
+/* 50 */ NdrFcShort( 0x0 ), /* 0 */
+/* 52 */ NdrFcShort( 0xfffffff4 ), /* Offset= -12 (40) */
+
+ 0x0
+ }
+ };
+
+const CInterfaceProxyVtbl * _MultiFace_ProxyVtblList[] =
+{
+ ( CInterfaceProxyVtbl *) &_IFace1ProxyVtbl,
+ ( CInterfaceProxyVtbl *) &_IFace2ProxyVtbl,
+ ( CInterfaceProxyVtbl *) &_IFace3ProxyVtbl,
+ 0
+};
+
+const CInterfaceStubVtbl * _MultiFace_StubVtblList[] =
+{
+ ( CInterfaceStubVtbl *) &_IFace1StubVtbl,
+ ( CInterfaceStubVtbl *) &_IFace2StubVtbl,
+ ( CInterfaceStubVtbl *) &_IFace3StubVtbl,
+ 0
+};
+
+PCInterfaceName const _MultiFace_InterfaceNamesList[] =
+{
+ "IFace1",
+ "IFace2",
+ "IFace3",
+ 0
+};
+
+const IID * _MultiFace_BaseIIDList[] =
+{
+ &IID_IDispatch,
+ &IID_IDispatch,
+ &IID_IDispatch,
+ 0
+};
+
+
+#define _MultiFace_CHECK_IID(n) IID_GENERIC_CHECK_IID( _MultiFace, pIID, n)
+
+int __stdcall _MultiFace_IID_Lookup( const IID * pIID, int * pIndex )
+{
+ IID_BS_LOOKUP_SETUP
+
+ IID_BS_LOOKUP_INITIAL_TEST( _MultiFace, 3, 2 )
+ IID_BS_LOOKUP_NEXT_TEST( _MultiFace, 1 )
+ IID_BS_LOOKUP_RETURN_RESULT( _MultiFace, 3, *pIndex )
+
+}
+
+const ExtendedProxyFileInfo MultiFace_ProxyFileInfo =
+{
+ (PCInterfaceProxyVtblList *) & _MultiFace_ProxyVtblList,
+ (PCInterfaceStubVtblList *) & _MultiFace_StubVtblList,
+ (const PCInterfaceName * ) & _MultiFace_InterfaceNamesList,
+ (const IID ** ) & _MultiFace_BaseIIDList,
+ & _MultiFace_IID_Lookup,
+ 3,
+ 2,
+ 0, /* table of [async_uuid] interfaces */
+ 0, /* Filler1 */
+ 0, /* Filler2 */
+ 0 /* Filler3 */
+};
diff --git a/jacob/samples/test/atl/MultiFace/MultiFaceps.def b/jacob/samples/test/atl/MultiFace/MultiFaceps.def
new file mode 100644
index 0000000..6c1fe81
--- /dev/null
+++ b/jacob/samples/test/atl/MultiFace/MultiFaceps.def
@@ -0,0 +1,11 @@
+
+LIBRARY "MultiFacePS"
+
+DESCRIPTION 'Proxy/Stub DLL'
+
+EXPORTS
+ DllGetClassObject @1 PRIVATE
+ DllCanUnloadNow @2 PRIVATE
+ GetProxyDllInfo @3 PRIVATE
+ DllRegisterServer @4 PRIVATE
+ DllUnregisterServer @5 PRIVATE
diff --git a/jacob/samples/test/atl/MultiFace/MultiFaceps.mk b/jacob/samples/test/atl/MultiFace/MultiFaceps.mk
new file mode 100644
index 0000000..25de3e7
--- /dev/null
+++ b/jacob/samples/test/atl/MultiFace/MultiFaceps.mk
@@ -0,0 +1,16 @@
+
+MultiFaceps.dll: dlldata.obj MultiFace_p.obj MultiFace_i.obj
+ link /dll /out:MultiFaceps.dll /def:MultiFaceps.def /entry:DllMain dlldata.obj MultiFace_p.obj MultiFace_i.obj \
+ kernel32.lib rpcndr.lib rpcns4.lib rpcrt4.lib oleaut32.lib uuid.lib \
+
+.c.obj:
+ cl /c /Ox /DWIN32 /D_WIN32_WINNT=0x0400 /DREGISTER_PROXY_DLL \
+ $<
+
+clean:
+ @del MultiFaceps.dll
+ @del MultiFaceps.lib
+ @del MultiFaceps.exp
+ @del dlldata.obj
+ @del MultiFace_p.obj
+ @del MultiFace_i.obj
diff --git a/jacob/samples/test/atl/MultiFace/StdAfx.cpp b/jacob/samples/test/atl/MultiFace/StdAfx.cpp
new file mode 100644
index 0000000..b39052a
--- /dev/null
+++ b/jacob/samples/test/atl/MultiFace/StdAfx.cpp
@@ -0,0 +1,12 @@
+// stdafx.cpp : source file that includes just the standard includes
+// stdafx.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+#ifdef _ATL_STATIC_REGISTRY
+#include
+#include
+#endif
+
+#include
diff --git a/jacob/samples/test/atl/MultiFace/StdAfx.h b/jacob/samples/test/atl/MultiFace/StdAfx.h
new file mode 100644
index 0000000..e8b7a84
--- /dev/null
+++ b/jacob/samples/test/atl/MultiFace/StdAfx.h
@@ -0,0 +1,27 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently,
+// but are changed infrequently
+
+#if !defined(AFX_STDAFX_H__9BF24406_B2E0_11D4_A695_00104BFF3241__INCLUDED_)
+#define AFX_STDAFX_H__9BF24406_B2E0_11D4_A695_00104BFF3241__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#define STRICT
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0400
+#endif
+#define _ATL_APARTMENT_THREADED
+
+#include
+//You may derive a class from CComModule and use it if you want to override
+//something, but do not change the name of _Module
+extern CComModule _Module;
+#include
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__9BF24406_B2E0_11D4_A695_00104BFF3241__INCLUDED)
diff --git a/jacob/samples/test/atl/MultiFace/dlldata.c b/jacob/samples/test/atl/MultiFace/dlldata.c
new file mode 100644
index 0000000..b8ef600
--- /dev/null
+++ b/jacob/samples/test/atl/MultiFace/dlldata.c
@@ -0,0 +1,38 @@
+/*********************************************************
+ DllData file -- generated by MIDL compiler
+
+ DO NOT ALTER THIS FILE
+
+ This file is regenerated by MIDL on every IDL file compile.
+
+ To completely reconstruct this file, delete it and rerun MIDL
+ on all the IDL files in this DLL, specifying this file for the
+ /dlldata command line option
+
+*********************************************************/
+
+#define PROXY_DELEGATION
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EXTERN_PROXY_FILE( MultiFace )
+
+
+PROXYFILE_LIST_START
+/* Start of list */
+ REFERENCE_PROXY_FILE( MultiFace ),
+/* End of list */
+PROXYFILE_LIST_END
+
+
+DLLDATA_ROUTINES( aProxyFileList, GET_DLL_CLSID )
+
+#ifdef __cplusplus
+} /*extern "C" */
+#endif
+
+/* end of generated dlldata file */
diff --git a/jacob/samples/test/atl/MultiFace/resource.h b/jacob/samples/test/atl/MultiFace/resource.h
new file mode 100644
index 0000000..1170388
--- /dev/null
+++ b/jacob/samples/test/atl/MultiFace/resource.h
@@ -0,0 +1,18 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by MultiFace.rc
+//
+#define IDS_PROJNAME 100
+#define IDS_FACE_DESC 101
+#define IDR_Face 102
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 201
+#define _APS_NEXT_COMMAND_VALUE 32768
+#define _APS_NEXT_CONTROL_VALUE 201
+#define _APS_NEXT_SYMED_VALUE 103
+#endif
+#endif
diff --git a/jacob/samples/test/atl/readme.txt b/jacob/samples/test/atl/readme.txt
new file mode 100644
index 0000000..1f6f5c7
--- /dev/null
+++ b/jacob/samples/test/atl/readme.txt
@@ -0,0 +1,14 @@
+This example demonstrates how to access multiple interfaces.
+
+To run it, chdir to MultiFace\Debug and run:
+regsvr32 MultiFace.dll
+
+Then, run (in this dir):
+java MultiFace
+
+As you can see from MultiFace\MultiFace.idl - there are 3 interfaces.
+
+By default JACOB attaches to the default interface.
+
+The file MultiFace.java shows how to use the new Dispatch.QueryInterface
+to get access to the other interfaces.
diff --git a/jacob/samples/test/foo.foo b/jacob/samples/test/foo.foo
new file mode 100644
index 0000000..a93e66f
Binary files /dev/null and b/jacob/samples/test/foo.foo differ
diff --git a/jacob/samples/test/foo.ser b/jacob/samples/test/foo.ser
new file mode 100644
index 0000000..2fe4986
Binary files /dev/null and b/jacob/samples/test/foo.ser differ
diff --git a/jacob/samples/test/jacobtest.xls b/jacob/samples/test/jacobtest.xls
new file mode 100644
index 0000000..26719c5
Binary files /dev/null and b/jacob/samples/test/jacobtest.xls differ
diff --git a/jacob/samples/test/math.java b/jacob/samples/test/math.java
new file mode 100644
index 0000000..991f875
--- /dev/null
+++ b/jacob/samples/test/math.java
@@ -0,0 +1,38 @@
+package samples.test;
+
+import com.jacob.com.*;
+
+/*
+ * This example uses the MathTest sample VB COM DLL under
+ * the MathProj directory
+ */
+class math
+{
+ public static void main(String[] args)
+ {
+ System.runFinalizersOnExit(true);
+ Dispatch test = new Dispatch("MathTest.Math");
+ testEvents te = new testEvents();
+ DispatchEvents de = new DispatchEvents(test, te);
+ System.out.println(Dispatch.call(test, "Add", new Variant(1), new Variant(2)));
+ System.out.println(Dispatch.call(test, "Mult", new Variant(2), new Variant(2)));
+ Variant v = Dispatch.call(test, "Mult", new Variant(2), new Variant(2));
+ // this should return false
+ System.out.println("v.isNull="+v.isNull());
+ v = Dispatch.call(test, "getNothing");
+ // these should return nothing
+ System.out.println("v.isNull="+v.isNull());
+ System.out.println("v.toDispatch="+v.toDispatch());
+ }
+}
+
+class testEvents {
+ public void DoneAdd(Variant[] args)
+ {
+ System.out.println("DoneAdd called in java");
+ }
+ public void DoneMult(Variant[] args)
+ {
+ System.out.println("DoneMult called in java");
+ }
+}
diff --git a/jacob/samples/test/sa_dispatch.java b/jacob/samples/test/sa_dispatch.java
new file mode 100644
index 0000000..4d89422
--- /dev/null
+++ b/jacob/samples/test/sa_dispatch.java
@@ -0,0 +1,41 @@
+package samples.test;
+
+import com.jacob.com.*;
+import com.jacob.activeX.*;
+
+class sa_dispatch
+{
+ public static void main(String args[])
+ {
+ System.runFinalizersOnExit(true);
+
+ try {
+ String lang = "VBScript";
+ ActiveXComponent sC = new ActiveXComponent("ScriptControl");
+ Dispatch sControl = (Dispatch)sC.getObject();
+ Dispatch.put(sControl, "Language", lang);
+
+ Variant result = Dispatch.call(sControl, "Eval", args[0]);
+ System.out.println("eval("+args[0]+") = "+ result);
+
+ // wrap the script control in a variant
+ Variant v = new Variant(sControl);
+
+ // create a safe array of type dispatch
+ SafeArray sa = new SafeArray(Variant.VariantDispatch, 1);
+
+ // put the variant in the array
+ sa.setVariant(0, v);
+
+ // take it back out
+ Variant v2 = sa.getVariant(0);
+ Dispatch d = v2.toDispatch();
+
+ // make sure you can call eval on it
+ result = Dispatch.call(d, "Eval", args[0]);
+ System.out.println("eval("+args[0]+") = "+ result);
+ } catch (ComException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/jacob/samples/test/sa_test.java b/jacob/samples/test/sa_test.java
new file mode 100644
index 0000000..24a8d91
--- /dev/null
+++ b/jacob/samples/test/sa_test.java
@@ -0,0 +1,58 @@
+package samples.test;
+
+import com.jacob.com.*;
+
+class sa_test
+{
+ public static void main(String[] args)
+ {
+ System.runFinalizersOnExit(true);
+ SafeArray sa = new SafeArray(Variant.VariantVariant, 3);
+
+ sa.fromShortArray(new short[] {1,2,3});
+ System.out.println("sa short="+sa);
+ int[] ai = sa.toIntArray();
+ for(int i=0;i
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=jacob - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "jacob.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "jacob.mak" CFG="jacob - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "jacob - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "jacob - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "jacob - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JACOB_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JACOB_EXPORTS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+
+!ELSEIF "$(CFG)" == "jacob - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JACOB_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JACOB_EXPORTS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "jacob - Win32 Release"
+# Name "jacob - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\ComThread.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Dispatch.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\DispatchEvents.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\DispatchProxy.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\EnumVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\EventProxy.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\SafeArray.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\STA.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\util.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Variant.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\ComThread.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Dispatch.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\DispatchEvents.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\DispatchProxy.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\EnumVariant.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\EventProxy.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\SafeArray.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\STA.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\util.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Variant.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/jacob/vstudio/jacob/jacob.dsw b/jacob/vstudio/jacob/jacob.dsw
new file mode 100644
index 0000000..66a1a20
--- /dev/null
+++ b/jacob/vstudio/jacob/jacob.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "jacob"=.\jacob.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/jacob/vstudio/jacob/jacob.ncb b/jacob/vstudio/jacob/jacob.ncb
new file mode 100644
index 0000000..3cd420c
Binary files /dev/null and b/jacob/vstudio/jacob/jacob.ncb differ
diff --git a/jacob/vstudio/jacob/jacob.opt b/jacob/vstudio/jacob/jacob.opt
new file mode 100644
index 0000000..3b96bde
Binary files /dev/null and b/jacob/vstudio/jacob/jacob.opt differ
diff --git a/jacob/vstudio/jacob/jacob.plg b/jacob/vstudio/jacob/jacob.plg
new file mode 100644
index 0000000..acd3115
--- /dev/null
+++ b/jacob/vstudio/jacob/jacob.plg
@@ -0,0 +1,66 @@
+
+
+
+Build Log
+
+--------------------Configuration: jacob - Win32 Debug--------------------
+
+Command Lines
+Creating temporary file "C:\TEMP\RSPED5.tmp" with contents
+[
+/nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JACOB_EXPORTS" /Fp"Debug/jacob.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c
+"D:\jacob_17\vstudio\jacob\ComThread.cpp"
+"D:\jacob_17\vstudio\jacob\Dispatch.cpp"
+"D:\jacob_17\vstudio\jacob\DispatchEvents.cpp"
+"D:\jacob_17\vstudio\jacob\EnumVariant.cpp"
+"D:\jacob_17\vstudio\jacob\EventProxy.cpp"
+"D:\jacob_17\vstudio\jacob\SafeArray.cpp"
+"D:\jacob_17\vstudio\jacob\STA.cpp"
+"D:\jacob_17\vstudio\jacob\StdAfx.cpp"
+"D:\jacob_17\vstudio\jacob\util.cpp"
+"D:\jacob_17\vstudio\jacob\Variant.cpp"
+"D:\jacob_17\vstudio\jacob\DispatchProxy.cpp"
+]
+Creating command line "cl.exe @C:\TEMP\RSPED5.tmp"
+Creating temporary file "C:\TEMP\RSPED6.tmp" with contents
+[
+kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:yes /pdb:"Debug/jacob.pdb" /debug /machine:I386 /out:"Debug/jacob.dll" /implib:"Debug/jacob.lib" /pdbtype:sept
+.\Debug\ComThread.obj
+.\Debug\Dispatch.obj
+.\Debug\DispatchEvents.obj
+.\Debug\EnumVariant.obj
+.\Debug\EventProxy.obj
+.\Debug\SafeArray.obj
+.\Debug\STA.obj
+.\Debug\StdAfx.obj
+.\Debug\util.obj
+.\Debug\Variant.obj
+.\Debug\DispatchProxy.obj
+]
+Creating command line "link.exe @C:\TEMP\RSPED6.tmp"
+Output Window
+Compiling...
+ComThread.cpp
+Dispatch.cpp
+d:\jacob_17\vstudio\jacob\dispatch.cpp(383) : warning C4244: 'argument' : conversion from 'long' to 'unsigned short', possible loss of data
+DispatchEvents.cpp
+d:\jacob_17\vstudio\jacob\dispatchevents.cpp(114) : warning C4101: 'dwEventCookie' : unreferenced local variable
+EnumVariant.cpp
+EventProxy.cpp
+d:\jacob_17\vstudio\jacob\eventproxy.cpp(119) : warning C4101: 'hr' : unreferenced local variable
+SafeArray.cpp
+STA.cpp
+StdAfx.cpp
+util.cpp
+Variant.cpp
+DispatchProxy.cpp
+Linking...
+ Creating library Debug/jacob.lib and object Debug/jacob.exp
+
+
+
+Results
+jacob.dll - 0 error(s), 3 warning(s)
+
+
+