JDirect
 In this topic

*OLE Mode Syntax

*How Win32 Functions Compare with OLE Functions

*Comparing Win32 Code to OLE Code

*Invoking OLE Functions

*How OLE Mode Works

*Passing and Receiving Strings from OLE Functions

*Passing GUIDs (and IIDs and CLSIDs)

*Passing VARIANTs

*Passing COM Interface Pointers

 

JDirect    PreviousJDirectNext
About J/Direct     Previous JDirect Next

 


Invoking OLE API Functions

OLE Mode Syntax

The @dll.import directive includes a special mode tailored for importing OLE API functions. To use this mode, simply include the ole modifier as in the following example.


  /** @dll.import("OLE32", ole) */
  public class OLE32 {
    ...
  } 

How Win32 Functions Compare with OLE Functions

In theory, the functions exported out of OLE32.DLL and OLEAUT32.DLL are no different from any other DLL function. In practice, the OLE functions follow a consistent calling style of their own. OLE functions differ from Win32 functions in the following ways:

  • OLE functions only come in Unicode. There are no ANSI OLE functions.
  • Virtually all OLE functions return a 32-bit status code known as an HRESULT through the normal function return value. The high-bit indicates whether the function succeeded (hi-bit off) or failed (hi-bit on). A few functions return multiple success values (typically S_OK and S_FALSE) but most return only one success value (S_OK).
  • If an OLE function returns some value other than the status code, it does so by having the caller supply a pointer to a variable that will receive the value on exit. This return value pointer is, by convention, the last parameter.
  • The Win32 style of returning strings is to fill in a caller-allocated buffer. OLE functions typically return strings by allocating them using CoTaskMemAlloc and expecting the caller to free them using CoTaskMemFree.

Comparing Win32 Code to OLE Code

The code for a simple Add function would look like this in the Win32 style of coding.


  int sum;
  sum = Add(10, 20);

In OLE style, the Add function would be written the following way.


  HRESULT hr;
  int sum;
  hr = Add(10, 20, &sum);
  if (FAILED(hr)) {
    ...handle error..
  } 

Invoking OLE Functions

The ole mode takes advantage of this consistent coding style to provide a Java-friendly way to call OLE functions. Invoking an OLE-style Add function from Java looks much like invoking a more traditional Win32-style function.


  /** dll.import("OLELIKEMATHDLL", ole) */
  private native static int Add(int x, int y);
  int sum = Add(10, 20);
  // if we got here, Add succeeded.

How OLE Mode Works

Because of the ole modifier, the Microsoft Win32 VM for Java automatically assumes that the native Add function returns an HRESULT. The Microsoft VM notices that the Add function returns an integer. When invoking Add, the VM automatically allocates a temporary variable of type int and inserts a pointer to it as a third parameter. After the native Add function returns, the VM automatically checks the HRESULT and if it indicates a failure (high-bit on), a Java exception of type com.ms.com.ComFailException is thrown. If the HRESULT does not indicate a failure, the VM retrieves the Add function's true return value from the temporary variable it created, and it returns that value.

Unlike Java/COM integration, a return value of S_FALSE does not cause a ComSuccessException to be thrown. If you need to distinguish between success results, you need to use normal DLL calling mode and treat the HRESULT as an integer return value.

To summarize, ole mode alters the semantics of DLL calling as follows:

  1. All strings and characters are assumed to be Unicode.
  2. The function return value of the native function is presumed to be an HRESULT. The Microsoft VM throws a ComFailException if the returned HRESULT indicates failure.
  3. If the Java method return type is not void, the Microsoft VM will assume that the native function returns an additional result through a pointer, which is the final argument to the function. The VM will supply this pointer argument and dereference it after the call to obtain the additional return value. This value will be returned as the value of the Java method.

Passing and Receiving Strings from OLE Functions

Declaring a parameter as type String on an ole mode function passes a LPCOLESTR. The Microsoft VM also includes a preceding length prefix so the string can also be treated as a BSTR.

Declaring a return value as type String in ole mode causes the Microsoft VM to pass a pointer to an uninitialized LPCOLESTR*. When the native function returns, the Microsoft VM will convert the returned LPCOLESTR to a Java String, and then call CoTaskMemFree to free the string.

Passing GUIDs (and IIDs and CLSIDs)

The system class com.ms.com._Guid is used to represent GUIDs. Passing a _Guid object as a parameter passes a pointer to a GUID to the native function. Declaring a return type of _Guid causes the Microsoft VM to pass a pointer to an uninitialized GUID that the function fills in (in ole mode only).

For example, OLE32 exports the functions CLSIDFromProgID and ProgIDFromCLSID to map between CLSIDs and the human-readable names used by the Visual Basic function CreateObject. These functions have the following prototypes.


HRESULT CLSIDFromProgID(LPCOLESTR szProgID, LPCLSID pclsid);
HRESULT ProgIDFromCLSID(REFCLSID clsid, LPOLESTR *lpszProgId);

In Java, you would declare these methods in the following way.


  import com.ms.com._Guid;
  class OLE {
    /** @dll.import("OLE32", ole) */
    public static native _Guid CLSIDFromProgID(String szProgID);
	    
    /** @dll.import("OLE32", ole) */
    public static native String ProgIDFromCLSID(_Guid clsid);
  } 

Do not confuse com.ms.com._Guid with com.ms.com.Guid (with no underscore). The latter is an obsolete class.

Passing VARIANTs

Declaring a parameter to be type com.ms.com.Variant passes a pointer to a VARIANT to the native function. Declaring a return value to be type com.ms.com.Variant (ole-mode only) passes a pointer to an uninitialized Variant for the native function to fill in.

Passing COM Interface Pointers

To pass a COM interface pointer, you must generate a Java/COM interface class using a tool such as jactivex.exe. You can then pass or receive COM interfaces by declaring a parameter to be of that interface type.

For example, the system class com.ms.com.IStream is a Java/COM interface that represents the Structured Storage IStream* interface. The OLE32 function CreateStreamOnHGlobal could be declared as follows.


import com.ms.com.*;
/** @dll.import("OLE32", ole) */
public static native IStream CreateStreamOnHGlobal(int hGlobal,
                                     boolean fDeleteOnRelease);

Java/COM integration is a complex topic and a full discussion is beyond the scope of this documentation. For more information, see the Low-Level Java/COM Integration article.

Top © 1998 Microsoft Corporation. All rights reserved. Terms of use.