Last active
December 28, 2015 01:59
-
-
Save gibwar/7424119 to your computer and use it in GitHub Desktop.
HashValidator used to hash files using hasher.dll.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace HashValidator { | |
#region Using directives | |
using System; | |
using System.Collections.Concurrent; | |
using System.Collections.Generic; | |
using System.Data; | |
using System.Data.SqlClient; | |
using System.IO; | |
using System.Runtime.InteropServices; | |
using System.Text; | |
using System.Threading; | |
using System.Threading.Tasks; | |
#endregion | |
delegate int OnHashProgress([MarshalAs(UnmanagedType.LPWStr)]string strFileName, int nProgressPct); | |
class Program { | |
const string ConnectionString = "Server=*\\JMM;Initial Catalog=JMMServer;User=*;Password=*"; | |
#region Static Fields | |
static readonly List<FileData> Files = new List<FileData>(8000); | |
static readonly BlockingCollection<FileData> Results = new BlockingCollection<FileData>(); | |
static readonly ManualResetEvent ResultsCompleted = new ManualResetEvent(false); | |
#endregion | |
#region Methods | |
static string CompactPath(string path, int length) { | |
StringBuilder builder = new StringBuilder(length + 5); | |
SafeNativeMethods.PathCompactPathEx(builder, path, length, 0); | |
return builder.ToString(); | |
} | |
static void Main(string[] args) { | |
// Load the available files. | |
using (SqlConnection connection = new SqlConnection(ConnectionString)) | |
using (SqlCommand command = connection.CreateCommand()) { | |
command.CommandText = "SELECT Filepath, ED2KHash FROM gibscan WHERE result IS NULL"; | |
connection.Open(); | |
using (SqlDataReader reader = command.ExecuteReader()) { | |
while (reader.Read()) { | |
Files.Add(new FileData((string)reader["Filepath"], (string)reader["ED2KHash"])); | |
} | |
} | |
} | |
Console.SetWindowPosition(0, 0); | |
Console.SetWindowSize(128, 50); | |
Console.BufferHeight = Math.Max(Console.BufferHeight, Files.Count + 5); | |
Console.WriteLine("{0,-80} {1,-32} {2}", "Filename", "Hash", "Stat"); | |
Console.WriteLine("{0,-80} {1} {2}", new string('=', 80), new string('=', 32), new string('=', 4)); | |
Task.Factory.StartNew(() => { | |
using (SqlConnection connection = new SqlConnection(ConnectionString)) | |
using (SqlCommand command = connection.CreateCommand()) { | |
command.CommandText = "UPDATE gibscan SET ComputedED2K = @ed2k, result = @result, scanned = (getdate()) WHERE Filepath = @filepath"; | |
SqlParameter sha1 = command.Parameters.Add("ed2k", SqlDbType.Char, 32); | |
SqlParameter result = command.Parameters.Add("result", SqlDbType.Char, 4); | |
SqlParameter path = command.Parameters.Add("filepath", SqlDbType.NVarChar, 2000); | |
connection.Open(); | |
foreach (FileData file in Results.GetConsumingEnumerable()) { | |
sha1.Value = file.ComputedED2K ?? ((object)DBNull.Value); | |
result.Value = file.Result; | |
path.Value = file.Path; | |
command.ExecuteNonQuery(); | |
} | |
} | |
ResultsCompleted.Set(); | |
}); | |
foreach (FileData fileData in Files) { | |
Console.Write("{0,-80} ", CompactPath(fileData.Path, 80)); | |
FileInfo file = new FileInfo(fileData.Path); | |
if (!file.Exists) { | |
fileData.Result = "NOTF"; | |
Results.Add(fileData); | |
Console.ForegroundColor = ConsoleColor.Yellow; | |
Console.WriteLine("{0,-32} NOTF", " "); | |
Console.ForegroundColor = ConsoleColor.Gray; | |
continue; | |
} | |
int pos = Console.CursorLeft; | |
int top = Console.CursorTop; | |
OnHashProgress progress = (path, pct) => { | |
if (pct % 5 == 0) { | |
Console.Write("*"); | |
} | |
return 1; | |
}; | |
GCHandle handle = GCHandle.Alloc(progress); | |
byte[] hash = new byte[56]; | |
SafeNativeMethods.CalculateHashes_callback_dll(fileData.Path, hash, progress, false, false, false); | |
handle.Free(); | |
GC.KeepAlive(progress); | |
StringBuilder hashResult = new StringBuilder(32); | |
for (int idx = 0; idx < 16; idx++) { | |
hashResult.Append(hash[idx].ToString("X2")); | |
} | |
fileData.ComputedED2K = hashResult.ToString(); | |
fileData.Result = String.Compare(fileData.ED2K, fileData.ComputedED2K, StringComparison.OrdinalIgnoreCase) == 0 ? "PASS" : "FAIL"; | |
Results.Add(fileData); | |
Console.SetCursorPosition(pos, top); | |
Console.Write("{0,-32} ", fileData.ComputedED2K); | |
Console.ForegroundColor = fileData.Result == "PASS" ? ConsoleColor.Green : ConsoleColor.Red; | |
Console.WriteLine(fileData.Result); | |
Console.ForegroundColor = ConsoleColor.Gray; | |
} | |
Results.CompleteAdding(); | |
ResultsCompleted.WaitOne(); | |
Console.WriteLine("Completed."); | |
Console.ReadKey(true); | |
} | |
#endregion | |
class FileData { | |
#region Fields | |
readonly string ed2k; | |
readonly string path; | |
string computedEd2k; | |
string result; | |
#endregion | |
#region Constructors and Destructors | |
internal FileData(string path, string ed2k) { | |
this.path = path; | |
this.ed2k = ed2k; | |
} | |
#endregion | |
#region Properties | |
internal string ComputedED2K { get { return this.computedEd2k; } set { this.computedEd2k = value; } } | |
internal string ED2K { get { return this.ed2k; } } | |
internal string Path { get { return this.path; } } | |
internal string Result { get { return this.result; } set { this.result = value; } } | |
#endregion | |
} | |
} | |
static class SafeNativeMethods { | |
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)] | |
internal static extern bool PathCompactPathEx([Out] StringBuilder pszOut, string szPath, int cchMax, int dwFlags); | |
[DllImport("hasher.dll", EntryPoint = "CalculateHashes_AsyncIO")] | |
internal static extern int CalculateHashes_callback_dll( | |
[MarshalAs(UnmanagedType.LPWStr)] string szFileName, | |
[MarshalAs(UnmanagedType.LPArray)] byte[] hash, | |
[MarshalAs(UnmanagedType.FunctionPtr)] OnHashProgress lpHashProgressFunc, | |
[MarshalAs(UnmanagedType.Bool)] bool getCRC32, | |
[MarshalAs(UnmanagedType.Bool)] bool getMD5, | |
[MarshalAs(UnmanagedType.Bool)] bool getSHA1 | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment