├── DiskReader.sln ├── DiskReader ├── DiskReader.csproj ├── DiskReader.csproj.user ├── FileSize.cs ├── Program.cs ├── Properties │ ├── PublishProfiles │ │ ├── FolderProfile.pubxml │ │ └── FolderProfile.pubxml.user │ └── launchSettings.json ├── ReadDisksClass.cs └── app.manifest ├── README.md └── README.md.backup /DiskReader.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.32126.315 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DiskReader", "DiskReader\DiskReader.csproj", "{24BD5838-898E-4050-B78D-7D0042F7798D}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {24BD5838-898E-4050-B78D-7D0042F7798D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {24BD5838-898E-4050-B78D-7D0042F7798D}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {24BD5838-898E-4050-B78D-7D0042F7798D}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {24BD5838-898E-4050-B78D-7D0042F7798D}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {100BCEB2-BFD3-4041-9A42-B15613AA20FD} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /DiskReader/DiskReader.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net5.0 6 | app.manifest 7 | empyreal96 8 | Backup Disks to files 9 | empyreal96 2022 10 | true 11 | EmpyKey_DiskReader.snk 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /DiskReader/DiskReader.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | <_LastSelectedProfileId>C:\Users\Empyreal96\source\repos\DiskReader\DiskReader\Properties\PublishProfiles\FolderProfile.pubxml 5 | 6 | -------------------------------------------------------------------------------- /DiskReader/FileSize.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DiskReader 8 | { 9 | public static class ExtensionMethods 10 | { 11 | public static string ToFileSize(this long l) 12 | { 13 | try 14 | { 15 | return string.Format(new FileSizeFormatProvider(), "{0:fs}", l); 16 | } 17 | catch (System.Exception e) 18 | { 19 | return "0 KB"; 20 | } 21 | } 22 | } 23 | 24 | public class FileSizeFormatProvider : IFormatProvider, ICustomFormatter 25 | { 26 | public object GetFormat(Type formatType) 27 | { 28 | if (formatType == typeof(ICustomFormatter)) return this; 29 | return null; 30 | } 31 | 32 | private const string fileSizeFormat = "fs"; 33 | private const Decimal OneKiloByte = 1024M; 34 | private const Decimal OneMegaByte = OneKiloByte * 1024M; 35 | private const Decimal OneGigaByte = OneMegaByte * 1024M; 36 | 37 | public string Format(string format, object arg, IFormatProvider formatProvider) 38 | { 39 | try 40 | { 41 | if (format == null || !format.StartsWith(fileSizeFormat)) 42 | { 43 | return defaultFormat(format, arg, formatProvider); 44 | } 45 | } 46 | catch (System.Exception e) 47 | { 48 | 49 | } 50 | if (arg is string) 51 | { 52 | return defaultFormat(format, arg, formatProvider); 53 | } 54 | 55 | Decimal size; 56 | 57 | try 58 | { 59 | size = Convert.ToDecimal(arg); 60 | } 61 | catch (System.Exception e) 62 | { 63 | return defaultFormat(format, arg, formatProvider); 64 | } 65 | 66 | string suffix; 67 | if (size > OneGigaByte) 68 | { 69 | size /= OneGigaByte; 70 | suffix = " GB"; 71 | } 72 | else if (size > OneMegaByte) 73 | { 74 | size /= OneMegaByte; 75 | suffix = " MB"; 76 | } 77 | else if (size > OneKiloByte) 78 | { 79 | size /= OneKiloByte; 80 | suffix = " KB"; 81 | } 82 | else 83 | { 84 | suffix = " B"; 85 | } 86 | 87 | string precision = format.Substring(2); 88 | if (String.IsNullOrEmpty(precision)) precision = "2"; 89 | return String.Format("{0:N" + precision + "}{1}", size, suffix); 90 | 91 | } 92 | 93 | private static string defaultFormat(string format, object arg, IFormatProvider formatProvider) 94 | { 95 | IFormattable formattableArg = arg as IFormattable; 96 | if (formattableArg != null) 97 | { 98 | return formattableArg.ToString(format, formatProvider); 99 | } 100 | return arg.ToString(); 101 | } 102 | 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /DiskReader/Program.cs: -------------------------------------------------------------------------------- 1 | using ReadFromDevice; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.IO; 6 | using System.Management; 7 | using System.Runtime.InteropServices; 8 | using System.Text; 9 | using System.Text.RegularExpressions; 10 | 11 | namespace DiskReader 12 | { 13 | class Program 14 | { 15 | static void Main(string[] args) 16 | { 17 | Console.WriteLine("DiskReader by Empyreal96 (c) 2022"); 18 | Console.WriteLine(""); 19 | if (args.Length == 0) 20 | { 21 | // Console.WriteLine($"Parameters incorrect: {args[0]}, {args[1]}\n\n"); 22 | Console.WriteLine("To read disk to file:"); 23 | Console.WriteLine(@"DiskReader.exe \\.\PhysicalDrive1 C:\Output\Path\image.img"); 24 | Console.WriteLine(""); 25 | Console.WriteLine("To view connected disks:"); 26 | Console.WriteLine(@"DiskReader.exe ListDisks "); 27 | Console.ReadLine(); 28 | Environment.Exit(1); 29 | } 30 | if (args[0] == "ListDisks") 31 | { 32 | var driveQuery = new ManagementObjectSearcher("select * from Win32_DiskDrive"); 33 | foreach (ManagementObject d in driveQuery.Get()) 34 | { 35 | var deviceId = d.Properties["DeviceId"].Value; 36 | var partitionQueryText = string.Format("associators of {{{0}}} where AssocClass = Win32_DiskDriveToDiskPartition", d.Path.RelativePath); 37 | var partitionQuery = new ManagementObjectSearcher(partitionQueryText); 38 | foreach (ManagementObject p in partitionQuery.Get()) 39 | { 40 | var logicalDriveQueryText = string.Format("associators of {{{0}}} where AssocClass = Win32_LogicalDiskToPartition", p.Path.RelativePath); 41 | var logicalDriveQuery = new ManagementObjectSearcher(logicalDriveQueryText); 42 | foreach (ManagementObject ld in logicalDriveQuery.Get()) 43 | { 44 | var physicalName = Convert.ToString(d.Properties["Name"].Value); // \\.\PHYSICALDRIVE2 45 | var diskName = Convert.ToString(d.Properties["Caption"].Value); // WDC WD5001AALS-xxxxxx 46 | var diskModel = Convert.ToString(d.Properties["Model"].Value); // WDC WD5001AALS-xxxxxx 47 | var diskInterface = Convert.ToString(d.Properties["InterfaceType"].Value); // IDE 48 | var capabilities = (UInt16[])d.Properties["Capabilities"].Value; // 3,4 - random access, supports writing 49 | var mediaLoaded = Convert.ToBoolean(d.Properties["MediaLoaded"].Value); // bool 50 | var mediaType = Convert.ToString(d.Properties["MediaType"].Value); // Fixed hard disk media 51 | var mediaSignature = Convert.ToUInt32(d.Properties["Signature"].Value); // int32 52 | var mediaStatus = Convert.ToString(d.Properties["Status"].Value); // OK 53 | 54 | var driveName = Convert.ToString(ld.Properties["Name"].Value); // C: 55 | var driveId = Convert.ToString(ld.Properties["DeviceId"].Value); // C: 56 | var driveCompressed = Convert.ToBoolean(ld.Properties["Compressed"].Value); 57 | var driveType = Convert.ToUInt32(ld.Properties["DriveType"].Value); // C: - 3 58 | var fileSystem = Convert.ToString(ld.Properties["FileSystem"].Value); // NTFS 59 | var freeSpace = Convert.ToUInt64(ld.Properties["FreeSpace"].Value); // in bytes 60 | long freespace = (long)freeSpace; 61 | var totalSpace = Convert.ToUInt64(ld.Properties["Size"].Value); // in bytes 62 | long totalspace = (long)totalSpace; 63 | var driveMediaType = Convert.ToUInt32(ld.Properties["MediaType"].Value); // c: 12 64 | var volumeName = Convert.ToString(ld.Properties["VolumeName"].Value); // System 65 | var volumeSerial = Convert.ToString(ld.Properties["VolumeSerialNumber"].Value); // 12345678 66 | 67 | Console.WriteLine("PhysicalName: {0}", physicalName); 68 | Console.WriteLine("Disk Name: {0}", diskName); 69 | Console.WriteLine("Disk Model: {0}", diskModel); 70 | Console.WriteLine("Interface: {0}", diskInterface); 71 | // Console.WriteLine("Capabilities: {0}", capabilities); 72 | Console.WriteLine("Media Loaded: {0}", mediaLoaded); 73 | Console.WriteLine("Media Type: {0}", mediaType); 74 | Console.WriteLine("Media Signature: {0}", mediaSignature); 75 | Console.WriteLine("Media Status: {0}", mediaStatus); 76 | 77 | Console.WriteLine("Drive Name: {0}", driveName); 78 | Console.WriteLine("Drive ID: {0}", driveId); 79 | Console.WriteLine("Compressed: {0}", driveCompressed); 80 | Console.WriteLine("Drive Type: {0}", driveType); 81 | Console.WriteLine("FileSystem: {0}", fileSystem); 82 | Console.WriteLine("Free Space: {0}", freespace.ToFileSize()); 83 | Console.WriteLine("Total Space: {0}", totalspace.ToFileSize()); 84 | Console.WriteLine("Drive Media Type: {0}", driveMediaType); 85 | Console.WriteLine("Volume Name: {0}", volumeName); 86 | Console.WriteLine("Volume Serial: {0}", volumeSerial); 87 | 88 | Console.WriteLine(new string('-', 79)); 89 | 90 | } 91 | } 92 | } 93 | Console.WriteLine("Done.."); 94 | Console.ReadLine(); 95 | 96 | } 97 | else 98 | { 99 | try 100 | { 101 | if (args.Length == 0) 102 | { 103 | Console.WriteLine($"Parameters incorrect: {args[0]}, {args[1]}\n\n"); 104 | Console.WriteLine("To read disk to file:"); 105 | Console.WriteLine(@"DiskReader.exe \\.\PhysicalDrive1 C:\Output\Path\image.img"); 106 | // Console.WriteLine(@"DiskReader.exe E:\ C:\Output\Path\Partition.img \n"); 107 | Console.WriteLine("To view connected disks:"); 108 | Console.WriteLine(@"DiskReader.exe ListDisks "); 109 | Console.WriteLine(@"DiskReader.exe Volumes "); 110 | Console.ReadLine(); 111 | Environment.Exit(1); 112 | } 113 | else 114 | { 115 | if (args[0].Contains(@"Volumes")) 116 | { 117 | Console.WriteLine("Reading connected volumes."); 118 | Console.WriteLine(""); 119 | 120 | DriveInfo[] allDrives = DriveInfo.GetDrives(); 121 | 122 | foreach (DriveInfo d in allDrives) 123 | { 124 | Console.WriteLine(new string('-', 74)); 125 | long totalsize; 126 | long freesize; 127 | string volume = DiskInfo.GetVolumeGuidPath(d.Name); 128 | if (d.IsReady == true) 129 | { 130 | totalsize = d.TotalSize; 131 | freesize = d.AvailableFreeSpace; 132 | 133 | Console.WriteLine($" {volume} | {d.Name} | {d.VolumeLabel}"); 134 | Console.WriteLine($" {freesize.ToFileSize()}\\{totalsize.ToFileSize()} | {d.DriveFormat} | {d.DriveType}"); 135 | Console.WriteLine(""); 136 | Console.WriteLine(""); 137 | 138 | } else 139 | { 140 | Console.WriteLine($" {volume} | {d.Name}"); 141 | Console.WriteLine(""); 142 | Console.WriteLine(""); 143 | } 144 | 145 | } 146 | Console.ReadLine(); 147 | } 148 | 149 | 150 | else 151 | { 152 | if (args[0].Contains(@":\")) 153 | { 154 | string path = args[1]; 155 | string mount = args[0]; 156 | string volume = DiskInfo.GetVolumeGuidPath(mount); 157 | 158 | Stream stream = new FileStream(volume, FileMode.Open); 159 | 160 | var reader = new BinaryReader(stream); 161 | 162 | var writer = new BinaryWriter(new FileStream(path, FileMode.Create)); 163 | 164 | var buffer = new byte[4096]; 165 | int count; 166 | int loopcount = 0; 167 | //DeviceStream diskStream = new DeviceStream(args[0]); 168 | //Stream fileStream = File.Create(path, 4096, FileOptions.RandomAccess); 169 | 170 | 171 | //int size = 0; 172 | try 173 | { 174 | 175 | //diskStream.CopyTo(fileStream); 176 | System.Console.WriteLine($"Writing {args[0]} to file, this will take several minutes"); 177 | while ((count = reader.Read(buffer, 0, buffer.Length)) > 0) 178 | { 179 | writer.Write(buffer, 0, buffer.Length); 180 | // System.Console.Write('.'); 181 | if (loopcount % 100 == 0) 182 | { 183 | 184 | 185 | 186 | // writer.Flush(); 187 | } 188 | loopcount++; 189 | 190 | } 191 | } 192 | catch (Exception e) 193 | { 194 | Debug.WriteLine(e.Message); 195 | Debug.WriteLine(""); 196 | Debug.WriteLine(e.StackTrace); 197 | Debug.WriteLine(""); 198 | Debug.WriteLine(e.Source); 199 | //Console.ReadLine(); 200 | } 201 | reader.Close(); 202 | writer.Flush(); 203 | writer.Close(); 204 | Console.WriteLine("Finished"); 205 | Console.ReadLine(); 206 | 207 | } 208 | if (args[0].Contains(@"\\.\PhysicalDrive")) 209 | { 210 | 211 | string path; 212 | 213 | if (string.IsNullOrEmpty(args[1])) 214 | { 215 | path = @".\image.img"; 216 | 217 | } 218 | else 219 | { 220 | path = $"{args[1]}"; 221 | 222 | } 223 | if (File.Exists(path)) 224 | { 225 | File.Delete(path); 226 | } 227 | 228 | var diskid = Regex.Match(args[0], @"\d+").Value; 229 | // string diskID = args[0].Replace(@"\\.\PhysicalDrive", ""); 230 | Debug.WriteLine($"DiskID: {Int32.Parse(diskid)}"); 231 | int partcount = 0; 232 | ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_DiskPartition"); 233 | 234 | Console.WriteLine(); 235 | foreach (ManagementObject queryObj in searcher.Get()) 236 | { 237 | 238 | if ((uint)queryObj["DiskIndex"] == Int32.Parse(diskid)) 239 | { 240 | partcount++; 241 | Debug.WriteLine("-----------------------------------"); 242 | 243 | Debug.WriteLine("Win32_DiskPartition instance"); 244 | 245 | Debug.WriteLine("Name:{0}", (string)queryObj["Name"]); 246 | 247 | Debug.WriteLine("Index:{0}", (uint)queryObj["Index"]); 248 | 249 | Debug.WriteLine("DiskIndex:{0}", (uint)queryObj["DiskIndex"]); 250 | 251 | Debug.WriteLine("BootPartition:{0}", (bool)queryObj["BootPartition"]); 252 | } 253 | 254 | 255 | 256 | 257 | } 258 | 259 | 260 | 261 | 262 | 263 | var diskSize = DiskInfo.GetPhysDiskSize(args[0]); 264 | Console.WriteLine($"Selected Disk: {args[0]}"); 265 | Console.WriteLine($"Disk Size: {diskSize.ToFileSize().ToString()}"); 266 | Console.WriteLine($"No. of Partitions = {partcount}"); 267 | Console.WriteLine(); 268 | Console.WriteLine($"Selected Output: {path}"); 269 | Console.WriteLine("ENTER to continue, or Close this window."); 270 | Console.ReadLine(); 271 | var reader = new BinaryReader(new DeviceStream(args[0])); 272 | 273 | var writer = new BinaryWriter(new FileStream(path, FileMode.Create)); 274 | 275 | var buffer = new byte[4096]; 276 | int count; 277 | int loopcount = 0; 278 | //DeviceStream diskStream = new DeviceStream(args[0]); 279 | //Stream fileStream = File.Create(path, 4096, FileOptions.RandomAccess); 280 | 281 | 282 | //int size = 0; 283 | try 284 | { 285 | 286 | //diskStream.CopyTo(fileStream); 287 | System.Console.WriteLine($"Writing Data to file, this will take several minutes"); 288 | while ((count = reader.Read(buffer, 0, buffer.Length)) > 0) 289 | { 290 | writer.Write(buffer, 0, buffer.Length); 291 | // System.Console.Write('.'); 292 | if (loopcount % 100 == 0) 293 | { 294 | 295 | 296 | 297 | // writer.Flush(); 298 | } 299 | loopcount++; 300 | 301 | } 302 | } 303 | catch (Exception e) 304 | { 305 | Debug.WriteLine(e.Message); 306 | Debug.WriteLine(""); 307 | Debug.WriteLine(e.StackTrace); 308 | Debug.WriteLine(""); 309 | Debug.WriteLine(e.Source); 310 | //Console.ReadLine(); 311 | } 312 | reader.Close(); 313 | writer.Flush(); 314 | writer.Close(); 315 | Console.WriteLine("Finished"); 316 | Console.ReadLine(); 317 | } 318 | else 319 | { 320 | Console.WriteLine($"Parameters incorrect: {args[0]}, {args[1]}\n\n"); 321 | Console.WriteLine("To read disk to file:"); 322 | Console.WriteLine(@"DiskReader.exe \\.\PhysicalDrive1 C:\Output\Path\image.img \n"); 323 | Console.WriteLine("To view connected disks:"); 324 | Console.WriteLine(@"DiskReader.exe ListDisks "); 325 | Console.ReadLine(); 326 | Environment.Exit(1); 327 | } 328 | } 329 | } 330 | } 331 | catch (Exception ex) 332 | { 333 | Console.WriteLine(ex.Message); 334 | Console.WriteLine(); 335 | Console.WriteLine(ex.StackTrace); 336 | Console.WriteLine(); 337 | Console.WriteLine(ex.Source); 338 | Console.ReadLine(); 339 | } 340 | } 341 | } 342 | public class DiskInfo 343 | { 344 | [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 345 | public static extern IntPtr CreateFile( 346 | [MarshalAs(UnmanagedType.LPTStr)] string filename, 347 | [MarshalAs(UnmanagedType.U4)] FileAccess access, 348 | [MarshalAs(UnmanagedType.U4)] FileShare share, 349 | IntPtr securityAttributes, // optional SECURITY_ATTRIBUTES struct or IntPtr.Zero 350 | [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition, 351 | [MarshalAs(UnmanagedType.U4)] FileAttributes flagsAndAttributes, 352 | IntPtr templateFile); 353 | 354 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] 355 | static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode, 356 | IntPtr lpInBuffer, uint nInBufferSize, 357 | IntPtr lpOutBuffer, uint nOutBufferSize, 358 | out uint lpBytesReturned, IntPtr lpOverlapped); 359 | 360 | [DllImport("kernel32.dll", SetLastError = true)] 361 | static extern bool CloseHandle(IntPtr hObject); 362 | 363 | struct GET_LENGTH_INFORMATION 364 | { 365 | public long Length; 366 | }; 367 | 368 | 369 | [DllImport("kernel32.dll", SetLastError = true)] 370 | public static extern bool GetVolumeNameForVolumeMountPoint( 371 | string lpszVolumeMountPoint, 372 | [Out] StringBuilder lpszVolumeName, 373 | int cchBufferLength); 374 | 375 | public static string GetVolumeGuidPath(string mountPoint) 376 | { 377 | StringBuilder sb = new StringBuilder(50); 378 | GetVolumeNameForVolumeMountPoint(mountPoint, sb, 50); 379 | return sb.ToString(); 380 | } 381 | 382 | 383 | 384 | 385 | 386 | 387 | public static long GetPhysDiskSize(string physDeviceID) 388 | { 389 | uint IOCTL_DISK_GET_LENGTH_INFO = 0x0007405C; 390 | uint dwBytesReturned; 391 | 392 | //Example, physDeviceID == @"\\.\PHYSICALDRIVE1" 393 | IntPtr hVolume = CreateFile(physDeviceID, FileAccess.ReadWrite, 394 | FileShare.None, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero); 395 | 396 | GET_LENGTH_INFORMATION outputInfo = new GET_LENGTH_INFORMATION(); 397 | outputInfo.Length = 0; 398 | 399 | IntPtr outBuff = Marshal.AllocHGlobal(Marshal.SizeOf(outputInfo)); 400 | 401 | bool devIOPass = DeviceIoControl(hVolume, 402 | IOCTL_DISK_GET_LENGTH_INFO, 403 | IntPtr.Zero, 0, 404 | outBuff, (uint)Marshal.SizeOf(outputInfo), 405 | out dwBytesReturned, 406 | IntPtr.Zero); 407 | 408 | CloseHandle(hVolume); 409 | 410 | outputInfo = (GET_LENGTH_INFORMATION)Marshal.PtrToStructure(outBuff, typeof(GET_LENGTH_INFORMATION)); 411 | 412 | Marshal.FreeHGlobal(hVolume); 413 | Marshal.FreeHGlobal(outBuff); 414 | 415 | return outputInfo.Length; 416 | } 417 | } 418 | } 419 | } 420 | -------------------------------------------------------------------------------- /DiskReader/Properties/PublishProfiles/FolderProfile.pubxml: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | Release 8 | Any CPU 9 | bin\Release\net5.0\publish\ 10 | FileSystem 11 | 12 | -------------------------------------------------------------------------------- /DiskReader/Properties/PublishProfiles/FolderProfile.pubxml.user: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | True|2022-04-15T00:40:12.2505262Z;True|2022-04-15T01:36:34.7185363+01:00;True|2022-04-15T01:06:41.5653825+01:00;True|2022-04-14T23:18:37.1512081+01:00;True|2022-04-14T23:18:11.4285514+01:00;True|2022-04-14T23:15:32.9656580+01:00;True|2022-04-14T23:06:13.4574811+01:00; 8 | 9 | -------------------------------------------------------------------------------- /DiskReader/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "DiskReader": { 4 | "commandName": "Project", 5 | "commandLineArgs": "\\\\.\\PhysicalDrive1 C:\\Test.img" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /DiskReader/ReadDisksClass.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.IO; 4 | using Microsoft.Win32.SafeHandles; 5 | using System.Diagnostics; 6 | 7 | namespace ReadFromDevice 8 | { 9 | public class DeviceStream : Stream, IDisposable 10 | { 11 | public const short FILE_ATTRIBUTE_NORMAL = 0x80; 12 | public const short INVALID_HANDLE_VALUE = -1; 13 | public const uint GENERIC_READ = 0x80000000; 14 | public const uint GENERIC_WRITE = 0x40000000; 15 | public const uint CREATE_NEW = 1; 16 | public const uint CREATE_ALWAYS = 2; 17 | public const uint OPEN_EXISTING = 3; 18 | 19 | // Use interop to call the CreateFile function. 20 | // For more information about CreateFile, 21 | // see the unmanaged MSDN reference library. 22 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 23 | private static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, 24 | uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, 25 | uint dwFlagsAndAttributes, IntPtr hTemplateFile); 26 | 27 | [DllImport("kernel32.dll", SetLastError = true)] 28 | private static extern bool ReadFile( 29 | IntPtr hFile, // handle to file 30 | byte[] lpBuffer, // data buffer 31 | int nNumberOfBytesToRead, // number of bytes to read 32 | ref int lpNumberOfBytesRead, // number of bytes read 33 | IntPtr lpOverlapped 34 | // 35 | // ref OVERLAPPED lpOverlapped // overlapped buffer 36 | ); 37 | 38 | private SafeFileHandle handleValue = null; 39 | private FileStream _fs = null; 40 | 41 | public DeviceStream(string device) 42 | { 43 | Load(device); 44 | } 45 | 46 | private void Load(string Path) 47 | { 48 | if (string.IsNullOrEmpty(Path)) 49 | { 50 | throw new ArgumentNullException("Path"); 51 | } 52 | 53 | // Try to open the file. 54 | IntPtr ptr = CreateFile(Path, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); 55 | 56 | handleValue = new SafeFileHandle(ptr, true); 57 | _fs = new FileStream(handleValue, FileAccess.Read); 58 | 59 | // If the handle is invalid, 60 | // get the last Win32 error 61 | // and throw a Win32Exception. 62 | if (handleValue.IsInvalid) 63 | { 64 | Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); 65 | } 66 | } 67 | 68 | public override bool CanRead 69 | { 70 | get { return true; } 71 | } 72 | 73 | public override bool CanSeek 74 | { 75 | get { return false; } 76 | } 77 | 78 | public override bool CanWrite 79 | { 80 | get { return false; } 81 | } 82 | 83 | public override void Flush() 84 | { 85 | return; 86 | } 87 | 88 | public override long Length 89 | { 90 | get { return -1; } 91 | } 92 | 93 | public override long Position 94 | { 95 | get 96 | { 97 | throw new NotImplementedException(); 98 | } 99 | set 100 | { 101 | throw new NotImplementedException(); 102 | } 103 | } 104 | /// 105 | /// 106 | /// An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and 107 | /// (offset + count - 1) replaced by the bytes read from the current source. 108 | /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream. 109 | /// The maximum number of bytes to be read from the current stream. 110 | /// 111 | public override int Read(byte[] buffer, int offset, int count) 112 | { 113 | int BytesRead = 0; 114 | var BufBytes = new byte[count]; 115 | if (!ReadFile(handleValue.DangerousGetHandle(), BufBytes, count, ref BytesRead, IntPtr.Zero)) 116 | { 117 | Debug.WriteLine(Marshal.GetHRForLastWin32Error()); 118 | Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); 119 | } 120 | for (int i = 0; i < BytesRead; i++) 121 | { 122 | buffer[offset + i] = BufBytes[i]; 123 | } 124 | return BytesRead; 125 | } 126 | public override int ReadByte() 127 | { 128 | int BytesRead = 0; 129 | var lpBuffer = new byte[1]; 130 | if (!ReadFile( 131 | handleValue.DangerousGetHandle(), // handle to file 132 | lpBuffer, // data buffer 133 | 1, // number of bytes to read 134 | ref BytesRead, // number of bytes read 135 | IntPtr.Zero 136 | )) 137 | { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); ; } 138 | return lpBuffer[0]; 139 | } 140 | 141 | public override long Seek(long offset, SeekOrigin origin) 142 | { 143 | // throw new NotImplementedException(); 144 | Debug.WriteLine("Not Implimented"); 145 | return 0; 146 | } 147 | 148 | public override void SetLength(long value) 149 | { 150 | //throw new NotImplementedException(); 151 | Debug.WriteLine("Not Implimented"); 152 | return; 153 | } 154 | 155 | public override void Write(byte[] buffer, int offset, int count) 156 | { 157 | //throw new NotImplementedException(); 158 | Debug.WriteLine("Not Implimented"); 159 | return; 160 | } 161 | 162 | public override void Close() 163 | { 164 | handleValue.Close(); 165 | handleValue.Dispose(); 166 | handleValue = null; 167 | base.Close(); 168 | } 169 | private bool disposed = false; 170 | 171 | new void Dispose() 172 | { 173 | Dispose(true); 174 | base.Dispose(); 175 | GC.SuppressFinalize(this); 176 | } 177 | 178 | private new void Dispose(bool disposing) 179 | { 180 | // Check to see if Dispose has already been called. 181 | if (!this.disposed) 182 | { 183 | if (disposing) 184 | { 185 | if (handleValue != null) 186 | { 187 | _fs.Dispose(); 188 | handleValue.Close(); 189 | handleValue.Dispose(); 190 | handleValue = null; 191 | } 192 | } 193 | // Note disposing has been done. 194 | disposed = true; 195 | 196 | } 197 | } 198 | 199 | } 200 | } -------------------------------------------------------------------------------- /DiskReader/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 54 | 62 | 63 | 64 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DiskReader 2 | A small tool to make backups of whole Physical Disks to file `(.img, .bin etc)` 3 | 4 | ### Usage: 5 | Open Administrator Command Prompt and type: 6 | 7 | `diskreader.exe \\.\PhysicalDisk1 E:\Images\Disk1.bin` 8 | 9 | List connected disks: 10 | 11 | `diskreader.exe ListDisks` 12 | 13 | `diskreader.exe Volumes` 14 | 15 | 16 | ### Notes: 17 | 18 | - I haven't tested restoring the backed up images, but they successfully mount in OSFMount. 19 | - Read progress isn't supported currently, I am looking to change this. 20 | -------------------------------------------------------------------------------- /README.md.backup: -------------------------------------------------------------------------------- 1 | # DiskReader 2 | A small tool to make backups of whole Physical Disks to file `(.img, .bin etc)` 3 | 4 | ### Usage: 5 | Open Administrator Command Prompt and type: 6 | 7 | `diskreader.exe \\.\PhysicalDisk1 E:\Images\Disk1.bin` 8 | 9 | List connected disks: 10 | 11 | `diskreader.exe ListDisks` 12 | 13 | 14 | ### Notes: 15 | 16 | - I haven't tested restoring the backed up images, but they successfully mount in OSFMount. 17 | - Read progress isn't supported currently, I am looking to change this. --------------------------------------------------------------------------------