Improved FID (File ID) allocation mechanism

This commit is contained in:
Tal Aloni 2017-01-13 14:26:24 +02:00
parent 617e5fb854
commit c11b987320
4 changed files with 54 additions and 23 deletions

View file

@ -26,6 +26,7 @@ namespace SMBLibrary
STATUS_MEDIA_WRITE_PROTECTED = 0xC00000A2, STATUS_MEDIA_WRITE_PROTECTED = 0xC00000A2,
STATUS_FILE_IS_A_DIRECTORY = 0xC00000BA, STATUS_FILE_IS_A_DIRECTORY = 0xC00000BA,
STATUS_NOT_SUPPORTED = 0xC00000BB, STATUS_NOT_SUPPORTED = 0xC00000BB,
STATUS_TOO_MANY_OPENED_FILES = 0xC000011F,
STATUS_CANNOT_DELETE = 0xC0000121, STATUS_CANNOT_DELETE = 0xC0000121,
STATUS_INSUFF_SERVER_RESOURCES = 0xC0000205, STATUS_INSUFF_SERVER_RESOURCES = 0xC0000205,

View file

@ -178,33 +178,43 @@ namespace SMBLibrary.Server
/// The value 0xFFFF MUST NOT be used as a valid FID. All other possible values for FID, including zero (0x0000) are valid. /// The value 0xFFFF MUST NOT be used as a valid FID. All other possible values for FID, including zero (0x0000) are valid.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
private ushort AllocateFileID() private ushort? AllocateFileID()
{ {
while (m_openedFiles.ContainsKey(m_nextFID) || m_nextFID == 0 || m_nextFID == 0xFFFF) for (ushort offset = 0; offset < UInt16.MaxValue; offset++)
{ {
m_nextFID++; ushort fileID = (ushort)(m_nextFID + offset);
if (fileID == 0 || fileID == 0xFFFF)
{
continue;
} }
ushort fileID = m_nextFID; if (!m_openedFiles.ContainsKey(fileID))
m_nextFID++; {
m_nextFID = (ushort)(fileID + 1);
return fileID; return fileID;
} }
}
return null;
}
/// <param name="relativePath">Should include the path relative to the file system</param> /// <param name="relativePath">Should include the path relative to the file system</param>
/// <returns>FileID</returns> /// <returns>FileID</returns>
public ushort AddOpenedFile(string relativePath) public ushort? AddOpenedFile(string relativePath)
{ {
return AddOpenedFile(relativePath, null); return AddOpenedFile(relativePath, null);
} }
public ushort AddOpenedFile(string relativePath, Stream stream) public ushort? AddOpenedFile(string relativePath, Stream stream)
{ {
return AddOpenedFile(relativePath, stream, false); return AddOpenedFile(relativePath, stream, false);
} }
public ushort AddOpenedFile(string relativePath, Stream stream, bool deleteOnClose) public ushort? AddOpenedFile(string relativePath, Stream stream, bool deleteOnClose)
{ {
ushort fileID = AllocateFileID(); ushort? fileID = AllocateFileID();
m_openedFiles.Add(fileID, new OpenedFileObject(relativePath, stream, deleteOnClose)); if (fileID.HasValue)
{
m_openedFiles.Add(fileID.Value, new OpenedFileObject(relativePath, stream, deleteOnClose));
}
return fileID; return fileID;
} }

View file

@ -25,14 +25,19 @@ namespace SMBLibrary.Server.SMB1
RemoteService service = ((NamedPipeShare)share).GetService(path); RemoteService service = ((NamedPipeShare)share).GetService(path);
if (service != null) if (service != null)
{ {
ushort fileID = state.AddOpenedFile(path); ushort? fileID = state.AddOpenedFile(path);
if (!fileID.HasValue)
{
header.Status = NTStatus.STATUS_TOO_MANY_OPENED_FILES;
return new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX);
}
if (isExtended) if (isExtended)
{ {
return CreateResponseExtendedForNamedPipe(fileID); return CreateResponseExtendedForNamedPipe(fileID.Value);
} }
else else
{ {
return CreateResponseForNamedPipe(fileID); return CreateResponseForNamedPipe(fileID.Value);
} }
} }
@ -294,10 +299,15 @@ namespace SMBLibrary.Server.SMB1
} }
} }
ushort fileID = state.AddOpenedFile(path, stream, deleteOnClose); ushort? fileID = state.AddOpenedFile(path, stream, deleteOnClose);
if (!fileID.HasValue)
{
header.Status = NTStatus.STATUS_TOO_MANY_OPENED_FILES;
return new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX);
}
if (isExtended) if (isExtended)
{ {
NTCreateAndXResponseExtended response = CreateResponseExtendedFromFileSystemEntry(entry, fileID); NTCreateAndXResponseExtended response = CreateResponseExtendedFromFileSystemEntry(entry, fileID.Value);
if ((request.Flags & NTCreateFlags.NT_CREATE_REQUEST_OPBATCH) > 0) if ((request.Flags & NTCreateFlags.NT_CREATE_REQUEST_OPBATCH) > 0)
{ {
response.OpLockLevel = OpLockLevel.BatchOpLockGranted; response.OpLockLevel = OpLockLevel.BatchOpLockGranted;
@ -306,7 +316,7 @@ namespace SMBLibrary.Server.SMB1
} }
else else
{ {
NTCreateAndXResponse response = CreateResponseFromFileSystemEntry(entry, fileID); NTCreateAndXResponse response = CreateResponseFromFileSystemEntry(entry, fileID.Value);
if ((request.Flags & NTCreateFlags.NT_CREATE_REQUEST_OPBATCH) > 0) if ((request.Flags & NTCreateFlags.NT_CREATE_REQUEST_OPBATCH) > 0)
{ {
response.OpLockLevel = OpLockLevel.BatchOpLockGranted; response.OpLockLevel = OpLockLevel.BatchOpLockGranted;

View file

@ -25,14 +25,19 @@ namespace SMBLibrary.Server.SMB1
RemoteService service = ((NamedPipeShare)share).GetService(path); RemoteService service = ((NamedPipeShare)share).GetService(path);
if (service != null) if (service != null)
{ {
ushort fileID = state.AddOpenedFile(path); ushort? fileID = state.AddOpenedFile(path);
if (!fileID.HasValue)
{
header.Status = NTStatus.STATUS_TOO_MANY_OPENED_FILES;
return new ErrorResponse(CommandName.SMB_COM_OPEN_ANDX);
}
if (isExtended) if (isExtended)
{ {
return CreateResponseExtendedForNamedPipe(fileID); return CreateResponseExtendedForNamedPipe(fileID.Value);
} }
else else
{ {
return CreateResponseForNamedPipe(fileID); return CreateResponseForNamedPipe(fileID.Value);
} }
} }
@ -128,14 +133,19 @@ namespace SMBLibrary.Server.SMB1
stream = new PrefetchedStream(stream); stream = new PrefetchedStream(stream);
} }
} }
ushort fileID = state.AddOpenedFile(path, stream); ushort? fileID = state.AddOpenedFile(path, stream);
if (!fileID.HasValue)
{
header.Status = NTStatus.STATUS_TOO_MANY_OPENED_FILES;
return new ErrorResponse(CommandName.SMB_COM_OPEN_ANDX);
}
if (isExtended) if (isExtended)
{ {
return CreateResponseExtendedFromFileSystemEntry(entry, fileID, openResult); return CreateResponseExtendedFromFileSystemEntry(entry, fileID.Value, openResult);
} }
else else
{ {
return CreateResponseFromFileSystemEntry(entry, fileID, openResult); return CreateResponseFromFileSystemEntry(entry, fileID.Value, openResult);
} }
} }
} }