/** * Pack the file name 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 packInfoFileName(FileInfo info, DataBuffer buf, boolean uni) { // Information format :- // ULONG NextEntryOffset // ULONG FileIndex // ULONG FileNameLength // STRING FileName // Pack the file id int startPos = buf.getPosition(); buf.putZeros(4); buf.putInt(EnableFileIdPacking ? info.getFileId() : 0); // 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 Macintosh format 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 packInfoMacHfs(FileInfo info, DataBuffer buf, boolean uni) { // Information format :- // ULONG NextEntryOffset // ULONG FileIndex // LARGE_INTEGER CreationTime // LARGE_INTEGER LastWriteTime // LARGE_INTEGER ChangeTime // LARGE_INTEGER Data stream length // LARGE_INTEGER Resource stream length // LARGE_INTEGER Data stream allocation size // LARGE_INTEGER Resource stream allocation size // ULONG ExtFileAttributes // UCHAR FLAttrib Macintosh SetFLock, 1 = file locked // UCHAR Pad // UWORD DrNmFls Number of items in a directory, zero for files // ULONG AccessControl // UCHAR FinderInfo[32] // ULONG FileNameLength // UCHAR ShortNameLength // UCHAR Pad // WCHAR ShortName[12] // STRING FileName // LONG UniqueId // 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 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 data stream size and resource stream size (always zero) buf.putLong(info.getSize()); buf.putZeros(8); // Pack the data stream allocation size and resource stream allocation size (always zero) if (info.getAllocationSize() < info.getSize()) buf.putLong(info.getSize()); else buf.putLong(info.getAllocationSize()); buf.putZeros(8); // Pack the file attributes buf.putInt(info.getFileAttributes()); // Pack the file lock and padding byte buf.putZeros(2); // Pack the number of items in a directory, always zero for now buf.putShort(0); // Pack the access control buf.putInt(0); // Pack the finder information buf.putZeros(32); // Pack the file name length int nameLen = info.getFileName().length(); if (uni) nameLen *= 2; buf.putInt(nameLen); // Pack the short file name length (8.3 name) and name pack8Dot3Name(buf, info.getFileName(), uni); // Pack the long file name string buf.putString(info.getFileName(), uni, false); // Pack the unique id buf.putInt(0); // 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 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 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 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); } }
/** * Calculate the required buffer space for the file information at the specified file information * level. * * @param info File information * @param infoLev File information level requested. * @param resKey true if resume keys are being returned, else false. * @param uni true if Unicode strings are being used, or false for ASCII strings * @return int Buffer space required, or -1 if unknown information level. */ public static final int calcInfoSize(FileInfo info, int infoLev, boolean resKey, boolean uni) { // Determine the information level requested int len = -1; int nameLen = info.getFileName().length() + 1; if (uni) nameLen *= 2; switch (infoLev) { // Standard information level case InfoStandard: len = InfoStandardLen + nameLen; break; // Standard + EA size case InfoQueryEASize: len = InfoQueryEASizeLen + nameLen; break; // File name information case InfoNames: len += InfoNamesLen + nameLen; break; // File/directory information case InfoDirectory: len = InfoDirectoryLen + nameLen; break; // File/directory information full case InfoFullDirectory: len += InfoFullDirectoryLen + nameLen; break; // Full file/directory information plus short name case InfoDirectoryBoth: len = InfoDirectoryBothLen + nameLen; break; // Maacintosh information level case InfoMacHfsInfo: len = InfoMacHfsLen + nameLen; break; // Full directory information with file id case InfoFullDirectoryId: len = InfoFullDirectoryIdLen + nameLen; break; // Full directory information with file id, and short file name case InfoDirectoryBothId: len = InfoFullDirectoryIdLen + nameLen + 26; break; } // Add extra space for the resume key, if enabled if (resKey) len += 4; // Return the buffer length required. return len; }
/** * 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); }
/** * Process a transact2 query file information (via handle) request. * * @param sess SMBSrvSession * @param vc VirtualCircuit * @param tbuf Transaction request details * @param smbPkt SMBSrvPacket * @exception IOException * @exception SMBSrvException */ protected static final void procTrans2QueryFile( SMBSrvSession sess, VirtualCircuit vc, SrvTransactBuffer tbuf, SMBSrvPacket smbPkt) throws IOException, SMBSrvException { // Get the tree connection details int treeId = tbuf.getTreeId(); TreeConnection conn = vc.findConnection(treeId); if (conn == null) { sess.sendErrorResponseSMB( smbPkt, SMBStatus.NTInvalidParameter, SMBStatus.DOSInvalidDrive, SMBStatus.ErrDos); return; } // Check if the user has the required access permission if (conn.hasReadAccess() == false) { // User does not have the required access rights sess.sendErrorResponseSMB( smbPkt, SMBStatus.NTAccessDenied, SMBStatus.DOSAccessDenied, SMBStatus.ErrDos); return; } // Get the file id and query path information level DataBuffer paramBuf = tbuf.getParameterBuffer(); int fid = paramBuf.getShort(); int infoLevl = paramBuf.getShort(); // Get the file details via the file id NetworkFile netFile = conn.findFile(fid); if (netFile == null) { sess.sendErrorResponseSMB(smbPkt, SMBStatus.DOSInvalidHandle, SMBStatus.ErrDos); return; } // Debug if (Debug.EnableInfo && sess.hasDebug(SMBSrvSession.DBG_IPC)) sess.debugPrintln( "IPC$ Query File - level=0x" + Integer.toHexString(infoLevl) + ", fid=" + fid + ", name=" + netFile.getFullName()); // Access the shared device disk interface try { // Set the return parameter count, so that the data area position can be calculated. smbPkt.setParameterCount(10); // Pack the file information into the data area of the transaction reply byte[] buf = smbPkt.getBuffer(); int prmPos = DataPacker.longwordAlign(smbPkt.getByteOffset()); int dataPos = prmPos + 4; // Pack the return parametes, EA error offset smbPkt.setPosition(prmPos); smbPkt.packWord(0); // Create a data buffer using the SMB packet. The response should always fit into a // single reply packet. DataBuffer replyBuf = new DataBuffer(buf, dataPos, buf.length - dataPos); // Build the file information from the network file details FileInfo fileInfo = new FileInfo(netFile.getName(), netFile.getFileSize(), netFile.getFileAttributes()); fileInfo.setAccessDateTime(netFile.getAccessDate()); fileInfo.setCreationDateTime(netFile.getCreationDate()); fileInfo.setModifyDateTime(netFile.getModifyDate()); fileInfo.setChangeDateTime(netFile.getModifyDate()); fileInfo.setFileId(netFile.getFileId()); // Set the file allocation size, looks like it is used as the pipe buffer size fileInfo.setAllocationSize(4096L); // Pack the file information into the return data packet int dataLen = QueryInfoPacker.packInfo(fileInfo, replyBuf, infoLevl, true); // Check if any data was packed, if not then the information level is not supported if (dataLen == 0) { sess.sendErrorResponseSMB( smbPkt, SMBStatus.NTInvalidParameter, SMBStatus.SRVNonSpecificError, SMBStatus.ErrSrv); return; } SMBSrvTransPacket.initTransactReply(smbPkt, 2, prmPos, dataLen, dataPos); smbPkt.setByteCount(replyBuf.getPosition() - smbPkt.getByteOffset()); // Send the transact reply sess.sendResponseSMB(smbPkt); } catch (FileNotFoundException ex) { // Requested file does not exist sess.sendErrorResponseSMB( smbPkt, SMBStatus.NTObjectNotFound, SMBStatus.DOSFileNotFound, SMBStatus.ErrDos); return; } catch (PathNotFoundException ex) { // Requested path does not exist sess.sendErrorResponseSMB( smbPkt, SMBStatus.NTObjectPathNotFound, SMBStatus.DOSFileNotFound, SMBStatus.ErrDos); return; } catch (UnsupportedInfoLevelException ex) { // Requested information level is not supported sess.sendErrorResponseSMB( smbPkt, SMBStatus.NTInvalidParameter, SMBStatus.SRVNonSpecificError, SMBStatus.ErrSrv); return; } catch (DiskOfflineException ex) { // Filesystem is offline sess.sendErrorResponseSMB( smbPkt, SMBStatus.NTObjectPathNotFound, SMBStatus.HRDDriveNotReady, SMBStatus.ErrHrd); } }