Examining Microsoft's J/Direct 
by Andrew Wilson




Figure 1:

/** @dll.import("KERNEL32" ) */
protected static native int GlobalLock ( int addr );

Figure 2:

/** @dll.import("KERNEL32", entrypoint="GlobalLock" ) */
protected static native int globalLock ( int addr );
// Converts the API to follow Java naming conventions

/** @dll.import("KERNEL32", entrypoint="#353" ) */
protected static native int globalLock ( int addr );
// Converts the ordinal to support valid java naming conventions 


Figure 3:

// Native C Version
typedef struct _MEMORYSTATUS { 
    DWORD dwLength;     
    DWORD dwMemoryLoad; 
    DWORD dwTotalPhys;  
    DWORD dwAvailPhys;  
    DWORD dwTotalPageFile;
    DWORD dwAvailPageFile;
    DWORD dwTotalVirtual; 
    DWORD dwAvailVirtual; 
} MEMORYSTATUS; 

// J/Direct Version
/** @dll.struct() */
class MEMORYSTATUS
{
    public int dwLength;     
    public int dwMemoryLoad; 
    public int dwTotalPhys;  
    public int dwAvailPhys;  
    public int dwTotalPageFile;
    public int dwAvailPageFile;
    public int dwTotalVirtual; 
    public int dwAvailVirtual; 
}

Figure 4:
//Native C Structure

typedef struct _MYSTRUCT
{
    DWORD dwLen;
    char szMyString[24];
} MYSTRUCT;

//J/Direct Structure Conversion for Fixed Length Types
/** @dll.struct() */
{
    int dwLen;
    /** @dll.structmap([type=FIXEDARRAY, size=24]) */
    char szMyString[];

}
//J/Direct Structure Conversion for String Types
/** @dll.struct() */
class MYSTRUCT
{
    int dwLen;
    /** @dll.structmap([type=char[24]) */
    String szMyString; // converted to a string object
}


Listing One
// J/Direct 
class WindowProc extends Callback
{
    int m_oldWndProc = 0;
    MessageHandler m_msgHndlr = null;
    /** @dll.import("USER32") */
    private static native int CallWindowProc ( int lpPrevWndFunc,
        int hwnd,
        int msg,
        int wParam,
        int lParam );
    public WindowProc ( int wndProc )
    {
       super();
       m_oldWndProc = wndProc;
    }
    public void setMessageHandler ( MessageHandler msgHndlr )  
                                               throws NullPointerException
    {
        if ( msgHndlr == null)
        {
            throw new NullPointerException ( "Bad MessageHandler" );
        }
        m_msgHndlr = msgHndlr;

    }
    public int callback ( int hwnd, int code,  int wParam, int lParam )
    {
       if ( m_msgHndlr != null )
           m_msgHndlr.MessageProc ( hwnd, code, wParam, lParam );
       return CallWindowProc(m_oldWndProc, hwnd, code, wParam, lParam );
    }
}

Listing Two
// WndFrame allows a developer to hook the Java application's
// WindowProc to allow real Window's message processing
/** @dll.import("USER32") */
class WndFrame extends AwtUIFrame
{   
    // Win32 API functions 
    private static native int FindWindow(String lpClassName,
        String lpWindowName);
    private static native int GetWindowLong ( int hwnd,
        int nIndex );
    private static native int SetWindowLong( int hWnd,
        int nIndex,
        Callback NewLong );
    // GetWindowLong and SetWindowLong index
    private final static int GWL_WNDPROC = (-4);
    // class fields
    int m_hwnd = 0;
    String m_windowName = null;
    WindowProc m_wndProc = null;
    WndFrame(String str)
    {
        super ( str );
        m_windowName = str;
    }
    public synchronized int hook() throws DLLException, APIException
    {  
        try
        {
            // Find the handle for the window
            m_hwnd = FindWindow("MSAWT_Comp_Class", m_windowName);
            if ( m_hwnd == 0 )
             throw new APIException("Could not find window:" + m_windowName);
            // get the window proc address
            int wndProc = GetWindowLong ( m_hwnd, GWL_WNDPROC );
            if ( wndProc == 0 )
              throw new APIException ( 
                           "Could not get windowProc for: " + m_windowName );
           m_wndProc = new WindowProc ( wndProc );
            // Set the new window proc with the J/Direct callback
            if ( SetWindowLong ( m_hwnd, GWL_WNDPROC, m_wndProc )== 0)
                throw new APIException ( "Unable to set new WindowProc" );
        } catch ( UnsatisfiedLinkError ule )
        {
            throw new DLLException ( "Unable to load User32.dll" );
        }
        return m_hwnd;
    }
    public synchronized WindowProc getWndProc ( ) throws NullPointerException
    {
        if( m_wndProc == null )
        {
            throw new NullPointerException ( "WindProc not initialized" );
        }
        return m_wndProc;
    }
}       


Listing Three
/** @dll.import("USER32") */
class Clipboard extends Object
{
    protected static native boolean OpenClipboard( int hWndNewOwner );
    protected static native int SetClipboardViewer( int hWndNewOwner );
    protected static native boolean ChangeClipboardChain( int hWndRemove,
        int hWndNewNext);
    protected static native boolean CloseClipboard();
    protected static native int GetPriorityClipboardFormat( 
                                             int[] formats, int length );
    protected static native int GetClipboardData( int format );

    /** @dll.import("KERNEL32" ) */
    protected static native int GlobalLock ( int addr );

    /** @dll.import("KERNEL32" ) */
    protected static native int GlobalUnlock ( int addr );

    protected int m_hwnd = 0;
    protected int m_oldHwnd = 0;

    protected static final int CF_TEXT = 1;
    Clipboard()
    { 
        super();
    }
    public void open ( ) throws DLLException, APIException

   {
        open ( 0 );
    }
    public void open( int hwnd ) throws DLLException, APIException
    {                       
        try
        {   
            if ( OpenClipboard ( hwnd ) == false)
                throw new APIException( "Could not open clipboard" );
        } catch ( UnsatisfiedLinkError ule )
        {
            throw new DLLException ( "Failed to load User32.dll" );
        }
    }
    public int setViewer ( int hwnd ) throws DLLException
    {
        m_hwnd = hwnd;
        try
        {
            m_oldHwnd = SetClipboardViewer ( hwnd );
            return m_oldHwnd;
        } catch ( UnsatisfiedLinkError ule )
        {
            throw new DLLException ( "Failed to load User32.dll" );
        }
    }
    public void closeViewer ( ) throws DLLException
    {
       try
       {
           ChangeClipboardChain ( m_hwnd, m_oldHwnd);
       } catch ( UnsatisfiedLinkError elu )
       {
           throw new DLLException ( "Failed to load USER32.DLL");
       }
    }
    public void close ( )
    {
        CloseClipboard();
    }
    public String getData() throws APIException
    {
        int [] priority = new int[1];
        priority[0] = CF_TEXT;
        int format = 
            GetPriorityClipboardFormat ( priority, priority.length );
        if ( (format == -1) || ( format == 0 ) )
           throw new APIException ( "No data ready" );
        int results = GetClipboardData( format );
        int locked = GlobalLock( results );
        String str = DllLib.ptrToStringAnsi( locked );
        GlobalUnlock( results );
        return str;
    }
}

Listing Four
public class DirectSample extends AwtUIApplet implements MessageHandler
{
    public Clipboard m_cp = null;
    public int m_oldHwnd = 0;
    int m_hwnd = 0;
    UIDrawText m_text = null;
    UIScrollViewer m_view = null;

    protected static final int WM_DRAWCLIPBOARD = 0x0308;
    protected static final int WM_CHANGECBCHAIN = 0x030D;

    DirectSample( )
    {
        super();
    }
    public static void main ( String arg[] )
    {
        WndFrame frame = new WndFrame("J/Direct Sample");
        frame.setLayout(new UIBorderLayout());
        DirectSample ds = new DirectSample();
        frame.add( "Center", ds);
        frame.resize ( new Dimension (320,200 ));
        ds.init();
        frame.show();
        try
        {
            ds.m_hwnd = frame.hook();
            WindowProc wndProc = frame.getWndProc();
            wndProc.setMessageHandler ( ds );

            ds.m_cp = new Clipboard();
            ds.m_oldHwnd = ds.m_cp.setViewer ( ds.m_hwnd );

        } catch ( DLLException ioe )
        {
            System.out.println ( "DLL Error: " + ioe.getMessage() );
        } catch ( APIException e )

       {
            System.out.println ( "API error: " + e.getMessage() );
        }
    }
    public void init ( )
    { 
        setLayout( new UIBorderLayout() );
        m_text = new  UIDrawText (  );
        m_view = new UIScrollViewer ( m_text );
        add( "Center", m_view );
    }
    /** @dll.import( "USER32" ) */
    private static native int SendMessage ( int hwnd, int code, 
                                                  int wParam, int lParam );
    public void MessageProc ( int hwnd, int code, int wParam, int lParam)
    {
        if ( code == WM_DRAWCLIPBOARD )
        {
            try
            {  
                m_cp.open ( m_hwnd );
                m_text.setText( m_cp.getData() );
                m_cp.close();
                m_view.invalidate();
            } catch ( DLLException de )
            {
                System.out.println ( "DllException: " + de.getMessage() );
            } catch ( APIException ae )
            {
                System.out.println ( "APIException: " + ae.getMessage () );
            }
            SendMessage ( m_oldHwnd, code, wParam, lParam);
        }
        if ( code == WM_CHANGECBCHAIN )
        {
            SendMessage ( m_oldHwnd, code, wParam, lParam);
        }
    }
    public void finalize ( ) throws Throwable
    {
        System.out.println ( "Exiting" );
        try
        {
            m_cp.closeViewer();
        //  m_cp.close();
        } catch ( DLLException de )
        {
            System.out.println ( "DLLException: " + de.getMessage() );
       }
        super.finalize();
    }
}
Listing One
// J/Direct 
class WindowProc extends Callback
{
    int m_oldWndProc = 0;
    MessageHandler m_msgHndlr = null;
    /** @dll.import("USER32") */
    private static native int CallWindowProc ( int lpPrevWndFunc,
        int hwnd,
        int msg,
        int wParam,
        int lParam );
    public WindowProc ( int wndProc )
    {
       super();
       m_oldWndProc = wndProc;
    }
    public void setMessageHandler ( MessageHandler msgHndlr )  
                                               throws NullPointerException
    {
        if ( msgHndlr == null)
        {
            throw new NullPointerException ( "Bad MessageHandler" );
        }
        m_msgHndlr = msgHndlr;

    }
    public int callback ( int hwnd, int code,  int wParam, int lParam )
    {
       if ( m_msgHndlr != null )
           m_msgHndlr.MessageProc ( hwnd, code, wParam, lParam );
       return CallWindowProc(m_oldWndProc, hwnd, code, wParam, lParam );
    }
}

Listing Two
// WndFrame allows a developer to hook the Java application's
// WindowProc to allow real Window's message processing
/** @dll.import("USER32") */
class WndFrame extends AwtUIFrame
{   
    // Win32 API functions 
    private static native int FindWindow(String lpClassName,
        String lpWindowName);
    private static native int GetWindowLong ( int hwnd,
        int nIndex );
    private static native int SetWindowLong( int hWnd,
        int nIndex,
        Callback NewLong );
    // GetWindowLong and SetWindowLong index
    private final static int GWL_WNDPROC = (-4);
    // class fields
    int m_hwnd = 0;
    String m_windowName = null;
    WindowProc m_wndProc = null;
    WndFrame(String str)
    {
        super ( str );
        m_windowName = str;
    }
    public synchronized int hook() throws DLLException, APIException
    {  
        try
        {
            // Find the handle for the window
            m_hwnd = FindWindow("MSAWT_Comp_Class", m_windowName);
            if ( m_hwnd == 0 )
              throw new APIException("Could not find window:" + m_windowName);
            // get the window proc address
            int wndProc = GetWindowLong ( m_hwnd, GWL_WNDPROC );
            if ( wndProc == 0 )
              throw new APIException ( 
                           "Could not get windowProc for: " + m_windowName );
           m_wndProc = new WindowProc ( wndProc );
            // Set the new window proc with the J/Direct callback
            if ( SetWindowLong ( m_hwnd, GWL_WNDPROC, m_wndProc )== 0)
                throw new APIException ( "Unable to set new WindowProc" );
        } catch ( UnsatisfiedLinkError ule )
        {
            throw new DLLException ( "Unable to load User32.dll" );
        }
        return m_hwnd;
    }
    public synchronized WindowProc getWndProc ( ) throws NullPointerException
    {
        if( m_wndProc == null )
        {
            throw new NullPointerException ( "WindProc not initialized" );
        }
        return m_wndProc;
    }
}       


Listing Three
/** @dll.import("USER32") */
class Clipboard extends Object
{
    protected static native boolean OpenClipboard( int hWndNewOwner );
    protected static native int SetClipboardViewer( int hWndNewOwner );
    protected static native boolean ChangeClipboardChain( int hWndRemove,
        int hWndNewNext);
    protected static native boolean CloseClipboard();
    protected static native int GetPriorityClipboardFormat( 
                                             int[] formats, int length );
    protected static native int GetClipboardData( int format );

    /** @dll.import("KERNEL32" ) */
    protected static native int GlobalLock ( int addr );

    /** @dll.import("KERNEL32" ) */
    protected static native int GlobalUnlock ( int addr );

    protected int m_hwnd = 0;
    protected int m_oldHwnd = 0;

    protected static final int CF_TEXT = 1;
    Clipboard()
    { 
        super();
    }
    public void open ( ) throws DLLException, APIException

   {
        open ( 0 );
    }
    public void open( int hwnd ) throws DLLException, APIException
    {                       
        try
        {   
            if ( OpenClipboard ( hwnd ) == false)
                throw new APIException( "Could not open clipboard" );
        } catch ( UnsatisfiedLinkError ule )
        {
            throw new DLLException ( "Failed to load User32.dll" );
        }
    }
    public int setViewer ( int hwnd ) throws DLLException
    {
        m_hwnd = hwnd;
        try
        {
            m_oldHwnd = SetClipboardViewer ( hwnd );
            return m_oldHwnd;
        } catch ( UnsatisfiedLinkError ule )
        {
            throw new DLLException ( "Failed to load User32.dll" );
        }
    }
    public void closeViewer ( ) throws DLLException
    {
       try
       {
           ChangeClipboardChain ( m_hwnd, m_oldHwnd);
       } catch ( UnsatisfiedLinkError elu )
       {
           throw new DLLException ( "Failed to load USER32.DLL");
       }
    }
    public void close ( )
    {
        CloseClipboard();
    }
    public String getData() throws APIException
    {
        int [] priority = new int[1];
        priority[0] = CF_TEXT;
        int format = 
            GetPriorityClipboardFormat ( priority, priority.length );
        if ( (format == -1) || ( format == 0 ) )
           throw new APIException ( "No data ready" );
        int results = GetClipboardData( format );
        int locked = GlobalLock( results );
        String str = DllLib.ptrToStringAnsi( locked );
        GlobalUnlock( results );
        return str;
    }
}

Listing Four
public class DirectSample extends AwtUIApplet implements MessageHandler
{
    public Clipboard m_cp = null;
    public int m_oldHwnd = 0;
    int m_hwnd = 0;
    UIDrawText m_text = null;
    UIScrollViewer m_view = null;

    protected static final int WM_DRAWCLIPBOARD = 0x0308;
    protected static final int WM_CHANGECBCHAIN = 0x030D;

    DirectSample( )
    {
        super();
    }
    public static void main ( String arg[] )
    {
        WndFrame frame = new WndFrame("J/Direct Sample");
        frame.setLayout(new UIBorderLayout());
        DirectSample ds = new DirectSample();
        frame.add( "Center", ds);
        frame.resize ( new Dimension (320,200 ));
        ds.init();
        frame.show();
        try
        {
            ds.m_hwnd = frame.hook();
            WindowProc wndProc = frame.getWndProc();
            wndProc.setMessageHandler ( ds );

            ds.m_cp = new Clipboard();
            ds.m_oldHwnd = ds.m_cp.setViewer ( ds.m_hwnd );

        } catch ( DLLException ioe )
        {
            System.out.println ( "DLL Error: " + ioe.getMessage() );
        } catch ( APIException e )

       {
            System.out.println ( "API error: " + e.getMessage() );
        }
    }
    public void init ( )
    { 
        setLayout( new UIBorderLayout() );
        m_text = new  UIDrawText (  );
        m_view = new UIScrollViewer ( m_text );
        add( "Center", m_view );
    }
    /** @dll.import( "USER32" ) */
    private static native int SendMessage ( int hwnd, int code, 
                                                  int wParam, int lParam );
    public void MessageProc ( int hwnd, int code, int wParam, int lParam)
    {
        if ( code == WM_DRAWCLIPBOARD )
        {
            try
            {  
                m_cp.open ( m_hwnd );
                m_text.setText( m_cp.getData() );
                m_cp.close();
                m_view.invalidate();
            } catch ( DLLException de )
            {
                System.out.println ( "DllException: " + de.getMessage() );
            } catch ( APIException ae )
            {
                System.out.println ( "APIException: " + ae.getMessage () );
            }
            SendMessage ( m_oldHwnd, code, wParam, lParam);
        }
        if ( code == WM_CHANGECBCHAIN )
        {
            SendMessage ( m_oldHwnd, code, wParam, lParam);
        }
    }
    public void finalize ( ) throws Throwable
    {
        System.out.println ( "Exiting" );
        try
        {
            m_cp.closeViewer();
        //  m_cp.close();
        } catch ( DLLException de )
        {
            System.out.println ( "DLLException: " + de.getMessage() );
       }
        super.finalize();
    }
}


12


