/// <summary> /// CheckTrim Checks for trim descriptor /// </summary> /// <param name="DiskIndex">Physical disk index</param> /// <returns> /// true if trim is enabled else false. /// </returns> private static bool CheckTrim(int DiskIndex) { DEVICE_TRIM_DESCRIPTOR TrimDesc = new DEVICE_TRIM_DESCRIPTOR(); STORAGE_PROPERTY_QUERY StorageQuery = new STORAGE_PROPERTY_QUERY(); uint BytesReturned = 0; StorageQuery.PropertyId = STORAGE_PROPERTY_ID.StorageDeviceTrimProperty; StorageQuery.QueryType = STORAGE_QUERY_TYPE.PropertyStandardQuery; IntPtr StorageQueryPtr = Marshal.AllocHGlobal(Marshal.SizeOf(StorageQuery)); IntPtr TrimDescPtr = Marshal.AllocHGlobal(Marshal.SizeOf(TrimDesc)); Marshal.StructureToPtr(StorageQuery, StorageQueryPtr, false); Marshal.StructureToPtr(TrimDesc, TrimDescPtr, false); SafeFileHandle physicalDisk = DeviceIO.CreateFile( "\\\\.\\PhysicalDrive" + DiskIndex, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, IntPtr.Zero); bool rs = DeviceIoControl(physicalDisk, IOCTL_STORAGE_QUERY_PROPERTY, StorageQueryPtr, (uint)Marshal.SizeOf(StorageQuery), TrimDescPtr, (uint)Marshal.SizeOf(TrimDesc), ref BytesReturned, IntPtr.Zero); if (rs == false) { throw new Exception(); } TrimDesc = (DEVICE_TRIM_DESCRIPTOR)Marshal.PtrToStructure(TrimDescPtr, typeof(DEVICE_TRIM_DESCRIPTOR)); return(TrimDesc.TrimEnabled); }
// public ulong SeekU(ulong offset, SeekOrigin origin) { ulong n = 0; if (!DeviceIO.SetFilePointerEx(this.fileHandle, offset, out n, (uint)origin)) { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); } return(n); }
/// <summary> /// Close Opened File Handles for current object /// </summary> public override void Close() { if (this.fileHandle != null) { DeviceIO.CloseHandle(this.fileHandle); this.fileHandle.SetHandleAsInvalid(); this.fileHandle = null; } base.Close(); }
/// <summary> /// Function to Write Data Pattern that is in buffer to disk sectors /// </summary> /// <param name="writeBuffer">The buffer that has the pattern of data to write</param> /// <param name="writeOffset">The byte offset in writeBuffer from which to begin copying bytes to the stream</param> /// <param name="writeCount">The maximum number of bytes to write</param> /// <returns></returns> public unsafe void Write(byte[] writeBuffer, uint writeOffset, uint writeCount) { uint BytesWritten = 0; UInt64 newFilePtr = 0; long sectorStart = -1; long sectorEnd = -1; while (true) { Console.WriteLine("Enter start sector to overwrite from : "); Wipe.sectorStart = Convert.ToUInt64(Console.ReadLine()); Console.WriteLine("\nEnter end sector to write till : "); Wipe.sectorEnd = Convert.ToUInt64(Console.ReadLine()); if (sectorStart < sectorEnd) { break; } else { Console.WriteLine("\nStart sector cannot be greater than end Sector.....Try again!!!\n"); } } long sectorDiff = sectorEnd - sectorStart; int size = Wipe.sectorWriteSize;// ((sectorDiff > 32) ? ((sectorDiff > 1024) ? (512 * 2 * 64) : (512 * 2 * 4)) : 512); //512 * 2 * 1024; ulong distanceToMove = (ulong)(sectorStart * size); Console.WriteLine("\nWriting entered pattern to disk\n"); try { fixed(byte *writeBufferPointer = writeBuffer) { DeviceIO.SetFilePointerEx(this.fileHandle, distanceToMove, out newFilePtr, DeviceIO.FILE_BEGIN); for (long i = sectorStart; i <= sectorEnd; i += (size / 512)) { if (!DeviceIO.WriteFile(this.fileHandle, writeBufferPointer + writeOffset, (uint)size, &BytesWritten, IntPtr.Zero)) { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); } //sectorStart += (size / 512); if (i % 100 == 0) { drawTextProgressBar((int)i, (int)sectorEnd); } } Console.WriteLine("After WriteFile"); } } catch (Exception e) { Console.WriteLine(e.Message); } }
/// <summary> /// Function to Lock Volumes /// </summary> /// <param name="drive">Volume label</param> /// <returns> /// true on successful lock of the volumes,else false /// </returns> public bool LockVolume(string drive) { try { uint bytesWritten = 0; bool locked = DeviceIO.DeviceIoControl(this.fileHandle, DeviceIO.FSCTL_LOCK_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 0, ref bytesWritten, IntPtr.Zero); if (locked == false) { Console.WriteLine("\nCoudln't lock volume\n"); } return(locked); } catch (Exception e) { Console.WriteLine(e.Message); return(false); } }
/// <summary> /// Function to Unmount Volumes /// </summary> /// <param name="drive">Volume label</param> /// <returns> /// true on successfull unmount of the volume, else false /// </returns> public bool UnmountVolume(string drive) { try { uint BytesWritten = 0; Console.WriteLine("\nAttempting to Unmount volume : " + drive + "\n"); bool unmounted = DeviceIO.DeviceIoControl(this.fileHandle, DeviceIO.FSCTL_DISMOUNT_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 0, ref BytesWritten, IntPtr.Zero); if (unmounted == false) { Console.WriteLine("\nCoudln't Dismount volume\n"); } return(unmounted); } catch (Exception e) { Console.WriteLine(e.Message); return(false); } }
/// <summary> /// Opens file handle for the required drive. /// </summary> /// <param name="id"></param> /// <param name="desiredAccess"></param> /// <returns> /// Pointer to the drive /// </returns> private SafeFileHandle OpenFile(string id, FileAccess desiredAccess) { uint access; switch (desiredAccess) { case FileAccess.Read: access = DeviceIO.GENERIC_READ; break; case FileAccess.Write: access = DeviceIO.GENERIC_WRITE; break; case FileAccess.ReadWrite: access = DeviceIO.GENERIC_READ | DeviceIO.GENERIC_WRITE; break; default: access = DeviceIO.GENERIC_READ; break; } SafeFileHandle ptr = DeviceIO.CreateFile( id, access, DeviceIO.FILE_SHARE_READ, IntPtr.Zero, DeviceIO.OPEN_EXISTING, DeviceIO.FILE_FLAG_NO_BUFFERING | DeviceIO.FILE_FLAG_WRITE_THROUGH, IntPtr.Zero); if (ptr.IsInvalid) { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); } return(ptr); }
/// <summary> /// Function to Read Data into the Buffer from disk /// </summary> /// <param name="readBuffer">bytes read from the current disk.</param> /// <param name="readOffset"> byte offset in readBuffer at which to begin storing the data read from the current stream.</param> /// <param name="readCount">The maximum number of bytes to be read from the current stream.</param> /// <returns> /// Number of bytes read into the buffer. /// </returns> public unsafe uint Read(byte[] readBuffer, uint readOffset, uint readCount) { uint BytesRead = 0; UInt64 newFilePtr = 0; uint size = 512;// ((sectorDiff > 32) ? ((sectorDiff > 1024) ? (512 * 2 * 64 ) : (512 * 2 * 4)) : 512); ulong distanceToMove = (ulong)(Wipe.sectorStart * size); Console.WriteLine("\nVerifying Write Pattern....\n"); fixed(byte *readBufferPointer = readBuffer) { DeviceIO.SetFilePointerEx(this.fileHandle, distanceToMove, out newFilePtr, DeviceIO.FILE_BEGIN); for (ulong i = Wipe.sectorStart; i <= Wipe.sectorEnd; i += ((ulong)size / 512)) { if (!DeviceIO.ReadFile(this.fileHandle, readBufferPointer + readOffset, size, &BytesRead, IntPtr.Zero)) { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); } if (!readBuffer.SequenceEqual(toWrite)) { Wipe.sectorErrorCount++; } /*else * { * Console.WriteLine("Could not verify"); * }*/ //Wipe.sectorStart += ((ulong)size / 512); } Console.WriteLine("Verification Complete....."); return(BytesRead); } }
/// <summary> /// The Main method, chooses on Trim or overwritting and executes accordingly. /// </summary> /// <param name="args"></param> static void Main(string[] args) { Console.WriteLine("***************************\n" + "*\t\t\t *\n*\tWipe Demo\t *\n*\t\t\t *\n" + "***************************\n"); Console.Write("Reading Drive Information"); int i = 0; while (i++ < 4) { Console.Write("."); Thread.Sleep(500); } RetrieveDiskInfo(); DisplayDiskVolInfo(); //BeginErase /* { * //while(diskIndices in List<Drives>) * { * //CheckTrim(); * //GetOffsets(); * //UnmountVolumes(); * //ExecuteTrim(); * //ExecuteOverwrite(); * } * } */ Console.WriteLine("Beginning Erase Procedure....Are you sure you want to continue Y/N ??"); char input = (char)Console.Read(); if (input == 'n' || input == 'N') { Environment.Exit(-1); } Console.WriteLine("Enter value to write within 0-255"); int val = Convert.ToInt32(Console.ReadLine()); Console.WriteLine("Enter how many sectors to write at a time"); sectorOffset = Convert.ToInt32(Console.ReadLine()); writeBuffer = Enumerable.Repeat((byte)val, writeBuffer.Length).ToArray(); foreach (Dictionary <String, Object> disk in PhysicalDriveInfo.Values) { bool doTrim = bool.Parse(disk["TrimSupported"].ToString()); BytesPerSector = int.Parse(disk["BytesPerSector"].ToString()); sectorWriteSize = BytesPerSector * sectorOffset; writeBuffer = new byte[sectorWriteSize]; readBuffer = new byte[sectorReadSize]; uint DiskIndex = (uint)disk["Index"]; DeviceIO diskObj = new DeviceIO(); List <Dictionary <String, Object> > volumes = VolumesInfo[(int)DiskIndex]; diskObj.OpenFileObject(DiskIndex, FileAccess.ReadWrite); foreach (Dictionary <String, Object> volumeInfo in volumes) { Regex regex = new Regex(@"\((.*?)\)"); Match tmpDriveName = regex.Match(volumeInfo["Name"].ToString()); String driveLetter = tmpDriveName.Value.Replace("(", "").Replace(")", "").Trim(); int volumeIndex = -1; Console.WriteLine("Partition letter : " + driveLetter); if (driveLetter.Equals("")) { volumeIndex = (int)volumeInfo["Index"]; } if (bool.Parse(volumeInfo["Erasable"].ToString()) == true) { sectorStart = Convert.ToUInt64(volumeInfo["StartingOffset"]) / 512; // startingOffsets.Add(Convert.ToString(volumeInfo["Name"]), sectorStart); UInt64 sectorStartInBytes = Convert.ToUInt64(volumeInfo["StartingOffset"]); UInt64 totalSpace = Convert.ToUInt64(volumeInfo["Size"]); UInt64 sectorEndInBytes = sectorStartInBytes + totalSpace; sectorEnd = (sectorStartInBytes + totalSpace) / 512; // UInt64 sectorDiff = sectorEnd - sectorStart; //writeBuffer = new Byte[1048576]; //writeBuffer = Enumerable.Repeat((byte)val, writeBuffer.Length).ToArray(); //readBuffer = new byte[1048576]; //endingOffsets.Add(Convert.ToString(volumeInfo["Name"]), sectorEnd); diskObj.LockVolume(driveLetter); diskObj.UnmountVolume(driveLetter); if (doTrim) { PerformTrim(driveLetter); } } diskObj.Write(writeBuffer, 0, writeBuffer.Length); diskObj.Read(readBuffer, 0, readBuffer.Length); } } }