public static byte[] PerformRead(SMBHeader header, object share, ushort FID, long offset, int maxCount, StateObject state) { OpenedFileObject openedFile = state.GetOpenedFileObject(FID); if (openedFile == null) { header.Status = NTStatus.STATUS_INVALID_HANDLE; return(null); } string openedFilePath = openedFile.Path; if (share is NamedPipeShare) { return(state.RetrieveNamedPipeReply(FID)); } else // FileSystemShare { FileSystemShare fileSystemShare = (FileSystemShare)share; IFileSystem fileSystem = fileSystemShare.FileSystem; if (openedFile.IsSequentialAccess) { bool isInCache = (offset >= openedFile.CacheOffset) && (offset + maxCount <= openedFile.CacheOffset + openedFile.Cache.Length); if (!isInCache) { int bytesRead; try { Stream stream = fileSystem.OpenFile(openedFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); stream.Seek(offset, SeekOrigin.Begin); openedFile.CacheOffset = offset; openedFile.Cache = new byte[OpenedFileObject.CacheSize]; bytesRead = stream.Read(openedFile.Cache, 0, OpenedFileObject.CacheSize); stream.Close(); } catch (IOException ex) { ushort errorCode = IOExceptionHelper.GetWin32ErrorCode(ex); if (errorCode == (ushort)Win32Error.ERROR_SHARING_VIOLATION) { // Returning STATUS_SHARING_VIOLATION is undocumented but apparently valid header.Status = NTStatus.STATUS_SHARING_VIOLATION; return(null); } else { header.Status = NTStatus.STATUS_DATA_ERROR; return(null); } } catch (UnauthorizedAccessException) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return(null); } if (bytesRead < OpenedFileObject.CacheSize) { // EOF, we must trim the response data array byte[] buffer = new byte[bytesRead]; Array.Copy(openedFile.Cache, 0, buffer, 0, bytesRead); openedFile.Cache = buffer; } } int offsetInCache = (int)(offset - openedFile.CacheOffset); int bytesRemained = openedFile.Cache.Length - offsetInCache; int dataLength = Math.Min(maxCount, bytesRemained); byte[] data = new byte[dataLength]; Array.Copy(openedFile.Cache, offsetInCache, data, 0, dataLength); return(data); } else { int bytesRead; byte[] data; try { Stream stream = fileSystem.OpenFile(openedFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); stream.Seek(offset, SeekOrigin.Begin); data = new byte[maxCount]; bytesRead = stream.Read(data, 0, maxCount); stream.Close(); } catch (IOException ex) { ushort errorCode = IOExceptionHelper.GetWin32ErrorCode(ex); if (errorCode == (ushort)Win32Error.ERROR_SHARING_VIOLATION) { // Returning STATUS_SHARING_VIOLATION is undocumented but apparently valid header.Status = NTStatus.STATUS_SHARING_VIOLATION; return(null); } else { header.Status = NTStatus.STATUS_DATA_ERROR; return(null); } } catch (ArgumentOutOfRangeException) { header.Status = NTStatus.STATUS_DATA_ERROR; return(null); } catch (UnauthorizedAccessException) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return(null); } if (bytesRead < maxCount) { // EOF, we must trim the response data array byte[] buffer = new byte[bytesRead]; Array.Copy(data, 0, buffer, 0, bytesRead); data = buffer; } return(data); } } }
public static uint PerformWrite(SMBHeader header, object share, ushort FID, ulong offset, byte[] data, StateObject state) { OpenedFileObject openedFile = state.GetOpenedFileObject(FID); if (openedFile == null) { header.Status = NTStatus.STATUS_INVALID_HANDLE; return(0); } string openedFilePath = openedFile.Path; if (share is NamedPipeShare) { RemoteService service = ((NamedPipeShare)share).GetService(openedFilePath); if (service != null) { RPCPDU rpcRequest = RPCPDU.GetPDU(data); RPCPDU rpcReply = RemoteServiceHelper.GetRPCReply(rpcRequest, service); byte[] replyData = rpcReply.GetBytes(); state.StoreNamedPipeReply(FID, replyData); return((uint)data.Length); } // This code should not execute unless the SMB request (sequence) is invalid header.Status = NTStatus.STATUS_INVALID_SMB; return(0); } else // FileSystemShare { FileSystemShare fileSystemShare = (FileSystemShare)share; IFileSystem fileSystem = fileSystemShare.FileSystem; if (openedFile.IsSequentialAccess && openedFile.Cache.Length > 0) { openedFile.Cache = new byte[0]; // Empty cache } try { Stream stream = fileSystem.OpenFile(openedFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite); stream.Seek((long)offset, SeekOrigin.Begin); stream.Write(data, 0, data.Length); stream.Close(); return((uint)data.Length); } catch (IOException ex) { ushort errorCode = IOExceptionHelper.GetWin32ErrorCode(ex); if (errorCode == (ushort)Win32Error.ERROR_DISK_FULL) { header.Status = NTStatus.STATUS_DISK_FULL; return(0); } else if (errorCode == (ushort)Win32Error.ERROR_SHARING_VIOLATION) { // Returning STATUS_SHARING_VIOLATION is undocumented but apparently valid header.Status = NTStatus.STATUS_SHARING_VIOLATION; return(0); } else { header.Status = NTStatus.STATUS_DATA_ERROR; return(0); } } catch (ArgumentOutOfRangeException) { header.Status = NTStatus.STATUS_DATA_ERROR; return(0); } catch (UnauthorizedAccessException) { // The user may have tried to write to a readonly file header.Status = NTStatus.STATUS_ACCESS_DENIED; return(0); } } }