Esempio n. 1
0
        /// <returns>Will return null if an unrecoverable IO Error has occured or read is aborted</returns>
        public byte[] ReadEverySectorUnbuffered(long sectorIndex, int sectorCount, out List <long> damagedSectors, out bool ioErrorOccured)
        {
            damagedSectors = new List <long>();
            ioErrorOccured = false;
            try
            {
                UpdateStatus(sectorIndex * m_disk.BytesPerSector);
                return(m_disk.ReadSectors(sectorIndex, sectorCount));
            }
            catch (IOException ex1)
            {
                int errorCode1 = IOExceptionHelper.GetWin32ErrorCode(ex1);
                AddToLog("Read failure (Win32 error: {0}) at {1:###,###,###,###,##0}-{2:###,###,###,###,##0}", errorCode1, sectorIndex, sectorIndex + sectorCount - 1);
                if (errorCode1 != (int)Win32Error.ERROR_IO_DEVICE && errorCode1 != (int)Win32Error.ERROR_CRC)
                {
                    ioErrorOccured = true;
                    return(null);
                }

                byte[] data = new byte[sectorCount * m_disk.BytesPerSector];
                // Try to read sector by sector (to maximize data recovery)
                for (long sectorOffset = 0; sectorOffset < sectorCount; sectorOffset++)
                {
                    long currentPosition = (sectorIndex + sectorOffset) * m_disk.BytesPerSector;
                    UpdateStatus(currentPosition);
                    try
                    {
                        byte[] sectorBytes = m_disk.ReadSector(sectorIndex + sectorOffset);
                        Array.Copy(sectorBytes, 0, data, sectorOffset * m_disk.BytesPerSector, m_disk.BytesPerSector);
                    }
                    catch (IOException ex2)
                    {
                        int errorCode2 = IOExceptionHelper.GetWin32ErrorCode(ex2);
                        AddToLog("Read failure (Win32 error: {0}) at sector {1:###,###,###,###,##0}", errorCode2, sectorIndex + sectorOffset);
                        if (errorCode2 == (int)Win32Error.ERROR_IO_DEVICE || errorCode2 == (int)Win32Error.ERROR_CRC)
                        {
                            damagedSectors.Add(sectorIndex + sectorOffset);
                        }
                        else // ERROR_FILE_NOT_FOUND, ERROR_DEVICE_NOT_CONNECTED, ERROR_DEV_NOT_EXIST etc.
                        {
                            ioErrorOccured = true;
                            return(null);
                        }
                    }
                    if (m_abort)
                    {
                        return(null);
                    }
                }

                if (damagedSectors.Count == 0)
                {
                    // Sometimes the bulk read will raise an exception but all sector by sector reads will succeed.
                    // This means that there is some serious (and most likely unrecoverable) issue with the disk
                    // so we report this as an unrecoverable IO error even though we managed to retrieve all of the data.
                    ioErrorOccured = true;
                }
                return(data);
            }
        }
Esempio n. 2
0
        /// <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
            }
        }
Esempio n. 3
0
        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. 4
0
 /// <returns>Will return null if an error has occured</returns>
 public byte[] ReadSectorsUnbuffered(long sectorIndex, int sectorCount, out bool ioErrorOccured)
 {
     ioErrorOccured = false;
     UpdateStatus(sectorIndex * m_disk.BytesPerSector);
     try
     {
         return(m_disk.ReadSectors(sectorIndex, sectorCount));
     }
     catch (IOException ex)
     {
         int errorCode = IOExceptionHelper.GetWin32ErrorCode(ex);
         AddToLog("Read failure (Win32 error: {0}) at {1:###,###,###,###,##0}-{2:###,###,###,###,##0}", errorCode, sectorIndex, sectorIndex + sectorCount - 1);
         if (errorCode != (int)Win32Error.ERROR_IO_DEVICE && errorCode != (int)Win32Error.ERROR_CRC)
         {
             ioErrorOccured = true;
         }
         return(null);
     }
 }
Esempio n. 5
0
        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);
            }
        }
Esempio n. 6
0
        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);
                }
            }
        }