/// <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); } }
/// <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 } }
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); } } }
/// <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); } }
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); } } }