GetFileInformation and GetFileSystemInformation now return NTStatus. STATUS_OS2_INVALID_LEVEL will now be returned when applicable.

This commit is contained in:
Tal Aloni 2017-01-19 23:02:38 +02:00
parent 859e939cff
commit 7eb4c1ab2b
4 changed files with 164 additions and 108 deletions

View file

@ -31,11 +31,12 @@ namespace SMBLibrary
STATUS_CANNOT_DELETE = 0xC0000121,
STATUS_USER_SESSION_DELETED = 0xC0000203,
STATUS_INSUFF_SERVER_RESOURCES = 0xC0000205,
STATUS_INVALID_SMB = 0x00010002, // CIFS/SMB1: A corrupt or invalid SMB request was received
STATUS_SMB_BAD_COMMAND = 0x00160002, // CIFS/SMB1: An unknown SMB command code was received by the server
STATUS_SMB_BAD_FID = 0x00060001, // CIFS/SMB1
STATUS_SMB_BAD_TID = 0x00050002, // CIFS/SMB1
STATUS_OS2_NO_MORE_SIDS = 0x00710001, // CIFS/SMB1
STATUS_INVALID_SMB = 0x00010002, // SMB1/CIFS: A corrupt or invalid SMB request was received
STATUS_SMB_BAD_COMMAND = 0x00160002, // SMB1/CIFS: An unknown SMB command code was received by the server
STATUS_SMB_BAD_FID = 0x00060001, // SMB1/CIFS
STATUS_SMB_BAD_TID = 0x00050002, // SMB1/CIFS
STATUS_OS2_NO_MORE_SIDS = 0x00710001, // SMB1/CIFS
STATUS_OS2_INVALID_LEVEL = 0x007C0001, // SMB1/CIFS
}
}

View file

@ -14,114 +14,128 @@ namespace SMBLibrary.Server.SMB1
{
public partial class SMB1FileSystemHelper
{
public static QueryInformation GetFileInformation(FileSystemEntry entry, bool deletePending, QueryInformationLevel informationLevel)
public static NTStatus GetFileInformation(out QueryInformation result, FileSystemEntry entry, bool deletePending, QueryInformationLevel informationLevel)
{
switch (informationLevel)
{
case QueryInformationLevel.SMB_INFO_STANDARD:
{
QueryInfoStandard result = new QueryInfoStandard();
result.CreationDateTime = entry.CreationTime;
result.LastAccessDateTime = entry.LastAccessTime;
result.LastWriteDateTime = entry.LastWriteTime;
result.FileDataSize = (uint)Math.Min(entry.Size, UInt32.MaxValue);
result.AllocationSize = (uint)Math.Min(NTFileSystemHelper.GetAllocationSize(entry.Size), UInt32.MaxValue);
return result;
QueryInfoStandard information = new QueryInfoStandard();
information.CreationDateTime = entry.CreationTime;
information.LastAccessDateTime = entry.LastAccessTime;
information.LastWriteDateTime = entry.LastWriteTime;
information.FileDataSize = (uint)Math.Min(entry.Size, UInt32.MaxValue);
information.AllocationSize = (uint)Math.Min(NTFileSystemHelper.GetAllocationSize(entry.Size), UInt32.MaxValue);
result = information;
return NTStatus.STATUS_SUCCESS;
}
case QueryInformationLevel.SMB_INFO_QUERY_EA_SIZE:
{
QueryEASize result = new QueryEASize();
result.CreationDateTime = entry.CreationTime;
result.LastAccessDateTime = entry.LastAccessTime;
result.LastWriteDateTime = entry.LastWriteTime;
result.FileDataSize = (uint)Math.Min(entry.Size, UInt32.MaxValue);
result.AllocationSize = (uint)Math.Min(NTFileSystemHelper.GetAllocationSize(entry.Size), UInt32.MaxValue);
result.Attributes = GetFileAttributes(entry);
result.EASize = 0;
return result;
QueryEASize information = new QueryEASize();
information.CreationDateTime = entry.CreationTime;
information.LastAccessDateTime = entry.LastAccessTime;
information.LastWriteDateTime = entry.LastWriteTime;
information.FileDataSize = (uint)Math.Min(entry.Size, UInt32.MaxValue);
information.AllocationSize = (uint)Math.Min(NTFileSystemHelper.GetAllocationSize(entry.Size), UInt32.MaxValue);
information.Attributes = GetFileAttributes(entry);
information.EASize = 0;
result = information;
return NTStatus.STATUS_SUCCESS;
}
case QueryInformationLevel.SMB_INFO_QUERY_EAS_FROM_LIST:
{
throw new NotImplementedException();
result = null;
return NTStatus.STATUS_NOT_IMPLEMENTED;
}
case QueryInformationLevel.SMB_INFO_QUERY_ALL_EAS:
{
throw new NotImplementedException();
result = null;
return NTStatus.STATUS_NOT_IMPLEMENTED;
}
case QueryInformationLevel.SMB_INFO_IS_NAME_VALID:
{
throw new NotImplementedException();
result = null;
return NTStatus.STATUS_NOT_IMPLEMENTED;
}
case QueryInformationLevel.SMB_QUERY_FILE_BASIC_INFO:
{
QueryFileBasicInfo result = new QueryFileBasicInfo();
result.CreationDateTime = entry.CreationTime;
result.LastAccessDateTime = entry.LastAccessTime;
result.LastWriteDateTime = entry.LastWriteTime;
result.LastChangeTime = entry.LastWriteTime;
result.ExtFileAttributes = GetExtendedFileAttributes(entry);
return result;
QueryFileBasicInfo information = new QueryFileBasicInfo();
information.CreationDateTime = entry.CreationTime;
information.LastAccessDateTime = entry.LastAccessTime;
information.LastWriteDateTime = entry.LastWriteTime;
information.LastChangeTime = entry.LastWriteTime;
information.ExtFileAttributes = GetExtendedFileAttributes(entry);
result = information;
return NTStatus.STATUS_SUCCESS;
}
case QueryInformationLevel.SMB_QUERY_FILE_STANDARD_INFO:
{
QueryFileStandardInfo result = new QueryFileStandardInfo();
result.AllocationSize = NTFileSystemHelper.GetAllocationSize(entry.Size);
result.EndOfFile = entry.Size;
result.DeletePending = deletePending;
result.Directory = entry.IsDirectory;
return result;
QueryFileStandardInfo information = new QueryFileStandardInfo();
information.AllocationSize = NTFileSystemHelper.GetAllocationSize(entry.Size);
information.EndOfFile = entry.Size;
information.DeletePending = deletePending;
information.Directory = entry.IsDirectory;
result = information;
return NTStatus.STATUS_SUCCESS;
}
case QueryInformationLevel.SMB_QUERY_FILE_EA_INFO:
{
QueryFileExtendedAttributeInfo result = new QueryFileExtendedAttributeInfo();
result.EASize = 0;
return result;
QueryFileExtendedAttributeInfo information = new QueryFileExtendedAttributeInfo();
information.EASize = 0;
result = information;
return NTStatus.STATUS_SUCCESS;
}
case QueryInformationLevel.SMB_QUERY_FILE_NAME_INFO:
{
QueryFileNameInfo result = new QueryFileNameInfo();
result.FileName = entry.Name;
return result;
QueryFileNameInfo information = new QueryFileNameInfo();
information.FileName = entry.Name;
result = information;
return NTStatus.STATUS_SUCCESS;
}
case QueryInformationLevel.SMB_QUERY_FILE_ALL_INFO:
{
QueryFileAllInfo result = new QueryFileAllInfo();
result.CreationDateTime = entry.CreationTime;
result.LastAccessDateTime = entry.LastAccessTime;
result.LastWriteDateTime = entry.LastWriteTime;
result.ExtFileAttributes = GetExtendedFileAttributes(entry);
result.LastChangeTime = entry.LastWriteTime;
result.AllocationSize = NTFileSystemHelper.GetAllocationSize(entry.Size);
result.EndOfFile = entry.Size;
result.DeletePending = deletePending;
result.Directory = entry.IsDirectory;
result.EASize = 0;
result.FileName = entry.Name;
return result;
QueryFileAllInfo information = new QueryFileAllInfo();
information.CreationDateTime = entry.CreationTime;
information.LastAccessDateTime = entry.LastAccessTime;
information.LastWriteDateTime = entry.LastWriteTime;
information.ExtFileAttributes = GetExtendedFileAttributes(entry);
information.LastChangeTime = entry.LastWriteTime;
information.AllocationSize = NTFileSystemHelper.GetAllocationSize(entry.Size);
information.EndOfFile = entry.Size;
information.DeletePending = deletePending;
information.Directory = entry.IsDirectory;
information.EASize = 0;
information.FileName = entry.Name;
result = information;
return NTStatus.STATUS_SUCCESS;
}
case QueryInformationLevel.SMB_QUERY_FILE_ALT_NAME_INFO:
{
QueryFileAltNameInfo result = new QueryFileAltNameInfo();
result.FileName = NTFileSystemHelper.GetShortName(entry.Name);
return result;
QueryFileAltNameInfo information = new QueryFileAltNameInfo();
information.FileName = NTFileSystemHelper.GetShortName(entry.Name);
result = information;
return NTStatus.STATUS_SUCCESS;
}
case QueryInformationLevel.SMB_QUERY_FILE_STREAM_INFO:
{
QueryFileStreamInfo result = new QueryFileStreamInfo();
result.StreamSize = entry.Size;
result.StreamAllocationSize = NTFileSystemHelper.GetAllocationSize(entry.Size);
result.StreamName = "::$DATA";
return result;
QueryFileStreamInfo information = new QueryFileStreamInfo();
information.StreamSize = entry.Size;
information.StreamAllocationSize = NTFileSystemHelper.GetAllocationSize(entry.Size);
information.StreamName = "::$DATA";
result = information;
return NTStatus.STATUS_SUCCESS;
}
case QueryInformationLevel.SMB_QUERY_FILE_COMPRESSION_INFO:
{
QueryFileCompressionInfo result = new QueryFileCompressionInfo();
result.CompressionFormat = CompressionFormat.COMPRESSION_FORMAT_NONE;
return result;
QueryFileCompressionInfo information = new QueryFileCompressionInfo();
information.CompressionFormat = CompressionFormat.COMPRESSION_FORMAT_NONE;
result = information;
return NTStatus.STATUS_SUCCESS;
}
default:
{
throw new UnsupportedInformationLevelException();
result = null;
return NTStatus.STATUS_OS2_INVALID_LEVEL;
}
}
}

View file

@ -14,60 +14,67 @@ namespace SMBLibrary.Server.SMB1
{
public partial class SMB1FileSystemHelper
{
public static QueryFSInformation GetFileSystemInformation(QueryFSInformationLevel informationLevel, IFileSystem fileSystem)
public static NTStatus GetFileSystemInformation(out QueryFSInformation result, QueryFSInformationLevel informationLevel, IFileSystem fileSystem)
{
switch (informationLevel)
{
case QueryFSInformationLevel.SMB_INFO_ALLOCATION:
{
QueryFSInfoAllocation result = new QueryFSInfoAllocation();
result.FileSystemID = 0;
result.SectorUnit = NTFileSystemHelper.ClusterSize / NTFileSystemHelper.BytesPerSector;
result.UnitsTotal = (uint)Math.Min(fileSystem.Size / NTFileSystemHelper.ClusterSize, UInt32.MaxValue);
result.UnitsAvailable = (uint)Math.Min(fileSystem.FreeSpace / NTFileSystemHelper.ClusterSize, UInt32.MaxValue);
result.Sector = NTFileSystemHelper.BytesPerSector;
return result;
QueryFSInfoAllocation information = new QueryFSInfoAllocation();
information.FileSystemID = 0;
information.SectorUnit = NTFileSystemHelper.ClusterSize / NTFileSystemHelper.BytesPerSector;
information.UnitsTotal = (uint)Math.Min(fileSystem.Size / NTFileSystemHelper.ClusterSize, UInt32.MaxValue);
information.UnitsAvailable = (uint)Math.Min(fileSystem.FreeSpace / NTFileSystemHelper.ClusterSize, UInt32.MaxValue);
information.Sector = NTFileSystemHelper.BytesPerSector;
result = information;
return NTStatus.STATUS_SUCCESS;
}
case QueryFSInformationLevel.SMB_INFO_VOLUME:
{
QueryFSInfoVolume result = new QueryFSInfoVolume();
result.VolumeLabel = String.Empty;
result.VolumeSerialNumber = 0;
return result;
QueryFSInfoVolume information = new QueryFSInfoVolume();
information.VolumeLabel = String.Empty;
information.VolumeSerialNumber = 0;
result = information;
return NTStatus.STATUS_SUCCESS;
}
case QueryFSInformationLevel.SMB_QUERY_FS_VOLUME_INFO:
{
QueryFSVolumeInfo result = new QueryFSVolumeInfo();
result.VolumeCreationTime = DateTime.Now;
return result;
QueryFSVolumeInfo information = new QueryFSVolumeInfo();
information.VolumeCreationTime = DateTime.Now;
result = information;
return NTStatus.STATUS_SUCCESS;
}
case QueryFSInformationLevel.SMB_QUERY_FS_SIZE_INFO:
{
QueryFSSizeInfo result = new QueryFSSizeInfo();
result.TotalAllocationUnits = (ulong)(fileSystem.Size / NTFileSystemHelper.ClusterSize);
result.TotalFreeAllocationUnits = (ulong)(fileSystem.FreeSpace / NTFileSystemHelper.ClusterSize);
result.BytesPerSector = NTFileSystemHelper.BytesPerSector;
result.SectorsPerAllocationUnit = NTFileSystemHelper.ClusterSize / NTFileSystemHelper.BytesPerSector;
return result;
QueryFSSizeInfo information = new QueryFSSizeInfo();
information.TotalAllocationUnits = (ulong)(fileSystem.Size / NTFileSystemHelper.ClusterSize);
information.TotalFreeAllocationUnits = (ulong)(fileSystem.FreeSpace / NTFileSystemHelper.ClusterSize);
information.BytesPerSector = NTFileSystemHelper.BytesPerSector;
information.SectorsPerAllocationUnit = NTFileSystemHelper.ClusterSize / NTFileSystemHelper.BytesPerSector;
result = information;
return NTStatus.STATUS_SUCCESS;
}
case QueryFSInformationLevel.SMB_QUERY_FS_DEVICE_INFO:
{
QueryFSDeviceInfo result = new QueryFSDeviceInfo();
result.DeviceCharacteristics = DeviceCharacteristics.IsMounted;
result.DeviceType = DeviceType.Disk;
return result;
QueryFSDeviceInfo information = new QueryFSDeviceInfo();
information.DeviceCharacteristics = DeviceCharacteristics.IsMounted;
information.DeviceType = DeviceType.Disk;
result = information;
return NTStatus.STATUS_SUCCESS;
}
case QueryFSInformationLevel.SMB_QUERY_FS_ATTRIBUTE_INFO:
{
QueryFSAttibuteInfo result = new QueryFSAttibuteInfo();
result.FileSystemAttributes = FileSystemAttributes.UnicodeOnDisk;
result.MaxFileNameLengthInBytes = 255;
result.FileSystemName = fileSystem.Name;
return result;
QueryFSAttibuteInfo information = new QueryFSAttibuteInfo();
information.FileSystemAttributes = FileSystemAttributes.UnicodeOnDisk;
information.MaxFileNameLengthInBytes = 255;
information.FileSystemName = fileSystem.Name;
result = information;
return NTStatus.STATUS_SUCCESS;
}
default:
{
throw new UnsupportedInformationLevelException();
result = null;
return NTStatus.STATUS_OS2_INVALID_LEVEL;
}
}
}

View file

@ -43,7 +43,16 @@ namespace SMBLibrary.Server.SMB1
int entriesToReturn = Math.Min(subcommand.SearchCount, entries.Count);
List<FileSystemEntry> temp = entries.GetRange(0, entriesToReturn);
int maxLength = (int)state.GetMaxDataCount(header.PID).Value;
FindInformationList findInformationList = SMB1FileSystemHelper.GetFindInformationList(temp, subcommand.InformationLevel, header.UnicodeFlag, returnResumeKeys, maxLength);
FindInformationList findInformationList;
try
{
findInformationList = SMB1FileSystemHelper.GetFindInformationList(temp, subcommand.InformationLevel, header.UnicodeFlag, returnResumeKeys, maxLength);
}
catch (UnsupportedInformationLevelException)
{
header.Status = NTStatus.STATUS_OS2_INVALID_LEVEL;
return null;
}
int returnCount = findInformationList.Count;
Transaction2FindFirst2Response response = new Transaction2FindFirst2Response();
response.SetFindInformationList(findInformationList, header.UnicodeFlag);
@ -83,7 +92,16 @@ namespace SMBLibrary.Server.SMB1
int maxLength = (int)state.GetMaxDataCount(header.PID).Value;
int maxCount = Math.Min(openSearch.Entries.Count - openSearch.EnumerationLocation, subcommand.SearchCount);
List<FileSystemEntry> temp = openSearch.Entries.GetRange(openSearch.EnumerationLocation, maxCount);
FindInformationList findInformationList = SMB1FileSystemHelper.GetFindInformationList(temp, subcommand.InformationLevel, header.UnicodeFlag, returnResumeKeys, maxLength);
FindInformationList findInformationList;
try
{
findInformationList = SMB1FileSystemHelper.GetFindInformationList(temp, subcommand.InformationLevel, header.UnicodeFlag, returnResumeKeys, maxLength);
}
catch (UnsupportedInformationLevelException)
{
header.Status = NTStatus.STATUS_OS2_INVALID_LEVEL;
return null;
}
int returnCount = findInformationList.Count;
Transaction2FindNext2Response response = new Transaction2FindNext2Response();
response.SetFindInformationList(findInformationList, header.UnicodeFlag);
@ -99,7 +117,13 @@ namespace SMBLibrary.Server.SMB1
internal static Transaction2QueryFSInformationResponse GetSubcommandResponse(SMB1Header header, Transaction2QueryFSInformationRequest subcommand, FileSystemShare share)
{
Transaction2QueryFSInformationResponse response = new Transaction2QueryFSInformationResponse();
QueryFSInformation queryFSInformation = SMB1FileSystemHelper.GetFileSystemInformation(subcommand.InformationLevel, share.FileSystem);
QueryFSInformation queryFSInformation;
NTStatus queryStatus = SMB1FileSystemHelper.GetFileSystemInformation(out queryFSInformation, subcommand.InformationLevel, share.FileSystem);
if (queryStatus != NTStatus.STATUS_SUCCESS)
{
header.Status = queryStatus;
return null;
}
response.SetQueryFSInformation(queryFSInformation, header.UnicodeFlag);
return response;
}
@ -118,9 +142,14 @@ namespace SMBLibrary.Server.SMB1
return null;
}
Transaction2QueryPathInformationResponse response = new Transaction2QueryPathInformationResponse();
QueryInformation queryInformation = SMB1FileSystemHelper.GetFileInformation(entry, false, subcommand.InformationLevel);
QueryInformation queryInformation;
NTStatus queryStatus = SMB1FileSystemHelper.GetFileInformation(out queryInformation, entry, false, subcommand.InformationLevel);
if (queryStatus != NTStatus.STATUS_SUCCESS)
{
header.Status = queryStatus;
return null;
}
response.SetQueryInformation(queryInformation);
return response;
}
@ -142,9 +171,14 @@ namespace SMBLibrary.Server.SMB1
return null;
}
Transaction2QueryFileInformationResponse response = new Transaction2QueryFileInformationResponse();
QueryInformation queryInformation = SMB1FileSystemHelper.GetFileInformation(entry, openFile.DeleteOnClose, subcommand.InformationLevel);
QueryInformation queryInformation;
NTStatus queryStatus = SMB1FileSystemHelper.GetFileInformation(out queryInformation, entry, openFile.DeleteOnClose, subcommand.InformationLevel);
if (queryStatus != NTStatus.STATUS_SUCCESS)
{
header.Status = queryStatus;
return null;
}
response.SetQueryInformation(queryInformation);
return response;
}