/// <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 = VolumeHandlePool.ObtainHandle(m_volumeGuid, 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) { VolumeHandlePool.ReleaseHandle(m_volumeGuid); } } return(buffer); } else { // we always release invalid handle VolumeHandlePool.ReleaseHandle(m_volumeGuid); // get error code and throw int errorCode = Marshal.GetLastWin32Error(); string message = String.Format("Can't read sector {0} from volume {1}, Win32 Error: {2}", sectorIndex, m_volumeGuid, errorCode); throw new IOException(message); } }
/// <summary> /// Windows will flush all cached data to the volume before locking it. /// Note: we can only lock a dynamic volume if the disk is online. /// </summary> /// <returns>True if a new lock has been obtained</returns> public static bool ExclusiveLock(Guid windowsVolumeGuid, FileAccess fileAccess) { bool newAllocation; // Windows Vista / 7: Valid handle cannot be obtained for a dynamic volume using ShareMode.ReadWrite. // The FSCTL_LOCK_VOLUME documentation demands ShareMode.ReadWrite, but ShareMode.None or ShareMode.Write will work too. SafeFileHandle handle = VolumeHandlePool.ObtainHandle(windowsVolumeGuid, fileAccess, ShareMode.None, out newAllocation); if (newAllocation) { if (!handle.IsInvalid) { bool success = VolumeUtils.LockVolume(handle); if (!success) { VolumeHandlePool.ReleaseHandle(windowsVolumeGuid); } return(success); } else { VolumeHandlePool.ReleaseHandle(windowsVolumeGuid); return(false); } } else { return(false); } }
/// <summary> /// Note that the volume will be remounted again on first access. /// </summary> public static bool DismountVolume(Guid windowsVolumeGuid) { bool releaseHandle; SafeFileHandle handle = VolumeHandlePool.ObtainHandle(windowsVolumeGuid, FileAccess.ReadWrite, ShareMode.ReadWrite, out releaseHandle); bool success = false; if (!handle.IsInvalid) { success = VolumeUtils.DismountVolume(handle); } if (releaseHandle) // new allocation { VolumeHandlePool.ReleaseHandle(windowsVolumeGuid); } return(success); }
/// <summary> /// Volume should be locked at this point for this call to have any effect /// </summary> /// <returns></returns> public bool AllowExtendedIO() { bool releaseHandle; SafeFileHandle handle = VolumeHandlePool.ObtainHandle(m_volumeGuid, FileAccess.ReadWrite, ShareMode.None, out releaseHandle); if (!handle.IsInvalid) { bool result = VolumeControl.AllowExtendedIO(handle); if (releaseHandle) { VolumeHandlePool.ReleaseHandle(m_volumeGuid); } return(result); } else { // we always release invalid handle VolumeHandlePool.ReleaseHandle(m_volumeGuid); return(false); } }
public void WriteSectorsUnbuffered(long sectorIndex, byte[] data) { if (data.Length % m_bytesPerSector > 0) { throw new IOException("Cannot write partial sectors"); } if (!m_isReadOnly) { bool releaseHandle; SafeFileHandle handle = VolumeHandlePool.ObtainHandle(m_volumeGuid, FileAccess.ReadWrite, ShareMode.None, 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) { VolumeHandlePool.ReleaseHandle(m_volumeGuid); } } } else { // we always release invalid handle VolumeHandlePool.ReleaseHandle(m_volumeGuid); // get error code and throw int errorCode = Marshal.GetLastWin32Error(); string message = String.Format("Can't write to sector {0} of volume {1}, Win32 errorCode: {2}", sectorIndex, m_volumeGuid, errorCode); throw new IOException(message); } } }
public static bool ReleaseLock(Guid windowsVolumeGuid) { return(VolumeHandlePool.ReleaseHandle(windowsVolumeGuid)); }