Re: Windows Programming using Java

From: Richard Sandoz (rsandoz_at_hotmail.com)
Date: 12/11/03


Date: 11 Dec 2003 13:24:08 -0800

vnssoftware@myway.com (vnssoftware) wrote in message news:<b19cd378.0311220853.1a9968d1@posting.google.com>...
> If I want to use Windows Functions through Java, can I?
> For example, when you right click on a File you get Open With..
> If I want to add something to it can I do so.
> If I want to play with Windows Taskbar can I do so.
> Is there a Java library available for doing such tasks.
>
> Thanks!
You can always do these thing from JNI. I have wrote a brief guide on
how to do this using ping as an example. These same concepts can be
applied to the same COM calls required to "register file extensions",
minimize, maximize, etc tasks on the taskbar (assuming this is what
you want). You may first want to define your requirements so you know
exactly what you are looking for:

(1) Introduction to JNI by example using Ping by Richard Sandoz

Ping is the defacto standard for testing point to point network
connectivity. It uses what is called an icmp packet. Java does not
include a "ping" command. Native code must be written to implement
ping.

(2) The signature:
      int ping(String host) {
        ...
        return timeInMilliSeconds;
      }

This provides two simple cases for input and output for native
functionality.

(3) Common Java

First create a directory structure. I will start the initial
development in the Windows environment. I will start with the C drive
as a point of reference. Create a directory called ICMPLibrary:
  C:\ICMPLibrary

Then create a subdirectory called src.
  C:\ICMPLibrary\src
    
Then create a subdirectory called icmp. This will serve as the
package.
  C:\ICMPLibrary\src\icmp

Now (inside the icmp subdirectory) create a file called
ICMPInterface.java and enter in the following code:
  /*
   * @(#) ICMPInterface.java
   */
  package icmp;

  public class ICMPInterface {
    final static String LIBRARY_NAME = "pinglib";
  
    static {
                  try {
        System.out.println("Loading (" +
System.mapLibraryName(LIBRARY_NAME) + ")");
        System.loadLibrary(LIBRARY_NAME);
                  } catch(UnsatisfiedLinkError e) {
        System.err.println("library path=" +
System.getProperty("java.library.path"));
                          System.err.println(e + ":cannot load (" +
System.mapLibraryName(LIBRARY_NAME) + ")");
                  }
    }
    
          static public native boolean ping(String host);
  }

This is the native interface portion of the project. It includes the
java native signature for the ping function.

Next create a file called ICMPTest.java and enter in the following
code:
  /*
  * @(#) ICMPTest.java
  */
  package icmp;
  
  public class ICMPTest {
    public static void main(String[] args) {
      String host = args[0];
                  for (int i =0; i < 5;i++)
                    System.out.println(host + "=" +
(ICMPInterface.ping(host)?"ALIVE":"NO RESPONSE"));
    }
  }

This is simple test code that will allow us to test our native
interface.

Now drop to a DOS prompt and change to the directory:
  C:\ICMPLibrary\src

Next compile the two java files you created from above.
  javac -classpath . icmp/ICMPTest.java

This will produce the files ICMPInterface.class and ICMPTest.class in
the icmp subdirectory.

(4) Platform specific code:
  (A) Windows - Visual C++
  Start Microsoft Visual Studio. I will be using Visual Studio 97 for
this example.
  
  Create a new project, specifically a "Win32 Dynamic-Link Library".
  
  In the location field, specify:
    C:\ICMPLibrary\
  
  In the project name field, specify:
    pinglib
  This will also append pinglib to the previous field. Click OK.
  
  Switch to the file view, then create a new file and add the
following code:
    typedef unsigned long IPAddr;
    
    typedef struct ip_option_information {
            UCHAR Ttl;
            UCHAR Tos;
            UCHAR Flags;
            UCHAR OptionsSize;
            PUCHAR OptionsData;
    } IP_OPTION_INFORMATION, *PIP_OPTION_INFORMATION;
    
    typedef struct icmp_echo_reply {
            IPAddr Address;
            ULONG Status;
            ULONG RoundTripTime;
            USHORT DataSize;
            USHORT Reserved;
            PVOID Data;
            IP_OPTION_INFORMATION Options;
    } ICMP_ECHO_REPLY, *PICMP_ECHO_REPLY;
    
    typedef HANDLE (CALLBACK* fnIcmpCreateFile)();
    typedef DWORD (CALLBACK* fnIcmpSendEcho)(HANDLE IcmpHandle,IPAddr
DestinationAddress,
      LPVOID RequestData,WORD RequestSize,PIP_OPTION_INFORMATION
RequestOptions,
      LPVOID ReplyBuffer,DWORD ReplySize, DWORD Timeout);
    typedef BOOL (CALLBACK* fnIcmpCloseHandle)(HANDLE IcmpHandle);
    
    BOOL ping(HANDLE hDll, const char* hostname);

  Save this as a file called pinglib.h and add it to the project.
  
  Next, create a new file and add the following code:
    #include <windows.h>
    #include <jni.h>
    #include "pinglib.h"
    
    extern "C" {
    JNIEXPORT jboolean JNICALL Java_icmp_ICMPInterface_ping(
            JNIEnv* env,
            jobject thisObj,
            jstring jhost)
    {
            char* strDll = "icmp.dll";
            HINSTANCE hDll = LoadLibrary(strDll);
    
            if (hDll) {
                    const char* host = env->GetStringUTFChars(jhost, FALSE);
    
                    jboolean retVal = ping(hDll, host);
    
                    env->ReleaseStringUTFChars(jhost, host);
    
                    FreeLibrary(hDll);
    
                    return retVal;
            } else {
                    printf("Error loading library %s\n", strDll);
                    exit(0);
            }
            return 0;
    }
    }
    
    BOOL ping(HANDLE hDll, const char* hostname) {
            fnIcmpCreateFile IcmpCreateFile =
(fnIcmpCreateFile)GetProcAddress(hDll, "IcmpCreateFile");
            fnIcmpSendEcho IcmpSendEcho =
(fnIcmpSendEcho)GetProcAddress(hDll, "IcmpSendEcho");
            fnIcmpCloseHandle IcmpCloseHandle =
(fnIcmpCloseHandle)GetProcAddress(hDll, "IcmpCloseHandle");
    
            // load winsock
            WSADATA WSAData;
            if (WSAStartup(MAKEWORD(1,1), &WSAData) != 0) {
                    fprintf (stderr, "Can't start up winsock.\n");
                    return FALSE;
            }
    
            HANDLE icmpHandle = IcmpCreateFile();
            if (icmpHandle == NULL) {
                    fprintf (stderr, "Can't open the icmp handle.\n");
                    return FALSE;
            }
    
            IPAddr addr = inet_addr(hostname);
            if (addr == INADDR_NONE) {
                    printf("Attempting to resolve %s\n", hostname);
                    PHOSTENT host = gethostbyname (hostname);
                    if (host == NULL) {
                            fprintf (stderr, "Can't figure out host name/ID %s.\n",
hostname);
                            return FALSE;
                    }
                    addr = *(long*)(*host->h_addr_list);
            }
    
            BYTE* rdata = (BYTE*)malloc(100);
            WORD rdatasize = 100;
            BYTE* rbuf = (BYTE*)malloc(3000);
            long rbufsize = 3000;
            // = new char[(sizeof(ICMP_ECHO_REPLY)+__max(8,rdatasize))];
            DWORD dwv = IcmpSendEcho( // return value is N responses
                                    icmpHandle, // Handle of ICMP "file"
                                    addr, // IP address of host
                                    rdata, // ICMP request data
                                    rdatasize, // sizeof above
                                    NULL, // IP request options TBS
                                    rbuf, // reply buffer
                                    rbufsize, // size of above
                                    50); // timeout, millisecondsp
    
            ICMP_ECHO_REPLY* rp = (ICMP_ECHO_REPLY*)rbuf;
    
            // optionally utilize the rp structure to get metrics about the
ping

            free(rbuf);
            free(rdata);
    
            // close icmp handle
            IcmpCloseHandle(icmpHandle);
            
            // unload winsock
            WSACleanup();
    
            return dwv!=0;
    }

  Save this as a file called pinglib.cpp and add it to the project.

  Next, create one last file and add the following code:
    EXPORTS
            Java_icmp_ICMPInterface_ping

  Save this as a file called pinglib.def and add it to the project.

  Now, access the project setting (from menu, project//settings).
  
  Select the "All configurations" as the settings for field.
  
  Switch to the "Link" tab and append "ws2_32.lib" to the
Object/library modules field
  and add "..\src\pinglib.dll" to the "Output file name" field
  
  Next, switch to the C/C++ tab, select Preprocessor from the dropdown
and add:
    c:\j2sdk1.4.1_01\include,c:\j2sdk1.4.1_01\include\win32
  to this field. Assuming you installed your Java SDK in this
location.
  
  Click OK, then build the project, by selecting build//rebuild all
from the menu.

(5) Run the program:

Now drop to a DOS prompt and change to the source directory:
  C:\ICMPLibrary\src

Next run the java test program created.
  java -cp . icmp/ICMPTest 127.0.0.1
  Loading (pinglib.dll)
  127.0.0.1=ALIVE
  127.0.0.1=ALIVE
  127.0.0.1=ALIVE
  127.0.0.1=ALIVE
  127.0.0.1=ALIVE

  java -cp . icmp/ICMPTest 128.0.0.1
  Loading (pinglib.dll)
  128.0.0.1=NO RESPONSE
  128.0.0.1=NO RESPONSE
  128.0.0.1=NO RESPONSE
  128.0.0.1=NO RESPONSE
  128.0.0.1=NO RESPONSE



Relevant Pages

  • ICMP packets
    ... I was doing a research looking for Java solutions that are able to do ... The only solution that I found was a "simulation" of a ping program ... "java.net" is able to send ICMP packets. ...
    (comp.lang.java)
  • Re: Ping Class java
    ... >Does anyone know a Ping Class in Java ... >to do a simple "ping" on a server and reading the response? ... Ping is a very low level protocol not supported by Java. ...
    (comp.lang.java.programmer)
  • Re: Question with regard to Sockets
    ... >> I wanted to try out a 'ping' program in Java, ... >> wherein I can construct a ICMP Header myself ... code in a custom SocketImpl subclass and to set a custom ...
    (comp.lang.java.programmer)
  • Re: IP Addresses - WTF?
    ... >> Kind of on the same subject, does anyone know of a Java based set of tools ... >> such as traceroute, nslookup and ping that would work on a mobile phone, or ... As a typio I like that (snadbox) it seems to describe gentoo's portage one ...
    (uk.misc)
  • Re: In the Shallow End
    ... Yes, with Apple finally getting in there, technology is finally moving along nicely again. ... What they like to do is use the Windows desktop as data gathering frontends to these operations. ... They had other plans for Java, ... They make computers for the elite. ...
    (comp.sys.mac.advocacy)