Post by zeeshan on Dec 21, 2013 6:50:50 GMT
Background:
In my project I need to scan my HDD sector by sector. I am using Pinvoke of Kernel32.dll. The size of the HDD is 160GB (nearly 312,000,000 LBA). The loop scans every single iteration 8000 sectors.
The problem:
Somehow, after scanning 40000 sectors successfuly, the loop stacks without moving, and I even cannot terminate the application unless I will disconnect the HDD (is external media). I know that my media doesn't have any corrupted sectors.
When setting the file pointer using SetFilePointer of Kernel32.dll, I pay attention to Low and High ints for offset, but the offset even not reaching 1GB, so I guess that there is nothing to do in this point, but somewhere else (I think so, but I am not sure, I am quite new to this Pinvoke).
This is my following code:
The program is Console application in order to speedup the process.
In my project I need to scan my HDD sector by sector. I am using Pinvoke of Kernel32.dll. The size of the HDD is 160GB (nearly 312,000,000 LBA). The loop scans every single iteration 8000 sectors.
The problem:
Somehow, after scanning 40000 sectors successfuly, the loop stacks without moving, and I even cannot terminate the application unless I will disconnect the HDD (is external media). I know that my media doesn't have any corrupted sectors.
When setting the file pointer using SetFilePointer of Kernel32.dll, I pay attention to Low and High ints for offset, but the offset even not reaching 1GB, so I guess that there is nothing to do in this point, but somewhere else (I think so, but I am not sure, I am quite new to this Pinvoke).
This is my following code:
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Linq;
using System.Management;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
namespace HDD_Raw_Read
{
class Program
{
static int MAX = 0, MyOffset = 0, BlockSize = -1;
static int DRV = -1;
static List<string> HDDs = new List<string>();
public enum EMoveMethod : uint
{
Begin = 0,
Current = 1,
End = 2
}
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint SetFilePointer(
[In] SafeFileHandle hFile,
[In] int lDistanceToMove,
[In, Out] ref 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);
static public 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;
}
static public int 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 int.Parse(t.ToString());
}
driveCount++;
}
}
catch (ManagementException) { return -1; }
return -1;
}
static private byte[] DumpSector(string drive, int sector, int bytesPerSector)
{
//const short FILE_ATTRIBUTE_NORMAL = 0x80;
//const short INVALID_HANDLE_VALUE = -1;
const uint GENERIC_READ = 0x80000000;
//const uint GENERIC_WRITE = 0x40000000;
//const uint CREATE_NEW = 1;
//const uint CREATE_ALWAYS = 2;
const 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()); }
long sec = (long)sector * (long)bytesPerSector;
byte[] buf = new byte[bytesPerSector];
int read = 0, moveToHigh=(int)(sec>>32);
SetFilePointer(handleValue, (int)(sec&0xffffffff), ref moveToHigh, EMoveMethod.Begin);
ReadFile(handleValue, buf, bytesPerSector, out read, IntPtr.Zero);
handleValue.Close();
return buf;
}
static public void Init()
{
Console.BufferHeight = 32700;
Console.BufferWidth = 85;
foreach (string dID in GetDriveList()) { HDDs.Add(dID); }
}
static 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;
}
static void Scanner()
{
if (DRV == -1) { Console.WriteLine("ERROR: Please select drive using <A>+ drive index number."); return; } // error
const int BFB = 8000;
byte[] b = DumpSector(HDDs[DRV], MyOffset, BlockSize * BFB);
int Sec16 = 0, IntOff = 0, JMP = 0;
string DMP = "";
long FF = ((long)MyOffset * BlockSize) + (IntOff * 16);
Console.Write("0x{0} ", FF.ToString("X10"));
for (int byt = 0; byt < b.Length; byt++)
{
DMP += (char)b[byt];
Console.Write("{0} ", b[byt].ToString("X2"));
Sec16++; FF++;
if (Sec16 == 8) Console.Write(" ");
if (Sec16 == 16)
{
Console.Write(" {0}", DMP.Replace("\x07", "").Replace("\x08", "").Replace("\x0a", "").Replace("\x0d", "").Replace("\x09", "")); Console.WriteLine();
DMP = ""; Sec16 = 0; IntOff++; JMP++;
if (JMP == 32) { JMP = 0; IntOff += 224; FF += 3584; byt += 3584; }
Console.Write("0x{0} ", FF.ToString("X10"));
}
}
Console.WriteLine("-----------------------------------------------------------------------");
}
static void Main(string[] args)
{
ConsoleKeyInfo t = new ConsoleKeyInfo();
byte[] B=null;
Init();
string CMD = "";
while (CMD != "Exit")
{
CMD = Console.ReadLine();
if (CMD == "DRV")
{
Console.WriteLine("Here are available drives ({0} drives found):", HDDs.Count);
foreach (string O in HDDs) Console.WriteLine(O);
Console.WriteLine("");
}
if (CMD[0] == 'A')
{
try { DRV = Int32.Parse(CMD.Substring(1)); }
catch { DRV = -1; Console.WriteLine("ERROR: Illegal drive index!"); continue; }
if (DRV < 0 || DRV >= HDDs.Count) { DRV = -1; Console.WriteLine("ERROR: Illegal drive index!"); continue; }
BlockSize = BytesPerSector(DRV);
MAX = GetTotalSectors(DRV);
Console.WriteLine("Drive {0} selected, size of {1} blocks:", DRV, MAX.ToString("N0"));
MyOffset = 0;
}
if (CMD == "DeepScan")
{
if (DRV == -1) { Console.WriteLine("ERROR: Please select drive using <A>+ drive index number."); continue; } // error
const int BFB = 1000;
byte[] b = DumpSector(HDDs[DRV], MyOffset, BlockSize * BFB);
int Sec16 = 0, IntOff = 0;
string DMP = "";
long FF = ((long)MyOffset * BlockSize) + (IntOff * 16);
Console.Write("0x{0} ", FF.ToString("X10"));
foreach (byte byt in b)
{
DMP += (char)byt;
Console.Write("{0} ", byt.ToString("X2"));
Sec16++; FF++;
if(Sec16==8) Console.Write(" ");
if (Sec16 == 16)
{
Console.Write(" {0}", DMP.Replace("\x07","").Replace("\x08","").Replace("\x0a","").Replace("\x0d","").Replace("\x09","")); Console.WriteLine();
DMP = ""; Sec16 = 0; IntOff++;
Console.Write("0x{0} ", FF.ToString("X10"));
}
}
Console.WriteLine("-----------------------------------------------------------------------");
}
if (CMD == "SurfaceScan") for (MyOffset = 0; MyOffset < 8000000; MyOffset+=8000 ) { Scanner(); }
if (CMD == "Scan") Scanner();
if (CMD[0] == 'J')
{
int J;
try { J = Int32.Parse(CMD.Substring(1)); }
catch { Console.WriteLine("Wrong jumping index!"); continue; }
if (J < 0 || J >= MAX) { Console.WriteLine("Wrong jumping index!"); continue; }
MyOffset = J;
Console.WriteLine("Jump to sector: {0}", MyOffset);
}
if (CMD.IndexOf("FilterScan?")==0)
{
string[] Q = CMD.Substring(11).Split(',');
if (Q.Length == 0 || (Q.Length == 1 && Q[0] == "")) { continue; }
B = new byte[Q.Length];
for (int I = 0; I < Q.Length; I++)
{
if (Q[I][0] >= '0' && Q[I][0] <= '9') { B[I] = (byte)((Q[I][0] - '0')*16); }
else if (Q[I][0] >= 'a' && Q[I][0] <= 'f') { B[I] = (byte)(((Q[I][0] - 'a')*16) + (byte)160); }
if (Q[I][1] >= '0' && Q[I][1] <= '9') { B[I] += (byte)(Q[I][1] - '0'); }
else if (Q[I][1] >= 'a' && Q[I][1] <= 'f') { B[I] += (byte)((Q[I][1] - 'a') + (byte)10); }
}
Console.WriteLine("Search pattern set successfuly: {0}", CMD.Substring(11));
}
if (CMD.IndexOf("DoFilterScan?")==0)
{
int Stop;
try { Stop = Int32.Parse(CMD.Substring(13)); }
catch { Console.WriteLine("ERROR: Wrong search range. Please fill stop point."); continue; }
if (B == null || B.Length == 0) { Console.WriteLine("ERROR: Search pattern is missing! Please use <FilterScan>"); continue; }
////////////////////////////////////////////////////////////////////////////////////////////
if (DRV == -1) { Console.WriteLine("ERROR: Please select drive using <A>+ drive index number."); continue; } // error
int LineCount = 0;
long FF = ((long)MyOffset * BlockSize);
while (LineCount < 32000)
{
if (MyOffset >= Stop) { break; }
byte[] b = DumpSector(HDDs[DRV], MyOffset, BlockSize * 800);
Console.Write("\rReading sectors {0} to {1}...", MyOffset, MyOffset + 800); // progress
int Sec16 = 0, IntOff = 0, JMP = 0;
string DMP = "";
int Found = 0;
for (int M = 0; M < 16; M++)
if (b[M] == B[M]) { Found++; if (Found == B.Length) { LineCount++; break; } }
else Found = 0;
if (Found == B.Length) Console.Write("\r0x{0} ", FF.ToString("X10"));
for (int byt = 0; byt < b.Length; byt++)
{
DMP += (char)b[byt];
Console.Write("{0} ", b[byt].ToString("X2"));
Sec16++; FF++;
if (Sec16 == 8) Console.Write(" ");
if (Sec16 == 16)
{
Console.Write(" {0}", DMP.Replace("\x07", "").Replace("\x08", "").Replace("\x0a", "").Replace("\x0d", "").Replace("\x09", "")); Console.WriteLine();
DMP = ""; Sec16 = 0; IntOff++; JMP++;
if (JMP == 32) { JMP = 0; IntOff += 224; FF += 3584; byt += 3584; }
if (byt >= b.Length) { break; }
for (int M = 0; M < 16; M++)
if (b[byt + M] == B[M]) { Found++; if (Found == B.Length) { LineCount++; break; } }
else Found = 0;
if (Found == B.Length) Console.Write("0x{0} ", FF.ToString("X10"));
}
// Wait for escaping:
t = Console.ReadKey(true);
if (t.Key == ConsoleKey.Escape) { Console.WriteLine("Operation stopped ~"); break; }
}
MyOffset+=800; // Move forward
if (t.Key == ConsoleKey.Escape) { Console.WriteLine("Operation stopped ~"); break; }
}
Console.WriteLine("----------------------------------------------------------------------");
}
}
}
}
}
The program is Console application in order to speedup the process.