/**
   * Pack the full file/directory id information
   *
   * @param info File information to be packed.
   * @param buf Buffer to pack the data into.
   * @param uni Pack Unicode strings if true, else pack ASCII strings
   */
  protected static final void packInfoDirectoryBothId(FileInfo info, DataBuffer buf, boolean uni) {

    //	Information format :-
    //		ULONG	NextEntryOffset
    //		ULONG	FileIndex
    //		LARGE_INTEGER CreationTime
    //		LARGE_INTEGER LastAccessTime
    //		LARGE_INTEGER LastWriteTime
    //		LARGE_INTEGER ChangeTime
    //		LARGE_INTEGER EndOfFile
    //		LARGE_INTEGER AllocationSize
    //		ULONG FileAttributes
    //		ULONG FileNameLength
    //		ULONG EaSize
    //		UCHAR ShortNameLength
    //		WCHAR ShortName[12]
    //      USHORT Reserved
    //      LARGE_INTEGER FileId
    //		STRING FileName

    //	Pack the file id

    int startPos = buf.getPosition();
    buf.putZeros(4);
    buf.putZeros(4);

    //  Pack the creation date/time

    if (info.hasCreationDateTime()) {
      buf.putLong(NTTime.toNTTime(info.getCreationDateTime()));
    } else buf.putZeros(8);

    //  Pack the last access date/time

    if (info.hasAccessDateTime()) {
      buf.putLong(NTTime.toNTTime(info.getAccessDateTime()));
    } else buf.putZeros(8);

    //  Pack the last write date/time and change time

    if (info.hasModifyDateTime()) {
      buf.putLong(NTTime.toNTTime(info.getModifyDateTime()));
      buf.putLong(NTTime.toNTTime(info.getModifyDateTime()));
    } else buf.putZeros(16);

    //  Pack the file size and allocation size

    buf.putLong(info.getSize());

    if (info.getAllocationSize() < info.getSize()) buf.putLong(info.getSize());
    else buf.putLong(info.getAllocationSize());

    //  Pack the file attributes

    buf.putInt(info.getFileAttributes());

    //	Pack the file name length

    int nameLen = info.getFileName().length();
    if (uni) nameLen *= 2;

    buf.putInt(nameLen);

    //	Pack the EA size, should always be 4 ?.

    //	buf.putInt(4);
    buf.putInt(0);

    //	Pack the short file name length (8.3 name)

    pack8Dot3Name(buf, info.getFileName(), uni);

    // Pack reserved field

    buf.putShort(0);

    // Pack the file id

    buf.putLong(info.getFileIdLong());

    //	Pack the long file name string

    buf.putString(info.getFileName(), uni, false);

    //	Align the buffer pointer and set the offset to the next file information entry

    buf.longwordAlign();

    int curPos = buf.getPosition();
    buf.setPosition(startPos);
    buf.putInt(curPos - startPos);
    buf.setPosition(curPos);
  }
  /**
   * Pack a file information object into the specified buffer. Use the standard information level if
   * the EA size flag is false, else add the EA size field.
   *
   * @param info File information to be packed.
   * @param buf Buffer to pack the data into.
   * @param EAflag Add EA size field if true.
   * @param uni Pack Unicode strings if true, else pack ASCII strings
   */
  protected static final void packInfoStandard(
      FileInfo info, DataBuffer buf, boolean EAflag, boolean uni) {

    //  Information format :-
    //    SMB_DATE  CreationDate
    //    SMB_TIME  CreationTime
    //    SMB_DATE  LastAccessDate
    //    SMB_TIME  LastAccessTime
    //    SMB_DATE  LastWriteDate
    //    SMB_TIME  LastWriteTime
    //    ULONG     File size
    //    ULONG     Allocation size
    //    USHORT    File attributes
    //  [ ULONG     EA size ]
    //    UCHAR     File name length
    //    STRING    File name, null terminated

    //  Pack the creation date/time

    SMBDate date = new SMBDate(0);

    if (info.hasCreationDateTime()) {
      date.setTime(info.getCreationDateTime());
      buf.putShort(date.asSMBDate());
      buf.putShort(date.asSMBTime());
    } else buf.putZeros(4);

    //  Pack the last access date/time

    if (info.hasAccessDateTime()) {
      date.setTime(info.getAccessDateTime());
      buf.putShort(date.asSMBDate());
      buf.putShort(date.asSMBTime());
    } else buf.putZeros(4);

    //  Pack the last write date/time

    if (info.hasModifyDateTime()) {
      date.setTime(info.getModifyDateTime());
      buf.putShort(date.asSMBDate());
      buf.putShort(date.asSMBTime());
    } else buf.putZeros(4);

    //  Pack the file size and allocation size

    buf.putInt(info.getSizeInt());

    if (info.getAllocationSize() < info.getSize()) buf.putInt(info.getSizeInt());
    else buf.putInt(info.getAllocationSizeInt());

    //  Pack the file attributes

    buf.putShort(info.getFileAttributes());

    //  Pack the EA size, always 4.

    if (EAflag)
      //    	buf.putInt(4);
      buf.putInt(0);

    //	Pack the file name

    if (uni == true) {

      //	Pack the number of bytes followed by the Unicode name word aligned

      buf.putByte(info.getFileName().length() * 2);
      buf.wordAlign();
      buf.putString(info.getFileName(), uni, true);
    } else {

      //	Pack the number of bytes followed by the ASCII name

      buf.putByte(info.getFileName().length());
      buf.putString(info.getFileName(), uni, true);
    }
  }
  /**
   * Pack the file/directory information
   *
   * @param info File information to be packed.
   * @param buf Buffer to pack the data into.
   * @param uni Pack Unicode strings if true, else pack ASCII strings
   */
  protected static final void packInfoDirectory(FileInfo info, DataBuffer buf, boolean uni) {

    //	Information format :-
    //		ULONG	NextEntryOffset
    //		ULONG	FileIndex
    //		LARGE_INTEGER CreationTime
    //		LARGE_INTEGER LastAccessTime
    //		LARGE_INTEGER LastWriteTime
    //		LARGE_INTEGER ChangeTime
    //		LARGE_INTEGER EndOfFile
    //		LARGE_INTEGER AllocationSize
    //		ULONG FileAttributes
    //		ULONG FileNameLength
    //		STRING FileName

    //	Pack the file id

    int startPos = buf.getPosition();
    buf.putZeros(4);
    buf.putInt(EnableFileIdPacking ? info.getFileId() : 0);

    //  Pack the creation date/time

    if (info.hasCreationDateTime()) {
      buf.putLong(NTTime.toNTTime(info.getCreationDateTime()));
    } else buf.putZeros(8);

    //  Pack the last access date/time

    if (info.hasAccessDateTime()) {
      buf.putLong(NTTime.toNTTime(info.getAccessDateTime()));
    } else buf.putZeros(8);

    //  Pack the last write date/time and change time

    if (info.hasModifyDateTime()) {
      buf.putLong(NTTime.toNTTime(info.getModifyDateTime()));
      buf.putLong(NTTime.toNTTime(info.getModifyDateTime()));
    } else buf.putZeros(16);

    //  Pack the file size and allocation size

    buf.putLong(info.getSize());

    if (info.getAllocationSize() < info.getSize()) buf.putLong(info.getSize());
    else buf.putLong(info.getAllocationSize());

    //  Pack the file attributes

    buf.putInt(info.getFileAttributes());

    //	Pack the file name length

    int nameLen = info.getFileName().length();
    if (uni) nameLen *= 2;

    buf.putInt(nameLen);

    //	Pack the long file name string

    buf.putString(info.getFileName(), uni, false);

    //	Align the buffer pointer and set the offset to the next file information entry

    buf.longwordAlign();

    int curPos = buf.getPosition();
    buf.setPosition(startPos);
    buf.putInt(curPos - startPos);
    buf.setPosition(curPos);
  }
  /**
   * Pack the full file/directory information with file id
   *
   * @param info File information to be packed.
   * @param buf Buffer to pack the data into.
   * @param uni Pack Unicode strings if true, else pack ASCII strings
   * @param shortName true if the 8.3 name should be packed
   */
  protected static final void packInfoFullDirectoryId(
      FileInfo info, DataBuffer buf, boolean uni, boolean shortName) {

    //  Information format :-
    //    ULONG NextEntryOffset
    //    ULONG FileIndex
    //    LARGE_INTEGER CreationTime
    //    LARGE_INTEGER LastAccessTime
    //    LARGE_INTEGER LastWriteTime
    //    LARGE_INTEGER ChangeTime
    //    LARGE_INTEGER EndOfFile
    //    LARGE_INTEGER AllocationSize
    //    ULONG FileAttributes
    //    ULONG FileNameLength
    //    ULONG EaSize
    //   [ UCHAR ShortNameLength ]
    //   [ WCHAR ShortName[12]   ]
    //    ULONG Unknown
    //    LARGE_INTEGER FileId
    //    STRING FileName

    //  Leave space for the offset to the next file entry

    int startPos = buf.getPosition();
    buf.putZeros(8);

    //  Pack the creation date/time

    if (info.hasCreationDateTime()) {
      buf.putLong(NTTime.toNTTime(info.getCreationDateTime()));
    } else buf.putZeros(8);

    //  Pack the last access date/time

    if (info.hasAccessDateTime()) {
      buf.putLong(NTTime.toNTTime(info.getAccessDateTime()));
    } else buf.putZeros(8);

    //  Pack the last write date/time and change time

    if (info.hasModifyDateTime()) {
      buf.putLong(NTTime.toNTTime(info.getModifyDateTime()));
      buf.putLong(NTTime.toNTTime(info.getModifyDateTime()));
    } else buf.putZeros(16);

    //  Pack the file size and allocation size

    buf.putLong(info.getSize());

    if (info.getAllocationSize() < info.getSize()) buf.putLong(info.getSize());
    else buf.putLong(info.getAllocationSize());

    //  Pack the file attributes

    buf.putInt(info.getFileAttributes());

    //  Pack the file name length

    int nameLen = info.getFileName().length();
    if (uni) nameLen *= 2;

    buf.putInt(nameLen);

    //  Pack the EA size

    buf.putInt(0);

    //  Reserved/unknown value

    buf.putInt(0);

    //  Pack the file id

    buf.putInt(EnableFileIdPacking ? info.getFileId() : 0);
    buf.putInt(0);

    //  Pack the short file name length (8.3 name)

    if (shortName == true) pack8Dot3Name(buf, info.getFileName(), uni);

    //  Pack the long file name string

    buf.putString(info.getFileName(), uni, false);

    //  Align the buffer pointer and set the offset to the next file information entry

    buf.longwordAlign();

    int curPos = buf.getPosition();
    buf.setPosition(startPos);
    buf.putInt(curPos - startPos);
    buf.setPosition(curPos);
  }