public ScannerWorker(ScanSettings settings, IScanComparer comparer) { Contract.Requires(settings != null); Contract.Requires(comparer != null); this.settings = settings; this.comparer = comparer; }
/// <summary> /// Excutes a new scan with the provided settings and comparer. /// </summary> /// <param name="settings">The scan settings.</param> /// <param name="comparer">The comparer.</param> public void ExcuteScan(ScanSettings settings, IScanComparer comparer) { Contract.Requires(settings != null); Contract.Requires(comparer != null); Reset(); SetGuiFromSettings(settings); Invoke((Action)(async() => await StartFirstScanEx(settings, comparer))); }
/// <summary> /// Starts an async next scan with the provided <see cref="IScanComparer"/>. /// The next scan uses the previous results to refine the results. /// </summary> /// <param name="comparer">The comparer to scan for values.</param> /// <param name="progress">The <see cref="IProgress{T}"/> object to report the current progress.</param> /// <param name="ct">The <see cref="CancellationToken"/> to stop the scan.</param> /// <returns> The asynchronous result indicating if the scan completed.</returns> private Task <bool> NextScan(IScanComparer comparer, IProgress <int> progress, CancellationToken ct) { Contract.Requires(comparer != null); Contract.Ensures(Contract.Result <Task <bool> >() != null); var store = CreateStore(); progress?.Report(0); var counter = 0; var totalResultCount = (float)CurrentStore.TotalResultCount; return(Task.Run(() => { var result = Parallel.ForEach( CurrentStore.GetResultBlocks(), () => new ScannerContext(Settings, comparer, 0), (b, state, _, context) => { if (!ct.IsCancellationRequested) { context.EnsureBufferSize(b.Size); var buffer = context.Buffer; if (process.ReadRemoteMemoryIntoBuffer(b.Start, ref buffer, 0, b.Size)) { var results = context.Worker.Search(buffer, buffer.Length, b.Results, ct) .OrderBy(r => r.Address, IntPtrComparer.Instance) .ToList(); if (results.Count > 0) { var block = CreateResultBlock(results, b.Start, comparer.ValueSize); store.AddBlock(block); } } progress?.Report((int)(Interlocked.Add(ref counter, b.Results.Count) / totalResultCount * 100)); } else { state.Stop(); } return context; }, w => { } ); store.Finish(); var previousStore = stores.Enqueue(store); previousStore?.Dispose(); return result.IsCompleted; }, ct)); }
public ScannerContext(ScanSettings settings, IScanComparer comparer, int bufferSize) { Contract.Requires(settings != null); Contract.Requires(comparer != null); Contract.Requires(bufferSize >= 0); Contract.Ensures(Buffer != null); Contract.Ensures(Worker != null); EnsureBufferSize(bufferSize); Worker = new ScannerWorker(settings, comparer); }
/// <summary> /// Starts a new first scan with the provided settings and comparer. /// </summary> /// <param name="settings">The scan settings.</param> /// <param name="comparer">The comparer.</param> private async Task StartFirstScanEx(ScanSettings settings, IScanComparer comparer) { if (!Program.RemoteProcess.IsValid) { return; } firstScanButton.Enabled = false; cancelScanIconButton.Visible = true; try { scanner = new Scanner(Program.RemoteProcess, settings); var report = new Progress <int>(i => { scanProgressBar.Value = i; SetResultCount(scanner.TotalResultCount); }); cts = new CancellationTokenSource(); await scanner.Search(comparer, report, cts.Token); ShowScannerResults(scanner); cancelScanIconButton.Visible = false; nextScanButton.Enabled = true; valueTypeComboBox.Enabled = false; floatingOptionsGroupBox.Enabled = false; stringOptionsGroupBox.Enabled = false; scanOptionsGroupBox.Enabled = false; isFirstScan = false; SetValidCompareTypes(); OnCompareTypeChanged(); } finally { firstScanButton.Enabled = true; scanProgressBar.Value = 0; } }
public static void StartMemoryScan(IScanComparer comparer) { Contract.Requires(comparer != null); var sf = GlobalWindowManager.Windows.OfType <ScannerForm>().FirstOrDefault(); if (sf != null) { if (MessageBox.Show("Open a new scanner window?", Constants.ApplicationName, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes) { sf = null; } } if (sf == null) { sf = new ScannerForm(); sf.Show(); } var settings = ScanSettings.Default; switch (comparer) { case ByteMemoryComparer _: settings.ValueType = ScanValueType.Byte; break; case ShortMemoryComparer _: settings.ValueType = ScanValueType.Short; settings.FastScanAlignment = 2; break; case IntegerMemoryComparer _: settings.ValueType = ScanValueType.Integer; settings.FastScanAlignment = 4; break; case LongMemoryComparer _: settings.ValueType = ScanValueType.Long; settings.FastScanAlignment = 4; break; case FloatMemoryComparer _: settings.ValueType = ScanValueType.Float; settings.FastScanAlignment = 4; break; case DoubleMemoryComparer _: settings.ValueType = ScanValueType.Double; settings.FastScanAlignment = 4; break; case ArrayOfBytesMemoryComparer _: settings.ValueType = ScanValueType.ArrayOfBytes; break; case StringMemoryComparer _: settings.ValueType = ScanValueType.String; break; } sf.ExcuteScan(settings, comparer); }
/// <summary> /// Starts an async first scan with the provided <see cref="IScanComparer"/>. /// </summary> /// <param name="comparer">The comparer to scan for values.</param> /// <param name="ct">The <see cref="CancellationToken"/> to stop the scan.</param> /// <param name="progress">The <see cref="IProgress{T}"/> object to report the current progress.</param> /// <returns> The asynchronous result indicating if the scan completed.</returns> private Task <bool> FirstScan(IScanComparer comparer, CancellationToken ct, IProgress <int> progress) { Contract.Requires(comparer != null); Contract.Ensures(Contract.Result <Task <bool> >() != null); var store = CreateStore(); var sections = GetSearchableSections(); if (sections.Count == 0) { return(Task.FromResult(true)); } var initialBufferSize = (int)sections.Average(s => s.Size.ToInt32()); progress?.Report(0); var counter = 0; var totalSectionCount = (float)sections.Count; return(Task.Run(() => { // Algorithm: // 1. Partition the sections for the worker threads. // 2. Create a ScannerContext per worker thread. // 3. n Worker -> m Sections: Read data, search results, store results var result = Parallel.ForEach( sections, // Sections get grouped by the framework to balance the workers. new ParallelOptions { CancellationToken = ct }, () => new ScannerContext(Settings, comparer, initialBufferSize), // Create a new context for every worker (thread). (s, state, _, context) => { var start = s.Start; var size = s.Size.ToInt32(); if (Settings.StartAddress.InRange(s.Start, s.End)) { start = Settings.StartAddress; size = size - Settings.StartAddress.Sub(s.Start).ToInt32(); } if (Settings.StopAddress.InRange(s.Start, s.End)) { size = size - s.End.Sub(Settings.StopAddress).ToInt32(); } context.EnsureBufferSize(size); var buffer = context.Buffer; if (process.ReadRemoteMemoryIntoBuffer(start, ref buffer, 0, size)) // Fill the buffer. { var results = context.Worker.Search(buffer, size) // Search for results. .OrderBy(r => r.Address, IntPtrComparer.Instance) .ToList(); if (results.Count > 0) { var block = CreateResultBlock(results, start, comparer.ValueSize); store.AddBlock(block); // Store the result block. } } progress?.Report((int)(Interlocked.Increment(ref counter) / totalSectionCount * 100)); return context; }, w => { } ); store.Finish(); var previousStore = stores.Enqueue(store); previousStore?.Dispose(); if (result.IsCompleted) { isFirstScan = false; return true; } return false; }, ct)); }
/// <summary> /// Starts an async search with the provided <see cref="IScanComparer"/>. /// The results are stored in the store. /// </summary> /// <param name="comparer">The comparer to scan for values.</param> /// <param name="ct">The <see cref="CancellationToken"/> to stop the scan.</param> /// <param name="progress">The <see cref="IProgress{T}"/> object to report the current progress.</param> /// <returns> The asynchronous result indicating if the scan completed.</returns> public Task <bool> Search(IScanComparer comparer, CancellationToken ct, IProgress <int> progress) { return(isFirstScan ? FirstScan(comparer, ct, progress) : NextScan(comparer, ct, progress)); }