/*
 * NATIVE_MAIN
 */

#include <nwthread.h>
#include <nwadv.h>
#include <ntypes.h>
#include <signal.h>

#include "jncp.h"
#include "JNIString.h"
#include "binderyJNI.h"
#include "netJNI.h"
#include "CLXJNI.h"
#include "xjni.h"

#pragma unreferenced (on)
N_GLOBAL_VAR char *productStr = JNCP_PRODUCT_STRING;
N_GLOBAL_VAR char *versionStr = JNCP_VERSION_STRING;
N_GLOBAL_VAR char *copyrightStr = JNCP_COPYRIGHT_STRING;
#pragma unreferenced (off)

N_GLOBAL_VAR int _JNCPThreadGroupID;


N_GLOBAL_VAR int _usingAliasFunctions = 0;
N_GLOBAL_VAR alias_func_t _aliasFunctions[] = { NULL, NULL };

char *makeName = "MakeAndLockAlias";
char *deleteName = "DeleteAndUnLockAlias";


N_GLOBAL_VAR int _usingNetWareFunctions = 0;
N_GLOBAL_VAR netware_func_t _netwareFunctions[] = { NULL, NULL };

char *enterName = "kEnterNetWare";
char *exitName = "kExitNetWare";


/*
 *
 */
N_GLOBAL_FUNC(void) __InitAliasFunctions(void)
{
   void *make, *delete;
   int hnd = GetNLMHandle();

   make = ImportSymbol(hnd, makeName);
   delete = ImportSymbol(hnd, deleteName);

   if (make == NULL || delete == NULL)
   {
      UnimportSymbol(hnd, makeName);
      UnimportSymbol(hnd, deleteName);

      _usingAliasFunctions = 0;
   }
   else
   {
      _aliasFunctions[0] = make;
      _aliasFunctions[1] = delete;

      _usingAliasFunctions = 1;
   }
}

/*
 *
 */
N_GLOBAL_FUNC(void) __CleanupAliasFunctions(void)
{
   if (_usingAliasFunctions)
   {
      int hnd = GetNLMHandle();

      UnimportSymbol(hnd, makeName);
      UnimportSymbol(hnd, deleteName);
   }
}


/*
 *
 */
N_GLOBAL_FUNC(void) __InitNetWareFunctions(void)
{
   void *enter, *exit;
   int hnd = GetNLMHandle();

   enter = ImportSymbol(hnd, enterName);
   exit = ImportSymbol(hnd, exitName);

   if (enter == NULL || exit == NULL)
   {
      UnimportSymbol(hnd, enterName);
      UnimportSymbol(hnd, exitName);

      _usingNetWareFunctions = 0;
   }
   else
   {
      _netwareFunctions[0] = enter;
      _netwareFunctions[1] = exit;

      _usingNetWareFunctions = 1;
   }
}

/*
 *
 */
N_GLOBAL_FUNC(void) __CleanupNetWareFunctions(void)
{
   if (_usingNetWareFunctions)
   {
      int hnd = GetNLMHandle();

      UnimportSymbol(hnd, enterName);
      UnimportSymbol(hnd, exitName);
   }
}


/*
 *
 */
void cleanup(int sig)
{
   int save = GetThreadGroupID();

   SetThreadGroupID(_JNCPThreadGroupID);

   __CleanupNASAndExFunctions();
   __CleanupGlobalThreadGroup();
   __CleanupNetWareFunctions();
   __CleanupAliasFunctions();
   __CleanupSkadsFunctions();
   __CleanupCLXJNI();
   __CleanupSLPCalls();
   __CleanupNativeUnicode();  // make sure unicode is uninit'd before NWCalls
   __CleanupNWCalls();

   SetThreadGroupID(save);
}

/*
 * main ()
 *
 * Main entry point -- don't do anything after the call to SynchronizeStart.
 * The loader process sleeps until the call to SynchronizeStart, so we DO
 * have a data segment when Java auto-loads us.  If this were not a
 * synchronized NLM, then we'd be forced to put all this resource
 * initialization in a native method, which would make Java's resource tag
 * get all of our memory allocation for unicode tables, etc.
 *
 * Entry:
 *
 * Exit:
 *    Nothing
 */

void main ()
{
   _JNCPThreadGroupID = GetThreadGroupID();

   __InitNWCalls();        // make sure NWCalls is init'd before unicode
   __InitNativeUnicode();
   __InitSLPCalls();
   __InitSkadsFunctions();
   __InitCLXJNI();
   __InitAliasFunctions();
   __InitNetWareFunctions();
   __InitGlobalThreadGroup();
   __InitNASAndExFunctions();

   signal(SIGTERM, cleanup);

   SynchronizeStart();

   ExitThread (TSR_THREAD, 0);
}


