
/* **************************************************************************

  %name: streamJNI.c %
  %version: 8 %
  %date_modified: Thu Feb 19 13:48:26 1998 %
 
  Copyright (c) 1997 Novell, Inc.  All Rights Reserved.

  THIS WORK IS AN UNPUBLISHED WORK AND CONTAINS CONFIDENTIAL PROPRIETARY
  AND TRADE SECRET INFORMATION OF NOVELL, INC. ACCESS  TO  THIS  WORK IS
  RESTRICTED TO (I) NOVELL, INC.  EMPLOYEES WHO HAVE A NEED TO  KNOW HOW
  TO  PERFORM  TASKS WITHIN  THE SCOPE  OF  THEIR   ASSIGNMENTS AND (II)
  ENTITIES OTHER  THAN  NOVELL, INC.  WHO  HAVE ENTERED INTO APPROPRIATE
  LICENSE   AGREEMENTS.  NO  PART  OF  THIS WORK MAY BE USED, PRACTICED,
  PERFORMED COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
  CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED,  RECAST, TRANSFORMED
  OR ADAPTED  WITHOUT THE PRIOR WRITTEN CONSENT OF NOVELL, INC.  ANY USE
  OR EXPLOITATION  OF  THIS WORK WITHOUT AUTHORIZATION COULD SUBJECT THE
  PERPETRATOR  TO CRIMINAL AND CIVIL LIABILITY.

****************************************************************************/


#include <sys_api.h>

#include <jni.h>

#include <ntypes.h>
#include "jncp.h"

#if defined (N_PLAT_MSW) && defined (N_ARCH_32)

#  include <windows.h> // for ReadFile, WriteFile, SetFilePointer, 
                       //   GetFileSize, FlushFileBuffers, and CloseHandle
#  include <io.h>      // for _open_osfhandle, _chsize
#  include <fcntl.h>

#elif defined (N_PLAT_NLM)

#  include <nlm\nwfileio.h>
#  include <nlm\unistd.h>
#  include <string.h>
#  include <errno.h>
#  include <nwerrno.h>

#endif

#include "com_novell_service_jncpv2r_cal_DeviceAccessJNI.h"

#define noMemoryAvailable 0xABCD;       //are there better numbers that are
#define shouldNeverGetHereError 0xBCDE; //never used to mean something else
#define shouldNeverGetHereError2 0xBCDF; //for now, use these hard coded ones.

#if defined (N_PLAT_MSW) && defined (N_ARCH_32)
#  define xFileClose(handle) \
            (N_TRUE == CloseHandle((HANDLE)(handle)))
#  define xFileGetLength(handle)  GetFileSize((HANDLE)(handle), NULL)
#  define xFileSetLength(handle,length) \
            _chsize( \
                     _open_osfhandle((LONG)(handle), \
                     _O_RDONLY), \
                     (long)(length))
#  define xFileGetPosition(handle) \
            SetFilePointer((HANDLE)(handle), 0L, NULL, FILE_CURRENT)
#  define xFileSetPosition(handle,position,mode)  SetFilePointer((HANDLE)(handle), (LONG)(position), NULL, (DWORD)(mode))
#  define xFileRead(handle,ptr,length,cActualLength) \
            (N_TRUE == ReadFile ( \
                                 (HANDLE)(handle), \
                                 (char *)(ptr), \
                                 (DWORD)(length), \
                                 &(cActualLength), \
                                 NULL))
#  define xFileWrite(handle,ptr,length,cActualLength)  (N_TRUE == WriteFile ((HANDLE)(handle), (char *)(ptr), (DWORD)(length), &(cActualLength), NULL))
#elif defined (N_PLAT_NLM)
#  define xFileClose(handle)  (0 == close((int)(handle)))
#  define xFileGetLength(handle)  filelength((int)(handle))
#  define xFileSetLength(handle,length)  chsize((int)(handle), (LONG)(length))
#  define xFileGetPosition(handle)  tell((int)(handle))
#  define xFileSetPosition(handle,position,mode)  lseek((int)(handle), (LONG)(position), (int)(mode))
#  define xFileRead(handle,ptr,length,cActualLength)  (-1 != (cActualLength = read ((int)(handle), (char *)(ptr), (size_t)(length))))
#  define xFileWrite(handle,ptr,length,cActualLength)  (-1 != (cActualLength = write ((int)(handle), (char *)(ptr), (size_t)(length))))
#else

#endif


/*
 * Class:     com_novell_service_jncpv2r_cal_DeviceAccessJNI
 * Method:    JDAClose
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_DeviceAccessJNI_JDAClose
(
   JNIEnv *env,
   jclass unused,
   /*in*/   jint     handle
)
{
   nint32 cCode = 0;
   
   #ifdef N_PLAT_NLM
   if(!close((int)handle))   
   {
      cCode = 0;
   }
   else
   {
      cCode = errno;
      if(0 == cCode)
         cCode = __get_NWErrno();
      if(0 == cCode)
         cCode = shouldNeverGetHereError;
   }
   return cCode;

   #else
   if(CloseHandle((HANDLE)handle))
   {
      cCode = 0;
   }
   else
   {
      cCode = GetLastError();
      if(0 == cCode)
         cCode = shouldNeverGetHereError;
   }
   return cCode;
   #endif

} /* JDAClose () */


/*
 * Class:     com_novell_service_jncpv2r_cal_DeviceAccessJNI
 * Method:    JDAFlush
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_DeviceAccessJNI_JDAFlush
(
   JNIEnv *env,
   jclass unused,
   /*in*/   jint     handle
)
{
   nint32 cCode = 0;

   #if defined (N_PLAT_MSW) && defined (N_ARCH_32)
   if(!FlushFileBuffers((HANDLE)handle))
   {
      cCode = GetLastError();
      if(0 == cCode)
         cCode = shouldNeverGetHereError;
   }
   
   #elif defined (N_PLAT_NLM)
   #endif

   return cCode;
} /* JDAFlush () */

/*
 * Class:     com_novell_service_jncpv2r_cal_DeviceAccessJNI
 * Method:    JDAGetLength
 * Signature: (I[I)I
 */
JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_DeviceAccessJNI_JDAGetLength
(
   JNIEnv *env,
   jclass unused,
   /*in*/   jint        handle,
   /*out*/  jintArray   length
)
{
   nint32 cLength;

   if (-1 != (cLength = xFileGetLength (handle)))
   {
      (*env)->SetIntArrayRegion (env, length, 0, 1, (jint *) &cLength);
      return (N_SUCCESS);
   }
   return (N_FAILURE);

} /* JDAGetLength () */

/*
 * Class:     com_novell_service_jncpv2r_cal_DeviceAccessJNI
 * Method:    JDASetLength
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_DeviceAccessJNI_JDASetLength
(
   JNIEnv *env,
   jclass unused,
   /*in*/   jint     handle,
   /*in*/   jint     length
)
{
   return (xFileSetLength (handle, length));
}

/*
 * Class:     com_novell_service_jncpv2r_cal_DeviceAccessJNI
 * Method:    JDAGetPosition
 * Signature: (I[I)I
 */
JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_DeviceAccessJNI_JDAGetPosition
(
   JNIEnv *env,
   jclass unused,
   /*in*/   jint        handle,
   /*out*/  jintArray   position
)
{
   nint32 cPosition;

   if (-1 != (cPosition = xFileGetPosition (handle)))
   {
      (*env)->SetIntArrayRegion (env, position, 0, 1, (jint *) &cPosition);
     return (N_SUCCESS);
   }
   return (N_FAILURE);

} /* JDAGetPosition () */

/*
 * Class:     com_novell_service_jncpv2r_cal_DeviceAccessJNI
 * Method:    JDASetPosition
 * Signature: (III)I
 */
JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_DeviceAccessJNI_JDASetPosition
(
   JNIEnv *env,
   jclass unused,
   /*in*/   jint     handle,
   /*in*/   jint     mode,
   /*in*/   jint     position
)
{
   if (-1 != xFileSetPosition (handle, position, mode))
   {
      return (N_SUCCESS);
   }
   return (N_FAILURE);

} /* JDASetPosition () */

/*
 * Class:     com_novell_service_jncpv2r_cal_DeviceAccessJNI
 * Method:    JDARead
 * Signature: (II[[B)I
 */
JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_DeviceAccessJNI_JDARead
(
   JNIEnv *env,
   jclass unused,
   /*in*/   jint           handle,
   /*in*/   jint           length,
   /*out*/  jobjectArray   buffer
)
{
   nint32 cCode;
   nptr cPtr, cRealPtr;
   nint32 cActualLength;

   // allocate input array
   if(NULL == (cRealPtr = cPtr = sysMalloc ((size_t) length)))
   {
      cCode = noMemoryAvailable;
      goto EXIT;
   }

   #ifdef N_PLAT_NLM
   if (_usingAliasFunctions)
      cRealPtr = (nptr)(*_aliasFunctions[0])((nptr) cPtr, (size_t) length);
   if (NULL == cRealPtr)
   {
      cCode = noMemoryAvailable;
      goto FREE;
   }
   if( (cActualLength = read(handle, cRealPtr, length)) == -1)
   {
      cCode = errno;
      if(0 == cCode)
         cCode = __get_NWErrno();
      if(0 == cCode)
         cCode = shouldNeverGetHereError;
   }
   else
      cCode = 0;

   #else

   if(!ReadFile((HANDLE)handle, cRealPtr, length, &cActualLength, NULL))
   {
      cCode = GetLastError();
      if(0 == cCode)
         cCode = shouldNeverGetHereError;
   }
   else
      cCode = 0;
   #endif

   if(0 == cCode)
   {
      // JNI variables
      jbyteArray byteArray;

      // allocate return byte[]
      if(NULL == (byteArray = (*env)->NewByteArray (env, cActualLength)))
      {
         cCode = noMemoryAvailable;
         goto CLEANUP;
      }
      // copy buffer to byte[]
      (*env)->SetByteArrayRegion(
         env, byteArray, 0, cActualLength, (jbyte*)cRealPtr);
      (*env)->SetObjectArrayElement (env, buffer, 0, byteArray);
   }

   CLEANUP:

   #ifdef N_PLAT_NLM
   if (_usingAliasFunctions)
      (*_aliasFunctions[1])((nptr) cRealPtr, (size_t) length);

   FREE:
   #endif

   // free temporary buffer
   sysFree (cPtr);

   EXIT:
   return (cCode);
} /* JDARead () */

/*
 * Class:     com_novell_service_jncpv2r_cal_DeviceAccessJNI
 * Method:    JDAWrite
 * Signature: (I[B)I
 */
JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_DeviceAccessJNI_JDAWrite
(
   JNIEnv *env,
   jclass unused,
   /*in*/   jint           handle,
   /*in*/   jbyteArray     buffer
)
{
   // JNI variables
   jbyte *ptr;
   jsize length;
   // NWNet variables
   nint32 cCode;
   nint32 cActualLength;

   ptr = (*env)->GetByteArrayElements (env, buffer, NULL);
   length = (*env)->GetArrayLength (env, buffer);

   #ifdef N_PLAT_NLM
   if( (cActualLength = write((int)handle, (char *)ptr, (size_t)length)) != length)
   {
      cCode = errno;
      if(0 == cCode)
         cCode = __get_NWErrno();
      if(0 == cCode)
         cCode = shouldNeverGetHereError;
   }
   else
      cCode = 0;

   #else

   if(!WriteFile((HANDLE)handle, (char *)ptr, (DWORD)length, &cActualLength, NULL))
   {
      cCode = GetLastError();
      if(0 == cCode)
         cCode = shouldNeverGetHereError;
   }
   else
   {
      cCode = 0;
      
      /* This doc is confusing about this case. I will set this to an
         explicit error for now. I dont think this will ever occur */
      if(cActualLength != length) 
         cCode = shouldNeverGetHereError2;
   }
   #endif

   (*env)->ReleaseByteArrayElements (env, buffer, ptr, 0);
   return cCode;
} /* JDAWrite () */

