예제 #1
0
        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);
                }
            }
        }
예제 #2
0
        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);
                }
            }
        }