private void PopulateDescription()
        {
            bool           releaseHandle;
            SafeFileHandle handle = PhysicalDiskHandlePool.ObtainHandle(m_physicalDiskIndex, FileAccess.Read, ShareMode.ReadWrite, out releaseHandle);

            if (!handle.IsInvalid)
            {
                m_description  = PhysicalDiskControl.GetDeviceDescription(handle);
                m_serialNumber = PhysicalDiskControl.GetDeviceSerialNumber(handle);
                if (releaseHandle)
                {
                    PhysicalDiskHandlePool.ReleaseHandle(m_physicalDiskIndex);
                }
            }
            else
            {
                // we always release invalid handle
                PhysicalDiskHandlePool.ReleaseHandle(m_physicalDiskIndex);

                // get error code and throw
                int    errorCode = Marshal.GetLastWin32Error();
                string message   = String.Format("Failed to access disk {0}.", m_physicalDiskIndex);
                if (errorCode == (int)Win32Error.ERROR_FILE_NOT_FOUND)
                {
                    throw new DriveNotFoundException(message);
                }
                else
                {
                    IOExceptionHelper.ThrowIOError(errorCode, message);
                }
            }
        }
Esempio n. 2
0
        private Stream OpenFileStream()
        {
            FileAccess fileAccess = IsReadOnly ? FileAccess.Read : FileAccess.ReadWrite;

            // We should use noncached I/O operations to avoid excessive RAM usage.
            // Note: KB99794 provides information about FILE_FLAG_WRITE_THROUGH and FILE_FLAG_NO_BUFFERING.
            // We must avoid using buffered writes, using it will negatively affect the performance and reliability.
            // Note: once the file system write buffer is filled, Windows may delay any (buffer-dependent) pending write operations, which will create a deadlock.
            if (IsWin32())
            {
                uint flags = unchecked ((uint)(FILE_FLAG_NO_BUFFERING | FileOptions.WriteThrough));
                if (m_useOverlappedIO)
                {
                    flags |= (uint)FILE_FLAG_OVERLAPPED;
                }
                Microsoft.Win32.SafeHandles.SafeFileHandle handle = HandleUtils.GetFileHandle(this.Path, fileAccess, ShareMode.Read, flags);
                if (!handle.IsInvalid)
                {
                    return(new FileStreamEx(handle, fileAccess));
                }
                else
                {
                    // we always release invalid handle
                    int    errorCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
                    string message   = String.Format("Failed to obtain file handle for file '{0}'.", this.Path);
                    IOExceptionHelper.ThrowIOError(errorCode, message);
                    return(null); // this line will not be reached
                }
            }
            else
            {
                return(new FileStream(this.Path, FileMode.Open, fileAccess, FileShare.Read, m_bytesPerSector, FILE_FLAG_NO_BUFFERING | FileOptions.WriteThrough));
            }
        }
        /// <remarks>
        /// The caller can use this method with both synchronous and asynchronous (FILE_FLAG_OVERLAPPED) file handles.
        /// </remarks>
        public int ReadOverlapped(byte[] array, int offset, int count, long position)
        {
            uint             temp; // will not be updated on async operation
            ManualResetEvent completionEvent = new ManualResetEvent(false);
            OVERLAPPED       overlapped      = new OVERLAPPED();

            overlapped.Offset = position;
            overlapped.hEvent = completionEvent.SafeWaitHandle.DangerousGetHandle();
            IntPtr lpOverlapped = Marshal.AllocHGlobal(Marshal.SizeOf(overlapped));

            Marshal.StructureToPtr(overlapped, lpOverlapped, false);
            bool success;

            byte[] buffer = null;
            // We MUST pin the buffer being passed to ReadFile until the operation is complete!
            // Otherwise it will only be pinned for the duration of the P/Invoke and the GC may move it to another
            // memory location before the callee completes the operation and writes to the original location.
            GCHandle bufferHandle;

            if (offset == 0)
            {
                bufferHandle = GCHandle.Alloc(array, GCHandleType.Pinned);
                success      = ReadFile(m_handle, array, (uint)count, out temp, lpOverlapped);
            }
            else
            {
                buffer       = new byte[count];
                bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
                success      = ReadFile(m_handle, buffer, (uint)buffer.Length, out temp, lpOverlapped);
            }

            uint numberOfBytesRead = 0;

            if (!success)
            {
                int errorCode = Marshal.GetLastWin32Error();
                if (errorCode != (int)Win32Error.ERROR_IO_PENDING)
                {
                    string message = String.Format("Failed to read from position {0} the requested number of bytes ({1}).", position, count);
                    IOExceptionHelper.ThrowIOError(errorCode, message);
                }
                bool completed = GetOverlappedResult(m_handle, lpOverlapped, out numberOfBytesRead, true);
            }
            bufferHandle.Free();
            completionEvent.Close();
            Marshal.FreeHGlobal(lpOverlapped);

            if (numberOfBytesRead != count)
            {
                int    errorCode = Marshal.GetLastWin32Error();
                string message   = String.Format("Failed to read from position {0} the requested number of bytes ({1}).", position, count);
                IOExceptionHelper.ThrowIOError(errorCode, message);
            }

            if (offset != 0)
            {
                Array.Copy(buffer, 0, array, offset, numberOfBytesRead);
            }
            return((int)numberOfBytesRead);
        }
Esempio n. 4
0
        /// <param name="offset">The byte offset in array at which the read bytes will be placed</param>
        /// <param name="count">The maximum number of bytes to read</param>
        public override int Read(byte[] array, int offset, int count)
        {
            uint numberOfBytesRead;

            if (offset == 0)
            {
                ReadFile(m_handle, array, (uint)count, out numberOfBytesRead, IntPtr.Zero);
            }
            else
            {
                byte[] buffer = new byte[count];
                ReadFile(m_handle, buffer, (uint)count, out numberOfBytesRead, IntPtr.Zero);
                Array.Copy(buffer, 0, array, offset, buffer.Length);
            }

            if (numberOfBytesRead == count)
            {
                m_position += count;
                return((int)numberOfBytesRead);
            }
            else
            {
                int    errorCode = Marshal.GetLastWin32Error();
                string message   = String.Format("Failed to read from position {0} the requested number of bytes ({1}).", this.Position, count);
                IOExceptionHelper.ThrowIOError(errorCode, message);
                return(0); // this line will not be reached
            }
        }
Esempio n. 5
0
        public override void Write(byte[] array, int offset, int count)
        {
            uint numberOfBytesWritten;

            if (offset == 0)
            {
                WriteFile(m_handle, array, (uint)count, out numberOfBytesWritten, IntPtr.Zero);
            }
            else
            {
                byte[] buffer = new byte[count];
                Array.Copy(array, offset, buffer, 0, buffer.Length);
                WriteFile(m_handle, buffer, (uint)count, out numberOfBytesWritten, IntPtr.Zero);
            }

            if (numberOfBytesWritten == count)
            {
                m_position += count;
            }
            else
            {
                int    errorCode = Marshal.GetLastWin32Error();
                string message   = String.Format("Failed to write to position {0} the requested number of bytes ({1}).", this.Position, count);
                IOExceptionHelper.ThrowIOError(errorCode, message);
            }
        }
        /// <summary>
        /// Sector refers to physical disk blocks, we can only read complete blocks
        /// </summary>
        public byte[] ReadSectorsUnbuffered(long sectorIndex, int sectorCount)
        {
            bool           releaseHandle;
            SafeFileHandle handle = PhysicalDiskHandlePool.ObtainHandle(m_physicalDiskIndex, FileAccess.Read, ShareMode.ReadWrite, out releaseHandle);

            if (!handle.IsInvalid)
            {
                FileStreamEx stream = new FileStreamEx(handle, FileAccess.Read);
                byte[]       buffer = new byte[m_bytesPerSector * sectorCount];
                try
                {
                    stream.Seek(sectorIndex * m_bytesPerSector, SeekOrigin.Begin);
                    stream.Read(buffer, 0, m_bytesPerSector * sectorCount);
                }
                finally
                {
                    stream.Close(releaseHandle);
                    if (releaseHandle)
                    {
                        PhysicalDiskHandlePool.ReleaseHandle(m_physicalDiskIndex);
                    }
                }
                return(buffer);
            }
            else
            {
                // we always release invalid handle
                PhysicalDiskHandlePool.ReleaseHandle(m_physicalDiskIndex);
                // get error code and throw
                int    errorCode = Marshal.GetLastWin32Error();
                string message   = String.Format("Failed to read sector {0} from disk {1}.", sectorIndex, m_physicalDiskIndex);
                IOExceptionHelper.ThrowIOError(errorCode, message);
                return(null); // this line will not be reached
            }
        }
        /// <summary>
        /// On NTFS, extending a file reserves disk space but does not zero out the data.
        /// Instead, NTFS keeps track of the "last byte written", technically known as the valid data length, and only zeroes out up to that point.
        /// The data past the valid data length are logically zero but are not physically zero on disk.
        /// When you write to a point past the current valid data length, all the bytes between the valid data length and the start of your write need to be zeroed out before the new valid data length can be set to the end of your write operation.
        /// Extending the file and then calling SetValidLength() may save a considerable amount of time zeroing out the extended portion of the file.
        /// </summary>
        /// <remarks>
        /// Calling SetFileValidData requires SeManageVolumePrivilege privileges.
        /// </remarks>
        public void SetValidLength(long value)
        {
            bool success = SetFileValidData(m_handle, value);

            if (!success)
            {
                int    errorCode = Marshal.GetLastWin32Error();
                string message   = String.Format("Failed to set valid file length to {0}.", value);
                IOExceptionHelper.ThrowIOError(errorCode, message);
            }
        }
        public override long Seek(long offset, SeekOrigin origin)
        {
            bool success = SetFilePointerEx(m_handle, offset, out m_position, (uint)origin);

            if (!success)
            {
                int    errorCode = Marshal.GetLastWin32Error();
                string message   = String.Format("Failed to seek to offset {0}, origin: {1}.", offset, origin);
                IOExceptionHelper.ThrowIOError(errorCode, message);
            }
            return(m_position);
        }
 public void Flush(bool flushToDisk)
 {
     if (flushToDisk)
     {
         bool success = FlushFileBuffers(m_handle);
         if (!success)
         {
             int    errorCode = Marshal.GetLastWin32Error();
             string message   = "Failed to flush file buffers.";
             IOExceptionHelper.ThrowIOError(errorCode, message);
         }
     }
 }
        /// <remarks>
        /// The caller can use this method with both synchronous and asynchronous (FILE_FLAG_OVERLAPPED) file handles.
        /// </remarks>
        public void WriteOverlapped(byte[] array, int offset, int count, long position)
        {
            uint             temp; // will not be updated on async operation
            ManualResetEvent completionEvent = new ManualResetEvent(false);
            OVERLAPPED       overlapped      = new OVERLAPPED();

            overlapped.Offset = position;
            overlapped.hEvent = completionEvent.SafeWaitHandle.DangerousGetHandle();
            IntPtr lpOverlapped = Marshal.AllocHGlobal(Marshal.SizeOf(overlapped));

            Marshal.StructureToPtr(overlapped, lpOverlapped, false);
            // We MUST pin the buffer being passed to WriteFile until the operation is complete!
            GCHandle bufferHandle;
            bool     success;

            if (offset == 0)
            {
                bufferHandle = GCHandle.Alloc(array, GCHandleType.Pinned);
                success      = WriteFile(m_handle, array, (uint)count, out temp, lpOverlapped);
            }
            else
            {
                byte[] buffer = new byte[count];
                Array.Copy(array, offset, buffer, 0, buffer.Length);
                bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
                success      = WriteFile(m_handle, buffer, (uint)buffer.Length, out temp, lpOverlapped);
            }

            uint numberOfBytesWritten = 0;

            if (!success)
            {
                int errorCode = Marshal.GetLastWin32Error();
                if (errorCode != (int)Win32Error.ERROR_IO_PENDING)
                {
                    string message = String.Format("Failed to write to position {0} the requested number of bytes ({1}).", position, count);
                    IOExceptionHelper.ThrowIOError(errorCode, message);
                }
                bool completed = GetOverlappedResult(m_handle, lpOverlapped, out numberOfBytesWritten, true);
            }
            bufferHandle.Free();
            completionEvent.Close();
            Marshal.FreeHGlobal(lpOverlapped);

            if (numberOfBytesWritten != count)
            {
                int    errorCode = Marshal.GetLastWin32Error();
                string message   = String.Format("Failed to write to position {0} the requested number of bytes ({1}).", position, count);
                IOExceptionHelper.ThrowIOError(errorCode, message);
            }
        }
        public override void SetLength(long value)
        {
            long position = m_position;

            Seek(value, SeekOrigin.Begin);
            bool success = SetEndOfFile(m_handle);

            if (!success)
            {
                int    errorCode = Marshal.GetLastWin32Error();
                string message   = String.Format("Failed to set file length to {0}.", value);
                IOExceptionHelper.ThrowIOError(errorCode, message);
            }
            Seek(position, SeekOrigin.Begin);
        }
        public void WriteSectorsUnbuffered(long sectorIndex, byte[] data)
        {
            if (data.Length % m_bytesPerSector > 0)
            {
                throw new IOException("Cannot write partial sectors");
            }

            if (IsReadOnly)
            {
                throw new UnauthorizedAccessException("Attempted to perform write on a readonly disk");
            }

            bool           releaseHandle;
            SafeFileHandle handle = PhysicalDiskHandlePool.ObtainHandle(m_physicalDiskIndex, FileAccess.ReadWrite, ShareMode.Read, out releaseHandle);

            if (!handle.IsInvalid)
            {
                FileStreamEx stream = new FileStreamEx(handle, FileAccess.Write);
                try
                {
                    stream.Seek(sectorIndex * m_bytesPerSector, SeekOrigin.Begin);
                    stream.Write(data, 0, data.Length);
                    stream.Flush();
                }
                finally
                {
                    stream.Close(releaseHandle);
                    if (releaseHandle)
                    {
                        PhysicalDiskHandlePool.ReleaseHandle(m_physicalDiskIndex);
                    }
                }
            }
            else
            {
                // we always release invalid handle
                PhysicalDiskHandlePool.ReleaseHandle(m_physicalDiskIndex);
                // get error code and throw
                int    errorCode = Marshal.GetLastWin32Error();
                string message   = String.Format("Failed to write to sector {0} of disk {1}.", sectorIndex, m_physicalDiskIndex);
                IOExceptionHelper.ThrowIOError(errorCode, message);
            }
        }
        private void PopulateDiskInfo()
        {
            bool           releaseHandle;
            SafeFileHandle handle = PhysicalDiskHandlePool.ObtainHandle(m_physicalDiskIndex, FileAccess.Read, ShareMode.ReadWrite, out releaseHandle);

            if (!handle.IsInvalid)
            {
                if (!PhysicalDiskControl.IsMediaAccesible(handle))
                {
                    throw new DeviceNotReadyException();
                }
                DISK_GEOMETRY diskGeometry = PhysicalDiskControl.GetDiskGeometryAndSize(handle, out m_size);
                if (releaseHandle)
                {
                    PhysicalDiskHandlePool.ReleaseHandle(m_physicalDiskIndex);
                }
                m_bytesPerSector = (int)diskGeometry.BytesPerSector;

                // CHS:
                m_cylinders         = diskGeometry.Cylinders;
                m_tracksPerCylinder = (int)diskGeometry.TracksPerCylinder;
                m_sectorsPerTrack   = (int)diskGeometry.SectorsPerTrack;
            }
            else
            {
                // we always release invalid handle
                PhysicalDiskHandlePool.ReleaseHandle(m_physicalDiskIndex);

                // get error code and throw
                int    errorCode = Marshal.GetLastWin32Error();
                string message   = String.Format("Failed to access disk {0}.", m_physicalDiskIndex);
                if (errorCode == (int)Win32Error.ERROR_FILE_NOT_FOUND)
                {
                    throw new DriveNotFoundException(message);
                }
                else
                {
                    IOExceptionHelper.ThrowIOError(errorCode, message);
                }
            }
        }
Esempio n. 14
0
        /// <remarks>
        /// The caller can use this method with both synchronous and asynchronous (FILE_FLAG_OVERLAPPED) file handles.
        /// </remarks>
        public int ReadOverlapped(byte[] array, int offset, int count, long position)
        {
            uint             temp; // will not be updated on async operation
            ManualResetEvent completionEvent = new ManualResetEvent(false);
            OVERLAPPED       overlapped      = new OVERLAPPED();

            overlapped.Offset = position;
            overlapped.hEvent = completionEvent.SafeWaitHandle.DangerousGetHandle();
            IntPtr lpOverlapped = Marshal.AllocHGlobal(Marshal.SizeOf(overlapped));

            Marshal.StructureToPtr(overlapped, lpOverlapped, false);
            bool success;

            if (offset == 0)
            {
                success = ReadFile(m_handle, array, (uint)count, out temp, lpOverlapped);
            }
            else
            {
                byte[] buffer = new byte[count];
                success = ReadFile(m_handle, buffer, (uint)buffer.Length, out temp, lpOverlapped);
                Array.Copy(buffer, 0, array, offset, buffer.Length);
            }

            if (!success)
            {
                int errorCode = Marshal.GetLastWin32Error();
                if (errorCode != (int)Win32Error.ERROR_IO_PENDING)
                {
                    string message = String.Format("Failed to read from position {0} the requested number of bytes ({1}).", position, count);
                    IOExceptionHelper.ThrowIOError(errorCode, message);
                }
                bool completed = completionEvent.WaitOne();
            }
            Marshal.FreeHGlobal(lpOverlapped);
            return(count);
        }
        public AlreadyExistsException(string message) : base(message)
        {
#if Win32
            HResult = IOExceptionHelper.GetHResultFromWin32Error(Win32Error.ERROR_ALREADY_EXISTS);
#endif
        }
        public InvalidNameException(string message) : base(message)
        {
#if Win32
            HResult = IOExceptionHelper.GetHResultFromWin32Error(Win32Error.ERROR_INVALID_NAME);
#endif
        }
        public DiskFullException(string message) : base(message)
        {
#if Win32
            HResult = IOExceptionHelper.GetHResultFromWin32Error(Win32Error.ERROR_DISK_FULL);
#endif
        }
        public CyclicRedundancyCheckException(string message) : base(message)
        {
#if Win32
            HResult = IOExceptionHelper.GetHResultFromWin32Error(Win32Error.ERROR_CRC);
#endif
        }
Esempio n. 19
0
 public InvalidPathException(string message) : base(message)
 {
     HResult = IOExceptionHelper.GetHResultFromWin32Error(Win32Error.ERROR_BAD_PATHNAME);
 }
        public DirectoryNotEmptyException(string message) : base(message)
        {
#if Win32
            HResult = IOExceptionHelper.GetHResultFromWin32Error(Win32Error.ERROR_DIR_NOT_EMPTY);
#endif
        }
        public DeviceNotReadyException(string message) : base(message)
        {
#if Win32
            HResult = IOExceptionHelper.GetHResultFromWin32Error(Win32Error.ERROR_NOT_READY);
#endif
        }
        public SharingViolationException(string message) : base(message)
        {
#if Win32
            HResult = IOExceptionHelper.GetHResultFromWin32Error(Win32Error.ERROR_SHARING_VIOLATION);
#endif
        }