The following contains instructions to use omniORB under ETS-Kernel. The
information is provided by David MorgenLender <dmorgen@alum.mit.edu> and
Jon Kristensen <jon.kristensen@kongsberg-simrad.com>.

1.  Install and/or build a Win32 configuration (x86 NT4.0 or
    win95). The ETS build process uses the x86_w32 binaries in
    <top>/bin/x86_win32.

2.  Do a "make clean" in <top>\src

    Note!   If you are building both the Win95/NT4 and ETS kernel
            versions, a "make clean" is required each time you switch
            configuration. Otherwise the make utility may not
            recompile all files with the required compiler switches. A
            "make clean" will remove all temporary object files, but
            not the libraries and binary executables.

3.  Set the configuration to x86_ets, and execute "make export" in
    <top>\src. See "Building omniORB from the source files" in
    README.win32. Only the libraries will be built and installed in
    <top>\lib\x86_win32_ets.

4.  If you have "VC60" set up to build both NT and ETS versions of
    your app, you may rename and move your libraries to
    <top>\lib\x86_win32 to avoid having to reconfigure your VC60
    library path setting each time you switch build config.

5.  The ETS-Kernel application should be built using the static version of
    omniORB (-D_WINSTATIC must be specified.) See mk/platforms/x86_ets.mk for
    an example. Also __ETS_KERNEL__ must be defined.

6.  ETS-Kernel does not support the registry. The default setup is to
    read the root context of the COSNaming service from a
    configuration file (C:\OMNIORB.CFG).
 
    eg.:   
        InitRef = NameService=corbaname::192.168.1.1

    Another option is to use command line switches, but this is only
    practical when debugging.


7.  omniORB requires that a hostname be specified, but ETS-Kernel does
    not support a pre-defined hostname.  The workaround is to specify
    a hostname via an environment variable (OMNIORB_USEHOSTNAME),
    which can be set during the initialization of the app.  An example
    that reads the IP address from the device driver and uses it as
    the HOST name is given below:

    // This code should go at the top of function main()
    #ifdef __ETS_KERNEL__
      char    envstr[40];
      IN_ADDR ip;

      /* Obtain TcpIP configuration for Ether0 */
      DEVHANDLE hEth0 = EtsTCPGetDeviceHandle( "ether0" );
      EK_TCPIPCFG*  pTcpCfg = EtsTCPGetDeviceCfg( hEth0 );
      if (NULL == pTcpCfg)
        {
          cerr << "Unable to Get device configuration for ether0" << endl;
          exit(1);
        }
      ip.S_un.S_addr = TcpCfg.nwIPAddress;
      strcpy( envstr, "OMNIORB_USEHOSTNAME=" );
      strcat( envstr, inet_ntoa(ip) );
      if (_putenv( envstr ) != 0)
        {
          cerr << "Unable to set host name" << endl;
          exit(1);
        }
      cerr << "Hostname set to " << getenv( "OMNIORB_USEHOSTNAME" ) << endl;
    #endif

8.  It's critical that ETS-Kernel is configured properly regarding the
    network card, IP information, etc.  The appropriate network card
    driver must be linked into the app.  The appropriate configuration
    information (e.g. IP address) must be configured into the
    ETS-Kernel monitor (which functions as a loader for the app).

9.  omniORB4 uses one winsock 2.0 function: WSAIoctl().  ETS supports
    only WINSOCK 1.1, and the ETS build calls the custom replacement
    function ETS_WSAIoctl(). Example source given below:


#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
#define _WIN32_WINNT 0x0400 // Required for timer-functions i winbase.h
#include <windows.h>

#include <embtcpip.h>


static DWORD addressListQuery( SOCKET_ADDRESS_LIST* pAL, DWORD nBufLen )
{

  DEVHANDLE	hDev;
  EK_TCPIPCFG  *pCfg;  // device driver configuration information
  DWORD len = sizeof(SOCKET_ADDRESS_LIST) - sizeof(SOCKET_ADDRESS);
  // SOCKET_ADDRESS_LIST includes one SOCKET_ADDRESS
  SOCKET_ADDRESS sa;

  static SOCKADDR_IN sain[16];

  memset( sain, 0, sizeof(sain) );

  pAL->iAddressCount = 0;

  for (hDev = EtsTCPIterateDeviceList(NULL);
       hDev;
       hDev = EtsTCPIterateDeviceList(hDev))
    {
      pCfg = EtsTCPGetDeviceCfg(hDev);
      if (pCfg == NULL)
	continue;

      if ((len+sizeof(SOCKET_ADDRESS)) > nBufLen)
	return(-1);

      sain[pAL->iAddressCount].sin_family = AF_INET;
      sain[pAL->iAddressCount].sin_addr.S_un.S_addr = pCfg->nwIPAddress;

      sa.iSockaddrLength = sizeof(sain[0]);
      sa.lpSockaddr = (struct sockaddr*)&sain[pAL->iAddressCount];
      pAL->Address[pAL->iAddressCount++] = sa;

      len += sizeof(SOCKET_ADDRESS);
    }

  return len;
}



int WSAAPI ETS_WSAIoctl(
			SOCKET s,
			DWORD dwIoControlCode,
			LPVOID lpvInBuffer,
			DWORD cbInBuffer,
			LPVOID lpvOutBuffer,
			DWORD cbOutBuffer,
			LPDWORD lpcbBytesReturned,
			LPWSAOVERLAPPED lpOverlapped,
			LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
			)
{
  int nBytes;

  if ((lpOverlapped != NULL) || (lpCompletionRoutine != NULL))
    {
      WSASetLastError( WSAEINVAL );
      return SOCKET_ERROR;
    }

  switch (dwIoControlCode)
    {
    case  SIO_ADDRESS_LIST_QUERY:
      nBytes = addressListQuery( (SOCKET_ADDRESS_LIST*) lpvOutBuffer,
				 cbOutBuffer );
      if (nBytes < 0)
	{
	  WSASetLastError( WSAEFAULT );
	  return SOCKET_ERROR;
	}
      *lpcbBytesReturned = (DWORD)nBytes;
      break;
    default:
      WSASetLastError( WSAEINVAL );
      return SOCKET_ERROR;
    }

  return 0;
}
