I got code from here
The problem is that no matter what sector number I send the function, it always dumps the first sector
DumpSector(string drive, double sector, int bytesPerSector)
always returns first disk sector
drive = "\\.\PHYSICALDRIVE1"
sector = from 0 to totalSectors
bytesPerSector = 512
I am sorry for huge amount of code.
class LowReader
{
#region "WMI LOW LEVEL COMMANDS"
public static int BytesPerSector(int drive)
{
int driveCounter = 0;
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_DiskDrive");
foreach (ManagementObject queryObj in searcher.Get())
{
if (driveCounter == drive)
{
var t = queryObj["BytesPerSector"];
return int.Parse(t.ToString());
}
driveCounter++;
}
}
catch (ManagementException)
{
return -1;
}
return 0;
}
public ArrayList GetDriveList()
{
ArrayList drivelist = new ArrayList();
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_DiskDrive");
foreach (ManagementObject queryObj in searcher.Get())
{
drivelist.Add(queryObj["DeviceID"].ToString());
}
}
catch (ManagementException)
{
return null;
}
return drivelist;
}
public static long GetTotalSectors(int drive)
{
int driveCount = 0;
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_DiskDrive");
foreach (ManagementObject queryObj in searcher.Get())
{
if (driveCount == drive)
{
var t = queryObj["TotalSectors"];
return long.Parse(t.ToString());
}
driveCount++;
}
}
catch (ManagementException)
{
return -1;
}
return -1;
}
public static int GetSectorsPerTrack(int drive)
{
int driveCount = 0;
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_DiskDrive");
foreach (ManagementObject queryObj in searcher.Get())
{
if (driveCount == drive)
{
var t = queryObj["SectorsPerTrack"];
return int.Parse(t.ToString());
}
driveCount++;
}
}
catch (ManagementException)
{
return -1;
}
return -1;
}
public static int GetTotalTracks(int drive)
{
int DriveCount = 0;
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_DiskDrive");
foreach (ManagementObject queryObj in searcher.Get())
{
if (DriveCount == drive)
{
var t = queryObj["TotalTracks"];
return int.Parse((t.ToString()));
}
DriveCount++;
}
}
catch (ManagementException)
{
return -1;
}
return -1;
}
#endregion
#region "API CALLS"
public enum EMoveMethod : uint
{
Begin = 0,
Current = 1,
End = 2
}
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.ThisCall)]
static extern uint SetFilePointer(
[In] SafeFileHandle hFile,
[In] long lDistanceToMove,
[Out] out int lpDistanceToMoveHigh,
[In] EMoveMethod dwMoveMethod);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess,
uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
uint dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32", SetLastError = true)]
internal extern static int ReadFile(SafeFileHandle handle, byte[] bytes,
int numBytesToRead, out int numBytesRead, IntPtr overlapped_MustBeZero);
#endregion
public byte[] DumpSector(string drive, double sector, int bytesPerSector)
{
short FILE_ATTRIBUTE_NORMAL = 0x80;
short INVALID_HANDLE_VALUE = -1;
uint GENERIC_READ = 0x80000000;
uint GENERIC_WRITE = 0x40000000;
uint CREATE_NEW = 1;
uint CREATE_ALWAYS = 2;
uint OPEN_EXISTING = 3;
SafeFileHandle handleValue = CreateFile(drive, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
if (handleValue.IsInvalid)
{
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}
double sec = sector * bytesPerSector;
int size = int.Parse(bytesPerSector.ToString());
byte[] buf = new byte[size];
int read = 0;
int moveToHigh;
SetFilePointer(handleValue, long.Parse(sec.ToString()), out moveToHigh, EMoveMethod.Begin);
ReadFile(handleValue, buf, size, out read, IntPtr.Zero);
handleValue.Close();
return buf;
}
private byte[] DumpTrack(string drive, double track, int bytesPerTrack, int TrackBufferSize)
{
short FILE_ATTRIBUTE_NORMAL = 0x80;
short INVALID_HANDLE_VALUE = -1;
uint GENERIC_READ = 0x80000000;
uint GENERIC_WRITE = 0x40000000;
uint CREATE_NEW = 1;
uint CREATE_ALWAYS = 2;
uint OPEN_EXISTING = 3;
SafeFileHandle handleValue = CreateFile(drive, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
if (handleValue.IsInvalid)
{
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}
double trx = (track * bytesPerTrack * TrackBufferSize);
int size = int.Parse(bytesPerTrack.ToString());
byte[] buf = new byte[size * TrackBufferSize];
int read = 0;
int moveToHigh;
SetFilePointer(handleValue, long.Parse(trx.ToString()), out moveToHigh, EMoveMethod.Begin);
ReadFile(handleValue, buf, size, out read, IntPtr.Zero);
handleValue.Close();
return buf;
}
}
As @HansPassant said
"The SetFilePointer() declaration is quite wrong. Wrong in the original code but made worse in the snippet, looks like it was randomly hacked until it stopped generating the MDA warning. Always mention such a thing when you ask for help. Favor SetFilePointerEx. "
I changed this
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.ThisCall)]
static extern uint SetFilePointer(
[In] SafeFileHandle hFile,
[In] long lDistanceToMove,
[Out] out int lpDistanceToMoveHigh,
[In] EMoveMethod dwMoveMethod);
to this
[DllImport("kernel32.dll")]
public static extern bool SetFilePointerEx(
SafeFileHandle hFile,
long liDistanceToMove,
out long lpNewFilePointer,
uint dwMoveMethod);
and I refactored usages in code.
User contributions licensed under CC BY-SA 3.0