├── 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.
--------------------------------------------------------------------------------