Further reduce awkward framework gating

This commit is contained in:
Matt Nadareski
2024-10-31 23:08:05 -04:00
parent 1bfb6cda08
commit 3188c6e922
5 changed files with 72 additions and 192 deletions

View File

@@ -4,8 +4,23 @@ namespace BinaryObjectScanner
/// Represents a mapping from checker to detected protection
/// </summary>
#if NET20 || NET35
public class CheckDictionary<T> : System.Collections.Generic.Dictionary<T, string> where T : notnull { }
public class CheckDictionary<T> : System.Collections.Generic.Dictionary<T, string> where T : notnull
#else
public class CheckDictionary<T> : System.Collections.Concurrent.ConcurrentDictionary<T, string> where T : notnull { }
public class CheckDictionary<T> : System.Collections.Concurrent.ConcurrentDictionary<T, string> where T : notnull
#endif
{
/// <inheritdoc cref="System.Collections.Generic.Dictionary{TKey, TValue}.Add(TKey, TValue)"/>
/// <remarks>Handles the proper Add implementation</remarks>
public void Append(T key, string? value)
{
if (value == null)
return;
#if NET20 || NET35
this[key] = value;
#else
TryAdd(key, value);
#endif
}
}
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
namespace BinaryObjectScanner
{
internal static class EnumerableExtensions
{
/// <summary>
/// Wrap iterating through an enumerable with an action
/// </summary>
/// <remarks>
/// .NET Frameworks 2.0 and 3.5 process in series.
/// .NET Frameworks 4.0 onward process in parallel.
/// </remarks>
public static void IterateWithAction<T>(this IEnumerable<T> source, Action<T> action)
{
#if NET20 || NET35
foreach (var item in source)
{
action(item);
}
#else
System.Threading.Tasks.Parallel.ForEach(source, action);
#endif
}
}
}

View File

@@ -3,9 +3,6 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
#if NET40_OR_GREATER || NETCOREAPP
using System.Threading.Tasks;
#endif
using BinaryObjectScanner.Interfaces;
using SabreTools.IO.Extensions;
using SabreTools.Serialization.Wrappers;
@@ -216,44 +213,23 @@ namespace BinaryObjectScanner.FileType
var protections = new CheckDictionary<IContentCheck>();
// Iterate through all checks
#if NET20 || NET35
foreach (var checkClass in ContentCheckClasses)
#else
Parallel.ForEach(ContentCheckClasses, checkClass =>
#endif
ContentCheckClasses.IterateWithAction(checkClass =>
{
// Get the protection for the class, if possible
var protection = checkClass.CheckContents(file!, fileContent, includeDebug);
if (string.IsNullOrEmpty(protection))
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on game engines
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on packers
if (CheckIfPacker(checkClass) && !IncludePackers)
#if NET20 || NET35
continue;
#else
return;
#endif
#if NET20 || NET35
protections[checkClass] = protection!;
}
#else
protections.TryAdd(checkClass, protection!);
protections.Append(checkClass, protection);
});
#endif
return protections;
}
@@ -271,44 +247,23 @@ namespace BinaryObjectScanner.FileType
var protections = new CheckDictionary<ILinearExecutableCheck>();
// Iterate through all checks
#if NET20 || NET35
foreach (var checkClass in LinearExecutableCheckClasses)
#else
Parallel.ForEach(LinearExecutableCheckClasses, checkClass =>
#endif
LinearExecutableCheckClasses.IterateWithAction(checkClass =>
{
// Get the protection for the class, if possible
var protection = checkClass.CheckLinearExecutable(file, lex, includeDebug);
if (string.IsNullOrEmpty(protection))
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on game engines
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on packers
if (CheckIfPacker(checkClass) && !IncludePackers)
#if NET20 || NET35
continue;
#else
return;
#endif
#if NET20 || NET35
protections[checkClass] = protection!;
}
#else
protections.TryAdd(checkClass, protection!);
protections.Append(checkClass, protection);
});
#endif
return protections;
}
@@ -326,44 +281,23 @@ namespace BinaryObjectScanner.FileType
var protections = new CheckDictionary<IMSDOSExecutableCheck>();
// Iterate through all checks
#if NET20 || NET35
foreach (var checkClass in MSDOSExecutableCheckClasses)
#else
Parallel.ForEach(MSDOSExecutableCheckClasses, checkClass =>
#endif
MSDOSExecutableCheckClasses.IterateWithAction(checkClass =>
{
// Get the protection for the class, if possible
var protection = checkClass.CheckMSDOSExecutable(file, mz, includeDebug);
if (string.IsNullOrEmpty(protection))
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on game engines
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on packers
if (CheckIfPacker(checkClass) && !IncludePackers)
#if NET20 || NET35
continue;
#else
return;
#endif
#if NET20 || NET35
protections[checkClass] = protection!;
}
#else
protections.TryAdd(checkClass, protection!);
protections.Append(checkClass, protection);
});
#endif
return protections;
}
@@ -381,44 +315,23 @@ namespace BinaryObjectScanner.FileType
var protections = new CheckDictionary<INewExecutableCheck>();
// Iterate through all checks
#if NET20 || NET35
foreach (var checkClass in NewExecutableCheckClasses)
#else
Parallel.ForEach(NewExecutableCheckClasses, checkClass =>
#endif
NewExecutableCheckClasses.IterateWithAction(checkClass =>
{
// Get the protection for the class, if possible
var protection = checkClass.CheckNewExecutable(file, nex, includeDebug);
if (string.IsNullOrEmpty(protection))
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on game engines
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on packers
if (CheckIfPacker(checkClass) && !IncludePackers)
#if NET20 || NET35
continue;
#else
return;
#endif
#if NET20 || NET35
protections[checkClass] = protection!;
}
#else
protections.TryAdd(checkClass, protection!);
protections.Append(checkClass, protection);
});
#endif
return protections;
}
@@ -436,44 +349,23 @@ namespace BinaryObjectScanner.FileType
var protections = new CheckDictionary<IPortableExecutableCheck>();
// Iterate through all checks
#if NET20 || NET35
foreach (var checkClass in PortableExecutableCheckClasses)
#else
Parallel.ForEach(PortableExecutableCheckClasses, checkClass =>
#endif
PortableExecutableCheckClasses.IterateWithAction(checkClass =>
{
// Get the protection for the class, if possible
var protection = checkClass.CheckPortableExecutable(file, pex, includeDebug);
if (string.IsNullOrEmpty(protection))
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on game engines
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on packers
if (CheckIfPacker(checkClass) && !IncludePackers)
#if NET20 || NET35
continue;
#else
return;
#endif
#if NET20 || NET35
protections[checkClass] = protection!;
}
#else
protections.TryAdd(checkClass, protection!);
protections.Append(checkClass, protection);
});
#endif
return protections;
}

View File

@@ -53,20 +53,12 @@ namespace BinaryObjectScanner
files = files?.Select(f => f.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar))?.ToList();
// Iterate through all checks
#if NET20 || NET35
foreach (var checkClass in PathCheckClasses)
#else
Parallel.ForEach(PathCheckClasses, checkClass =>
#endif
PathCheckClasses.IterateWithAction(checkClass =>
{
var subProtections = checkClass?.PerformCheck(path, files);
if (subProtections != null)
protections.Append(path, subProtections);
#if NET20 || NET35
}
#else
});
#endif
return protections;
}

View File

@@ -2,12 +2,6 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
#if NET462_OR_GREATER || NETCOREAPP
using System.Text;
#endif
#if NET40_OR_GREATER || NETCOREAPP
using System.Threading.Tasks;
#endif
using BinaryObjectScanner.FileType;
using BinaryObjectScanner.Interfaces;
using SabreTools.IO.Extensions;
@@ -76,7 +70,7 @@ namespace BinaryObjectScanner
#if NET462_OR_GREATER || NETCOREAPP
// Register the codepages
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
#endif
}
@@ -466,30 +460,20 @@ namespace BinaryObjectScanner
var protections = new ProtectionDictionary();
// If we have any extractable packers
var extractables = classes.Where(c => c is IExtractableMSDOSExecutable).Select(c => c as IExtractableMSDOSExecutable);
#if NET20 || NET35
foreach (var extractable in extractables)
#else
Parallel.ForEach(extractables, extractable =>
#endif
var extractables = classes
.Where(c => c is IExtractableMSDOSExecutable)
.Select(c => c as IExtractableMSDOSExecutable);
extractables.IterateWithAction(extractable =>
{
// If we have an invalid extractable somehow
if (extractable == null)
#if NET20 || NET35
continue;
#else
return;
#endif
// Get the protection for the class, if possible
var extractedProtections = Handler.HandleExtractable(extractable, fileName, mz, this);
if (extractedProtections != null)
protections.Append(extractedProtections);
#if NET20 || NET35
}
#else
});
#endif
return protections;
}
@@ -511,30 +495,20 @@ namespace BinaryObjectScanner
var protections = new ProtectionDictionary();
// If we have any extractable packers
var extractables = classes.Where(c => c is IExtractableLinearExecutable).Select(c => c as IExtractableLinearExecutable);
#if NET20 || NET35
foreach (var extractable in extractables)
#else
Parallel.ForEach(extractables, extractable =>
#endif
var extractables = classes
.Where(c => c is IExtractableLinearExecutable)
.Select(c => c as IExtractableLinearExecutable);
extractables.IterateWithAction(extractable =>
{
// If we have an invalid extractable somehow
if (extractable == null)
#if NET20 || NET35
continue;
#else
return;
#endif
// Get the protection for the class, if possible
var extractedProtections = Handler.HandleExtractable(extractable, fileName, lex, this);
if (extractedProtections != null)
protections.Append(extractedProtections);
#if NET20 || NET35
}
#else
});
#endif
return protections;
}
@@ -556,30 +530,20 @@ namespace BinaryObjectScanner
var protections = new ProtectionDictionary();
// If we have any extractable packers
var extractables = classes.Where(c => c is IExtractableNewExecutable).Select(c => c as IExtractableNewExecutable);
#if NET20 || NET35
foreach (var extractable in extractables)
#else
Parallel.ForEach(extractables, extractable =>
#endif
var extractables = classes
.Where(c => c is IExtractableNewExecutable)
.Select(c => c as IExtractableNewExecutable);
extractables.IterateWithAction(extractable =>
{
// If we have an invalid extractable somehow
if (extractable == null)
#if NET20 || NET35
continue;
#else
return;
#endif
// Get the protection for the class, if possible
var extractedProtections = Handler.HandleExtractable(extractable, fileName, nex, this);
if (extractedProtections != null)
protections.Append(extractedProtections);
#if NET20 || NET35
}
#else
});
#endif
return protections;
}
@@ -601,30 +565,20 @@ namespace BinaryObjectScanner
var protections = new ProtectionDictionary();
// If we have any extractable packers
var extractables = classes.Where(c => c is IExtractablePortableExecutable).Select(c => c as IExtractablePortableExecutable);
#if NET20 || NET35
foreach (var extractable in extractables)
#else
Parallel.ForEach(extractables, extractable =>
#endif
var extractables = classes
.Where(c => c is IExtractablePortableExecutable)
.Select(c => c as IExtractablePortableExecutable);
extractables.IterateWithAction(extractable =>
{
// If we have an invalid extractable somehow
if (extractable == null)
#if NET20 || NET35
continue;
#else
return;
#endif
// Get the protection for the class, if possible
var extractedProtections = Handler.HandleExtractable(extractable, fileName, pex, this);
if (extractedProtections != null)
protections.Append(extractedProtections);
#if NET20 || NET35
}
#else
});
#endif
return protections;
}