Skip to content

Instantly share code, notes, and snippets.

@gibwar
Last active December 28, 2015 01:59
Show Gist options
  • Save gibwar/7424119 to your computer and use it in GitHub Desktop.
Save gibwar/7424119 to your computer and use it in GitHub Desktop.
HashValidator used to hash files using hasher.dll.
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