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

  %name: fileJNI.c %
  %version: 2 %
  %date_modified: Mon Jun 14 14:20:02 2004 %

  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_jncpv2_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"

/*
 * As of this build (01/04) we now handle all file paths in unicode - no more
 * translation.
 */

#define __jncpv2_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,
   pnuint8 path,        //null terminated UTF8 string
   nuint16 pathLen,     //for convienence
   nuint8 nameSpace,
   NWDIR_HANDLE *newDirHandle,
   nuint8 destNameSpace,
   pnuint8 atomicEntry  //will be set to a null terminated UTF8 string
)
{
   NWRCODE ccode;
   nuint8 working;
   pnuint8 srchPattern;

   /*...cut off last portion of path...*/
   srchPattern = &path[pathLen-1];

   working = *srchPattern;

   //This comparison still works with UTF8 encoded multibyte characters because
   //trailing bytes always have the high bit set so they will never match.
   while((srchPattern != path) &&
         (working != '\\') &&
         (working != '/') &&
         (working != ':'))
   {
      srchPattern--;
      working = *srchPattern;
   }

   if (srchPattern != path)  // if atomic entry was found
   {
      nuint8 containerStr[__jncpv2_MAX_PATH_LENGTH*3];
      int bytesToCopy = srchPattern - path;

      // copy all chars up to but not including the separator char
      memcpy (containerStr, path, bytesToCopy);
      containerStr[bytesToCopy] = 0;

      srchPattern++; //skip past the separator

      if (newDirHandle != NULL)
      {
         nuint8 nameSpaceHolder;

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

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

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

      //copy the rest of the string including the null terminator
      memcpy(atomicEntry, srchPattern, ((&path[pathLen]) - srchPattern) + 1 );

      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,
   pnuint8 path,        //null term UTF8 string
   nuint16 pathLen,
   nuint8 nameSpace,
   NWDIR_HANDLE *newDirHandle,
   pnuint8 atomicEntry  //null term UTF8 string
)
{
   return (__AllocTempNSContainerDirHandle2(connHandle, dirHandle, path, pathLen,
         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 utf8 arrays.
 */

NWRCODE
__GetNSPath
(
   NWCONN_HANDLE connHandle,
   NWDIR_HANDLE dirHandle,
   pnuint8 srcPath,       //null term UTF8 string
   nuint16 srcPathLen,
   nuint8 srcNameSpace,
   pnuint8 dstPath,       //will be set to null term UTF8 string
   pnuint16 dstPathLen,   //will be set to length
   nuint8 dstNameSpace
)
{
   if (srcNameSpace == dstNameSpace)
   {
      memcpy(dstPath, srcPath, srcPathLen + 1); //include null term
      *dstPathLen = srcPathLen;
   }
   else
   {
      NWRCODE ccode;
      NW_ENTRY_INFO_EXT info;
      int fileFlag;
      nuint8 buf[2048*3];
      NW_NS_PATH pathStruct;
      pnuint8 tmp;
      nuint8 pathSeparator = '\\';
      nuint16 dstLen, entryLen; 

      ccode = NWGetNSEntryInfoExt (
            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 = NWGetNSPathExt (
            connHandle,
            dirHandle,
            (nuint16) fileFlag,
            srcNameSpace,
            dstNameSpace,
            &pathStruct);

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

      tmp = dstPath;

      dstLen = NWstrlen(pathStruct.dstPath);
      memcpy(tmp, pathStruct.dstPath, dstLen+1); //include null term
      //tmp += (dstLen+1); //BWD - DEFECT000374475 
      if(fileFlag)
      {
         tmp += dstLen; //BWD - DEFECT000374475 
         entryLen = NWstrlen(info.entryName);
         memcpy(tmp++, &pathSeparator, 1);
         memcpy(tmp, info.entryName, entryLen+1); //include null term
         *dstPathLen = dstLen + 1 + entryLen;
      }
      else
      {
         *dstPathLen = dstLen;
      }
   }

   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,
   pnuint8  srcPath,        //null term UTF8 string
   nuint16  srcPathLen,
   nuint8   srcNameSpace,
   pnuint8  dstPath,        //null term UTF8 string
   pnuint16 dstPathLen
)
{
   nuint8 dstNameSpace;

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

   return (__GetNSPath(connHandle, dirHandle, srcPath, srcPathLen, srcNameSpace,
         dstPath, dstPathLen, 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,
   pnuint8 path,      //null term UTF8 string
   nuint16 pathLen,
   nuint8 srcNameSpace,
   nuint8 dstNameSpace,
   NW_IDX *idx
)
{
   NWRCODE ccode;
   NW_ENTRY_INFO_EXT entryInfo;

   ccode = NWGetNSEntryInfoExt (
         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_jncpv2_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_EXT entryInfo;
   nuint8 pathStr[__jncpv2_MAX_PATH_LENGTH * 3];
   pnuint8 utfPathStr;

   utfPathStr = (pnuint8) (*env)->GetStringUTFChars (env, path, NULL);

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

   (*env)->ReleaseStringUTFChars (env, path, utfPathStr);

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

      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

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

      name = (*env)->NewStringUTF(env, pathStr);

      if (name == NULL)
      {
         ccode = -1;
         goto HARD_EXIT;
      }

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

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

   HARD_EXIT:

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2_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_EXT entryInfo;
   SEARCH_SEQUENCE searchSequence;
   nuint8 patternStr[__jncpv2_MAX_PATH_LENGTH * 3];
   pnuint8 utfStr;
   nuint16 strLen;
   NWDIR_HANDLE tmpDirHandle = 0;
   jint *volNumberArr, *dirNumberArr, *searchDirNumberArr;
   jint searchDirNumberHolder;
   int firstScan;

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

   firstScan = (searchDirNumberHolder == -1);

   utfStr = (pnuint8) (*env)->GetStringUTFChars(env, pattern, NULL);
   strLen = (nuint16) (*env)->GetStringUTFLength(env, pattern);
   memcpy(patternStr, utfStr, strLen+1);
   (*env)->ReleaseStringUTFChars (env, pattern, utfStr);

   ccode = __AllocTempNSContainerDirHandle (
         connHandle,
         (nuint8) dirHandle,
         patternStr,
         strLen,
         (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 = NWScanNSEntryInfoExt (
         (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;

      // 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';

      name = (*env)->NewStringUTF(env, patternStr);
      if (name == NULL)
      {
         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:

HARD_EXIT:

   return ((jint) ccode);
}

/* volume names are 8bit so we dont need to multi byte enable volume only functions */
JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2_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_jncpv2_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_jncpv2_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_jncpv2_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;
   pnuint8 utfPathStr;

   utfPathStr = (pnuint8) (*env)->GetStringUTFChars (env, path, NULL);

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

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

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

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

   (*env)->ReleaseStringUTFChars (env, path, utfPathStr);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2_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;
   pnuint8 utfPathStr;

   utfPathStr = (pnuint8) (*env)->GetStringUTFChars (env, path, NULL);

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

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

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

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

   (*env)->ReleaseStringUTFChars (env, path, utfPathStr);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2_cal_CalJNI_NWDeleteNSEntry
(
   JNIEnv   *env,
   jclass   unused,
   jint     connHandle,
   jint     dirHandle,
   jstring  path,
   jint     nameSpace,
   jint     searchAttr
)
{
   NWRCODE ccode;
   pnuint8 utfPathStr;

   utfPathStr = (pnuint8) (*env)->GetStringUTFChars (env, path, NULL);

   ccode = NWDeleteNSEntryExt (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         utfPathStr,
         (nuint8) nameSpace,
         (nuint16) searchAttr);

   (*env)->ReleaseStringUTFChars (env, path, utfPathStr);

   return ((jint) ccode);
}


//
// only works when the dir handle coming in is zero (0)
//
JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2_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;
   nuint8 oldNameStr[__jncpv2_MAX_PATH_LENGTH * 3];
   nuint8 newNameStr[__jncpv2_MAX_PATH_LENGTH * 3];
   pnuint8 utfOldNameStr, utfNewNameStr;
   nuint16 oldLen, newLen;

   utfOldNameStr = (pnuint8) (*env)->GetStringUTFChars (env, oldName, NULL);
   utfNewNameStr = (pnuint8) (*env)->GetStringUTFChars (env, newName, NULL);
   oldLen = (nuint16) (*env)->GetStringUTFLength (env, oldName);
   newLen = (nuint16) (*env)->GetStringUTFLength (env, newName);

   memcpy(oldNameStr, utfOldNameStr, oldLen + 1 ); //include null term
   memcpy(newNameStr, utfNewNameStr, newLen + 1 ); //include null term

   (*env)->ReleaseStringUTFChars (env, oldName, utfOldNameStr);
   (*env)->ReleaseStringUTFChars (env, newName, utfNewNameStr);

   if (dirHandle == 0)
   {
      ccode = __AllocTempNSContainerDirHandle (
            connHandle,
            (nuint8) dirHandle,
            oldNameStr,
            oldLen,
            (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 = NWNSRenameExt (
         (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:

   return ((jint) ccode);
}

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

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

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

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2_cal_CalJNI_NWOpenEA
(
   JNIEnv   *env,
   jclass   unused,
   jint     connHandle,
   jint     dirHandle,
   jstring  path,
   jstring  EAName,
   jint     nameSpace,
   jint     EAHandle
)
{
   NWRCODE ccode;
   NW_EA_HANDLE_EXT *EAHandlePtr;
   pnuint8 utfPathStr, utfEANameStr;

   utfPathStr = (pnuint8) (*env)->GetStringUTFChars (env, path, NULL);
   utfEANameStr = (pnuint8) (*env)->GetStringUTFChars (env, EAName, NULL);

#ifdef N_PLAT_NLM

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

#endif

   EAHandlePtr = (NW_EA_HANDLE_EXT *) EAHandle;

   ccode = NWOpenEAExt (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         utfPathStr,
         utfEANameStr,
         (nuint8) nameSpace,
         EAHandlePtr);

#ifdef N_PLAT_NLM

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

#endif

   (*env)->ReleaseStringUTFChars (env, path, utfPathStr);
   (*env)->ReleaseStringUTFChars (env, EAName, utfEANameStr);

   return ((jint) ccode);
}

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

#ifdef N_PLAT_NLM

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

#endif

   EAHandlePtr = (NW_EA_HANDLE_EXT *) EAHandle;

   ccode = NWCloseEAExt (EAHandlePtr);

#ifdef N_PLAT_NLM

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

#endif

   return ((jint) ccode);
}

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

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

#ifdef N_PLAT_NLM

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

#endif

   EAHandlePtr = (NW_EA_HANDLE_EXT *) EAHandle;

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

#ifdef N_PLAT_NLM

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

#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_jncpv2_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_EXT *EAHandlePtr;

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

#ifdef N_PLAT_NLM

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

#endif

   EAHandlePtr = (NW_EA_HANDLE_EXT *) EAHandle;

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

#ifdef N_PLAT_NLM

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

#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_jncpv2_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;
   nuint8 EANameStr[__jncpv2_MAX_PATH_LENGTH * 3];
   pnuint8 utfPathStr;
   nuint16 utfPathStrLen;
   NW_EA_FF_STRUCT_EXT *ffStructPtr;
   NW_EA_HANDLE_EXT *EAHandlePtr;

   utfPathStr = (pnuint8) (*env)->GetStringUTFChars (env, path, NULL);
   utfPathStrLen = (nuint16) (*env)->GetStringUTFLength (env, path);

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

   if (ccode != 0)
      goto EXIT;

#ifdef N_PLAT_NLM

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

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

#endif

   {
      ffStructPtr = (NW_EA_FF_STRUCT_EXT *) EAFFStruct;
      EAHandlePtr = (NW_EA_HANDLE_EXT *) EAHandle;
   }

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

#ifdef N_PLAT_NLM

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

#endif

   if (ccode == 0)
   {
      jclass clazz;
      jmethodID mid;
      jstring javaEAName;

      javaEAName = (*env)->NewStringUTF(env, EANameStr);

      if (javaEAName == NULL)
      {
         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)->ReleaseStringUTFChars (env, path, utfPathStr);

HARD_EXIT:

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2_cal_CalJNI_NWFindNextEA
(
   JNIEnv   *env,
   jclass   unused,
   jint     EAFFStruct,
   jint     EAHandle,
   jobject  EAName
)
{
   NWRCODE ccode;
   nuint8 EANameStr[__jncpv2_MAX_PATH_LENGTH * 3];
   NW_EA_FF_STRUCT_EXT *ffStructPtr;
   NW_EA_HANDLE_EXT *EAHandlePtr;

#ifdef N_PLAT_NLM

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

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

#endif

   {
      ffStructPtr = (NW_EA_FF_STRUCT_EXT *) EAFFStruct;
      EAHandlePtr = (NW_EA_HANDLE_EXT *) EAHandle;
   }

   ccode = NWFindNextEAExt (
         ffStructPtr,
         EAHandlePtr,
         EANameStr);

#ifdef N_PLAT_NLM

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

#endif

   if (ccode == 0)
   {
      jclass clazz;
      jmethodID mid;
      jstring javaEAName;

      javaEAName = (*env)->NewStringUTF(env, EANameStr);

      if (javaEAName == NULL)
         ccode = -1;
      else
      {
         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_jncpv2_cal_CalJNI_NWScanForTrustees
(
   JNIEnv   *env,
   jclass   unused,
   jint     connHandle,
   jint     dirHandle,
   jstring  path,
   jint     nameSpace,
   jobject  tEnum
)
{
   NWRCODE ccode;
   NWET_INFO_EXT trustees;
   nuint32 iterHandle;
   nuint16 numOfEntries;
   jclass clazz;
   jfieldID fid;
   nuint8 defaultNSName[__jncpv2_MAX_PATH_LENGTH * 3];
   pnuint8 utfPathStr;
   nuint16 utfPathLen, scratchLen;

   utfPathStr = (pnuint8) (*env)->GetStringUTFChars (env, path, NULL);
   utfPathLen = (nuint16) (*env)->GetStringUTFLength (env, path);

   ccode = __GetDefaultNSPath (
         (NWCONN_HANDLE) connHandle,
         0,       // no dir handle
         utfPathStr,
         utfPathLen,
         (nuint8) nameSpace,
         defaultNSName,
         &scratchLen);

   (*env)->ReleaseStringUTFChars (env, path, utfPathStr);
   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 = NWScanForTrusteesExt (
         (NWCONN_HANDLE) connHandle,
         0,    // no dir handle
         defaultNSName,
         &iterHandle,
         &numOfEntries,
         &trustees);

   if (ccode == 0)
   {
      jobjectArray trusteeList;
      jintArray objectIDList;
      jint *objectIDArr;
      int firstTime = 1;

      (*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, "trusteeList",
            "[Lcom/novell/service/file/nw/Trustee;");
      trusteeList = (*env)->GetObjectField (env, tEnum, fid);

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

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

      while (numOfEntries--)
      {
         jobject trustee;

         trustee = (*env)->GetObjectArrayElement (env, trusteeList,
               numOfEntries);

         if (firstTime)
         {
            clazz = (*env)->GetObjectClass (env, trustee);
            fid = (*env)->GetFieldID (env, clazz, "objectRights", "I");

            firstTime = !firstTime;
         }

         (*env)->SetIntField (env, trustee, fid,
               (jint) trustees.trusteeList[numOfEntries].objectRights);

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

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

EXIT:

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2_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];
   pnuint8 utfPathStr;

   utfPathStr = (pnuint8) (*env)->GetStringUTFChars (env, path, NULL);

   ccode = NWAllocTempNSDirHandle2Ext (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         utfPathStr,
         (nuint8) nameSpace,
         &newDirHandle,
         (nuint8) nameSpace);

   (*env)->ReleaseStringUTFChars (env, path, utfPathStr);

   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:

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2_cal_CalJNI_NWSetDirSpaceLimit
(
   JNIEnv   *env,
   jclass   unused,
   jint     connHandle,
   jint     dirHandle,
   jstring  path,
   jint     nameSpace,
   jint     limit
)
{
   NWRCODE ccode;
   NWDIR_HANDLE newDirHandle;
   pnuint8 utfPathStr;

   utfPathStr = (pnuint8) (*env)->GetStringUTFChars (env, path, NULL);

   ccode = NWAllocTempNSDirHandle2Ext (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         utfPathStr,
         (nuint8) nameSpace,
         &newDirHandle,
         (nuint8) nameSpace);

   (*env)->ReleaseStringUTFChars (env, path, utfPathStr);
   if (ccode != 0)
      goto EXIT;

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

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

EXIT:

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2_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_jncpv2_cal_CalJNI_NWAddTrustee
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint dirHandle,
   jstring path,
   jint nameSpace,
   jint objID,
   jint rightsMask
)
{
   NWRCODE ccode;
   nuint8 defaultNSPathStr[__jncpv2_MAX_PATH_LENGTH * 3];
   pnuint8 utfPathStr;
   nuint16 utfPathLen, scratchLen;

   utfPathStr = (pnuint8) (*env)->GetStringUTFChars (env, path, NULL);
   utfPathLen = (nuint16) (*env)->GetStringUTFLength(env, path);

   ccode = __GetDefaultNSPath (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         utfPathStr,
         utfPathLen,
         (nuint8) nameSpace,
         defaultNSPathStr,
         &scratchLen);

   (*env)->ReleaseStringUTFChars (env, path, utfPathStr);
   if (ccode != 0)
      goto EXIT;

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

EXIT:

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2_cal_CalJNI_NWDeleteTrustee
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint dirHandle,
   jstring path,
   jint nameSpace,
   jint objID
)
{
   NWRCODE ccode;
   nuint8 defaultNSPathStr[__jncpv2_MAX_PATH_LENGTH * 3];
   pnuint8 utfPathStr;
   nuint16 utfPathLen, scratchLen;

   utfPathStr = (pnuint8) (*env)->GetStringUTFChars (env, path, NULL);
   utfPathLen = (nuint16) (*env)->GetStringUTFLength(env, path);

   ccode = __GetDefaultNSPath (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         utfPathStr,
         utfPathLen,
         (nuint8) nameSpace,
         defaultNSPathStr,
         &scratchLen);
   
   (*env)->ReleaseStringUTFChars (env, path, utfPathStr);
   if (ccode != 0)
      goto EXIT;

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

EXIT:

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2_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);
}

//This method (CalJNI.NWReadNSInfo) is not currently used.
// the 'data' array must be 512 bytes long
JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2_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;
   pnuint8 utfPathStr;
   nuint16 utfPathLen;

   utfPathStr = (pnuint8) (*env)->GetStringUTFChars (env, path, NULL);
   utfPathLen = (nuint16) (*env)->GetStringUTFLength (env, path);

   ccode = __FillIDXStruct (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         utfPathStr,
         utfPathLen,
         (nuint8) nameSpace,
         (nuint8) dstNameSpace,
         &idx);
   
   (*env)->ReleaseStringUTFChars (env, path, utfPathStr);
   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:

   return ((jint) ccode);
}

//This method (CalJNI.NWWriteNSInfo) is not currently used.
// the 'data' array must be 512 bytes long
JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2_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;
   pnuint8 utfPathStr;
   nuint16 utfPathLen;

   utfPathStr = (pnuint8) (*env)->GetStringUTFChars (env, path, NULL);
   utfPathLen = (nuint16) (*env)->GetStringUTFLength (env, path);

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

   (*env)->ReleaseStringUTFChars (env, path, utfPathStr);
   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:

   return ((jint) ccode);
}

//This method (CalJNI.NWReadExtendedNSInfo) is not currently used.
// 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_jncpv2_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;
   pnuint8 utfPathStr;
   nuint16 utfPathLen;

   utfPathStr = (pnuint8) (*env)->GetStringUTFChars (env, path, NULL);
   utfPathLen = (nuint16) (*env)->GetStringUTFLength (env, path);

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

   (*env)->ReleaseStringUTFChars (env, path, utfPathStr);
   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:

   return ((jint) ccode);
}

//This method (CalJNI.NWWriteExtendedNSInfo) is not currently used.
// 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_jncpv2_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;
   pnuint8 utfPathStr;
   nuint16 utfPathLen;

   utfPathStr = (pnuint8) (*env)->GetStringUTFChars (env, path, NULL);
   utfPathLen = (nuint16) (*env)->GetStringUTFLength (env, path);

   ccode = __FillIDXStruct (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         utfPathStr,
         utfPathLen,
         (nuint8) nameSpace,
         (nuint8) dstNameSpace,
         &idx);
   
   (*env)->ReleaseStringUTFChars (env, path, utfPathStr);
   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:

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2_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;
   pnuint8 utfPathStr;

   utfPathStr = (pnuint8) (*env)->GetStringUTFChars (env, path, NULL);

   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 = NWSetNSEntryDOSInfoExt (
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         utfPathStr,
         (nuint8) nameSpace,
         (nuint16) searchAttr,
         (nuint32) modifyMask,
         &infoStruct);

   (*env)->ReleaseStringUTFChars (env, path, utfPathStr);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2_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_jncpv2_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_jncpv2_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_jncpv2_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)
   {
      pnuint8 utfPathStr;
      utfPathStr = (pnuint8) (*env)->GetStringUTFChars (env, path, NULL);

      ccode = NWAllocTempNSDirHandle2Ext (
            (NWCONN_HANDLE) connHandle,
            0,
            utfPathStr,
            (nuint8) nameSpace,
            &newDirHandle,
            (nuint8) nameSpace);

      (*env)->ReleaseStringUTFChars (env, path, utfPathStr);

      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_jncpv2_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_jncpv2_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_jncpv2_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_jncpv2_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_jncpv2_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_jncpv2_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_jncpv2_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_jncpv2_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_jncpv2_cal_CalJNI_NWAllocTempNSDirHandle
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint dirHandle,
   jstring path,
   jint srcNameSpace,
   jint dstNameSpace,
   jintArray newDirHandle
)
{
   NWRCODE ccode;
   pnuint8 utfPathStr;
   nuint8 buNewDirHandle;

   utfPathStr = (pnuint8) (*env)->GetStringUTFChars(env, path, NULL);

   ccode = NWAllocTempNSDirHandle2Ext(
         (NWCONN_HANDLE) connHandle,
         (nuint8) dirHandle,
         utfPathStr,
         (nuint8) srcNameSpace,
         &buNewDirHandle,
         (nuint8) dstNameSpace);

   (*env)->ReleaseStringUTFChars(env, path, utfPathStr);
   
   if (0 == ccode)
   {
      jint temp = (jint) buNewDirHandle;

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

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2_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_jncpv2_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_EXT i;
   jint temp;

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

   luIterHandle = (nuint32) temp;

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

   if (0 == ccode)
   {
      jclass clazz;
      jfieldID fid;
      jstring javaName;
      nuint8 nameStr[__jncpv2_MAX_PATH_LENGTH * 3];

      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);

      memcpy(nameStr, i.name, i.nameLength);
      nameStr[i.nameLength] = 0;
      javaName = (*env)->NewStringUTF(env, nameStr);
      if(javaName == NULL)
         return -1;

      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_jncpv2_cal_CalJNI_NWPurgeDeletedFile
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint dirHandle,
   jint iterHandle,
   jint volNum,
   jint dirBase,
   jstring delFileName
)
{
   NWRCODE ccode;
   pnuint8 utfNameStr;

   utfNameStr = (pnuint8) (*env)->GetStringUTFChars(env, delFileName, NULL);

   //chaofeng says only the vol name is used so we can still call old one.
   ccode = NWPurgeDeletedFile(
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         (nuint32) iterHandle,
         (nuint32) volNum,
         (nuint32) dirBase,
         utfNameStr);

   (*env)->ReleaseStringUTFChars(env, delFileName, utfNameStr);

   return ((jint) ccode);
}

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

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2_cal_CalJNI_NWRecoverDeletedFile
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint dirHandle,
   jint iterHandle,
   jint volNum,
   jint dirBase,
   jstring delFileName,
   jstring newFileName
)
{
   NWRCODE ccode;
   pnuint8 utfNameStr;
   pnuint8 utfNewNameStr;

   utfNameStr = (pnuint8) (*env)->GetStringUTFChars(env, delFileName, NULL);
   utfNewNameStr = (pnuint8) (*env)->GetStringUTFChars(env, newFileName, NULL);

   ccode = NWRecoverDeletedFileExt(
         (NWCONN_HANDLE) connHandle,
         (NWDIR_HANDLE) dirHandle,
         (nuint32) iterHandle,
         (nuint32) volNum,
         (nuint32) dirBase,
         utfNameStr,
         utfNewNameStr);

   (*env)->ReleaseStringUTFChars(env, delFileName, utfNameStr);
   (*env)->ReleaseStringUTFChars(env, newFileName, utfNewNameStr);

   return ((jint) ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2_cal_CalJNI_NWGetEffectiveRights
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint dirHandle,
   jstring path,
   jint nameSpace,
   jintArray effectiveRights
)
{
   NWRCODE ccode;
   nuint8 defNSPathStr[__jncpv2_MAX_PATH_LENGTH * 3];
   pnuint8 utfPathStr;
   nuint16 utfPathLen, scratchLen, suEffectiveRights;

   utfPathStr = (pnuint8) (*env)->GetStringUTFChars(env, path, NULL);
   utfPathLen = (nuint16) (*env)->GetStringUTFLength(env, path);

   ccode = __GetDefaultNSPath(
         (NWCONN_HANDLE) connHandle,
         (nuint8) dirHandle,
         utfPathStr,
         utfPathLen,
         (nuint8) nameSpace,
         defNSPathStr,
         &scratchLen);

   (*env)->ReleaseStringUTFChars(env, path, utfPathStr);
   if (ccode != 0)
      return ((jint) ccode);

   ccode = NWGetEffectiveRightsExt(
         (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_jncpv2_cal_CalJNI_NWGetObjectEffectiveRights
(
   JNIEnv   *env,
   jclass   obj,
   jint     connHandle,
   jint     objID,
   jint     dirHandle,
   jstring  path,
   jint     nameSpace,
   jintArray  rights
)
{
   NWCCODE ccode;
   nuint8 pathStr[__jncpv2_MAX_PATH_LENGTH * 3];
   nuint8 scratch[__jncpv2_MAX_PATH_LENGTH * 3];
   nuint16 utfPathLen;
   pnuint8 utfPath;
   nuint16 suEffectiveRights;
   NW_ENTRY_INFO_EXT info;
   nuint8 tmpDirHandle;
   int isDir;

   // Convert Java variable into 'C' variable
   utfPath = (pnuint8) (*env)->GetStringUTFChars(env,path,0);
   utfPathLen = (nuint16) (*env)->GetStringUTFLength(env,path);
   memcpy(pathStr, utfPath, utfPathLen + 1); //copy the null term

   (*env)->ReleaseStringUTFChars(env,path,utfPath);

   ccode = NWGetNSEntryInfoExt(
         (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 = NWAllocTempNSDirHandle2Ext(
            (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,
            utfPathLen,
            (nuint8) nameSpace,
            &tmpDirHandle,
            0,    // we have to force DOS name space for the eff. rights
            scratch);
   }

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

   ccode = NWGetObjectEffectiveRightsExt (
               connHandle,
               (nuint32) objID,
               tmpDirHandle,
               isDir ? "" : info.entryName,
               (nuint8)nameSpace,
               &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_jncpv2_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;
   nuint8 pathStr[1507]; //new length from nwbindry.h
   jint temp;

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

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

   if (ccode == 0)
   {
      jstring jPath;

      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)
      {
         nuint8 scratch[1507];
         nuint16 scratchLen;
         ccode = __GetNSPath((NWCONN_HANDLE) connHandle, (NWDIR_HANDLE)0,
            pathStr, (nuint16)NWstrlen(pathStr), (nuint8)NW_NS_DOS,
            scratch, &scratchLen, (nuint8) nameSpace);
         if (ccode != 0)
            return ((jint) ccode);

         memcpy(pathStr, scratch, scratchLen+1); //include null term
      }

      jPath = (*env)->NewStringUTF(env, pathStr);

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

   return (ccode);
}

JNIEXPORT jint JNICALL
Java_com_novell_service_jncpv2_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_jncpv2_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_jncpv2_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_jncpv2_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_jncpv2_cal_CalJNI_NWCloseSemaphore
(
   JNIEnv *env,
   jclass unused,
   jint connHandle,
   jint semaphoreHandle
)
{
   NWRCODE ccode;

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

