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

  %name: fileJNI.c %
  %version: 22 %
  %date_modified: Mon Feb 23 21:10:59 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 "com_novell_service_jncpv2r_cal_CalJNI.h"

#include <sys_api.h>

#include <nwbindry.h>
#include <nwdirect.h>
#include <nwnamspc.h>
#include <nwdentry.h>
#include <nwvol.h>
#include <nwnamspc.h>
#include <nwfile.h>
#include <nwdel.h>
#include <nwerror.h>
#include <nwea.h>
#include <nwsm.h>
#include <nwsync.h>
#include <nwmisc.h>

#include <nwlocale.h>
#include <assert.h>
#include <string.h>

#include "jncp.h"
#include "JNIString.h"

/*
 * For the file system natives, we have to call a special unicode
 * translation function to handle translation of the backslash character
 * as a path separator, not a unicode backslash.  Most of the calls
 * below that translate unicodes->bytes use __UnicodePathToLocalStr()
 * to accomplish this special translation.
 */

#define __jncpv2r_MAX_PATH_LENGTH 257

/*
 * Takes a composite path, which must contain some leaf entry, and
 * allocates a dir handle for the container and copies the atomic entry
 * into the 'atomicEntry' parameter.  The dir handle will be in the
 * destination name space that is specified.
 *
 * Example: "VOL:FILE.TXT" is the smallest valid path -- there must
 *   be an atomic entry of some sort.
 *
 * Example: "VOL:" is not a valid path because there is no atomic entry.
 *
 * It is all right to have 'path' and 'atomicEntry' be the same location
 * in memory -- no overlapping problems will occur.
 *
 * Passing NULL for 'newDirHandle' means do not try to allocate a directory
 * handle, just separate the names like you were going to.
 *
 * Passing -1 for the destination name space will allocate the dir handle
 * in the name space of the path passed in.
 */

NWRCODE
__AllocTempNSContainerDirHandle2
(
   NWCONN_HANDLE connHandle,
   nuint8 dirHandle,
   pnstr path,
   nuint8 nameSpace,
   NWDIR_HANDLE *newDirHandle,
   nuint8 destNameSpace,
   pnstr atomicEntry
)
{
   NWRCODE ccode;
   nstr working;
   pnstr srchPattern;

   /*...cut off last portion of path...*/
   srchPattern = &path[NWstrlen (path)];

   working = NWCharVal (srchPattern);

   while((srchPattern != path) &&
         (working != '\\') &&
         (working != '/') &&
         (working != ':'))
   {
      srchPattern = NWPrevChar ((const pnstr) path, srchPattern);
      working = NWCharVal (srchPattern);
   }

   if (srchPattern != path)  // if atomic entry was found
   {
      nstr containerStr[__jncpv2r_MAX_PATH_LENGTH];
      nstr atomicPattern[__jncpv2r_MAX_PATH_LENGTH];
      int bytesToCopy = srchPattern - path;

      // copy all chars up to but not including the separator char
      memcpy (containerStr, path, bytesToCopy);
      containerStr[bytesToCopy] = 0;   // make sure its null terminated
      containerStr[bytesToCopy+1] = 0;

      srchPattern = NWNextChar (srchPattern);
      NWLstrbcpy (atomicPattern, srchPattern, sizeof (atomicPattern));

      if (newDirHandle != NULL)
      {
         nuint8 nameSpaceHolder;

         if (destNameSpace == 0xFF)
            nameSpaceHolder = nameSpace;
         else
            nameSpaceHolder = destNameSpace;

         ccode = NWAllocTempNSDirHandle2 (
               (NWCONN_HANDLE) connHandle,
               (NWDIR_HANDLE) dirHandle,
               containerStr,
               nameSpace,
               newDirHandle,
               nameSpaceHolder);

         if (ccode != 0)
            return ((jint) ccode);
      }

      NWLstrbcpy (atomicEntry, atomicPattern, sizeof (atomicPattern));

      return (0);
   }

   return (INVALID_PATH);
}


/*
 * Takes a composite path, which must contain some leaf entry, and
 * allocates a dir handle for the container and copies the atomic entry
 * into the 'atomicEntry' parameter.
 *
 * Example: "VOL:FILE.TXT" is the smallest valid path -- there must
 *   be an atomic entry of some sort.
 *
 * Example: "VOL:" is not a valid path because there is no atomic entry.
 *
 * It is all right to have 'path' and 'atomicEntry' be the same location
 * in memory -- no overlapping problems will occur.
 *
 * Passing NULL for 'newDirHandle' means do not try to allocate a directory
 * handle, just separate the names like you were going to.
 */

NWRCODE
__AllocTempNSContainerDirHandle
(
   NWCONN_HANDLE connHandle,
   nuint8 dirHandle,
   pnstr path,
   nuint8 nameSpace,
   NWDIR_HANDLE *newDirHandle,
   pnstr atomicEntry
)
{
   return (__AllocTempNSContainerDirHandle2(connHandle, dirHandle, path,
         nameSpace, newDirHandle, 0xFF, atomicEntry));
}


/*
 * Retrieves the full dir entry name (no dir handle) in the specified name
 * space.  This is to accomodate calling functions which require the dir
 * entry name to be in the name space specified, when you have a dir entry
 * name in a specific name space.
 *
 * Required: a full dir entry name in a specific name space
 *           the name space number in which the dir entry name is in
 *           the name space to return the path in
 *
 * Returned: the full dir entry name in the specified name space
 *
 * 'srcPath' and 'dstPath' must be separate char arrays.
 */

NWRCODE
__GetNSPath
(
   NWCONN_HANDLE connHandle,
   NWDIR_HANDLE dirHandle,
   pnstr srcPath,
   nuint8 srcNameSpace,
   pnstr dstPath,
   nuint8 dstNameSpace
)
{
   if (srcNameSpace == dstNameSpace)
      NWstrncpy (dstPath, srcPath, NWLmbslen (srcPath) + 1);
   else
   {
      NWRCODE ccode;
      NW_ENTRY_INFO info;
      int fileFlag;
      char buf[2048];
      NW_NS_PATH pathStruct;

      ccode = NWGetNSEntryInfo (
            connHandle,
            dirHandle,
            srcPath,
            srcNameSpace,
            dstNameSpace,
            0xFB, // search all entries
            IM_ENTRY_NAME | IM_ATTRIBUTES,
            &info);

      if (ccode != 0)
         return ((jint) ccode);

      if (info.attributes & 0x10)
         fileFlag = 0;
      else
         fileFlag = 1;

      pathStruct.srcPath = srcPath;
      pathStruct.dstPath = buf;

      pathStruct.dstPathSize = sizeof (buf);

      ccode = NWGetNSPath (
            connHandle,
            dirHandle,
            (nuint16) fileFlag,
            srcNameSpace,
            dstNameSpace,
            &pathStruct);

      if (ccode != 0)
         return ((jint) ccode);

      if(fileFlag)
         NWsprintf  (dstPath, "%s\\%s", buf, info.entryName);
      else
         NWLstrbcpy (dstPath, buf, __jncpv2r_MAX_PATH_LENGTH);
   }

   return ((NWRCODE) 0);
}


/*
 * Retrieves the full dir entry name (no dir handle) in the "default" name
 * space -- see __NWGetCurNS().  This is to accomodate calling functions
 * which require the dir entry name to be in the "default" name space,
 * but you have a dir entry name in a specific name space.
 *
 * Required: a full dir entry name in a specific name space
 *           the name space number in which the dir entry name is in
 *
 * Returned: the full dir entry name in the "default" name space
 *
 * Example: "VOL:users\jsumsion" in NS 4 would return "VOL:users\jsumsion"
 *          on a Win95 box, but "VOL:USERS\JSUMSION" on a DOS or NetWare
 *          machine.
 *
 * 'srcPath' and 'dstPath' must be separate char arrays.
 */

NWRCODE
__GetDefaultNSPath
(
   NWCONN_HANDLE connHandle,
   NWDIR_HANDLE dirHandle,
   pnstr srcPath,
   nuint8 srcNameSpace,
   pnstr dstPath
)
{
   nuint8 dstNameSpace;

   dstNameSpace = (nuint8) __NWGetCurNS (connHandle, dirHandle, srcPath);

   return (__GetNSPath(connHandle, dirHandle, srcPath, srcNameSpace,
         dstPath, dstNameSpace));
}


/*
 * The NWGetMiscInfo API does not allow you to specify a dirhandle/path in an
 * arbitrary name space, which is what we need.  Thus, this is a rewrite
 * of NWGetMiscInfo that allows specification of the name space.
 *
 * Result: the NW_IDX struct gets filled like this:
 *   volNumber = the volume number where the dir entry resides
 *   srcNameSpace = the name space you pass in
 *   dstNameSpace = the dst name space you pass in
 *   srcDirBase = the dir. entry number of the DOS dir. entry
 *   dstDirBase = the dir. entry number of the dir. entry in 'dstNameSpace'
 */

NWRCODE
__FillIDXStruct
(
   NWCONN_HANDLE connHandle,
   NWDIR_HANDLE dirHandle,
   pnstr path,
   nuint8 srcNameSpace,
   nuint8 dstNameSpace,
   NW_IDX *idx
)
{
   NWRCODE ccode;
   NW_ENTRY_INFO entryInfo;

   ccode = NWGetNSEntryInfo (
         connHandle,
         dirHandle,
         path,
         (nuint8) srcNameSpace,
         (nuint8) dstNameSpace,
         (nuint16) 0xFB,
         IM_DIRECTORY,
         &entryInfo);

   if (ccode != 0)
      return ((jint) ccode);

   idx->volNumber = (nuint8) entryInfo.volNumber;
   idx->srcNameSpace = srcNameSpace;
   idx->dstNameSpace = dstNameSpace;
   idx->srcDirBase = entryInfo.DosDirNum;
   idx->dstDirBase = entryInfo.dirEntNum;

   return ((NWRCODE) 0);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWGetNSEntryInfo
(
   JNIEnv   *env,
   jclass   unused,
   jint     connHandle,
   jint     dirHandle,
   jstring  path,
   jint     srcNamSpc,
   jint     dstNamSpc,
   jint     attributes,
   jint     mask,
   jobject  info
)
{
   NWRCODE ccode;
   NW_ENTRY_INFO entryInfo;
   nstr8 pathStr[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniPathStr;

   uniPathStr = (punicode) (*env)->GetStringChars (env, path, NULL);

   ccode = __UnicodePathToLocalStr (
         pathStr,
         sizeof (pathStr),
         uniPathStr,
         (*env)->GetStringLength (env, path));

   if (ccode != 0)
      goto EXIT;

   ccode = NWGetNSEntryInfo (
         (NWCONN_HANDLE) connHandle,
         (nuint8) dirHandle,
         pathStr,
         (nuint8) srcNamSpc,
         (nuint8) dstNamSpc,
         (nuint16) attributes,
         (nuint32) mask,
         &entryInfo);

   if (ccode == 0)
   {
      jclass clazz;
      jfieldID fid;
      jstring name;
      unicode uniEntryNameStr[sizeof (pathStr)];

      clazz = (*env)->GetObjectClass (env, info);

      fid = (*env)->GetFieldID (env, clazz, "spaceAlloc", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.spaceAlloc);

      fid = (*env)->GetFieldID (env, clazz, "attributes", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.attributes);

      fid = (*env)->GetFieldID (env, clazz, "flags", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.flags);

      fid = (*env)->GetFieldID (env, clazz, "dataStreamSize", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.dataStreamSize);

      fid = (*env)->GetFieldID (env, clazz, "totalStreamSize", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.totalStreamSize);

      fid = (*env)->GetFieldID (env, clazz, "numberOfStreams", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.numberOfStreams);

      fid = (*env)->GetFieldID (env, clazz, "creationTime", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.creationTime);

      fid = (*env)->GetFieldID (env, clazz, "creationDate", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.creationDate);

      fid = (*env)->GetFieldID (env, clazz, "creatorID", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.creatorID);

      fid = (*env)->GetFieldID (env, clazz, "modifyTime", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.modifyTime);

      fid = (*env)->GetFieldID (env, clazz, "modifyDate", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.modifyDate);

      fid = (*env)->GetFieldID (env, clazz, "modifierID", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.modifierID);

      fid = (*env)->GetFieldID (env, clazz, "lastAccessDate", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.lastAccessDate);

      fid = (*env)->GetFieldID (env, clazz, "archiveTime", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.archiveTime);

      fid = (*env)->GetFieldID (env, clazz, "archiveDate", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.archiveDate);

      fid = (*env)->GetFieldID (env, clazz, "archiverID", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.archiverID);

      fid = (*env)->GetFieldID (env, clazz, "inheritedRightsMask", "I");
      (*env)->SetIntField (env, info, fid,
            (jint) entryInfo.inheritedRightsMask);

      fid = (*env)->GetFieldID (env, clazz, "dirEntNum", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.dirEntNum);

      fid = (*env)->GetFieldID (env, clazz, "DosDirNum", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.DosDirNum);

      fid = (*env)->GetFieldID (env, clazz, "volNumber", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.volNumber);

      fid = (*env)->GetFieldID (env, clazz, "EADataSize", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.EADataSize);

      fid = (*env)->GetFieldID (env, clazz, "EAKeyCount", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.EAKeyCount);

      fid = (*env)->GetFieldID (env, clazz, "EAKeySize", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.EAKeySize);

      fid = (*env)->GetFieldID (env, clazz, "NSCreator", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.NSCreator);

      fid = (*env)->GetFieldID (env, clazz, "nameLength", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.nameLength);

      // in order to guarantee null termination of the entry name, we have
      //   to copy the name to another, bigger buffer, and physically do it
      // we'll reuse pathStr -- it isn't used any more

      memcpy (pathStr, entryInfo.entryName, entryInfo.nameLength);
      pathStr[entryInfo.nameLength] = '\0';

      ccode = __LocalToJavaStr (
            env,
            &name,
            uniEntryNameStr,
            pathStr);   // we're reusing pathStr as a buffer for null-term.

      if (ccode == -1)
         goto HARD_EXIT;

      if (ccode == 0)
      {
         fid = (*env)->GetFieldID(env,clazz, "entryName",
               "Ljava/lang/String;");

         (*env)->SetObjectField (env, info, fid, name);
      }
   }

EXIT:

   (*env)->ReleaseStringChars (env, path, uniPathStr);

HARD_EXIT:

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWScanNSEntryInfo
(
   JNIEnv     *env,
   jclass     unused,
   jint       connHandle,
   jint       dirHandle,
   jint       nameSpace,
   jint       attr,
   jintArray  volNumber,
   jintArray  dirNumber,
   jintArray  searchDirNumber,
   jstring    pattern,
   jint       retInfoMask,
   jobject    info
)
{
   NWRCODE ccode;
   NW_ENTRY_INFO entryInfo;
   SEARCH_SEQUENCE searchSequence;
   nstr8 patternStr[__jncpv2r_MAX_PATH_LENGTH + 3];
   punicode uniPatternStr;
   NWDIR_HANDLE tmpDirHandle = 0;
   jint *volNumberArr, *dirNumberArr, *searchDirNumberArr;
   jint searchDirNumberHolder;
   int firstScan;

   (*env)->GetIntArrayRegion (env, searchDirNumber, 0, 1,
         &searchDirNumberHolder);

   firstScan = (searchDirNumberHolder == -1);

   uniPatternStr = (punicode) (*env)->GetStringChars(env, pattern, NULL);

   ccode = __UnicodePathToLocalStr (
         patternStr,
         sizeof (patternStr),
         uniPatternStr,
         (*env)->GetStringLength (env, pattern));

   if (ccode != 0)
      goto EXIT;

   ccode = __AllocTempNSContainerDirHandle (
         connHandle,
         (nuint8) dirHandle,
         patternStr,
         (nuint8) nameSpace,
         firstScan ? &tmpDirHandle : NULL,   // passing NULL means no alloc
         patternStr);

   // if patternStr was composite coming in, now it's not

   if (ccode != 0)
      goto EXIT;

   if (firstScan)
      dirHandle = tmpDirHandle;

   // after this point, use the RELEASE_ARRAYS label at end of function to
   //   return ccode, so that the arrays are guaranteed to be released

   volNumberArr = (*env)->GetIntArrayElements (env, volNumber, 0);
   searchSequence.volNumber = (nuint8) volNumberArr[0];

   dirNumberArr = (*env)->GetIntArrayElements (env, dirNumber, 0);
   searchSequence.dirNumber = (nuint32) dirNumberArr[0];

   searchDirNumberArr = (*env)->GetIntArrayElements(env, searchDirNumber, 0);
   searchSequence.searchDirNumber = (nuint32) searchDirNumberArr[0];

   ccode = NWScanNSEntryInfo (
         (NWCONN_HANDLE) connHandle,
         (nuint8) dirHandle,
         (nuint8) nameSpace,
         (nuint16) attr,
         &searchSequence,
         patternStr,
         (nuint32) retInfoMask,
         &entryInfo);

   if (firstScan)
   {
      if (tmpDirHandle != 0)
      {
         NWRCODE ccode2;

         ccode2 = NWDeallocateDirectoryHandle (
               (NWCONN_HANDLE) connHandle,
               tmpDirHandle);

         if (ccode == 0 && ccode2 != 0)
         {
            ccode = ccode2;
            goto RELEASE_ARRAYS;
         }
      }
   }

   if (ccode == 0)
   {
      jclass clazz;
      jfieldID fid;
      jstring name;
      unicode uniEntryNameStr[sizeof (patternStr)];

      // pass the data back to java

      volNumberArr[0] = (jint) searchSequence.volNumber;
      dirNumberArr[0] = (jint) searchSequence.dirNumber;
      searchDirNumberArr[0] = (jint) searchSequence.searchDirNumber;

      clazz = (*env)->GetObjectClass(env, info);

      fid = (*env)->GetFieldID (env, clazz, "spaceAlloc", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.spaceAlloc);

      fid = (*env)->GetFieldID (env, clazz, "attributes", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.attributes);

      fid = (*env)->GetFieldID (env, clazz, "flags", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.flags);

      fid = (*env)->GetFieldID (env, clazz, "dataStreamSize", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.dataStreamSize);

      fid = (*env)->GetFieldID (env, clazz, "totalStreamSize", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.totalStreamSize);

      fid = (*env)->GetFieldID (env, clazz, "numberOfStreams", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.numberOfStreams);

      fid = (*env)->GetFieldID (env, clazz, "creationTime", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.creationTime);

      fid = (*env)->GetFieldID (env, clazz, "creationDate", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.creationDate);

      fid = (*env)->GetFieldID (env, clazz, "creatorID", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.creatorID);

      fid = (*env)->GetFieldID (env, clazz, "modifyTime", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.modifyTime);

      fid = (*env)->GetFieldID (env, clazz, "modifyDate", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.modifyDate);

      fid = (*env)->GetFieldID (env, clazz, "modifierID", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.modifierID);

      fid = (*env)->GetFieldID (env, clazz, "lastAccessDate", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.lastAccessDate);

      fid = (*env)->GetFieldID (env, clazz, "archiveTime", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.archiveTime);

      fid = (*env)->GetFieldID (env, clazz, "archiveDate", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.archiveDate);

      fid = (*env)->GetFieldID (env, clazz, "archiverID", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.archiverID);

      fid = (*env)->GetFieldID (env, clazz, "inheritedRightsMask", "I");
      (*env)->SetIntField (env, info, fid,
            (jint) entryInfo.inheritedRightsMask);

      fid = (*env)->GetFieldID (env, clazz, "dirEntNum", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.dirEntNum);

      fid = (*env)->GetFieldID (env, clazz, "DosDirNum", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.DosDirNum);

      fid = (*env)->GetFieldID (env, clazz, "volNumber", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.volNumber);

      fid = (*env)->GetFieldID (env, clazz, "EADataSize", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.EADataSize);

      fid = (*env)->GetFieldID (env, clazz, "EAKeyCount", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.EAKeyCount);

      fid = (*env)->GetFieldID (env, clazz, "EAKeySize", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.EAKeySize);

      fid = (*env)->GetFieldID (env, clazz, "NSCreator", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.NSCreator);

      fid = (*env)->GetFieldID (env, clazz, "nameLength", "I");
      (*env)->SetIntField (env, info, fid, (jint) entryInfo.nameLength);

      // in order to guarantee null termination of the entry name, we have
      //   to copy the name to another, bigger buffer, and physically do it
      // we'll reuse patternStr -- it isn't used any more

      memcpy (patternStr, entryInfo.entryName, entryInfo.nameLength);
      patternStr[entryInfo.nameLength] = '\0';

      ccode = __LocalToJavaStr (
            env,
            &name,
            uniEntryNameStr,
            patternStr);   // reuse patternStr as a buffer for null-term.

      if (ccode == -1)
         goto HARD_EXIT;

      if (ccode == 0)
      {
         fid = (*env)->GetFieldID (env, clazz, "entryName",
               "Ljava/lang/String;");

         (*env)->SetObjectField (env, info, fid, name);
      }
   }

RELEASE_ARRAYS:

   (*env)->ReleaseIntArrayElements (env, volNumber, volNumberArr, 0);
   (*env)->ReleaseIntArrayElements (env, dirNumber, dirNumberArr, 0);
   (*env)->ReleaseIntArrayElements (env, searchDirNumber,
         searchDirNumberArr, 0);

EXIT:

   (*env)->ReleaseStringChars (env, pattern, uniPatternStr);

HARD_EXIT:

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWGetVolumeName
(
   JNIEnv       *env,
   jclass       unused,
   jint         connHandle,
   jint         volNumber,
   jobjectArray volName
)
{
   NWRCODE ccode;
   nstr8 volNameStr[17];

   ccode = NWGetVolumeName (
               (NWCONN_HANDLE) connHandle,
               (nuint16) volNumber,
               volNameStr);

   if (ccode == 0)
   {
      jstring jVolName;
      unicode uniVolNameStr[sizeof (volNameStr)];

      ccode = __LocalToJavaStr (
            env,
            &jVolName,
            uniVolNameStr,
            volNameStr);      // null-terminated coming back from NW call

      if (ccode == 0)
         (*env)->SetObjectArrayElement (env, volName, 0, jVolName);
   }

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWGetVolumeNumber
(
   JNIEnv      *env,
   jclass      unused,
   jint        connHandle,
   jstring     volumeName,
   jintArray   volumeNumber
)
{
   NWRCODE ccode;
   nstr8 volNameStr[17];
   nuint16 suVolNum;
   punicode uniVolNameStr;

   uniVolNameStr = (punicode) (*env)->GetStringChars (env, volumeName, NULL);

   /* do NOT call __UnicodePathToLocalStr() here because this is not
      a string that should treat the backslash special */

   ccode = __UnicodeToLocalStr (
         volNameStr,
         sizeof (volNameStr),
         uniVolNameStr,
         (*env)->GetStringLength (env, volumeName));

   if (ccode != 0)
      goto EXIT;

   ccode = NWGetVolumeNumber (
         (NWCONN_HANDLE) connHandle,
         volNameStr,
         &suVolNum);

   if (ccode == 0)
   {
      jint temp = (jint) suVolNum;

      (*env)->SetIntArrayRegion (env, volumeNumber, 0, 1, &temp);
   }

EXIT:

   (*env)->ReleaseStringChars (env, volumeName, uniVolNameStr);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWGetNSLoadedList
(
   JNIEnv         *env,
   jclass         unused,
   jint           connHandle,
   jint           volNumber,
   jobjectArray   NSLoadedList
)
{
   NWRCODE ccode;
   nuint8 abuNSLoadedArr[30]; // high
   nuint8 buActualNSCount;

   ccode = NWGetNSLoadedList (
         (NWCONN_HANDLE) connHandle,
         (nuint8) volNumber,
         (nuint8) sizeof (abuNSLoadedArr),
         abuNSLoadedArr,
         &buActualNSCount);

   if (ccode == 0)
   {
      jintArray javaNSList;
      jint *body;
      int i;

      javaNSList = (*env)->NewIntArray(env, buActualNSCount);

      if (javaNSList == NULL)
      {
         __ThrowException (env, JAVAPKG "OutOfMemoryError", "JNI");
         return (-1);
      }

      body = (*env)->GetIntArrayElements (env, javaNSList, NULL);

      // store all name space numers in the allocated array
      for (i = 0; i < buActualNSCount; i++)
         body[i] = (jint) abuNSLoadedArr[i];

      (*env)->ReleaseIntArrayElements (env, javaNSList, body, 0);

      // put the newly built java array into NSLoadedList
      (*env)->SetObjectArrayElement (env, NSLoadedList, 0, javaNSList);
   }

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWOpenCreateNSEntry
(
   JNIEnv      *env,
   jclass      unused,
   jint        connHandle,
   jint        dirHandle,
   jstring     path,
   jint        nameSpace,
   jint        openCreateMode,
   jint        searchAttributes,
   jint        createAttributes,
   jint        accessRights,
   jintArray   fileHandle
)
{
   NW_NS_OPENCREATE openStruct;
   NWFILE_HANDLE nativeFileHandle;
   NWCCODE ccode;
   nstr8 pathStr[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniPathStr;

   uniPathStr = (punicode) (*env)->GetStringChars (env, path, NULL);

   ccode = __UnicodePathToLocalStr (
         pathStr,
         sizeof (pathStr),
         uniPathStr,
         (*env)->GetStringLength (env, path));

   if (ccode != 0)
      goto EXIT;

   openStruct.openCreateMode     = (nuint8)  openCreateMode;
   openStruct.searchAttributes   = (nuint16) searchAttributes;
   openStruct.reserved           = 0;
   openStruct.createAttributes   = (nuint32) createAttributes;
   openStruct.accessRights       = (nuint16) accessRights;

   ccode = NWOpenCreateNSEntry (
         (NWCONN_HANDLE) connHandle,
         (nuint8) dirHandle,
         (nuint8) nameSpace, // name space in which to create file
         pathStr,
         &openStruct,
         &nativeFileHandle);

   if (ccode == 0)
   {
      jint temp = (jint) nativeFileHandle;

      (*env)->SetIntArrayRegion(env, fileHandle, 0, 1, &temp);
   }

EXIT:

   (*env)->ReleaseStringChars (env, path, uniPathStr);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWOpenNSEntry
(
   JNIEnv      *env,
   jclass      unused,
   jint        connHandle,
   jint        dirHandle,
   jint        nameSpace,
   jint        dataStream,
   jstring     path,
   jint        openCreateMode,
   jint        searchAttributes,
   jint        createAttributes,
   jint        accessRights,
   jintArray   fileHandle
)
{
   NW_NS_OPENCREATE openStruct;
   NWFILE_HANDLE nativeFileHandle;
   NWCCODE ccode;
   nstr8 pathStr[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniPathStr;

   uniPathStr = (punicode) (*env)->GetStringChars (env, path, NULL);

   ccode = __UnicodePathToLocalStr (
         pathStr,
         sizeof (pathStr),
         uniPathStr,
         (*env)->GetStringLength (env, path));

   if (ccode != 0)
      goto EXIT;

   openStruct.openCreateMode     = (nuint8)  openCreateMode;
   openStruct.searchAttributes   = (nuint16) searchAttributes;
   openStruct.reserved           = 0;
   openStruct.createAttributes   = (nuint32) createAttributes;
   openStruct.accessRights       = (nuint16) accessRights;

   ccode = NWOpenNSEntry (
         (NWCONN_HANDLE) connHandle,
         (nuint8) dirHandle,
         (nuint8) nameSpace,  // name space in which to create file
         (nuint8) dataStream, // data stream to open
         pathStr,
         &openStruct,
         &nativeFileHandle);

   if (ccode == 0)
   {
      jint temp = (jint) nativeFileHandle;

      (*env)->SetIntArrayRegion(env, fileHandle, 0, 1, &temp);
   }

EXIT:

   (*env)->ReleaseStringChars (env, path, uniPathStr);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWDeleteNSEntry
(
   JNIEnv   *env,
   jclass   unused,
   jint     connHandle,
   jint     dirHandle,
   jstring  path,
   jint     nameSpace,
   jint     searchAttr
)
{
   NWRCODE ccode;
   nstr8 pathStr[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniPathStr;

   uniPathStr = (punicode) (*env)->GetStringChars (env, path, NULL);

   ccode = __UnicodePathToLocalStr (
         pathStr,
         sizeof (pathStr),
         uniPathStr,
         (*env)->GetStringLength (env, path));

   if (ccode != 0)
      goto EXIT;

   ccode = NWDeleteNSEntry (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         pathStr,
         (nuint8) nameSpace,
         (nuint16) searchAttr);

EXIT:

   (*env)->ReleaseStringChars (env, path, uniPathStr);

   return ((jint) ccode);
}


//
// only works when the dir handle coming in is zero (0)
//
JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWNSRename
(
   JNIEnv   *env,
   jclass   unused,
   jint     connHandle,
   jint     dirHandle,
   jint     nameSpace,
   jstring  oldName,
   jboolean isFile,
   jstring  newName,
   jboolean renameInAllNS
)
{
   NWRCODE ccode;
   nuint16 suEntryType;
   nuint8  buRenameFlag;
   NWDIR_HANDLE tmpDirHandle = 0;
   nstr8 oldNameStr[__jncpv2r_MAX_PATH_LENGTH];
   nstr8 newNameStr[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniOldNameStr, uniNewNameStr;

   uniOldNameStr = (punicode) (*env)->GetStringChars (env, oldName, NULL);
   uniNewNameStr = (punicode) (*env)->GetStringChars (env, newName, NULL);

   ccode = __UnicodePathToLocalStr (
         oldNameStr,
         sizeof (oldNameStr),
         uniOldNameStr,
         (*env)->GetStringLength (env, oldName));

   if (ccode != 0)
      goto EXIT;

   ccode = __UnicodePathToLocalStr (
         newNameStr,
         sizeof (newNameStr),
         uniNewNameStr,
         (*env)->GetStringLength (env, newName));

   if (ccode != 0)
      goto EXIT;

   if (dirHandle == 0)
   {
      ccode = __AllocTempNSContainerDirHandle (
            connHandle,
            (nuint8) dirHandle,
            oldNameStr,
            (nuint8) nameSpace,
            &tmpDirHandle,
            oldNameStr);

      if (ccode != 0)
         goto EXIT;

      dirHandle = tmpDirHandle;
   }

   if (isFile)
      suEntryType = 0x0800;   // flag for files
   else
      suEntryType = 0x0010;   // flag for directories

   if (renameInAllNS)
      buRenameFlag = 0x03;    // entry will be renamed in all name spaces
   else
      buRenameFlag = 0x04;    // entry will be renamed only in current NS

   ccode = NWNSRename (
         (NWCONN_HANDLE) connHandle,
         (nuint8) dirHandle,
         (nuint8) nameSpace,
         oldNameStr,
         suEntryType,
         newNameStr,
         buRenameFlag);

   if (tmpDirHandle != 0)
   {
      NWRCODE ccode2;

      ccode2 = NWDeallocateDirectoryHandle (
                  (NWCONN_HANDLE) connHandle,
                  tmpDirHandle);

      if (ccode == 0 && ccode2 != 0)
      {
         ccode = ccode2;
         goto EXIT;
      }
   }


EXIT:

   (*env)->ReleaseStringChars (env, oldName, uniOldNameStr);
   (*env)->ReleaseStringChars (env, newName, uniNewNameStr);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_allocEAHandle
(
   JNIEnv *env,
   jclass unused
)
{
   return ((jint) sysMalloc (sizeof (NW_EA_HANDLE)));
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_allocEAFFStruct
(
   JNIEnv *env,
   jclass unused
)
{
   return ((jint) sysMalloc (sizeof (NW_EA_FF_STRUCT)));
}

JNIEXPORT void JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_freePtr
(
   JNIEnv   *env,
   jclass   unused,
   jint     mallocedPtr
)
{
   sysFree ((void *) mallocedPtr);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWOpenEA
(
   JNIEnv   *env,
   jclass   unused,
   jint     connHandle,
   jint     dirHandle,
   jstring  path,
   jstring  EAName,
   jint     nameSpace,
   jint     EAHandle
)
{
   NWRCODE ccode;
   NW_EA_HANDLE *EAHandlePtr;
   nstr8 pathStr[__jncpv2r_MAX_PATH_LENGTH];
   nstr8 EANameStr[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniPathStr, uniEANameStr;

   uniPathStr = (punicode) (*env)->GetStringChars (env, path, NULL);
   uniEANameStr = (punicode) (*env)->GetStringChars (env, EAName, NULL);

   ccode = __UnicodePathToLocalStr (
         pathStr,
         sizeof (pathStr),
         uniPathStr,
         (*env)->GetStringLength (env, path));

   if (ccode != 0)
      goto EXIT;

   /* do NOT call __UnicodePathToLocalStr() here because this is not
      a string that should treat the backslash special */

   ccode = __UnicodeToLocalStr (
         EANameStr,
         sizeof (EANameStr),
         uniEANameStr,
         (*env)->GetStringLength (env, EAName));

   if (ccode != 0)
      goto EXIT;

#ifdef N_PLAT_NLM

   if (_usingAliasFunctions)
   {
      EAHandlePtr = (NW_EA_HANDLE *)
            (*_aliasFunctions[0])((nptr) EAHandle, sizeof(NW_EA_HANDLE));
   }
   else

#endif

   EAHandlePtr = (NW_EA_HANDLE *) EAHandle;

   ccode = NWOpenEA (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         pathStr,
         EANameStr,
         (nuint8) nameSpace,
         EAHandlePtr);

#ifdef N_PLAT_NLM

   if (_usingAliasFunctions)
      (*_aliasFunctions[1])((nptr) EAHandlePtr, sizeof(NW_EA_HANDLE));

#endif

EXIT:

   (*env)->ReleaseStringChars (env, path, uniPathStr);
   (*env)->ReleaseStringChars (env, EAName, uniEANameStr);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWCloseEA
(
   JNIEnv   *env,
   jclass   unused,
   jint     EAHandle
)
{
   NWRCODE ccode;
   NW_EA_HANDLE *EAHandlePtr;

#ifdef N_PLAT_NLM

   if (_usingAliasFunctions)
   {
      EAHandlePtr = (NW_EA_HANDLE *)
            (*_aliasFunctions[0])((nptr) EAHandle, sizeof(NW_EA_HANDLE));
   }
   else

#endif

   EAHandlePtr = (NW_EA_HANDLE *) EAHandle;

   ccode = NWCloseEA (EAHandlePtr);

#ifdef N_PLAT_NLM

   if (_usingAliasFunctions)
      (*_aliasFunctions[1])((nptr) EAHandlePtr, sizeof(NW_EA_HANDLE));

#endif

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWReadEA
(
   JNIEnv      *env,
   jclass      unused,
   jint        EAHandle,
   jbyteArray  buf,
   jint        off,
   jint        len,
   jintArray   totalEASize,
   jintArray   bytesRead
)
{
   NWRCODE ccode;
   NW_EA_HANDLE *EAHandlePtr;
   nuint32 luTotalEASize;
   nuint32 luBytesRead;
   jbyte *bufPtr;

   bufPtr = (*env)->GetByteArrayElements (env, buf, NULL);

#ifdef N_PLAT_NLM

   if (_usingAliasFunctions)
   {
      EAHandlePtr = (NW_EA_HANDLE *)
            (*_aliasFunctions[0])((nptr) EAHandle, sizeof(NW_EA_HANDLE));
   }
   else

#endif

   EAHandlePtr = (NW_EA_HANDLE *) EAHandle;

   ccode = NWReadEA (
         EAHandlePtr,
         (nuint32) len,
         (pnuint8) (bufPtr + off),
         &luTotalEASize,
         &luBytesRead);

#ifdef N_PLAT_NLM

   if (_usingAliasFunctions)
      (*_aliasFunctions[1])((nptr) EAHandlePtr, sizeof(NW_EA_HANDLE));

#endif

   // store the result back to Java
   (*env)->ReleaseByteArrayElements (env, buf, bufPtr, 0);

   if (ccode == 0 || ccode == 1)
   {
      jint temp;

      temp = (jint) luTotalEASize;
      (*env)->SetIntArrayRegion (env, totalEASize, 0, 1, &temp);

      temp = (jint) luBytesRead;
      (*env)->SetIntArrayRegion (env, bytesRead, 0, 1, &temp);
   }

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWWriteEA
(
   JNIEnv      *env,
   jclass      unused,
   jint        EAHandle,
   jint        totalWriteSize,
   jbyteArray  buf,
   jint        off,
   jint        len,
   jintArray   bytesWritten
)
{
   NWRCODE ccode;
   nuint32 luBytesWritten;
   jbyte *bufPtr;
   NW_EA_HANDLE *EAHandlePtr;

   bufPtr = (*env)->GetByteArrayElements (env, buf, NULL);

#ifdef N_PLAT_NLM

   if (_usingAliasFunctions)
   {
      EAHandlePtr = (NW_EA_HANDLE *)
            (*_aliasFunctions[0])((nptr) EAHandle, sizeof(NW_EA_HANDLE));
   }
   else

#endif

   EAHandlePtr = (NW_EA_HANDLE *) EAHandle;

   ccode = NWWriteEA (
         EAHandlePtr,
         (nuint32) totalWriteSize,
         (nuint32) len,
         (pnuint8) (bufPtr + off),
         &luBytesWritten);

#ifdef N_PLAT_NLM

   if (_usingAliasFunctions)
      (*_aliasFunctions[1])((nptr) EAHandlePtr, sizeof(NW_EA_HANDLE));

#endif

   (*env)->ReleaseByteArrayElements (env, buf, bufPtr, 0);

   if (ccode == 0 || ccode == 1)
   {
      jint temp = (jint) luBytesWritten;

      (*env)->SetIntArrayRegion(env, bytesWritten, 0, 1, &temp);
   }

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWFindFirstEA
(
   JNIEnv   *env,
   jclass   unused,
   jint     connHandle,
   jint     dirHandle,
   jstring  path,
   jint     dstNamSpc,
   jint     EAFFStruct,
   jint     EAHandle,
   jobject  EAName
)
{
   NWRCODE ccode;
   NW_IDX idx;
   nstr8 pathStr[__jncpv2r_MAX_PATH_LENGTH];
   nstr8 EANameStr[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniPathStr;
   NW_EA_FF_STRUCT *ffStructPtr;
   NW_EA_HANDLE *EAHandlePtr;

   uniPathStr = (punicode) (*env)->GetStringChars (env, path, NULL);

   ccode = __UnicodePathToLocalStr (
         pathStr,
         sizeof (pathStr),
         uniPathStr,
         (*env)->GetStringLength (env, path));

   if (ccode != 0)
      goto EXIT;

   ccode = __FillIDXStruct (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         pathStr,
         (nuint8) dstNamSpc,
         (nuint8) dstNamSpc,
         &idx);

   if (ccode != 0)
      goto EXIT;

#ifdef N_PLAT_NLM

   if (_usingAliasFunctions)
   {
      ffStructPtr = (NW_EA_FF_STRUCT *)
            (*_aliasFunctions[0])((nptr) EAFFStruct,sizeof(NW_EA_FF_STRUCT));

      EAHandlePtr = (NW_EA_HANDLE *)
            (*_aliasFunctions[0])((nptr) EAHandle, sizeof(NW_EA_HANDLE));
   }
   else

#endif

   {
      ffStructPtr = (NW_EA_FF_STRUCT *) EAFFStruct;
      EAHandlePtr = (NW_EA_HANDLE *) EAHandle;
   }

   ccode = NWFindFirstEA (
         (NWCONN_HANDLE) connHandle,
         &idx,
         ffStructPtr,
         EAHandlePtr,
         EANameStr);

#ifdef N_PLAT_NLM

   if (_usingAliasFunctions)
   {
      (*_aliasFunctions[1])((nptr) ffStructPtr, sizeof(NW_EA_FF_STRUCT));
      (*_aliasFunctions[1])((nptr) EAHandlePtr, sizeof(NW_EA_HANDLE));
   }

#endif

   if (ccode == 0)
   {
      jclass clazz;
      jmethodID mid;
      jstring javaEAName;
      unicode uniEANameStr[sizeof (EANameStr)];

      ccode = __LocalToJavaStr (
            env,
            &javaEAName,
            uniEANameStr,
            EANameStr);

      if (ccode == -1)
         goto HARD_EXIT;

      if (ccode == 0)
      {
         clazz = (*env)->GetObjectClass (env, EAName);
         mid = (*env)->GetMethodID(env, clazz, "append",
               "(Ljava/lang/String;)Ljava/lang/StringBuffer;");

         (*env)->CallObjectMethod(env, EAName, mid, javaEAName);

         // don't call any JNI functions if exception is pending
         if ((*env)->ExceptionOccurred (env))
            goto HARD_EXIT;
      }
   }

EXIT:

   (*env)->ReleaseStringChars (env, path, uniPathStr);

HARD_EXIT:

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWFindNextEA
(
   JNIEnv   *env,
   jclass   unused,
   jint     EAFFStruct,
   jint     EAHandle,
   jobject  EAName
)
{
   NWRCODE ccode;
   nstr8 EANameStr[__jncpv2r_MAX_PATH_LENGTH];
   NW_EA_FF_STRUCT *ffStructPtr;
   NW_EA_HANDLE *EAHandlePtr;

#ifdef N_PLAT_NLM

   if (_usingAliasFunctions)
   {
      ffStructPtr = (NW_EA_FF_STRUCT *)
            (*_aliasFunctions[0])((nptr) EAFFStruct,sizeof(NW_EA_FF_STRUCT));

      EAHandlePtr = (NW_EA_HANDLE *)
            (*_aliasFunctions[0])((nptr) EAHandle, sizeof(NW_EA_HANDLE));
   }
   else

#endif

   {
      ffStructPtr = (NW_EA_FF_STRUCT *) EAFFStruct;
      EAHandlePtr = (NW_EA_HANDLE *) EAHandle;
   }

   ccode = NWFindNextEA (
         ffStructPtr,
         EAHandlePtr,
         EANameStr);

#ifdef N_PLAT_NLM

   if (_usingAliasFunctions)
   {
      (*_aliasFunctions[1])((nptr) ffStructPtr, sizeof(NW_EA_FF_STRUCT));
      (*_aliasFunctions[1])((nptr) EAHandlePtr, sizeof(NW_EA_HANDLE));
   }

#endif

   if (ccode == 0)
   {
      jclass clazz;
      jmethodID mid;
      jstring javaEAName;
      unicode uniEANameStr[sizeof (EANameStr)];

      ccode = __LocalToJavaStr (
            env,
            &javaEAName,
            uniEANameStr,
            EANameStr);

      if (ccode == 0)
      {
         clazz = (*env)->GetObjectClass (env, EAName);
         mid = (*env)->GetMethodID (env, clazz, "append",
               "(Ljava/lang/String;)Ljava/lang/StringBuffer;");

         (*env)->CallObjectMethod (env, EAName, mid, javaEAName);
      }
   }

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWScanForTrustees
(
   JNIEnv   *env,
   jclass   unused,
   jint     connHandle,
   jint     dirHandle,
   jstring  path,
   jint     nameSpace,
   jobject  tEnum
)
{
   NWRCODE ccode;
   NWET_INFO trustees;
   nuint32 iterHandle;
   nuint16 numOfEntries;
   jclass clazz;
   jfieldID fid;
   nstr8 defaultNSName[__jncpv2r_MAX_PATH_LENGTH];
   nstr8 pathStr[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniPathStr;

   uniPathStr = (punicode) (*env)->GetStringChars (env, path, NULL);

   ccode = __UnicodePathToLocalStr (
         pathStr,
         sizeof (pathStr),
         uniPathStr,
         (*env)->GetStringLength (env, path));

   if (ccode != 0)
      goto EXIT;

   ccode = __GetDefaultNSPath (
         (NWCONN_HANDLE) connHandle,
         0,       // no dir handle
         pathStr,
         (nuint8) nameSpace,
         defaultNSName);

   if (ccode != 0)
      goto EXIT;

   clazz = (*env)->GetObjectClass (env, tEnum);
   fid = (*env)->GetFieldID (env, clazz, "iterHandle", "I");

   iterHandle = (nuint32) (*env)->GetIntField (env, tEnum, fid);

   ccode = NWScanForTrustees (
         (NWCONN_HANDLE) connHandle,
         0,    // no dir handle
         defaultNSName,
         &iterHandle,
         &numOfEntries,
         &trustees);

   if (ccode == 0)
   {
      jintArray rightsList;
      jintArray objectIDList;
      jint *rightsArr;
      jint *objectIDArr;

      (*env)->SetIntField (env, tEnum, fid, (jint) iterHandle);

      fid = (*env)->GetFieldID (env, clazz, "entryCount", "I");
      (*env)->SetIntField (env, tEnum, fid, (jint) numOfEntries);

      fid = (*env)->GetFieldID (env, clazz, "objectRights", "[I");
      rightsList = (jintArray) (*env)->GetObjectField (env, tEnum, fid);

      fid = (*env)->GetFieldID (env, clazz, "objectIds", "[I");
      objectIDList = (jintArray) (*env)->GetObjectField (env, tEnum, fid);

      rightsArr = (jint *) (*env)->GetIntArrayElements (env,
            rightsList, NULL);

      objectIDArr = (jint *) (*env)->GetIntArrayElements (env,
            objectIDList, NULL);

      while (numOfEntries--)
      {
         rightsArr[numOfEntries] =
               (jint) trustees.trusteeList[numOfEntries].objectRights;

         objectIDArr[numOfEntries] =
               (jint) trustees.trusteeList[numOfEntries].objectID;
      }

      (*env)->ReleaseIntArrayElements (env, objectIDList, objectIDArr, 0);
      (*env)->ReleaseIntArrayElements (env, rightsList, rightsArr, 0);
   }

EXIT:

   (*env)->ReleaseStringChars (env, path, uniPathStr);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWGetDirSpaceLimitList
(
   JNIEnv    *env,
   jclass    unused,
   jint      connHandle,
   jint      dirHandle,
   jstring   path,
   jint      nameSpace,
   jintArray maxLimit,
   jintArray currentUse
)
{
   NWRCODE ccode;
   NWDIR_HANDLE newDirHandle;
   char limitBuf[512];
   nstr8 pathStr[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniPathStr;

   uniPathStr = (punicode) (*env)->GetStringChars (env, path, NULL);

   ccode = __UnicodePathToLocalStr (
         pathStr,
         sizeof (pathStr),
         uniPathStr,
         (*env)->GetStringLength (env, path));

   if (ccode != 0)
      goto EXIT;

   ccode = NWAllocTempNSDirHandle2 (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         pathStr,
         (nuint8) nameSpace,
         &newDirHandle,
         (nuint8) nameSpace);

   if (ccode != 0)
      goto EXIT;

   ccode = NWGetDirSpaceLimitList (
         (NWCONN_HANDLE) connHandle,
         newDirHandle,
         limitBuf);

   if (ccode == 0)
   {
      nuint32 smallestLimit = 0x7FFFFFFFL;
      nint32 current;
      int off = 0;
      int item = 0;
      int count;
      jint temp;

      count = limitBuf[off++];

      while (item < count)
      {
         nuint32 limit, c;

         NCopyLoHi32 (&limit, &limitBuf[off + 1]);
         NCopyLoHi32 (&c, &limitBuf[off + 5]);

         if (limit == 0xFFFFFFFFL)
            smallestLimit = 0;
         else if (limit < smallestLimit)
            smallestLimit = limit;

         if (item == 0)
         {
            if (limit == 0xFFFFFFFFL)
               current = 0 - c;
            else
               current = limit - c;
         }

         off += 9;
         item++;
      }

      temp = (jint) smallestLimit;
      (*env)->SetIntArrayRegion (env, maxLimit, 0, 1, &temp);

      temp = (jint) current;
      (*env)->SetIntArrayRegion (env, currentUse, 0, 1, &temp);
   }

   (void) NWDeallocateDirectoryHandle (
         (NWCONN_HANDLE) connHandle,
         newDirHandle);

EXIT:

   (*env)->ReleaseStringChars (env, path, uniPathStr);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWSetDirSpaceLimit
(
   JNIEnv   *env,
   jclass   unused,
   jint     connHandle,
   jint     dirHandle,
   jstring  path,
   jint     nameSpace,
   jint     limit
)
{
   NWRCODE ccode;
   NWDIR_HANDLE newDirHandle;
   nstr8 pathStr[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniPathStr;

   uniPathStr = (punicode) (*env)->GetStringChars (env, path, NULL);

   ccode = __UnicodePathToLocalStr (
         pathStr,
         sizeof (pathStr),
         uniPathStr,
         (*env)->GetStringLength (env, path));

   if (ccode != 0)
      goto EXIT;

   ccode = NWAllocTempNSDirHandle2 (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         pathStr,
         (nuint8) nameSpace,
         &newDirHandle,
         (nuint8) nameSpace);

   if (ccode != 0)
      goto EXIT;

   ccode = NWSetDirSpaceLimit (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) newDirHandle,
         (nuint32) limit);

   (void) NWDeallocateDirectoryHandle (
         (NWCONN_HANDLE) connHandle,
         newDirHandle);

EXIT:

   (*env)->ReleaseStringChars (env, path, uniPathStr);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWSetCompressedFileSize
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint OSFileHandle,
   jint desiredSize,
   jintArray actualSize
)
{
   NWRCODE ccode;
   nuint32 luActualSize;

   ccode = NWSetCompressedFileSize (
         (NWCONN_HANDLE) connHandle,
         (NWFILE_HANDLE) OSFileHandle,
         (nuint32) desiredSize,
         &luActualSize);

   if (ccode == 0)
   {
      jint temp = (jint) luActualSize;

      (*env)->SetIntArrayRegion (env, actualSize, 0, 1, &temp);
   }

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWAddTrustee
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint dirHandle,
   jstring path,
   jint nameSpace,
   jint objID,
   jint rightsMask
)
{
   NWRCODE ccode;
   nstr8 defaultNSPathStr[__jncpv2r_MAX_PATH_LENGTH];
   nstr8 pathStr[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniPathStr;

   uniPathStr = (punicode) (*env)->GetStringChars (env, path, NULL);

   ccode = __UnicodePathToLocalStr (
         pathStr,
         sizeof (pathStr),
         uniPathStr,
         (*env)->GetStringLength (env, path));

   if (ccode != 0)
      goto EXIT;

   ccode = __GetDefaultNSPath (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         pathStr,
         (nuint8) nameSpace,
         defaultNSPathStr);

   if (ccode != 0)
      goto EXIT;

   ccode = NWAddTrustee (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         defaultNSPathStr,
         (nuint32) objID,
         (nuint16) rightsMask);

EXIT:

   (*env)->ReleaseStringChars (env, path, uniPathStr);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWDeleteTrustee
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint dirHandle,
   jstring path,
   jint nameSpace,
   jint objID
)
{
   NWRCODE ccode;
   nstr8 defaultNSPathStr[__jncpv2r_MAX_PATH_LENGTH];
   nstr8 pathStr[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniPathStr;

   uniPathStr = (punicode) (*env)->GetStringChars (env, path, NULL);

   ccode = __UnicodePathToLocalStr (
         pathStr,
         sizeof (pathStr),
         uniPathStr,
         (*env)->GetStringLength (env, path));

   if (ccode != 0)
      goto EXIT;

   ccode = __GetDefaultNSPath (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         pathStr,
         (nuint8) nameSpace,
         defaultNSPathStr);

   if (ccode != 0)
      goto EXIT;

   ccode = NWDeleteTrustee (
               (NWCONN_HANDLE) connHandle,
               (NWDIR_HANDLE) dirHandle,
               defaultNSPathStr,
               (nuint32) objID);

EXIT:

   (*env)->ReleaseStringChars (env, path, uniPathStr);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWGetNSInfo
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint volumeNumber,
   jint nameSpace
//   jobject info
)
{
/*
   NWRCODE ccode;
   NW_IDX idx;
   NW_NS_INFO nsInfo;

   idx.volNumber = (nuint8) volumeNumber;
   idx.dstNameSpace = (nuint8) nameSpace;

   ccode = NWGetNSInfo (
         (NWCONN_HANDLE) connHandle,
         &idx,
         &nsInfo);

   if (ccode == 0)
   {
      int i;
      jclass clazz = (*env)->GetObjectClass (env, info);
      jfieldID fid;
      jobject fieldsLenTable;
      jint *ptr;

      fid = (*env)->GetFieldID (env, clazz, "NSInfoBitMask", "I");
      (*env)->SetIntField (env, info, fid, (jint) nsInfo.NSInfoBitMask);

      fid = (*env)->GetFieldID (env, clazz, "fixedBitMask", "I");
      (*env)->SetIntField (env, info, fid, (jint) nsInfo.fixedBitMask);

      fid = (*env)->GetFieldID (env, clazz, "variableBitMask", "I");
      (*env)->SetIntField (env, info, fid, (jint) nsInfo.reservedBitMask);

      fid = (*env)->GetFieldID (env, clazz, "hugeBitMask", "I");
      (*env)->SetIntField (env, info, fid, (jint) nsInfo.extendedBitMask);

      fid = (*env)->GetFieldID (env, clazz, "fixedBitsDefined", "I");
      (*env)->SetIntField (env, info, fid, (jint) nsInfo.fixedBitsDefined);

      fid = (*env)->GetFieldID (env, clazz, "variableBitsDefined", "I");
      (*env)->SetIntField (env, info, fid,(jint) nsInfo.reservedBitsDefined);

      fid = (*env)->GetFieldID (env, clazz, "hugeBitsDefined", "I");
      (*env)->SetIntField (env, info, fid,(jint) nsInfo.extendedBitsDefined);

      // now get the array field and set all values in the array
      fid = (*env)->GetFieldID (env, clazz, "fieldsLengthTable", "[I");
      fieldsLenTable = (*env)->GetObjectField (env, info, fid);

      ptr = (*env)->GetIntArrayElements (env, fieldsLenTable, NULL);

      for (i = 0; i < 32; i++)
         ptr[i] = (jint) nsInfo.fieldsLenTable[i];

      (*env)->ReleaseIntArrayElements (env, fieldsLenTable, ptr, 0);
   }

   return ((jint) ccode);
*/
   return ((jint) -1);
}

// the 'data' array must be 512 bytes long
JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWReadNSInfo
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint dirHandle,
   jstring path,
   jint nameSpace,
   jint dstNameSpace,
   jint NSInfoBitMask,
   jintArray data
)
{
   NWRCODE ccode;
   NW_IDX idx;
   NW_NS_INFO info;
   jbyte *dataPtr;
   nuint32 temp;
   nstr8 pathStr[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniPathStr;

   uniPathStr = (punicode) (*env)->GetStringChars (env, path, NULL);

   ccode = __UnicodePathToLocalStr (
         pathStr,
         sizeof (pathStr),
         uniPathStr,
         (*env)->GetStringLength (env, path));

   if (ccode != 0)
      goto EXIT;

   ccode = __FillIDXStruct (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         pathStr,
         (nuint8) nameSpace,
         (nuint8) dstNameSpace,
         &idx);

   if (ccode != 0)
      goto EXIT;

   info.NSInfoBitMask = (nuint32) NSInfoBitMask;

   dataPtr = (*env)->GetByteArrayElements (env, data, NULL);

   // the dir bases have to be in the reverse order than in the case
   //   when we read an EA...  Don't ask me why, but it works.
   temp = idx.srcDirBase;
   idx.srcDirBase = idx.dstDirBase;
   idx.dstDirBase = temp;

   ccode = NWReadNSInfo (
         (NWCONN_HANDLE) connHandle,
         &idx,
         &info,
         (pnuint8) dataPtr);

   // store the result back to Java
   (*env)->ReleaseByteArrayElements (env, data, dataPtr, 0);

EXIT:

   (*env)->ReleaseStringChars (env, path, uniPathStr);

   return ((jint) ccode);
}

// the 'data' array must be 512 bytes long
JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWWriteNSInfo
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint dirHandle,
   jstring path,
   jint nameSpace,
   jint dstNameSpace,
   jint NSInfoBitMask,
   jintArray data
)
{
   NWRCODE ccode;
   NW_IDX idx;
   NW_NS_INFO info;
   jbyte *dataPtr;
   nstr8 pathStr[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniPathStr;

   uniPathStr = (punicode) (*env)->GetStringChars (env, path, NULL);

   ccode = __UnicodePathToLocalStr (
         pathStr,
         sizeof (pathStr),
         uniPathStr,
         (*env)->GetStringLength (env, path));

   if (ccode != 0)
      goto EXIT;

   ccode = __FillIDXStruct (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         pathStr,
         (nuint8) nameSpace,
         (nuint8) dstNameSpace,
         &idx);

   if (ccode != 0)
      goto EXIT;

   info.NSInfoBitMask = (nuint32) NSInfoBitMask;

   dataPtr = (*env)->GetByteArrayElements (env, data, NULL);

   ccode = NWWriteNSInfo (
         (NWCONN_HANDLE) connHandle,
         &idx,
         &info,
         (pnuint8) dataPtr);

   (*env)->ReleaseByteArrayElements (env, data, dataPtr, 0);

EXIT:

   (*env)->ReleaseStringChars (env, path, uniPathStr);

   return ((jint) ccode);
}

// the 'hugeData' array must be big enough to hold any huge data that the
//   server may choose to send -- it's not doc'd in the NCP doc how big
// the 'hugeStateInfo' is a 16-byte iter handle
JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWReadExtendedNSInfo
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint dirHandle,
   jstring path,
   jint nameSpace,
   jint dstNameSpace,
   jint extendedBitMask,
   jbyteArray hugeStateInfo,
   jintArray hugeDataLength,  // output parameter
   jbyteArray hugeData        // output parameter
)
{
   NWRCODE ccode;
   NW_IDX idx;
   NW_NS_INFO info;
   int i;
   char *ptr;
   jbyte *hugeStateInfoPtr;
   jbyte *hugeDataPtr;
   nstr8 pathStr[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniPathStr;

   uniPathStr = (punicode) (*env)->GetStringChars (env, path, NULL);

   ccode = __UnicodePathToLocalStr (
         pathStr,
         sizeof (pathStr),
         uniPathStr,
         (*env)->GetStringLength (env, path));

   if (ccode != 0)
      goto EXIT;

   ccode = __FillIDXStruct (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         pathStr,
         (nuint8) nameSpace,
         (nuint8) dstNameSpace,
         &idx);

   if (ccode != 0)
      goto EXIT;

   hugeStateInfoPtr = (*env)->GetByteArrayElements(env, hugeStateInfo, NULL);
   hugeDataPtr = (*env)->GetByteArrayElements (env, hugeData, NULL);

   for (i = 0, ptr = (char *) hugeStateInfoPtr; i < 16; i++)
      info.hugeStateInfo[i] = *ptr++;

   info.extendedBitMask = (nuint32) extendedBitMask;

   ccode = NWReadExtendedNSInfo (
         (NWCONN_HANDLE) connHandle,
         &idx,
         &info,
         (pnuint8) hugeDataPtr);

   if (ccode == 0)
   {
      jint temp;

      for (i = 0, ptr = (char *) hugeStateInfoPtr; i < 16; i++)
         *ptr++ = info.hugeStateInfo[i];

      temp = (jint) info.hugeDataLength;
      (*env)->SetIntArrayRegion (env, hugeDataLength, 0, 1, &temp);
   }

   // store the result back to Java
   (*env)->ReleaseByteArrayElements(env, hugeStateInfo, hugeStateInfoPtr, 0);
   (*env)->ReleaseByteArrayElements(env, hugeData, hugeDataPtr, 0);

EXIT:

   (*env)->ReleaseStringChars (env, path, uniPathStr);

   return ((jint) ccode);
}

// the 'hugeStateInfo' is a 16-byte iter handle
// when this function returns, 'hugeDataLength' will contain an int
//   that is returned from the server specifying how much of the huge
//   data was consumed by the name space module
JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWWriteExtendedNSInfo
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint dirHandle,
   jstring path,
   jint nameSpace,
   jint dstNameSpace,
   jint extendedBitMask,
   jbyteArray hugeStateInfo,
   jintArray hugeDataLength,  // input/output parameter
   jbyteArray hugeData,       // input parameter
   jint offset
)
{
   NWRCODE ccode;
   NW_IDX idx;
   NW_NS_INFO info;
   int i;
   char *ptr;
   jbyte *hugeStateInfoPtr;
   jbyte *hugeDataPtr;
   jint *hugeDataLengthPtr;
   nstr8 pathStr[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniPathStr;

   uniPathStr = (punicode) (*env)->GetStringChars (env, path, NULL);

   ccode = __UnicodePathToLocalStr (
         pathStr,
         sizeof (pathStr),
         uniPathStr,
         (*env)->GetStringLength (env, path));

   if (ccode != 0)
      goto EXIT;

   ccode = __FillIDXStruct (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         pathStr,
         (nuint8) nameSpace,
         (nuint8) dstNameSpace,
         &idx);

   if (ccode != 0)
      goto EXIT;

   hugeStateInfoPtr = (*env)->GetByteArrayElements(env, hugeStateInfo, NULL);
   hugeDataPtr = (*env)->GetByteArrayElements (env, hugeData, NULL);

   hugeDataLengthPtr = (*env)->GetIntArrayElements (env,
         hugeDataLength, NULL);

   for (i = 0, ptr = (char *) hugeStateInfoPtr; i < 16; i++)
      info.hugeStateInfo[i] = *ptr++;

   info.extendedBitMask = (nuint32) extendedBitMask;
   info.hugeDataLength = (nuint32) hugeDataLengthPtr[0];

   ccode = NWWriteExtendedNSInfo (
         (NWCONN_HANDLE) connHandle,
         &idx,
         &info,
         (pnuint8) (hugeDataPtr + offset));

   if (ccode == 0)
   {
      for (i = 0, ptr = (char *) hugeStateInfoPtr; i < 16; i++)
         *ptr++ = info.hugeStateInfo[i];

      hugeDataLengthPtr[0] = info.hugeDataLength;
   }

   (*env)->ReleaseByteArrayElements(env, hugeStateInfo, hugeStateInfoPtr, 0);
   (*env)->ReleaseByteArrayElements(env, hugeData, hugeDataPtr, 0);

   (*env)->ReleaseIntArrayElements(env,hugeDataLength, hugeDataLengthPtr, 0);

EXIT:

   (*env)->ReleaseStringChars (env, path, uniPathStr);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWSetNSEntryDOSInfo
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint dirHandle,
   jstring path,
   jint nameSpace,
   jint searchAttr,
   jint modifyMask,
   jobject info
)
{
   NWRCODE ccode;
   MODIFY_DOS_INFO infoStruct;
   nuint32 mask;
   jclass clazz;
   jfieldID fid;
   nstr8 pathStr[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniPathStr;

   uniPathStr = (punicode) (*env)->GetStringChars (env, path, NULL);

   ccode = __UnicodePathToLocalStr (
         pathStr,
         sizeof (pathStr),
         uniPathStr,
         (*env)->GetStringLength (env, path));

   if (ccode != 0)
      goto EXIT;

   clazz = (*env)->GetObjectClass (env, info);

   fid = (*env)->GetFieldID (env, clazz, "attributes", "I");
   infoStruct.attributes = (nuint32) (*env)->GetIntField (env, info, fid);

   fid = (*env)->GetFieldID (env, clazz, "creationDate", "I");
   infoStruct.createDate = (nuint16) (*env)->GetIntField (env, info, fid);

   fid = (*env)->GetFieldID (env, clazz, "creationTime", "I");
   infoStruct.createTime = (nuint16) (*env)->GetIntField (env, info, fid);

   fid = (*env)->GetFieldID (env, clazz, "creatorID", "I");
   infoStruct.creatorID = (nuint32) (*env)->GetIntField (env, info, fid);

   fid = (*env)->GetFieldID (env, clazz, "modifyDate", "I");
   infoStruct.modifyDate = (nuint16) (*env)->GetIntField (env, info, fid);

   fid = (*env)->GetFieldID (env, clazz, "modifyTime", "I");
   infoStruct.modifyTime = (nuint16) (*env)->GetIntField (env, info, fid);

   fid = (*env)->GetFieldID (env, clazz, "modifierID", "I");
   infoStruct.modifierID = (nuint32) (*env)->GetIntField (env, info, fid);

   fid = (*env)->GetFieldID (env, clazz, "archiveDate", "I");
   infoStruct.archiveDate = (nuint16) (*env)->GetIntField (env, info, fid);

   fid = (*env)->GetFieldID (env, clazz, "archiveTime", "I");
   infoStruct.archiveTime = (nuint16) (*env)->GetIntField (env, info, fid);

   fid = (*env)->GetFieldID (env, clazz, "archiverID", "I");
   infoStruct.archiverID = (nuint32) (*env)->GetIntField (env, info, fid);

   fid = (*env)->GetFieldID (env, clazz, "lastAccessDate", "I");
   infoStruct.lastAccessDate = (nuint16) (*env)->GetIntField(env, info, fid);

   fid = (*env)->GetFieldID (env, clazz, "inheritedRightsMask", "I");
   mask = (nuint32) (*env)->GetIntField(env, info, fid);

   infoStruct.inheritanceGrantMask = (nuint16) (mask & 0xFFFF);
   infoStruct.inheritanceRevokeMask = (nuint16) ((mask >> 16) & 0xFFFF);

   fid = (*env)->GetFieldID (env, clazz, "spaceAlloc", "I");
   infoStruct.maximumSpace = (nuint32) (*env)->GetIntField (env, info, fid);

   ccode = NWSetNSEntryDOSInfo (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         pathStr,
         (nuint8) nameSpace,
         (nuint16) searchAttr,
         (nuint32) modifyMask,
         &infoStruct);

EXIT:

   (*env)->ReleaseStringChars (env, path, uniPathStr);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWGetVolumeInfoWithNumber
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint volNumber,
   jobject info
)
{
   NWRCODE ccode;
   nstr8 volNameStr[17];
   nuint16 totalBlocks;
   nuint16 sectorsPerBlock;
   nuint16 availableBlocks;
   nuint16 totalDirEntries;
   nuint16 availableDirEntries;
   nuint16 volIsRemovableFlag;

   ccode = NWGetVolumeInfoWithNumber (
         (NWCONN_HANDLE) connHandle,
         (nuint16) volNumber,
         volNameStr,
         &totalBlocks,
         &sectorsPerBlock,
         &availableBlocks,
         &totalDirEntries,
         &availableDirEntries,
         &volIsRemovableFlag);

   if (ccode == 0)
   {
      jclass clazz;
      jfieldID fid;
      jstring javaVolName;
      unicode uniVolNameStr[sizeof (volNameStr)];

      ccode = __LocalToJavaStr (
            env,
            &javaVolName,
            uniVolNameStr,
            volNameStr);

      if (ccode != 0)
         return ((jint) ccode);

      clazz = (*env)->GetObjectClass (env, info);

      fid = (*env)->GetFieldID (env, clazz, "volName", "Ljava/lang/String;");
      (*env)->SetObjectField (env, info, fid, javaVolName);

      fid = (*env)->GetFieldID (env, clazz, "totalBlocks", "I");
      (*env)->SetIntField (env, info, fid, (jint) totalBlocks);

      fid = (*env)->GetFieldID (env, clazz, "sectorsPerBlock", "I");
      (*env)->SetIntField (env, info, fid, (jint) sectorsPerBlock);

      fid = (*env)->GetFieldID (env, clazz, "availableBlocks", "I");
      (*env)->SetIntField (env, info, fid, (jint) availableBlocks);

      fid = (*env)->GetFieldID (env, clazz, "totalDirEntries", "I");
      (*env)->SetIntField (env, info, fid, (jint) totalDirEntries);

      fid = (*env)->GetFieldID (env, clazz, "availableDirEntries", "I");
      (*env)->SetIntField (env, info, fid, (jint) availableDirEntries);

      fid = (*env)->GetFieldID (env, clazz, "volIsRemovableFlag", "I");
      (*env)->SetIntField (env, info, fid, (jint) volIsRemovableFlag);
   }

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWGetExtendedVolumeInfo
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint volNumber,
   jobject info
)
{
   NWRCODE ccode;
   NWVolExtendedInfo s;

   ccode = NWGetExtendedVolumeInfo (
               (NWCONN_HANDLE) connHandle,
               (nuint16) volNumber,
               &s);

   if (ccode == 0)
   {
      jclass clazz;
      jfieldID fid;

      clazz = (*env)->GetObjectClass (env, info);

      fid = (*env)->GetFieldID (env, clazz, "volType", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.volType);

      fid = (*env)->GetFieldID (env, clazz, "statusFlag", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.statusFlag);

      fid = (*env)->GetFieldID (env, clazz, "sectorSize", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.sectorSize);

      fid = (*env)->GetFieldID (env, clazz, "sectorsPerCluster", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.sectorsPerCluster);

      fid = (*env)->GetFieldID (env, clazz, "volSizeInClusters", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.volSizeInClusters);

      fid = (*env)->GetFieldID (env, clazz, "freeClusters", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.freeClusters);

      fid = (*env)->GetFieldID (env, clazz, "subAllocFreeableClusters", "I");
      (*env)->SetIntField (env, info, fid,
            (jint) s.subAllocFreeableClusters);

      fid = (*env)->GetFieldID (env, clazz, "freeableLimboSectors", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.freeableLimboSectors);

      fid = (*env)->GetFieldID (env, clazz, "nonfreeableLimboSectors", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.nonfreeableLimboSectors);

      fid = (*env)->GetFieldID (env, clazz, "availSubAllocSectors", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.availSubAllocSectors);

      fid = (*env)->GetFieldID (env, clazz,
            "nonuseableSubAllocSectors", "I");
      (*env)->SetIntField (env, info, fid,
            (jint) s.nonuseableSubAllocSectors);

      fid = (*env)->GetFieldID (env, clazz, "subAllocClusters", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.subAllocClusters);

      fid = (*env)->GetFieldID (env, clazz, "numDataStreams", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.numDataStreams);

      fid = (*env)->GetFieldID (env, clazz, "numLimboDataStreams", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.numLimboDataStreams);

      fid = (*env)->GetFieldID (env, clazz, "oldestDelFileAgeInTicks", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.oldestDelFileAgeInTicks);

      fid = (*env)->GetFieldID (env, clazz, "numCompressedDataStreams", "I");
      (*env)->SetIntField (env, info, fid, (jint)s.numCompressedDataStreams);

      fid = (*env)->GetFieldID (env, clazz,
            "numCompressedLimboDataStreams", "I");
      (*env)->SetIntField (env, info, fid,
            (jint) s.numCompressedLimboDataStreams);

      fid = (*env)->GetFieldID (env, clazz,
            "numNoncompressibleDataStreams", "I");
      (*env)->SetIntField (env, info, fid,
            (jint) s.numNoncompressibleDataStreams);

      fid = (*env)->GetFieldID (env, clazz, "precompressedSectors", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.precompressedSectors);

      fid = (*env)->GetFieldID (env, clazz, "compressedSectors", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.compressedSectors);

      fid = (*env)->GetFieldID (env, clazz, "numMigratedDataStreams", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.numMigratedDataStreams);

      fid = (*env)->GetFieldID (env, clazz, "migratedSectors", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.migratedSectors);

      fid = (*env)->GetFieldID (env, clazz, "clustersUsedByFAT", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.clustersUsedByFAT);

      fid = (*env)->GetFieldID (env, clazz, "clustersUsedByDirs", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.clustersUsedByDirs);

      fid = (*env)->GetFieldID (env, clazz, "clustersUsedByExtDirs", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.clustersUsedByExtDirs);

      fid = (*env)->GetFieldID (env, clazz, "totalDirEntries", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.totalDirEntries);

      fid = (*env)->GetFieldID (env, clazz, "unusedDirEntries", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.unusedDirEntries);

      fid = (*env)->GetFieldID (env, clazz, "totalExtDirExtants", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.totalExtDirExtants);

      fid = (*env)->GetFieldID (env, clazz, "unusedExtDirExtants", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.unusedExtDirExtants);

      fid = (*env)->GetFieldID (env, clazz, "extAttrsDefined", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.extAttrsDefined);

      fid = (*env)->GetFieldID (env, clazz, "extAttrExtantsUsed", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.extAttrExtantsUsed);

      fid = (*env)->GetFieldID (env, clazz,
            "directoryServicesObjectId", "I");
      (*env)->SetIntField (env, info, fid,
            (jint) s.DirectoryServicesObjectID);

      fid = (*env)->GetFieldID (env, clazz,
            "volLastModifiedDateAndTime", "I");
      (*env)->SetIntField (env, info, fid,
            (jint) s.volLastModifiedDateAndTime);
   }

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWGetVolumeStats
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint volNumber,
   jobject info
)
{
   NWRCODE ccode;
   VOL_STATS s;

   ccode = NWGetVolumeStats (
         (NWCONN_HANDLE) connHandle,
         (nuint8) volNumber,
         &s);

   if (ccode == 0)
   {
      jclass clazz;
      jfieldID fid;
      jstring javaVolName;
      unicode uniVolNameStr[sizeof (s.volumeName) + 1];
      nstr8 volNameStr[17];

      // s.volumeName isn't big enough for a null terminator if the
      //   volume name is 16 bytes long.  So we have to do this kludge
      //   to get around it.  (shorter names come back null-terminated)

      memcpy (volNameStr, s.volumeName, 16);
      volNameStr[16] = '\0';

      ccode = __LocalToJavaStr (
            env,
            &javaVolName,
            uniVolNameStr,
            volNameStr);

      if (ccode != 0)
         return ((jint) ccode);

      clazz = (*env)->GetObjectClass (env, info);

      fid = (*env)->GetFieldID (env, clazz, "volumeName",
            "Ljava/lang/String;");
      (*env)->SetObjectField (env, info, fid, (jobject) javaVolName);

      fid = (*env)->GetFieldID (env, clazz, "systemElapsedTime", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.systemElapsedTime);

      fid = (*env)->GetFieldID (env, clazz, "volumeNumber", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.volumeNumber);

      fid = (*env)->GetFieldID (env, clazz, "logicalDriveNumber", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.logicalDriveNumber);

      fid = (*env)->GetFieldID (env, clazz, "sectorsPerBlock", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.sectorsPerBlock);

      fid = (*env)->GetFieldID (env, clazz, "startingBlock", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.startingBlock);

      fid = (*env)->GetFieldID (env, clazz, "totalBlocks", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.totalBlocks);

      fid = (*env)->GetFieldID (env, clazz, "availableBlocks", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.availableBlocks);

      fid = (*env)->GetFieldID (env, clazz, "totalDirectorySlots", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.totalDirectorySlots);

      fid = (*env)->GetFieldID (env, clazz, "availableDirectorySlots", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.availableDirectorySlots);

      fid = (*env)->GetFieldID (env, clazz, "maxDirectorySlotsUsed", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.maxDirectorySlotsUsed);

      fid = (*env)->GetFieldID (env, clazz, "isHashing", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.isHashing);

      fid = (*env)->GetFieldID (env, clazz, "isCaching", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.isCaching);

      fid = (*env)->GetFieldID (env, clazz, "isRemovable", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.isRemovable);

      fid = (*env)->GetFieldID (env, clazz, "isMounted", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.isMounted);
   }

   return ((jint) ccode);
}

// 'path' can be null coming from Java, in which case, we get info about
//   the root of the vol.
JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWGetDirSpaceInfo
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint volNumber,
   jstring path,
   jint nameSpace,
   jobject info
)
{
   NWRCODE ccode;
   DIR_SPACE_INFO s;
   NWDIR_HANDLE newDirHandle;

   if (path)
   {
      nstr8 pathStr[__jncpv2r_MAX_PATH_LENGTH];
      punicode uniPathStr;

      uniPathStr = (punicode) (*env)->GetStringChars (env, path, NULL);

      ccode = __UnicodePathToLocalStr (
            pathStr,
            sizeof (pathStr),
            uniPathStr,
            (*env)->GetStringLength (env, path));

      if (ccode == 0)
      {
         ccode = NWAllocTempNSDirHandle2 (
               (NWCONN_HANDLE) connHandle,
               0,
               pathStr,
               (nuint8) nameSpace,
               &newDirHandle,
               (nuint8) nameSpace);

      }

      (*env)->ReleaseStringChars (env, path, uniPathStr);

      if (ccode != 0)
         return ((jint) ccode);
   }
   else
      newDirHandle = 0;

   ccode = NWGetDirSpaceInfo (
         (NWCONN_HANDLE) connHandle,
         newDirHandle,
         (nuint16) volNumber,
         &s);

   if (path)
   {
      (void) NWDeallocateDirectoryHandle (
               (NWCONN_HANDLE) connHandle,
               newDirHandle);
   }

   if (ccode == 0)
   {
      jclass clazz;
      jfieldID fid;
      jstring javaVolName;
      unicode uniVolNameStr[sizeof (s.volName)];

      s.volName[s.volLen] = 0;

      ccode = __LocalToJavaStr (
            env,
            &javaVolName,
            uniVolNameStr,
            s.volName);

      if (ccode != 0)
         goto EXIT;

      clazz = (*env)->GetObjectClass (env, info);

      fid = (*env)->GetFieldID (env, clazz, "volName", "Ljava/lang/String;");
      (*env)->SetObjectField (env, info, fid, (jobject) javaVolName);

      fid = (*env)->GetFieldID (env, clazz, "totalBlocks", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.totalBlocks);

      fid = (*env)->GetFieldID (env, clazz, "availableBlocks", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.availableBlocks);

      fid = (*env)->GetFieldID (env, clazz, "purgeableBlocks", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.purgeableBlocks);

      fid = (*env)->GetFieldID (env, clazz, "notYetPurgeableBlocks", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.notYetPurgeableBlocks);

      fid = (*env)->GetFieldID (env, clazz, "totalDirEntries", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.totalDirEntries);

      fid = (*env)->GetFieldID (env, clazz, "availableDirEntries", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.availableDirEntries);

      fid = (*env)->GetFieldID (env, clazz, "reserved", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.reserved);

      fid = (*env)->GetFieldID (env, clazz, "sectorsPerBlock", "I");
      (*env)->SetIntField (env, info, fid, (jint) s.sectorsPerBlock);
   }

EXIT:

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWGetDiskUtilization
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint objID,
   jint volNum,
   jobject data
)
{
   NWRCODE ccode;
   nuint16 usedDirectories;
   nuint16 usedFiles;
   nuint16 usedBlocks;

   ccode = NWGetDiskUtilization (
         (NWCONN_HANDLE) connHandle,
         (nuint32) objID,
         (nuint8) volNum,
         &usedDirectories,
         &usedFiles,
         &usedBlocks);

   if (ccode == 0)
   {
      jclass clazz;
      jfieldID fid;

      clazz = (*env)->GetObjectClass (env, data);

      fid = (*env)->GetFieldID (env, clazz, "usedDirectories", "I");
      (*env)->SetIntField (env, data, fid, (jint) usedDirectories);

      fid = (*env)->GetFieldID (env, clazz, "usedFiles", "I");
      (*env)->SetIntField (env, data, fid, (jint) usedFiles);

      fid = (*env)->GetFieldID (env, clazz, "usedBlocks", "I");
      (*env)->SetIntField (env, data, fid, (jint) usedBlocks);
   }

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWGetObjDiskRestrictions
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint volNumber,
   jint objectId,
   jobject data
)
{
   NWRCODE ccode;
   nuint32 restriction;
   nuint32 inUse;

   ccode = NWGetObjDiskRestrictions (
         (NWCONN_HANDLE) connHandle,
         (nuint8) volNumber,
         (nuint32) objectId,
         &restriction,
         &inUse);

   if (ccode == 0)
   {
      jclass clazz;
      jfieldID fid;

      clazz = (*env)->GetObjectClass (env, data);

      fid = (*env)->GetFieldID (env, clazz, "restriction", "I");
      (*env)->SetIntField (env, data, fid, (jint) restriction);

      fid = (*env)->GetFieldID (env, clazz, "inUse", "I");
      (*env)->SetIntField (env, data, fid, (jint) inUse);
   }

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWScanVolDiskRestrictions2
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint volNumber,
   jobject data
)
{
   NWRCODE ccode;
   nuint32 iterHandle;
   NWVOL_RESTRICTIONS info;
   jclass clazz;
   jfieldID fid;

   clazz = (*env)->GetObjectClass (env, data);

   fid = (*env)->GetFieldID (env, clazz, "iterHandle", "I");
   iterHandle = (nuint32) (*env)->GetIntField (env, data, fid);

   ccode = NWScanVolDiskRestrictions2 (
         (NWCONN_HANDLE) connHandle,
         (nuint8) volNumber,
         &iterHandle,
         &info);

   if (ccode == 0)
   {
      int entryCount = info.numberOfEntries;
      int i;
      jobjectArray restrictionArr;

      (*env)->SetIntField (env, data, fid, (jint) iterHandle);

      fid = (*env)->GetFieldID (env, clazz, "entryCount", "I");
      (*env)->SetIntField (env, data, fid, (jint) entryCount);

      fid = (*env)->GetFieldID (env, clazz, "vRestrictions",
            "[Lcom/novell/service/file/nw/VolumeRestriction;");
      restrictionArr = (*env)->GetObjectField (env, data, fid);

      clazz = 0;

      for (i = 0; i < entryCount; i++)
      {
         jobject restriction;

         restriction = (*env)->GetObjectArrayElement (env, restrictionArr,
               (jsize) i);

         if (clazz == 0)
            clazz = (*env)->GetObjectClass (env, restriction);

         fid = (*env)->GetFieldID (env, clazz, "objectId", "I");
         (*env)->SetIntField (env, restriction, fid,
               (jint) info.resInfo[i].objectID);

         fid = (*env)->GetFieldID (env, clazz, "restriction", "I");
         (*env)->SetIntField (env, restriction, fid,
               (jint) info.resInfo[i].restriction);
      }
   }

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWRemoveObjectDiskRestrictions
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint volNumber,
   jint objectId
)
{
   NWRCODE ccode;

   ccode = NWRemoveObjectDiskRestrictions (
         (NWCONN_HANDLE) connHandle,
         (nuint8) volNumber,
         (nuint32) objectId);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWSetObjectVolSpaceLimit
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint volNumber,
   jint objectId,
   jint restriction
)
{
   NWRCODE ccode;

   ccode = NWSetObjectVolSpaceLimit(
               (NWCONN_HANDLE) connHandle,
               (nuint8) volNumber,
               (nuint32) objectId,
               (nuint32) restriction);

   return ((jint) ccode);
}

// 'volNumber' can be null coming from Java
JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWSMMountVolume
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jstring volName,
   jintArray volNumber
)
{
   NWRCODE ccode;
   nuint32 newVolNumber;
   nstr8 volNameStr[17];
   punicode uniVolNameStr;

   uniVolNameStr = (punicode) (*env)->GetStringChars (env, volName, NULL);

   /* do NOT call __UnicodePathToLocalStr() here because this is not
      a string that should treat the backslash special */

   ccode = __UnicodeToLocalStr (
         volNameStr,
         sizeof (volNameStr),
         uniVolNameStr,
         (*env)->GetStringLength (env, volName));

   if (ccode != 0)
      goto EXIT;

   ccode = NWSMMountVolume (
         (NWCONN_HANDLE) connHandle,
         volNameStr,
         &newVolNumber);

   if (ccode == 0)
   {
      if (volNumber != NULL)
      {
         jint temp = (jint) newVolNumber;

         (*env)->SetIntArrayRegion (env, volNumber, 0, 1, &temp);
      }
   }

EXIT:

   (*env)->ReleaseStringChars (env, volName, uniVolNameStr);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWSMDismountVolumeByName
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jstring volName
)
{
   NWRCODE ccode;
   nstr8 volNameStr[17];
   punicode uniVolNameStr;

   uniVolNameStr = (punicode) (*env)->GetStringChars (env, volName, NULL);
   if(uniVolNameStr == NULL)
      return -1;

   /* do NOT call __UnicodePathToLocalStr() here because this is not
      a string that should treat the backslash special */

   ccode = __UnicodeToLocalStr (
         volNameStr,
         sizeof (volNameStr),
         uniVolNameStr,
         (*env)->GetStringLength (env, volName));

   if (ccode == 0)
   {
      ccode = NWSMDismountVolumeByName (
            (NWCONN_HANDLE) connHandle,
            volNameStr);
   }

   (*env)->ReleaseStringChars (env, volName, uniVolNameStr);

   return ((jint) ccode);
}

//
// START copy of code from new library function
// NOTE: REMOVE THIS CODE WHEN WE START USING THE SDK WITH THIS NEW API
//

typedef struct tagNWNCPVolMountStruct_internal
{
   nuint32  luVolumeNumber;
} NWNCPVolMountStruct_internal, N_FAR *pNWNCPVolMountStruct_internal;

typedef struct tagNWNCPVolMountStructWithName_internal
{
   nuint32  luVolumeNumber;
   nuint8   buVolumeNameLength;
   nstr8    pbstrVolumeName[16];
} NWNCPVolMountStructWithName_internal,
  N_FAR *pNWNCPVolMountStructWithName_internal;

typedef struct tagNWNCPVolMountStructItems_internal
{
   nuint32 luItemsReturned;
   union
   {
      NWNCPVolMountStruct_internal           aItemsB64[64];
      NWNCPVolMountStructWithName_internal   aItemsWithNameB64[64];
   } u;
} NWNCPVolMountStructItems_internal,
  N_FAR *pNWNCPVolMountStructItems_internal;

/* define the constant for volume request flag for NWScanMountedVolumeList */
#ifndef NW_VOLUME_NUMBER_ONLY
#define NW_VOLUME_NUMBER_ONLY       0
#endif
#ifndef NW_VOLUME_NUMBER_AND_NAME
#define NW_VOLUME_NUMBER_AND_NAME   1
#endif

typedef struct NWVolMountNumWithName_tag_internal
{
   nuint32 volumeNumber;
   nstr8   volumeName[NW_MAX_VOLUME_NAME_LEN];
} NWVolMountNumWithName_internal;

NWRCODE
__NWNCP22s52GetMountVolList
(
   NWCONN_HANDLE     connHandle,
   nuint32           luVolNum,
   nuint32           luVolRequestFlags,
   nuint32           luNameSpace,
   pnuint32          pluNextVolNumber,
   pNWNCPVolMountStructItems_internal  pVolMountItems
)
{
   #define NCP_FUNCTION    ((nuint) 22)
   #define NCP_SUBFUNCTION ((nuint8) 52)
   #define NCP_STRUCT_LEN  ((nuint16) 13)
   #define MAX_VOLMOUNT_LEN ((nuint) 530)
   #define NCP_REQ_LEN     ((nuint) 15)
   #define NCP_REPLY_LEN   ((nuint) 8)
   #define NCP_REQ_FRAGS   ((nuint) 1)
   #define NCP_REPLY_FRAGS ((nuint) 2)

   nint32  lCode;
   nuint16 suNCPLen;
   NW_FRAGMENT reqFrag[NCP_REQ_FRAGS], replyFrag[NCP_REPLY_FRAGS];
   nuint8  abuReq[NCP_REQ_LEN], abuReply[NCP_REPLY_LEN];
   nuint8  abuVolMountInfo[MAX_VOLMOUNT_LEN];

   suNCPLen  = NCP_STRUCT_LEN;
   NCopyHiLo16(&abuReq[0], &suNCPLen);

   abuReq[2] = NCP_SUBFUNCTION;
   NCopyLoHi32(&abuReq[3], &luVolNum);
   NCopyLoHi32(&abuReq[7], &luVolRequestFlags);
   NCopyLoHi32(&abuReq[11], &luNameSpace);

   reqFrag[0].fragAddress   = abuReq;
   reqFrag[0].fragSize      = NCP_REQ_LEN;

   replyFrag[0].fragAddress = abuReply;
   replyFrag[0].fragSize    = NCP_REPLY_LEN;

   replyFrag[1].fragAddress = abuVolMountInfo;
   replyFrag[1].fragSize    = MAX_VOLMOUNT_LEN;

   lCode = NWRequest(connHandle, NCP_FUNCTION, NCP_REQ_FRAGS, reqFrag,
               NCP_REPLY_FRAGS, replyFrag);
   if (lCode == 0)
   {
      nuint32 max, i = 0;
      int counter;

      NCopyLoHi32(&pVolMountItems->luItemsReturned, &abuReply[0]);
      NCopyLoHi32(pluNextVolNumber,                 &abuReply[4]);

      counter = 0;
      i = 0;
      max = pVolMountItems->luItemsReturned;

      if ((luVolRequestFlags & NW_VOLUME_NUMBER_AND_NAME) != 0)
      {
         #if defined DEBUG
         {
            nuint32 avail =
               MAX_VOLMOUNT_LEN / sizeof(NWNCPVolMountStructWithName_internal);
            assert( max <= avail);
         }
         #endif

         for (; i < max; i++)
         {
            NCopyLoHi32(&pVolMountItems->u.aItemsWithNameB64[i].
                  luVolumeNumber, &abuVolMountInfo[counter]);

            pVolMountItems->u.aItemsWithNameB64[i].buVolumeNameLength
                   =	abuVolMountInfo[counter + 4];

            memcpy(pVolMountItems->u.aItemsWithNameB64[i].pbstrVolumeName,
                  &abuVolMountInfo[counter + 5],
                  pVolMountItems->u.aItemsWithNameB64[i].buVolumeNameLength);

            counter += 5 + pVolMountItems->u.aItemsWithNameB64[i].
                  buVolumeNameLength;
         }
      }
      else
      {
         #if defined DEBUG
         {
            nuint32 avail =
               MAX_VOLMOUNT_LEN / sizeof(NWNCPVolMountStruct_internal);
            assert( max <= avail);
         }
         #endif

         for (; i < max; i++)
         {
            NCopyLoHi32(&pVolMountItems->u.aItemsB64[i].
                  luVolumeNumber, &abuVolMountInfo[counter]);

            counter += 4;
         }
      }
   }

   return ((NWRCODE) lCode);

   #undef NCP_FUNCTION
   #undef NCP_SUBFUNCTION
   #undef NCP_STRUCT_LEN
   #undef MAX_VOLMOUNT_LEN
   #undef NCP_REQ_LEN
   #undef NCP_REPLY_LEN
   #undef NCP_REQ_FRAGS
   #undef NCP_REPLY_FRAGS
}

NWRCODE
__NWScanMountedVolumeList
(
   NWCONN_HANDLE        conn,
   nuint32              volRequestFlags,
   nuint32              nameSpace,
   pnuint32             volNumber,
   nuint32              numberItems,
   pnuint32             numberReturned,
   NWVolMountNumWithName_internal *volMountArr
)
{
   NWRCODE ccode;
   nuint32 volNum = *volNumber;
   NWNCPVolMountStructItems_internal volItems;
   nuint32 i=0, j;
   nuint32 breakflag = 0;

   if(0 == numberItems)
      return INVALID_PARAMETER;

   if((NW_VOLUME_NUMBER_ONLY != volRequestFlags)
      && (NW_VOLUME_NUMBER_AND_NAME != volRequestFlags))
      return INVALID_PARAMETER;

   do
   {
      ccode = __NWNCP22s52GetMountVolList(conn,
                                          volNum,
                                          volRequestFlags,
                                          nameSpace,
                                          &volNum,
                                          &volItems);
      if(0 == ccode)
      {
         for(j = 0; j < volItems.luItemsReturned; j++)
         {
            if(i < numberItems)
            {
               if(NW_VOLUME_NUMBER_ONLY == volRequestFlags)
               {
                  volMountArr[i].volumeNumber =
                     volItems.u.aItemsB64[j].luVolumeNumber;
               }
               else
               {
                  pNWNCPVolMountStructWithName_internal ptr =
                     &volItems.u.aItemsWithNameB64[j];

                  volMountArr[i].volumeNumber = ptr->luVolumeNumber;
                  memcpy(volMountArr[i].volumeName,
                             ptr->pbstrVolumeName,
                             ptr->buVolumeNameLength);

                  volMountArr[i].volumeName[ptr->buVolumeNameLength] = '\0';
               }
               ++i;
            }
            else
            {
               /* buffer from users is full */
               breakflag = 1;
               *volNumber = *volNumber + i;
               *numberReturned = i;

               break;
            }
         }

         if((0 == breakflag) && (0 == volNum))
         {
            /* Done with all volume */
            breakflag = 1;
            *volNumber = 0;
            *numberReturned = i;
         }
      }
      else
         breakflag = 1;

   } while(0 == breakflag);

   return(ccode);
}

//
// END copy of code from new library function
// NOTE: REMOVE THIS CODE WHEN WE START USING THE SDK WITH THIS NEW API
//

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWScanMountedVolumes
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint startVolNumber,
   jobjectArray numbers,   // int[1][]
   jobjectArray names,     // String[1][]
   jintArray nextVolNumber
)
{
   NWRCODE ccode;
   NWVolMountNumWithName_internal mountedVols[15];
   nuint32 itemsReturned;
   nuint32 volNumber = (nuint32) startVolNumber;

   ccode = __NWScanMountedVolumeList(
         (NWCONN_HANDLE) connHandle,
         NW_VOLUME_NUMBER_AND_NAME,
         0,    // pass DOS name space
         &volNumber,
         sizeof(mountedVols) / sizeof(NWVolMountNumWithName_internal),
         &itemsReturned,
         mountedVols);

   if (0 == ccode)
   {
      jclass clazz;
      jobjectArray nameArr;
      jobjectArray numberArr;
      unicode volNameBuf[NW_MAX_VOLUME_NAME_LEN];

      clazz = (*env)->FindClass(env, "java/lang/String");
      if (0 == clazz)
         return (-1);      // exception already posted

      nameArr = (*env)->NewObjectArray(env, (jsize) itemsReturned,
            clazz, NULL);

      if (NULL == nameArr)
         return (-1);

      numberArr = (*env)->NewIntArray(env, (jsize) itemsReturned);
      if (NULL == numberArr)
         return (-1);

      while (itemsReturned--)
      {
         jstring jVolName;
         jint temp;

         ccode = __LocalToJavaStr(
               env,
               &jVolName,
               volNameBuf,
               mountedVols[itemsReturned].volumeName);

         if (ccode != 0)
            return ((jint) ccode);

         (*env)->SetObjectArrayElement(env, nameArr, itemsReturned,
               jVolName);

         temp = (jint) mountedVols[itemsReturned].volumeNumber;

         (*env)->SetIntArrayRegion(env, numberArr, (jsize) itemsReturned,
               1, &temp);
      }

      // actually store the new string array as the first element in 'names'
      (*env)->SetObjectArrayElement(env, names, 0, nameArr);

      // actually store the new int array as the first element in 'numbers'
      (*env)->SetObjectArrayElement(env, numbers, 0, numberArr);

      // store the next volume number into the array
      startVolNumber = (jint) volNumber;
      (*env)->SetIntArrayRegion(env, nextVolNumber, 0, 1, &startVolNumber);
   }

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWAllocTempNSDirHandle
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint dirHandle,
   jstring path,
   jint srcNameSpace,
   jint dstNameSpace,
   jintArray newDirHandle
)
{
   NWRCODE ccode;
   nstr8 pathStr[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniPathStr;
   nuint8 buNewDirHandle;

   uniPathStr = (punicode) (*env)->GetStringChars(env, path, NULL);

   ccode = __UnicodePathToLocalStr(
         pathStr,
         sizeof(pathStr),
         uniPathStr,
         (*env)->GetStringLength (env, path));

   if (ccode != 0)
      goto EXIT;

   ccode = NWAllocTempNSDirHandle2(
         (NWCONN_HANDLE) connHandle,
         (nuint8) dirHandle,
         pathStr,
         (nuint8) srcNameSpace,
         &buNewDirHandle,
         (nuint8) dstNameSpace);

   if (0 == ccode)
   {
      jint temp = (jint) buNewDirHandle;

      (*env)->SetIntArrayRegion(env, newDirHandle, 0, 1, &temp);
   }

EXIT:

   (*env)->ReleaseStringChars(env, path, uniPathStr);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWDeallocateDirectoryHandle
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint dirHandle
)
{
   return ((jint) NWDeallocateDirectoryHandle((NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle));
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWScanForDeletedFiles
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint dirHandle,
   jintArray iterHandle,
   jintArray volNum,
   jintArray dirBase,
   jobject info      // DeletedFileInfoImpl
)
{
   NWRCODE ccode;
   nuint32 luIterHandle;
   nuint32 luVolNum, luDirBase;
   NWDELETED_INFO i;
   jint temp;

   (*env)->GetIntArrayRegion(env, iterHandle, 0, 1, &temp);

   luIterHandle = (nuint32) temp;

   ccode = NWScanForDeletedFiles(
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         &luIterHandle,
         &luVolNum,
         &luDirBase,
         &i);

   if (0 == ccode)
   {
      jclass clazz;
      jfieldID fid;
      jstring javaName;
      unicode uniNameStr[__jncpv2r_MAX_PATH_LENGTH];
      nstr8 nameStr[__jncpv2r_MAX_PATH_LENGTH];

      temp = (jint) luIterHandle;
      (*env)->SetIntArrayRegion(env, iterHandle, 0, 1, &temp);

      temp = (jint) luVolNum;
      (*env)->SetIntArrayRegion(env, volNum, 0, 1, &temp);

      temp = (jint) luDirBase;
      (*env)->SetIntArrayRegion(env, dirBase, 0, 1, &temp);

      clazz = (*env)->GetObjectClass(env, info);
      fid = (*env)->GetFieldID(env, clazz, "parent", "I");
      (*env)->SetIntField(env, info, fid, (jint) i.parent);

      fid = (*env)->GetFieldID(env, clazz, "attributes", "I");
      (*env)->SetIntField(env, info, fid, (jint) i.attributes);

      fid = (*env)->GetFieldID(env, clazz, "uniqueID", "I");
      (*env)->SetIntField(env, info, fid, (jint) i.uniqueID);

      fid = (*env)->GetFieldID(env, clazz, "flags", "I");
      (*env)->SetIntField(env, info, fid, (jint) i.flags);

      fid = (*env)->GetFieldID(env, clazz, "nameSpace", "I");
      (*env)->SetIntField(env, info, fid, (jint) i.nameSpace);

      fid = (*env)->GetFieldID(env, clazz, "creationDateAndTime", "I");
      (*env)->SetIntField(env, info, fid, (jint) i.creationDateAndTime);

      fid = (*env)->GetFieldID(env, clazz, "ownerID", "I");
      (*env)->SetIntField(env, info, fid, (jint) i.ownerID);

      fid = (*env)->GetFieldID(env, clazz, "lastArchiveDateAndTime", "I");
      (*env)->SetIntField(env, info, fid, (jint) i.lastArchiveDateAndTime);

      fid = (*env)->GetFieldID(env, clazz, "lastArchiverID", "I");
      (*env)->SetIntField(env, info, fid, (jint) i.lastArchiverID);

      fid = (*env)->GetFieldID(env, clazz, "updateDateAndTime", "I");
      (*env)->SetIntField(env, info, fid, (jint) i.updateDateAndTime);

      fid = (*env)->GetFieldID(env, clazz, "updatorID", "I");
      (*env)->SetIntField(env, info, fid, (jint) i.updatorID);

      fid = (*env)->GetFieldID(env, clazz, "fileSize", "I");
      (*env)->SetIntField(env, info, fid, (jint) i.fileSize);

      fid = (*env)->GetFieldID(env, clazz, "inheritedRightsMask", "I");
      (*env)->SetIntField(env, info, fid, (jint) i.inheritedRightsMask);

      fid = (*env)->GetFieldID(env, clazz, "lastAccessDate", "I");
      (*env)->SetIntField(env, info, fid, (jint) i.lastAccessDate);

      fid = (*env)->GetFieldID(env, clazz, "deletedTime", "I");
      (*env)->SetIntField(env, info, fid, (jint) i.deletedTime);

      fid = (*env)->GetFieldID(env, clazz, "deletedDateAndTime", "I");
      (*env)->SetIntField(env, info, fid, (jint) i.deletedDateAndTime);

      fid = (*env)->GetFieldID(env, clazz, "deletorID", "I");
      (*env)->SetIntField(env, info, fid, (jint) i.deletorID);

      // make sure the string is null-terminated
      memcpy(nameStr, i.name, i.nameLength);
      nameStr[i.nameLength] = 0;

      ccode = __LocalToJavaStr(
            env,
            &javaName,
            uniNameStr,
            nameStr);

      if (ccode != 0)
         return ((jint) ccode);

      fid = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;");
      (*env)->SetObjectField(env, info, fid, javaName);
   }

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWPurgeDeletedFile
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint dirHandle,
   jint iterHandle,
   jint volNum,
   jint dirBase,
   jstring delFileName
)
{
   NWRCODE ccode;
   nstr8 delFileNameStr[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniNameStr;

   uniNameStr = (punicode) (*env)->GetStringChars(env, delFileName, NULL);

   //
   // do not need to call __UnicodePathToLocalStr because this name
   //   does not contain any separators
   //

   ccode = __UnicodeToLocalStr(
         delFileNameStr,
         sizeof(delFileNameStr),
         uniNameStr,
         (*env)->GetStringLength(env, delFileName));

   if (ccode != 0)
      goto EXIT;

   ccode = NWPurgeDeletedFile(
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         (nuint32) iterHandle,
         (nuint32) volNum,
         (nuint32) dirBase,
         delFileNameStr);

EXIT:

   (*env)->ReleaseStringChars(env, delFileName, uniNameStr);

   return ((jint) ccode);
}

//
// does not support the 2.x variant of NWRecoverDeletedFile
//

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWRecoverDeletedFile
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint dirHandle,
   jint iterHandle,
   jint volNum,
   jint dirBase,
   jstring delFileName,
   jstring newFileName
)
{
   NWRCODE ccode;
   nstr8 delFileNameStr[__jncpv2r_MAX_PATH_LENGTH];
   nstr8 newFileNameStr[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniNameStr;
   punicode uniNewNameStr;

   uniNameStr = (punicode) (*env)->GetStringChars(env, delFileName, NULL);
   uniNewNameStr = (punicode) (*env)->GetStringChars(env, newFileName, NULL);

   //
   // do not need to call __UnicodePathToLocalStr because this name
   //   does not contain any separators
   //

   ccode = __UnicodeToLocalStr(
         delFileNameStr,
         sizeof(delFileNameStr),
         uniNameStr,
         (*env)->GetStringLength(env, delFileName));

   if (ccode != 0)
      goto EXIT;

   ccode = __UnicodeToLocalStr(
         newFileNameStr,
         sizeof(newFileNameStr),
         uniNewNameStr,
         (*env)->GetStringLength(env, newFileName));

   if (ccode != 0)
      goto EXIT;

   ccode = NWRecoverDeletedFile(
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         (nuint32) iterHandle,
         (nuint32) volNum,
         (nuint32) dirBase,
         delFileNameStr,
         newFileNameStr);

EXIT:

   (*env)->ReleaseStringChars(env, delFileName, uniNameStr);
   (*env)->ReleaseStringChars(env, newFileName, uniNewNameStr);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWGetEffectiveRights
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint dirHandle,
   jstring path,
   jint nameSpace,
   jintArray effectiveRights
)
{
   NWRCODE ccode;
   nstr8 pathStr[__jncpv2r_MAX_PATH_LENGTH];
   nstr8 defNSPathStr[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniPathStr;
   nuint16 suEffectiveRights;

   uniPathStr = (punicode) (*env)->GetStringChars(env, path, NULL);

   ccode = __UnicodePathToLocalStr(
         pathStr,
         sizeof(pathStr),
         uniPathStr,
         (*env)->GetStringLength (env, path));

   (*env)->ReleaseStringChars(env, path, uniPathStr);

   if (ccode != 0)
      return ((jint) ccode);

   ccode = __GetDefaultNSPath(
         (NWCONN_HANDLE) connHandle,
         (nuint8) dirHandle,
         pathStr,
         (nuint8) nameSpace,
         defNSPathStr);

   if (ccode != 0)
      return ((jint) ccode);

   ccode = NWGetEffectiveRights(
         (NWCONN_HANDLE) connHandle,
         (nuint8) dirHandle,
         defNSPathStr,
         &suEffectiveRights);

   if (0 == ccode)
   {
      jint temp = (jint) suEffectiveRights;

      (*env)->SetIntArrayRegion(env, effectiveRights, 0, 1, &temp);
   }

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWGetObjectEffectiveRights
(
   JNIEnv   *env,
   jclass   obj,
   jint     connHandle,
   jint     objID,
   jint     dirHandle,
   jstring  path,
   jint     nameSpace,
   jintArray  rights
)
{
   NWCCODE ccode;
   nstr8 pathStr[__jncpv2r_MAX_PATH_LENGTH];
   nstr8 scratch[__jncpv2r_MAX_PATH_LENGTH];
   punicode uniPath;
   nuint16 suEffectiveRights;
   NW_ENTRY_INFO info;
   nuint8 tmpDirHandle;
   int isDir;

   // Convert Java variable into 'C' variable
   uniPath = (punicode) (*env)->GetStringChars(env,path,0);

   ccode = __UnicodePathToLocalStr (
               pathStr,
               sizeof(pathStr),
               uniPath,
               (*env)->GetStringLength(env,path));

   (*env)->ReleaseStringChars(env,path,uniPath);

   if (ccode != 0)
      return ((jint) ccode);

   ccode = NWGetNSEntryInfo(
         (NWCONN_HANDLE) connHandle,
         (nuint8) dirHandle,
         pathStr,
         (nuint8) nameSpace,
         0,    // DOS name space info
         TA_ALL,  // search all entries
         IM_ENTRY_NAME | IM_ATTRIBUTES,
         &info);

   if (ccode != 0)
      return ((jint) ccode);

   if ((info.attributes & FA_DIRECTORY) != 0)
      isDir = 1;
   else
      isDir = 0;

   if (isDir)
   {
      ccode = NWAllocTempNSDirHandle2(
            (NWCONN_HANDLE) connHandle,
            (nuint8) dirHandle,
            pathStr,
            (nuint8) nameSpace,
            &tmpDirHandle,
            0);   // we have to force DOS name space for the eff. rights
   }
   else
   {
      ccode = __AllocTempNSContainerDirHandle2(
            (NWCONN_HANDLE) connHandle,
            (nuint8) dirHandle,
            pathStr,
            (nuint8) nameSpace,
            &tmpDirHandle,
            0,    // we have to force DOS name space for the eff. rights
            scratch);
   }

   if (ccode != 0)
      return ((jint) ccode);

   ccode = NWGetObjectEffectiveRights (
               connHandle,
               (nuint32) objID,
               tmpDirHandle,
               isDir ? "" : info.entryName,
               &suEffectiveRights);

   (void) NWDeallocateDirectoryHandle(
         (NWCONN_HANDLE) connHandle,
         tmpDirHandle);

   if (0 == ccode)
   {
      jint temp = (jint) suEffectiveRights;

      (*env)->SetIntArrayRegion(env, rights, 0, 1, &temp);
   }

   return (ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWScanObjectTrusteePaths
(
   JNIEnv   *env,
   jclass   obj,
   jint     connHandle,
   jint     objID,
   jint     volNumber,
   jint     nameSpace,
   jintArray iterHandle,
   jintArray rights,
   jobjectArray path
)
{
   NWCCODE ccode;
   nuint16 suIterHandle;
   nuint8 buRights;
   nstr8 pathStr[__jncpv2r_MAX_PATH_LENGTH];
   jint temp;

   (*env)->GetIntArrayRegion(env, iterHandle, 0, 1, &temp);
   suIterHandle = (nuint16) temp;

   ccode = NWScanObjectTrusteePaths(
         (NWCONN_HANDLE) connHandle,
         (nuint32) objID,
         (nuint16) volNumber,
         &suIterHandle,
         &buRights,
         pathStr);

   if (ccode == 0)
   {
      jstring jPath;
      unicode uniPath[sizeof(pathStr)];

      temp = (jint) suIterHandle;
      (*env)->SetIntArrayRegion(env, iterHandle, 0, 1, &temp);

      if (rights != NULL)
      {
         temp = (jint) buRights;
         (*env)->SetIntArrayRegion(env, rights, 0, 1, &temp);
      }

      // empty string in 'pathStr' signifies end-of-list
      // no NS conversion necessary for DOS name space
      if (nameSpace != NW_NS_DOS && NWstrlen(pathStr) > 0)
      {
         nstr8 scratch[__jncpv2r_MAX_PATH_LENGTH];
         ccode = __GetNSPath((NWCONN_HANDLE) connHandle, (NWDIR_HANDLE)0,
            pathStr, NW_NS_DOS, scratch, (nuint8) nameSpace);
         if (ccode != 0)
            return ((jint) ccode);

         NWLstrbcpy(pathStr, scratch, sizeof(pathStr));
      }

      ccode = __LocalToJavaStr (
            env,
            &jPath,
            uniPath,
            pathStr);

      if (ccode == 0)
         (*env)->SetObjectArrayElement (env, path, 0, jPath);
   }

   return (ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWOpenSemaphore
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jstring semaphoreName,
   jint resourceAccessCount,
   jintArray semaphoreHandle,
   jintArray semaphoreOpenCount
)
{
   NWRCODE ccode;
   nstr8 nameStr[128];  // see nwsync.h - CONN_SEMAPHORE.semaphoreName
   punicode uniNameStr;
   nuint32 semHandle;
   nuint16 semOpenCount;

   uniNameStr = (punicode) (*env)->GetStringChars (env, semaphoreName, NULL);

   /* do NOT call __UnicodePathToLocalStr() here because this is not
      a string that should treat the backslash special */

   ccode = __UnicodeToLocalStr (
         nameStr,
         sizeof (nameStr),
         uniNameStr,
         (*env)->GetStringLength (env, semaphoreName));

   if (ccode != 0)
      goto EXIT;

   ccode = NWOpenSemaphore(
      (NWCONN_HANDLE) connHandle,
      nameStr,
      (nint16) resourceAccessCount,
      &semHandle,
      &semOpenCount);

   if (ccode == 0)
   {
      if (semaphoreHandle != NULL)
      {
         jint temp = (jint) semHandle;

         (*env)->SetIntArrayRegion (env, semaphoreHandle, 0, 1, &temp);
      }

      if (semaphoreOpenCount != NULL)
      {
         jint temp = (jint) semOpenCount;

         (*env)->SetIntArrayRegion (env, semaphoreOpenCount, 0, 1, &temp);
      }
   }

EXIT:

   (*env)->ReleaseStringChars (env, semaphoreName, uniNameStr);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWExamineSemaphore
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint semaphoreHandle,
   jintArray semaphoreValue,
   jintArray semaphoreOpenCount
)
{
   NWRCODE ccode;
   nint16 semValue;
   nuint16 semOpenCount;

   ccode = NWExamineSemaphore(
            (NWCONN_HANDLE) connHandle,
            (nuint32) semaphoreHandle,
            &semValue,
            &semOpenCount);

   if (ccode == 0)
   {
      if (semaphoreValue != NULL)
      {
         jint temp = (jint) semValue;

         (*env)->SetIntArrayRegion (env, semaphoreValue, 0, 1, &temp);
      }

      if (semaphoreOpenCount != NULL)
      {
         jint temp = (jint) semOpenCount;

         (*env)->SetIntArrayRegion (env, semaphoreOpenCount, 0, 1, &temp);
      }
   }
   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWWaitOnSemaphore
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint semaphoreHandle,
   jint timeOutValue
)
{
   NWRCODE ccode;

   ccode = NWWaitOnSemaphore(
            (NWCONN_HANDLE) connHandle,
            (nuint32) semaphoreHandle,
            (nuint16) timeOutValue);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWSignalSemaphore
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint semaphoreHandle
)
{
   NWRCODE ccode;

   ccode = NWSignalSemaphore(
            (NWCONN_HANDLE) connHandle,
            (nuint32) semaphoreHandle);
   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2r_cal_CalJNI_NWCloseSemaphore
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint semaphoreHandle
)
{
   NWRCODE ccode;

   ccode = NWCloseSemaphore(
            (NWCONN_HANDLE) connHandle,
            (nuint32) semaphoreHandle);
   return ((jint) ccode);
}

