mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-02-05 13:49:37 +00:00
Compare commits
104 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ec4872b36 | ||
|
|
30bfff833f | ||
|
|
e37d5a80ab | ||
|
|
df1081507d | ||
|
|
a140e1c444 | ||
|
|
f9a990b27b | ||
|
|
b841c7aa94 | ||
|
|
554520ae1f | ||
|
|
3155b3fe41 | ||
|
|
e52cfd244a | ||
|
|
c52b22fb4e | ||
|
|
b3f72bbbe1 | ||
|
|
9ebcfdba53 | ||
|
|
15f020cb06 | ||
|
|
4b387f86c1 | ||
|
|
1a3a73a86d | ||
|
|
31eff196e6 | ||
|
|
828d3403f1 | ||
|
|
28d6d06033 | ||
|
|
0a2477e1b3 | ||
|
|
01451d7009 | ||
|
|
cff9582bf5 | ||
|
|
428d839700 | ||
|
|
50db0044b0 | ||
|
|
68b1ec7b3f | ||
|
|
fd524e1d5c | ||
|
|
ef581c3f36 | ||
|
|
64e67b8daa | ||
|
|
8624350b82 | ||
|
|
e3b32fd974 | ||
|
|
6f789d2454 | ||
|
|
d365dd1164 | ||
|
|
aa3afd676b | ||
|
|
69a04ff825 | ||
|
|
938e1f94bb | ||
|
|
3eda785a5a | ||
|
|
6b895fa7c8 | ||
|
|
45e10a84ae | ||
|
|
81f0400790 | ||
|
|
df90583f73 | ||
|
|
5b980e138a | ||
|
|
0dd71d72ca | ||
|
|
a7364eab67 | ||
|
|
99013e3448 | ||
|
|
7f5e93db95 | ||
|
|
4aa9662ebe | ||
|
|
68dc6c3139 | ||
|
|
8b99577c66 | ||
|
|
20ea1b4427 | ||
|
|
cf0c6126b9 | ||
|
|
49eef3f45a | ||
|
|
23e852bbdb | ||
|
|
f182dccbf2 | ||
|
|
2d2cff4d0e | ||
|
|
c0621a83cb | ||
|
|
3c5da9f7ec | ||
|
|
a7b5288277 | ||
|
|
fee980e048 | ||
|
|
21eac43e9f | ||
|
|
b55698004c | ||
|
|
40bdb9b2d9 | ||
|
|
dfabb1a244 | ||
|
|
cd5f9561bf | ||
|
|
d8d6fac67e | ||
|
|
965c32482d | ||
|
|
c8c9d4ac64 | ||
|
|
5f5abf8a14 | ||
|
|
406791b938 | ||
|
|
eb2e6e7029 | ||
|
|
9f0b41c6aa | ||
|
|
e2b72d8a5b | ||
|
|
9802840309 | ||
|
|
4a6e2fd62d | ||
|
|
79c706e35a | ||
|
|
9be19d6925 | ||
|
|
0cfb9907d0 | ||
|
|
c18e9b3538 | ||
|
|
3754c3a65b | ||
|
|
513a64df4c | ||
|
|
d18a51c7fa | ||
|
|
b43433b9ed | ||
|
|
d553395f3f | ||
|
|
28dbe8542b | ||
|
|
912e605dc8 | ||
|
|
039982d02d | ||
|
|
1a40c6cbb2 | ||
|
|
35921e3cac | ||
|
|
a42040d644 | ||
|
|
e1fb1c7bcf | ||
|
|
095de1441d | ||
|
|
43cbafc0f5 | ||
|
|
9143e4c02c | ||
|
|
2af0692ab4 | ||
|
|
e00c8786b9 | ||
|
|
ab6298ac67 | ||
|
|
aaad56794b | ||
|
|
77d99460ab | ||
|
|
4b222003d2 | ||
|
|
517d5528c9 | ||
|
|
0c137e97f0 | ||
|
|
c4f8fa4b0d | ||
|
|
0bc1d1efa6 | ||
|
|
c78229c3cd | ||
|
|
aa41cb9edf |
27
.vscode/launch.json
vendored
Normal file
27
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
// Use IntelliSense to find out which attributes exist for C# debugging
|
||||
// Use hover for the description of the existing attributes
|
||||
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": ".NET Core Launch (console)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"program": "${workspaceFolder}/Test/bin/Debug/netcoreapp3.1/Test.dll",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/Test",
|
||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false
|
||||
},
|
||||
{
|
||||
"name": ".NET Core Attach",
|
||||
"type": "coreclr",
|
||||
"request": "attach",
|
||||
"processId": "${command:pickProcess}"
|
||||
}
|
||||
]
|
||||
}
|
||||
42
.vscode/tasks.json
vendored
Normal file
42
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "build",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"build",
|
||||
"${workspaceFolder}/Test/Test.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "publish",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"publish",
|
||||
"${workspaceFolder}/Test/Test.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "watch",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"watch",
|
||||
"run",
|
||||
"${workspaceFolder}/Test/Test.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -3,12 +3,13 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29306.81
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BurnOutSharp", "BurnOutSharp\BurnOutSharp.csproj", "{1DA4212E-6071-4951-B45D-BB74A7838246}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BurnOutSharp", "BurnOutSharp\BurnOutSharp.csproj", "{1DA4212E-6071-4951-B45D-BB74A7838246}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{88735BA2-778D-4192-8EB2-FFF6843719E2}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{68D10531-99CB-40B1-8912-73FA286C9433}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
LICENSE = LICENSE
|
||||
README.md = README.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
|
||||
@@ -1,27 +1,56 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net462;net472;netcoreapp3.0</TargetFrameworks>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<TargetFrameworks>net472;net48;netcoreapp3.1;net5.0</TargetFrameworks>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<Title>BurnOutSharp</Title>
|
||||
<AssemblyName>BurnOutSharp</AssemblyName>
|
||||
<Description>Port of BurnOut to C#, with additions</Description>
|
||||
<Authors>Matt Nadareski;Gernot Knippen</Authors>
|
||||
<Product>BurnOutSharp</Product>
|
||||
<Copyright>Copyright (c)2005-2010 Gernot Knippen, Copyright (c)2018-2021 Matt Nadareski</Copyright>
|
||||
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile>
|
||||
<RepositoryUrl>https://github.com/mnadareski/BurnOutSharp</RepositoryUrl>
|
||||
<Version>1.5.1</Version>
|
||||
<AssemblyVersion>1.5.1</AssemblyVersion>
|
||||
<FileVersion>1.5.1</FileVersion>
|
||||
<IncludeSource>true</IncludeSource>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
|
||||
<DefineConstants>NET_FRAMEWORK</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="BurnOutSharp.nuspec" />
|
||||
<PackageReference Include="LessIO" Version="1.0.34" Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'" />
|
||||
<PackageReference Include="libmspack4n" Version="0.9.10" Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'" />
|
||||
<PackageReference Include="SharpCompress" Version="0.26.0" />
|
||||
<PackageReference Include="UnshieldSharp" Version="1.4.2.4" />
|
||||
<PackageReference Include="WiseUnpacker" Version="1.0.1" />
|
||||
<PackageReference Include="wix-libs" Version="3.11.1" Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="LessIO">
|
||||
<Version>0.6.16</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="libmspack4n">
|
||||
<Version>0.9.10</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="UnshieldSharp">
|
||||
<Version>1.4.2.3</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="zlib.net">
|
||||
<Version>1.0.4</Version>
|
||||
</PackageReference>
|
||||
<None Include="LICENSE.txt" Pack="true" PackagePath="$(PackageLicenseFile)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="*.dll" Pack="true">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
|
||||
<PackageCopyToOutput>true</PackageCopyToOutput>
|
||||
</None>
|
||||
<None Include="*.pdb" Pack="true">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
|
||||
<PackageCopyToOutput>true</PackageCopyToOutput>
|
||||
</None>
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<package >
|
||||
<metadata>
|
||||
<id>BurnOutSharp</id>
|
||||
<version>1.03.9.0</version>
|
||||
<title>BurnOutSharp</title>
|
||||
<authors>Matt Nadareski, Gernot Knippen</authors>
|
||||
<owners>Matt Nadareski, Gernot Knippen</owners>
|
||||
<licenseUrl>https://www.gnu.org/licenses/gpl-3.0.txt</licenseUrl>
|
||||
<projectUrl>https://github.com/mnadareski/BurnOutSharp</projectUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>Port of BurnOut to C#, with additions</description>
|
||||
<copyright>Copyright (c)2005-2010 Gernot Knippen, Copyright (c)2018-2020 Matt Nadareski</copyright>
|
||||
<tags>protection scan burnout</tags>
|
||||
<dependencies>
|
||||
<dependency id="LessIO" version="0.5.0" />
|
||||
<dependency id="libmspack4n" version="0.8.0" />
|
||||
<dependency id="UnshieldSharp" version="1.4.2.3" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="bin\Debug\net462\BurnOutSharp.dll" target="lib\net462\BurnOutSharp.dll" />
|
||||
<file src="bin\Debug\net462\BurnOutSharp.pdb" target="lib\net462\BurnOutSharp.pdb" />
|
||||
<file src="bin\Debug\net472\BurnOutSharp.dll" target="lib\net472\BurnOutSharp.dll" />
|
||||
<file src="bin\Debug\net472\BurnOutSharp.pdb" target="lib\net472\BurnOutSharp.pdb" />
|
||||
<file src="bin\Debug\netcoreapp3.0\BurnOutSharp.dll" target="lib\netcoreapp3.0\BurnOutSharp.dll" />
|
||||
<file src="bin\Debug\netcoreapp3.0\BurnOutSharp.pdb" target="lib\netcoreapp3.0\BurnOutSharp.pdb" />
|
||||
</files>
|
||||
</package>
|
||||
@@ -19,23 +19,131 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.ExecutableType.Microsoft;
|
||||
|
||||
namespace BurnOutSharp
|
||||
{
|
||||
internal static class EVORE
|
||||
{
|
||||
private struct Section
|
||||
/// <summary>
|
||||
/// Checks if the file contents that represent a PE is a DLL or an EXE
|
||||
/// </summary>
|
||||
/// <param name="fileContent">File contents to check</param>
|
||||
/// <returns>True if the file is an EXE, false if it's a DLL</returns>
|
||||
internal static bool IsEXE(byte[] fileContent)
|
||||
{
|
||||
public uint iVirtualSize;
|
||||
public uint iVirtualOffset;
|
||||
public uint iRawOffset;
|
||||
int PEHeaderOffset = BitConverter.ToInt32(fileContent, 60);
|
||||
short Characteristics = BitConverter.ToInt16(fileContent, PEHeaderOffset + 22);
|
||||
|
||||
// Check if file is dll
|
||||
if ((Characteristics & 0x2000) == 0x2000)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
private const int WaitSeconds = 20;
|
||||
/// <summary>
|
||||
/// Writes the file contents to a temporary file, if possible
|
||||
/// </summary>
|
||||
/// <param name="fileContent">File contents to write</param>
|
||||
/// <param name="sExtension">Optional extension for the temproary file, defaults to ".exe"</param>
|
||||
/// <returns>Name of the new temporary file, null on error</returns>
|
||||
internal static string MakeTempFile(byte[] fileContent, string sExtension = ".exe")
|
||||
{
|
||||
string filei = Guid.NewGuid().ToString();
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), "tmp", $"{filei}{sExtension}");
|
||||
try
|
||||
{
|
||||
File.Delete(tempPath);
|
||||
}
|
||||
catch { }
|
||||
|
||||
private static Process StartSafe(string file)
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(tempPath));
|
||||
using (BinaryWriter bw = new BinaryWriter(File.OpenWrite(tempPath)))
|
||||
{
|
||||
bw.Write(fileContent);
|
||||
}
|
||||
|
||||
return Path.GetFullPath(tempPath);
|
||||
}
|
||||
catch { }
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies all required DLLs for a given executable
|
||||
/// </summary>
|
||||
/// <param name="file">Temporary file path</param>
|
||||
/// <param name="fileContent">File contents to read</param>
|
||||
/// <returns>Paths for all of the copied DLLs, null on error</returns>
|
||||
internal static string[] CopyDependentDlls(string file, byte[] fileContent)
|
||||
{
|
||||
var sections = ReadSections(fileContent);
|
||||
|
||||
long lastPosition;
|
||||
string[] saDependentDLLs = null;
|
||||
int index = 60;
|
||||
int PEHeaderOffset = BitConverter.ToInt32(fileContent, index);
|
||||
index = PEHeaderOffset + 120 + 8; //120 Bytes till IMAGE_DATA_DIRECTORY array,8 Bytes=size of IMAGE_DATA_DIRECTORY
|
||||
uint ImportTableRVA = BitConverter.ToUInt32(fileContent, index);
|
||||
index += 4;
|
||||
uint ImportTableSize = BitConverter.ToUInt32(fileContent, index);
|
||||
index = (int)RVA2Offset(ImportTableRVA, sections);
|
||||
index += 12;
|
||||
uint DllNameRVA = BitConverter.ToUInt32(fileContent, index);
|
||||
index += 4;
|
||||
while (DllNameRVA != 0)
|
||||
{
|
||||
string sDllName = "";
|
||||
byte bChar;
|
||||
lastPosition = index;
|
||||
uint DLLNameOffset = RVA2Offset(DllNameRVA, sections);
|
||||
if (DLLNameOffset > 0)
|
||||
{
|
||||
index = (int)DLLNameOffset;
|
||||
if ((char)fileContent[index] > -1)
|
||||
{
|
||||
do
|
||||
{
|
||||
bChar = fileContent[index];
|
||||
index++;
|
||||
sDllName += (char)bChar;
|
||||
} while (bChar != 0 && (char)fileContent[index] > -1);
|
||||
|
||||
sDllName = sDllName.Remove(sDllName.Length - 1, 1);
|
||||
if (File.Exists(Path.Combine(Path.GetDirectoryName(file), sDllName)))
|
||||
{
|
||||
if (saDependentDLLs == null)
|
||||
saDependentDLLs = new string[0];
|
||||
else
|
||||
saDependentDLLs = new string[saDependentDLLs.Length];
|
||||
|
||||
FileInfo fiDLL = new FileInfo(Path.Combine(Path.GetDirectoryName(file), sDllName));
|
||||
saDependentDLLs[saDependentDLLs.Length - 1] = fiDLL.CopyTo(Path.GetTempPath() + sDllName, true).FullName;
|
||||
}
|
||||
}
|
||||
|
||||
index = (int)lastPosition;
|
||||
}
|
||||
|
||||
index += 4 + 12;
|
||||
DllNameRVA = BitConverter.ToUInt32(fileContent, index);
|
||||
index += 4;
|
||||
}
|
||||
|
||||
return saDependentDLLs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to run an executable
|
||||
/// </summary>
|
||||
/// <param name="file">Executable to attempt to run</param>
|
||||
/// <returns>Process representing the running executable, null on error</returns>
|
||||
internal static Process StartSafe(string file)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return null;
|
||||
@@ -49,398 +157,85 @@ namespace BurnOutSharp
|
||||
{
|
||||
startingprocess.Start();
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
return null;
|
||||
}
|
||||
|
||||
return startingprocess;
|
||||
}
|
||||
|
||||
private static string MakeTempFile(string file, string sExtension = ".exe")
|
||||
private static IMAGE_SECTION_HEADER?[] ReadSections(byte[] fileContent)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
|
||||
FileInfo filei = new FileInfo(file);
|
||||
try
|
||||
{
|
||||
File.Delete(Path.Combine(Path.GetTempPath(), "tmp", filei.Name + "*" + sExtension));
|
||||
}
|
||||
catch { }
|
||||
filei = filei.CopyTo(Path.GetTempPath() + "tmp" + filei.Name + Directory.GetFiles(Path.GetTempPath(), "tmp" + filei.Name + "*" + sExtension).Length + sExtension, true);
|
||||
filei.Attributes = FileAttributes.Temporary | FileAttributes.NotContentIndexed;
|
||||
return filei.FullName;
|
||||
}
|
||||
|
||||
private static bool IsEXE(string file)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return false;
|
||||
|
||||
BinaryReader breader = new BinaryReader(File.OpenRead(file));
|
||||
breader.ReadBytes(60);
|
||||
int PEHeaderOffset = breader.ReadInt32();
|
||||
breader.BaseStream.Seek(PEHeaderOffset, SeekOrigin.Begin);
|
||||
breader.ReadBytes(22);
|
||||
short Characteristics = breader.ReadInt16();
|
||||
breader.Close();
|
||||
//check if file is dll
|
||||
if ((Characteristics & 0x2000) == 0x2000)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
private static string[] CopyDependentDlls(string exefile)
|
||||
{
|
||||
if (exefile == null)
|
||||
if (fileContent == null)
|
||||
return null;
|
||||
|
||||
FileInfo fiExe = new FileInfo(exefile);
|
||||
Section[] sections = ReadSections(exefile);
|
||||
BinaryReader breader = new BinaryReader(File.OpenRead(exefile), Encoding.Default);
|
||||
long lastPosition;
|
||||
string[] saDependentDLLs = null;
|
||||
breader.ReadBytes(60);
|
||||
int PEHeaderOffset = breader.ReadInt32();
|
||||
breader.BaseStream.Seek(PEHeaderOffset + 120 + 8, SeekOrigin.Begin); //120 Bytes till IMAGE_DATA_DIRECTORY array,8 Bytes=size of IMAGE_DATA_DIRECTORY
|
||||
uint ImportTableRVA = breader.ReadUInt32();
|
||||
uint ImportTableSize = breader.ReadUInt32();
|
||||
breader.BaseStream.Seek(RVA2Offset(ImportTableRVA, sections), SeekOrigin.Begin);
|
||||
breader.BaseStream.Seek(12, SeekOrigin.Current);
|
||||
uint DllNameRVA = breader.ReadUInt32();
|
||||
while (DllNameRVA != 0)
|
||||
{
|
||||
string sDllName = "";
|
||||
byte bChar;
|
||||
lastPosition = breader.BaseStream.Position;
|
||||
uint DLLNameOffset = RVA2Offset(DllNameRVA, sections);
|
||||
if (DLLNameOffset > 0)
|
||||
{
|
||||
breader.BaseStream.Seek(DLLNameOffset, SeekOrigin.Begin);
|
||||
if (breader.PeekChar() > -1)
|
||||
{
|
||||
do
|
||||
{
|
||||
bChar = breader.ReadByte();
|
||||
sDllName += (char)bChar;
|
||||
} while (bChar != 0 && breader.PeekChar() > -1);
|
||||
|
||||
sDllName = sDllName.Remove(sDllName.Length - 1, 1);
|
||||
if (File.Exists(Path.Combine(fiExe.DirectoryName, sDllName)))
|
||||
{
|
||||
if (saDependentDLLs == null)
|
||||
saDependentDLLs = new string[0];
|
||||
else
|
||||
saDependentDLLs = new string[saDependentDLLs.Length];
|
||||
|
||||
FileInfo fiDLL = new FileInfo(Path.Combine(fiExe.DirectoryName, sDllName));
|
||||
saDependentDLLs[saDependentDLLs.Length - 1] = fiDLL.CopyTo(Path.GetTempPath() + sDllName, true).FullName;
|
||||
}
|
||||
}
|
||||
|
||||
breader.BaseStream.Seek(lastPosition, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
breader.BaseStream.Seek(4 + 12, SeekOrigin.Current);
|
||||
DllNameRVA = breader.ReadUInt32();
|
||||
}
|
||||
|
||||
breader.Close();
|
||||
return saDependentDLLs;
|
||||
}
|
||||
|
||||
private static Section[] ReadSections(string exefile)
|
||||
{
|
||||
if (exefile == null)
|
||||
return null;
|
||||
|
||||
BinaryReader breader = new BinaryReader(File.OpenRead(exefile));
|
||||
breader.ReadBytes(60);
|
||||
uint PEHeaderOffset = breader.ReadUInt32();
|
||||
breader.BaseStream.Seek(PEHeaderOffset + 6, SeekOrigin.Begin);
|
||||
ushort NumberOfSections = breader.ReadUInt16();
|
||||
breader.BaseStream.Seek(PEHeaderOffset + 120 + 16 * 8, SeekOrigin.Begin);
|
||||
Section[] sections = new Section[NumberOfSections];
|
||||
uint PEHeaderOffset = BitConverter.ToUInt32(fileContent, 60);
|
||||
ushort NumberOfSections = BitConverter.ToUInt16(fileContent, (int)PEHeaderOffset + 6);
|
||||
var sections = new IMAGE_SECTION_HEADER?[NumberOfSections];
|
||||
int index = (int)PEHeaderOffset + 120 + 16 * 8;
|
||||
for (int i = 0; i < NumberOfSections; i++)
|
||||
{
|
||||
breader.BaseStream.Seek(8, SeekOrigin.Current);
|
||||
uint ivs = breader.ReadUInt32();
|
||||
uint ivo = breader.ReadUInt32();
|
||||
breader.BaseStream.Seek(4, SeekOrigin.Current);
|
||||
uint iro = breader.ReadUInt32();
|
||||
breader.BaseStream.Seek(16, SeekOrigin.Current);
|
||||
|
||||
sections[i] = new Section()
|
||||
{
|
||||
iVirtualSize = ivs,
|
||||
iVirtualOffset = ivo,
|
||||
iRawOffset = iro,
|
||||
};
|
||||
sections[i] = ReadSection(fileContent, index);
|
||||
}
|
||||
breader.Close();
|
||||
|
||||
return sections;
|
||||
}
|
||||
|
||||
private static uint RVA2Offset(uint RVA, Section[] sections)
|
||||
private static IMAGE_SECTION_HEADER? ReadSection(byte[] fileContent, int ptr)
|
||||
{
|
||||
int i = 0;
|
||||
while (i != sections.Length)
|
||||
// Get the size of a section header for later
|
||||
int sectionSize = Marshal.SizeOf<IMAGE_SECTION_HEADER>();
|
||||
|
||||
// If the contents are null or the wrong size, we can't read a section
|
||||
if (fileContent == null || fileContent.Length < sectionSize)
|
||||
return null;
|
||||
|
||||
// Create a new section and try our best to read one
|
||||
IMAGE_SECTION_HEADER? section = null;
|
||||
IntPtr tempPtr = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
if (sections[i].iVirtualOffset <= RVA && sections[i].iVirtualOffset + sections[i].iVirtualSize > RVA)
|
||||
return RVA - sections[i].iVirtualOffset + sections[i].iRawOffset;
|
||||
i++;
|
||||
// Get the pointer to where the section will go
|
||||
tempPtr = Marshal.AllocHGlobal(sectionSize);
|
||||
|
||||
// If we couldn't get the space, just return null
|
||||
if (tempPtr == IntPtr.Zero)
|
||||
return null;
|
||||
|
||||
// Copy from the array to the new space
|
||||
Marshal.Copy(fileContent, ptr, tempPtr, sectionSize);
|
||||
|
||||
// Get the new section and return
|
||||
section = Marshal.PtrToStructure<IMAGE_SECTION_HEADER>(tempPtr);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (tempPtr != IntPtr.Zero)
|
||||
Marshal.FreeHGlobal(tempPtr);
|
||||
}
|
||||
|
||||
return section;
|
||||
}
|
||||
|
||||
private static uint RVA2Offset(uint RVA, IMAGE_SECTION_HEADER?[] sections)
|
||||
{
|
||||
for (int i = 0; i < sections.Length; i++)
|
||||
{
|
||||
if (!sections[i].HasValue)
|
||||
continue;
|
||||
|
||||
var section = sections[i].Value;
|
||||
if (section.VirtualAddress <= RVA && section.VirtualAddress + section.PhysicalAddressOrVirtualSize > RVA)
|
||||
return RVA - section.VirtualAddress + section.PointerToRawData;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#region "EVORE version-search-functions"
|
||||
|
||||
public static string SearchProtectDiscVersion(string file)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
|
||||
Process exe = new Process();
|
||||
Process[] processes = new Process[0];
|
||||
string version = "";
|
||||
DateTime timestart;
|
||||
if (!IsEXE(file))
|
||||
return "";
|
||||
string tempexe = MakeTempFile(file);
|
||||
string[] DependentDlls = CopyDependentDlls(file);
|
||||
try
|
||||
{
|
||||
File.Delete(Path.Combine(Path.GetTempPath(), "a*.tmp"));
|
||||
}
|
||||
catch { }
|
||||
try
|
||||
{
|
||||
File.Delete(Path.Combine(Path.GetTempPath(), "PCD*.sys"));
|
||||
}
|
||||
catch { }
|
||||
if (Directory.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ProtectDisc")))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ProtectDisc", "p*.dll"));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
exe = StartSafe(tempexe);
|
||||
if (exe == null)
|
||||
return "";
|
||||
timestart = DateTime.Now;
|
||||
do
|
||||
{
|
||||
exe.Refresh();
|
||||
string[] files = null;
|
||||
|
||||
//check for ProtectDisc 8.2-x
|
||||
if (Directory.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ProtectDisc")))
|
||||
{
|
||||
files = Directory.GetFiles(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ProtectDisc"), "p*.dll");
|
||||
}
|
||||
if (files != null)
|
||||
{
|
||||
if (files.Length > 0)
|
||||
{
|
||||
FileVersionInfo fvinfo = FileVersionInfo.GetVersionInfo(files[0]);
|
||||
if (fvinfo.FileVersion != "")
|
||||
{
|
||||
version = fvinfo.FileVersion.Replace(" ", "").Replace(",", ".");
|
||||
//ProtectDisc 9 uses a ProtectDisc-Core dll version 8.0.x
|
||||
if (version.StartsWith("8.0"))
|
||||
version = "";
|
||||
fvinfo = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//check for ProtectDisc 7.1-8.1
|
||||
files = Directory.GetFiles(Path.GetTempPath(), "a*.tmp");
|
||||
if (files.Length > 0)
|
||||
{
|
||||
FileVersionInfo fvinfo = FileVersionInfo.GetVersionInfo(files[0]);
|
||||
if (fvinfo.FileVersion != "")
|
||||
{
|
||||
version = fvinfo.FileVersion.Replace(" ", "").Replace(",", ".");
|
||||
fvinfo = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (exe.HasExited)
|
||||
break;
|
||||
|
||||
processes = Process.GetProcessesByName(exe.ProcessName);
|
||||
if (processes.Length == 2)
|
||||
{
|
||||
processes[0].Refresh();
|
||||
processes[1].Refresh();
|
||||
if (processes[1].WorkingSet64 > exe.WorkingSet64)
|
||||
exe = processes[1];
|
||||
else if (processes[0].WorkingSet64 > exe.WorkingSet64) //else if (processes[0].Modules.Count > exe.Modules.Count)
|
||||
exe = processes[0];
|
||||
}
|
||||
} while (processes.Length > 0 && DateTime.Now.Subtract(timestart).TotalSeconds < WaitSeconds);
|
||||
|
||||
Thread.Sleep(500);
|
||||
if (!exe.HasExited)
|
||||
{
|
||||
processes = Process.GetProcessesByName(exe.ProcessName);
|
||||
if (processes.Length == 2)
|
||||
{
|
||||
try
|
||||
{
|
||||
processes[0].Kill();
|
||||
}
|
||||
catch { }
|
||||
processes[0].Close();
|
||||
try
|
||||
{
|
||||
processes[1].Kill();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
else
|
||||
{
|
||||
exe.Refresh();
|
||||
try
|
||||
{
|
||||
exe.Kill();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
exe.Close();
|
||||
Thread.Sleep(500);
|
||||
if (Directory.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ProtectDisc")))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ProtectDisc", "p*.dll"));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
try
|
||||
{
|
||||
File.Delete(Path.Combine(Path.GetTempPath(), "a*.tmp"));
|
||||
}
|
||||
catch { }
|
||||
try
|
||||
{
|
||||
File.Delete(Path.Combine(Path.GetTempPath(), "PCD*.sys"));
|
||||
}
|
||||
catch { }
|
||||
File.Delete(tempexe);
|
||||
if (DependentDlls != null)
|
||||
{
|
||||
for (int i = 0; i < DependentDlls.Length; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(DependentDlls[i]);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("!error while deleting file " + DependentDlls[i] + "; " + ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
public static string SearchSafeDiscVersion(string file)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
|
||||
Process exe = new Process();
|
||||
string version = "";
|
||||
DateTime timestart;
|
||||
if (!IsEXE(file))
|
||||
return "";
|
||||
|
||||
string tempexe = MakeTempFile(file);
|
||||
string[] DependentDlls = CopyDependentDlls(file);
|
||||
try
|
||||
{
|
||||
Directory.Delete(Path.Combine(Path.GetTempPath(), "~e*"), true);
|
||||
}
|
||||
catch { }
|
||||
try
|
||||
{
|
||||
File.Delete(Path.Combine(Path.GetTempPath(), "~e*"));
|
||||
}
|
||||
catch { }
|
||||
|
||||
exe = StartSafe(tempexe);
|
||||
if (exe == null)
|
||||
return "";
|
||||
|
||||
timestart = DateTime.Now;
|
||||
do
|
||||
{
|
||||
if (Directory.GetDirectories(Path.GetTempPath(), "~e*").Length > 0)
|
||||
{
|
||||
string[] files = Directory.GetFiles(Directory.GetDirectories(Path.GetTempPath(), "~e*")[0], "~de*.tmp");
|
||||
if (files.Length > 0)
|
||||
{
|
||||
StreamReader sr;
|
||||
try
|
||||
{
|
||||
sr = new StreamReader(files[0], Encoding.Default);
|
||||
string FileContent = sr.ReadToEnd();
|
||||
sr.Close();
|
||||
int position = FileContent.IndexOf("%ld.%ld.%ld, %ld, %s,") - 1;
|
||||
if (position > -1)
|
||||
version = FileContent.Substring(position + 28, 12);
|
||||
break;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
} while (!exe.HasExited && DateTime.Now.Subtract(timestart).TotalSeconds < WaitSeconds);
|
||||
|
||||
if (!exe.HasExited)
|
||||
exe.Kill();
|
||||
exe.Close();
|
||||
|
||||
try
|
||||
{
|
||||
Directory.Delete(Path.Combine(Path.GetTempPath(), "~e*"), true);
|
||||
}
|
||||
catch { }
|
||||
try
|
||||
{
|
||||
File.Delete(Path.Combine(Path.GetTempPath(), "~e*"));
|
||||
}
|
||||
catch { }
|
||||
File.Delete(tempexe);
|
||||
|
||||
if (DependentDlls != null)
|
||||
{
|
||||
for (int i = 0; i < DependentDlls.Length; i--)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(DependentDlls[i]);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("!error while deleting file " + DependentDlls[i] + "; " + ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Converted from https://github.com/wine-mirror/wine/blob/master/include/winnt.h
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct IMAGE_DATA_DIRECTORY
|
||||
{
|
||||
public uint VirtualAddress;
|
||||
public uint Size;
|
||||
}
|
||||
}
|
||||
30
BurnOutSharp/ExecutableType/Microsoft/IMAGE_DOS_HEADER.cs
Normal file
30
BurnOutSharp/ExecutableType/Microsoft/IMAGE_DOS_HEADER.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Converted from https://github.com/wine-mirror/wine/blob/master/include/winnt.h
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct IMAGE_DOS_HEADER
|
||||
{
|
||||
public ushort e_magic; /* 00: MZ Header signature */
|
||||
public ushort e_cblp; /* 02: Bytes on last page of file */
|
||||
public ushort e_cp; /* 04: Pages in file */
|
||||
public ushort e_crlc; /* 06: Relocations */
|
||||
public ushort e_cparhdr; /* 08: Size of header in paragraphs */
|
||||
public ushort e_minalloc; /* 0a: Minimum extra paragraphs needed */
|
||||
public ushort e_maxalloc; /* 0c: Maximum extra paragraphs needed */
|
||||
public ushort e_ss; /* 0e: Initial (relative) SS value */
|
||||
public ushort e_sp; /* 10: Initial SP value */
|
||||
public ushort e_csum; /* 12: Checksum */
|
||||
public ushort e_ip; /* 14: Initial IP value */
|
||||
public ushort e_cs; /* 16: Initial (relative) CS value */
|
||||
public ushort e_lfarlc; /* 18: File address of relocation table */
|
||||
public ushort e_ovno; /* 1a: Overlay number */
|
||||
public ushort[] e_res; /* 1c: Reserved words [4] */
|
||||
public ushort e_oemid; /* 24: OEM identifier (for e_oeminfo) */
|
||||
public ushort e_oeminfo; /* 26: OEM information; e_oemid specific */
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
|
||||
public ushort[] e_res2; /* 28: Reserved words [10] */
|
||||
public uint e_lfanew; /* 3c: Offset to extended header */
|
||||
}
|
||||
}
|
||||
17
BurnOutSharp/ExecutableType/Microsoft/IMAGE_FILE_HEADER.cs
Normal file
17
BurnOutSharp/ExecutableType/Microsoft/IMAGE_FILE_HEADER.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Converted from https://github.com/wine-mirror/wine/blob/master/include/winnt.h
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct IMAGE_FILE_HEADER
|
||||
{
|
||||
public ushort Machine;
|
||||
public ushort NumberOfSections;
|
||||
public uint TimeDateStamp;
|
||||
public uint PointerToSymbolTable;
|
||||
public uint NumberOfSymbols;
|
||||
public ushort SizeOfOptionalHeader;
|
||||
public FileCharacteristics Characteristics;
|
||||
}
|
||||
}
|
||||
13
BurnOutSharp/ExecutableType/Microsoft/IMAGE_NT_HEADERS32.cs
Normal file
13
BurnOutSharp/ExecutableType/Microsoft/IMAGE_NT_HEADERS32.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Converted from https://github.com/wine-mirror/wine/blob/master/include/winnt.h
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct IMAGE_NT_HEADERS32
|
||||
{
|
||||
public uint Signature; /* "PE"\0\0 */ /* 0x00 */
|
||||
public IMAGE_FILE_HEADER FileHeader; /* 0x04 */
|
||||
public IMAGE_OPTIONAL_HEADER32 OptionalHeader; /* 0x18 */
|
||||
}
|
||||
}
|
||||
13
BurnOutSharp/ExecutableType/Microsoft/IMAGE_NT_HEADERS64.cs
Normal file
13
BurnOutSharp/ExecutableType/Microsoft/IMAGE_NT_HEADERS64.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Converted from https://github.com/wine-mirror/wine/blob/master/include/winnt.h
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct IMAGE_NT_HEADERS64
|
||||
{
|
||||
public uint Signature;
|
||||
public IMAGE_FILE_HEADER FileHeader;
|
||||
public IMAGE_OPTIONAL_HEADER64 OptionalHeader;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Converted from https://github.com/wine-mirror/wine/blob/master/include/winnt.h
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct IMAGE_OPTIONAL_HEADER32
|
||||
{
|
||||
/* Standard fields */
|
||||
|
||||
public ushort Magic; /* 0x10b or 0x107 */ /* 0x00 */
|
||||
public byte MajorLinkerVersion;
|
||||
public byte MinorLinkerVersion;
|
||||
public uint SizeOfCode;
|
||||
public uint SizeOfInitializedData;
|
||||
public uint SizeOfUninitializedData;
|
||||
public uint AddressOfEntryPoint; /* 0x10 */
|
||||
public uint BaseOfCode;
|
||||
public uint BaseOfData;
|
||||
|
||||
/* NT additional fields */
|
||||
|
||||
public uint ImageBase;
|
||||
public uint SectionAlignment; /* 0x20 */
|
||||
public uint FileAlignment;
|
||||
public ushort MajorOperatingSystemVersion;
|
||||
public ushort MinorOperatingSystemVersion;
|
||||
public ushort MajorImageVersion;
|
||||
public ushort MinorImageVersion;
|
||||
public ushort MajorSubsystemVersion; /* 0x30 */
|
||||
public ushort MinorSubsystemVersion;
|
||||
public uint Win32VersionValue;
|
||||
public uint SizeOfImage;
|
||||
public uint SizeOfHeaders;
|
||||
public uint CheckSum; /* 0x40 */
|
||||
public ushort Subsystem;
|
||||
public DllCharacteristics DllCharacteristics;
|
||||
public uint SizeOfStackReserve;
|
||||
public uint SizeOfStackCommit;
|
||||
public uint SizeOfHeapReserve; /* 0x50 */
|
||||
public uint SizeOfHeapCommit;
|
||||
public uint LoaderFlags;
|
||||
public uint NumberOfRvaAndSizes;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES)]
|
||||
public IMAGE_DATA_DIRECTORY[] DataDirectory; /* 0x60, [IMAGE_NUMBEROF_DIRECTORY_ENTRIES] */
|
||||
/* 0xE0 */
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Converted from https://github.com/wine-mirror/wine/blob/master/include/winnt.h
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct IMAGE_OPTIONAL_HEADER64
|
||||
{
|
||||
public ushort Magic; /* 0x20b */
|
||||
public byte MajorLinkerVersion;
|
||||
public byte MinorLinkerVersion;
|
||||
public uint SizeOfCode;
|
||||
public uint SizeOfInitializedData;
|
||||
public uint SizeOfUninitializedData;
|
||||
public uint AddressOfEntryPoint;
|
||||
public uint BaseOfCode;
|
||||
public ulong ImageBase;
|
||||
public uint SectionAlignment;
|
||||
public uint FileAlignment;
|
||||
public ushort MajorOperatingSystemVersion;
|
||||
public ushort MinorOperatingSystemVersion;
|
||||
public ushort MajorImageVersion;
|
||||
public ushort MinorImageVersion;
|
||||
public ushort MajorSubsystemVersion;
|
||||
public ushort MinorSubsystemVersion;
|
||||
public uint Win32VersionValue;
|
||||
public uint SizeOfImage;
|
||||
public uint SizeOfHeaders;
|
||||
public uint CheckSum;
|
||||
public ushort Subsystem;
|
||||
public DllCharacteristics DllCharacteristics;
|
||||
public ulong SizeOfStackReserve;
|
||||
public ulong SizeOfStackCommit;
|
||||
public ulong SizeOfHeapReserve;
|
||||
public ulong SizeOfHeapCommit;
|
||||
public uint LoaderFlags;
|
||||
public uint NumberOfRvaAndSizes;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES)]
|
||||
public IMAGE_DATA_DIRECTORY[] DataDirectory; // [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]
|
||||
}
|
||||
}
|
||||
40
BurnOutSharp/ExecutableType/Microsoft/IMAGE_OS2_HEADER.cs
Normal file
40
BurnOutSharp/ExecutableType/Microsoft/IMAGE_OS2_HEADER.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Converted from https://github.com/wine-mirror/wine/blob/master/include/winnt.h
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct IMAGE_OS2_HEADER
|
||||
{
|
||||
public ushort ne_magic; /* 00 NE signature 'NE' */
|
||||
public byte ne_ver; /* 02 Linker version number */
|
||||
public byte ne_rev; /* 03 Linker revision number */
|
||||
public ushort ne_enttab; /* 04 Offset to entry table relative to NE */
|
||||
public ushort ne_cbenttab; /* 06 Length of entry table in bytes */
|
||||
public uint ne_crc; /* 08 Checksum */
|
||||
public ushort ne_flags; /* 0c Flags about segments in this file */
|
||||
public ushort ne_autodata; /* 0e Automatic data segment number */
|
||||
public ushort ne_heap; /* 10 Initial size of local heap */
|
||||
public ushort ne_stack; /* 12 Initial size of stack */
|
||||
public uint ne_csip; /* 14 Initial CS:IP */
|
||||
public uint ne_sssp; /* 18 Initial SS:SP */
|
||||
public ushort ne_cseg; /* 1c # of entries in segment table */
|
||||
public ushort ne_cmod; /* 1e # of entries in module reference tab. */
|
||||
public ushort ne_cbnrestab; /* 20 Length of nonresident-name table */
|
||||
public ushort ne_segtab; /* 22 Offset to segment table */
|
||||
public ushort ne_rsrctab; /* 24 Offset to resource table */
|
||||
public ushort ne_restab; /* 26 Offset to resident-name table */
|
||||
public ushort ne_modtab; /* 28 Offset to module reference table */
|
||||
public ushort ne_imptab; /* 2a Offset to imported name table */
|
||||
public uint ne_nrestab; /* 2c Offset to nonresident-name table */
|
||||
public ushort ne_cmovent; /* 30 # of movable entry points */
|
||||
public ushort ne_align; /* 32 Logical sector alignment shift count */
|
||||
public ushort ne_cres; /* 34 # of resource segments */
|
||||
public byte ne_exetyp; /* 36 Flags indicating target OS */
|
||||
public byte ne_flagsothers; /* 37 Additional information flags */
|
||||
public ushort ne_pretthunks; /* 38 Offset to return thunks */
|
||||
public ushort ne_psegrefbytes; /* 3a Offset to segment ref. bytes */
|
||||
public ushort ne_swaparea; /* 3c Reserved by Microsoft */
|
||||
public ushort ne_expver; /* 3e Expected Windows version number */
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Converted from https://github.com/wine-mirror/wine/blob/master/include/winnt.h
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct IMAGE_SECTION_HEADER
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.IMAGE_SIZEOF_SHORT_NAME)]
|
||||
public byte[] Name; // [IMAGE_SIZEOF_SHORT_NAME];
|
||||
public uint PhysicalAddressOrVirtualSize; // Misc
|
||||
public uint VirtualAddress;
|
||||
public uint SizeOfRawData;
|
||||
public uint PointerToRawData;
|
||||
public uint PointerToRelocations;
|
||||
public uint PointerToLinenumbers;
|
||||
public ushort NumberOfRelocations;
|
||||
public ushort NumberOfLinenumbers;
|
||||
public SectionCharacteristics Characteristics;
|
||||
}
|
||||
}
|
||||
62
BurnOutSharp/ExecutableType/Microsoft/IMAGE_VXD_HEADER.cs
Normal file
62
BurnOutSharp/ExecutableType/Microsoft/IMAGE_VXD_HEADER.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Converted from https://github.com/wine-mirror/wine/blob/master/include/winnt.h
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct IMAGE_VXD_HEADER
|
||||
{
|
||||
public ushort e32_magic;
|
||||
public byte e32_border;
|
||||
public byte e32_worder;
|
||||
public uint e32_level;
|
||||
public ushort e32_cpu;
|
||||
public ushort e32_os;
|
||||
public uint e32_ver;
|
||||
public uint e32_mflags;
|
||||
public uint e32_mpages;
|
||||
public uint e32_startobj;
|
||||
public uint e32_eip;
|
||||
public uint e32_stackobj;
|
||||
public uint e32_esp;
|
||||
public uint e32_pagesize;
|
||||
public uint e32_lastpagesize;
|
||||
public uint e32_fixupsize;
|
||||
public uint e32_fixupsum;
|
||||
public uint e32_ldrsize;
|
||||
public uint e32_ldrsum;
|
||||
public uint e32_objtab;
|
||||
public uint e32_objcnt;
|
||||
public uint e32_objmap;
|
||||
public uint e32_itermap;
|
||||
public uint e32_rsrctab;
|
||||
public uint e32_rsrccnt;
|
||||
public uint e32_restab;
|
||||
public uint e32_enttab;
|
||||
public uint e32_dirtab;
|
||||
public uint e32_dircnt;
|
||||
public uint e32_fpagetab;
|
||||
public uint e32_frectab;
|
||||
public uint e32_impmod;
|
||||
public uint e32_impmodcnt;
|
||||
public uint e32_impproc;
|
||||
public uint e32_pagesum;
|
||||
public uint e32_datapage;
|
||||
public uint e32_preload;
|
||||
public uint e32_nrestab;
|
||||
public uint e32_cbnrestab;
|
||||
public uint e32_nressum;
|
||||
public uint e32_autodata;
|
||||
public uint e32_debuginfo;
|
||||
public uint e32_debuglen;
|
||||
public uint e32_instpreload;
|
||||
public uint e32_instdemand;
|
||||
public uint e32_heapsize;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
|
||||
public byte[] e32_res3; // [12]
|
||||
public uint e32_winresoff;
|
||||
public uint e32_winreslen;
|
||||
public ushort e32_devid;
|
||||
public ushort e32_ddkver;
|
||||
}
|
||||
}
|
||||
203
BurnOutSharp/ExecutableType/Microsoft/winnt.cs
Normal file
203
BurnOutSharp/ExecutableType/Microsoft/winnt.cs
Normal file
@@ -0,0 +1,203 @@
|
||||
using System;
|
||||
|
||||
// Converted from https://github.com/wine-mirror/wine/blob/master/include/winnt.h
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
internal enum DirectoryEntries
|
||||
{
|
||||
IMAGE_DIRECTORY_ENTRY_EXPORT = 0,
|
||||
IMAGE_DIRECTORY_ENTRY_IMPORT = 1,
|
||||
IMAGE_DIRECTORY_ENTRY_RESOURCE = 2,
|
||||
IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3,
|
||||
IMAGE_DIRECTORY_ENTRY_SECURIT = 4,
|
||||
IMAGE_DIRECTORY_ENTRY_BASERELOC = 5,
|
||||
IMAGE_DIRECTORY_ENTRY_DEBUG = 6,
|
||||
IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7,
|
||||
IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8, // (MIPS GP)
|
||||
IMAGE_DIRECTORY_ENTRY_TLS = 9,
|
||||
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10,
|
||||
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11,
|
||||
IMAGE_DIRECTORY_ENTRY_IAT = 12, // Import Address Table
|
||||
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13,
|
||||
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum DllCharacteristics : ushort
|
||||
{
|
||||
IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040,
|
||||
IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = 0x0080,
|
||||
IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 0x0100,
|
||||
IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 0x0200,
|
||||
IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400,
|
||||
IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800,
|
||||
IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000,
|
||||
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum FileCharacteristics : ushort
|
||||
{
|
||||
IMAGE_FILE_RELOCS_STRIPPED = 0x0001, /* No relocation info */
|
||||
IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002,
|
||||
IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004,
|
||||
IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008,
|
||||
IMAGE_FILE_AGGRESIVE_WS_TRIM = 0x0010,
|
||||
IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020,
|
||||
IMAGE_FILE_16BIT_MACHINE = 0x0040,
|
||||
IMAGE_FILE_BYTES_REVERSED_LO = 0x0080,
|
||||
IMAGE_FILE_32BIT_MACHINE = 0x0100,
|
||||
IMAGE_FILE_DEBUG_STRIPPED = 0x0200,
|
||||
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400,
|
||||
IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800,
|
||||
IMAGE_FILE_SYSTEM = 0x1000,
|
||||
IMAGE_FILE_DLL = 0x2000,
|
||||
IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000,
|
||||
IMAGE_FILE_BYTES_REVERSED_HI = 0x8000,
|
||||
}
|
||||
|
||||
internal enum MachineSettings : ushort
|
||||
{
|
||||
IMAGE_FILE_MACHINE_UNKNOWN = 0,
|
||||
IMAGE_FILE_MACHINE_TARGET_HOST = 0x0001,
|
||||
IMAGE_FILE_MACHINE_I860 = 0x014d,
|
||||
IMAGE_FILE_MACHINE_I386 = 0x014c,
|
||||
IMAGE_FILE_MACHINE_R3000 = 0x0162,
|
||||
IMAGE_FILE_MACHINE_R4000 = 0x0166,
|
||||
IMAGE_FILE_MACHINE_R10000 = 0x0168,
|
||||
IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x0169,
|
||||
IMAGE_FILE_MACHINE_ALPHA = 0x0184,
|
||||
IMAGE_FILE_MACHINE_SH3 = 0x01a2,
|
||||
IMAGE_FILE_MACHINE_SH3DSP = 0x01a3,
|
||||
IMAGE_FILE_MACHINE_SH3E = 0x01a4,
|
||||
IMAGE_FILE_MACHINE_SH4 = 0x01a6,
|
||||
IMAGE_FILE_MACHINE_SH5 = 0x01a8,
|
||||
IMAGE_FILE_MACHINE_ARM = 0x01c0,
|
||||
IMAGE_FILE_MACHINE_THUMB = 0x01c2,
|
||||
IMAGE_FILE_MACHINE_ARMNT = 0x01c4,
|
||||
IMAGE_FILE_MACHINE_ARM64 = 0xaa64,
|
||||
IMAGE_FILE_MACHINE_AM33 = 0x01d3,
|
||||
IMAGE_FILE_MACHINE_POWERPC = 0x01f0,
|
||||
IMAGE_FILE_MACHINE_POWERPCFP = 0x01f1,
|
||||
IMAGE_FILE_MACHINE_IA64 = 0x0200,
|
||||
IMAGE_FILE_MACHINE_MIPS16 = 0x0266,
|
||||
IMAGE_FILE_MACHINE_ALPHA64 = 0x0284,
|
||||
IMAGE_FILE_MACHINE_MIPSFPU = 0x0366,
|
||||
IMAGE_FILE_MACHINE_MIPSFPU16 = 0x0466,
|
||||
IMAGE_FILE_MACHINE_AXP64 = 0x0284,
|
||||
IMAGE_FILE_MACHINE_TRICORE = 0x0520,
|
||||
IMAGE_FILE_MACHINE_CEF = 0x0cef,
|
||||
IMAGE_FILE_MACHINE_EBC = 0x0ebc,
|
||||
IMAGE_FILE_MACHINE_AMD64 = 0x8664,
|
||||
IMAGE_FILE_MACHINE_M32R = 0x9041,
|
||||
IMAGE_FILE_MACHINE_CEE = 0xc0ee,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum SectionCharacteristics : uint
|
||||
{
|
||||
IMAGE_SCN_TYPE_REG = 0x00000000, // Reserved
|
||||
IMAGE_SCN_TYPE_DSECT = 0x00000001, // Reserved
|
||||
IMAGE_SCN_TYPE_NOLOAD = 0x00000002, // Reserved
|
||||
IMAGE_SCN_TYPE_GROUP = 0x00000004, // Reserved
|
||||
IMAGE_SCN_TYPE_NO_PAD = 0x00000008, // Reserved
|
||||
IMAGE_SCN_TYPE_COPY = 0x00000010, // Reserved
|
||||
|
||||
IMAGE_SCN_CNT_CODE = 0x00000020,
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040,
|
||||
IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080,
|
||||
|
||||
IMAGE_SCN_LNK_OTHER = 0x00000100,
|
||||
IMAGE_SCN_LNK_INFO = 0x00000200,
|
||||
IMAGE_SCN_TYPE_OVER = 0x00000400, // Reserved
|
||||
IMAGE_SCN_LNK_REMOVE = 0x00000800,
|
||||
IMAGE_SCN_LNK_COMDAT = 0x00001000,
|
||||
|
||||
/* 0x00002000 - Reserved */
|
||||
IMAGE_SCN_MEM_PROTECTED = 0x00004000, // Obsolete
|
||||
IMAGE_SCN_MEM_FARDATA = 0x00008000,
|
||||
|
||||
IMAGE_SCN_MEM_SYSHEAP = 0x00010000, // Obsolete
|
||||
IMAGE_SCN_MEM_PURGEABLE = 0x00020000,
|
||||
IMAGE_SCN_MEM_16BIT = 0x00020000,
|
||||
IMAGE_SCN_MEM_LOCKED = 0x00040000,
|
||||
IMAGE_SCN_MEM_PRELOAD = 0x00080000,
|
||||
|
||||
IMAGE_SCN_ALIGN_1BYTES = 0x00100000,
|
||||
IMAGE_SCN_ALIGN_2BYTES = 0x00200000,
|
||||
IMAGE_SCN_ALIGN_4BYTES = 0x00300000,
|
||||
IMAGE_SCN_ALIGN_8BYTES = 0x00400000,
|
||||
IMAGE_SCN_ALIGN_16BYTES = 0x00500000, // Default
|
||||
IMAGE_SCN_ALIGN_32BYTES = 0x00600000,
|
||||
IMAGE_SCN_ALIGN_64BYTES = 0x00700000,
|
||||
IMAGE_SCN_ALIGN_128BYTES = 0x00800000,
|
||||
IMAGE_SCN_ALIGN_256BYTES = 0x00900000,
|
||||
IMAGE_SCN_ALIGN_512BYTES = 0x00A00000,
|
||||
IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000,
|
||||
IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000,
|
||||
IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000,
|
||||
IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000,
|
||||
/* 0x00F00000 - Unused */
|
||||
IMAGE_SCN_ALIGN_MASK = 0x00F00000,
|
||||
|
||||
IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000,
|
||||
|
||||
|
||||
IMAGE_SCN_MEM_DISCARDABLE = 0x02000000,
|
||||
IMAGE_SCN_MEM_NOT_CACHED = 0x04000000,
|
||||
IMAGE_SCN_MEM_NOT_PAGED = 0x08000000,
|
||||
IMAGE_SCN_MEM_SHARED = 0x10000000,
|
||||
IMAGE_SCN_MEM_EXECUTE = 0x20000000,
|
||||
IMAGE_SCN_MEM_READ = 0x40000000,
|
||||
IMAGE_SCN_MEM_WRITE = 0x80000000,
|
||||
}
|
||||
|
||||
internal enum Subsystem : ushort
|
||||
{
|
||||
IMAGE_SUBSYSTEM_UNKNOWN = 0,
|
||||
IMAGE_SUBSYSTEM_NATIVE = 1,
|
||||
IMAGE_SUBSYSTEM_WINDOWS_GUI = 2, // Windows GUI subsystem
|
||||
IMAGE_SUBSYSTEM_WINDOWS_CUI = 3, // Windows character subsystem
|
||||
IMAGE_SUBSYSTEM_OS2_CUI = 5,
|
||||
IMAGE_SUBSYSTEM_POSIX_CUI = 7,
|
||||
IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8, // native Win9x driver
|
||||
IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9, // Windows CE subsystem
|
||||
IMAGE_SUBSYSTEM_EFI_APPLICATION = 10,
|
||||
IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11,
|
||||
IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12,
|
||||
IMAGE_SUBSYSTEM_EFI_ROM = 13,
|
||||
IMAGE_SUBSYSTEM_XBOX = 14,
|
||||
IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16,
|
||||
}
|
||||
|
||||
internal static class Constants
|
||||
{
|
||||
public const ushort IMAGE_DOS_SIGNATURE = 0x5A4D; /* MZ */
|
||||
public const ushort IMAGE_OS2_SIGNATURE = 0x454E; /* NE */
|
||||
public const ushort IMAGE_OS2_SIGNATURE_LE = 0x454C; /* LE */
|
||||
public const ushort IMAGE_OS2_SIGNATURE_LX = 0x584C; /* LX */
|
||||
public const ushort IMAGE_VXD_SIGNATURE = 0x454C; /* LE */
|
||||
public const uint IMAGE_NT_SIGNATURE = 0x00004550; /* PE00 */
|
||||
|
||||
public const int IMAGE_SIZEOF_FILE_HEADER = 20;
|
||||
public const int IMAGE_SIZEOF_ROM_OPTIONAL_HEADER = 56;
|
||||
public const int IMAGE_SIZEOF_STD_OPTIONAL_HEADER = 28;
|
||||
public const int IMAGE_SIZEOF_NT_OPTIONAL32_HEADER = 224;
|
||||
public const int IMAGE_SIZEOF_NT_OPTIONAL64_HEADER = 240;
|
||||
public const int IMAGE_SIZEOF_SHORT_NAME = 8;
|
||||
public const int IMAGE_SIZEOF_SECTION_HEADER = 40;
|
||||
public const int IMAGE_SIZEOF_SYMBOL = 18;
|
||||
public const int IMAGE_SIZEOF_AUX_SYMBOL = 18;
|
||||
public const int IMAGE_SIZEOF_RELOCATION = 10;
|
||||
public const int IMAGE_SIZEOF_BASE_RELOCATION = 8;
|
||||
public const int IMAGE_SIZEOF_LINENUMBER = 6;
|
||||
public const int IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR = 60;
|
||||
|
||||
// Possible Magic values
|
||||
public const ushort IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;
|
||||
public const ushort IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
|
||||
public const ushort IMAGE_ROM_OPTIONAL_HDR_MAGIC = 0x107;
|
||||
|
||||
public const int IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
|
||||
}
|
||||
}
|
||||
1663
BurnOutSharp/External/HLLib/HLExtract.Net/HLLib.cs
vendored
Normal file
1663
BurnOutSharp/External/HLLib/HLExtract.Net/HLLib.cs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1158
BurnOutSharp/External/HLLib/HLExtract.Net/Program.cs
vendored
Normal file
1158
BurnOutSharp/External/HLLib/HLExtract.Net/Program.cs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
414
BurnOutSharp/External/StormLibSharp/MpqArchive.cs
vendored
Normal file
414
BurnOutSharp/External/StormLibSharp/MpqArchive.cs
vendored
Normal file
@@ -0,0 +1,414 @@
|
||||
using StormLibSharp.Native;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.IO.MemoryMappedFiles;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace StormLibSharp
|
||||
{
|
||||
public class MpqArchive : IDisposable
|
||||
{
|
||||
private MpqArchiveSafeHandle _handle;
|
||||
private List<MpqFileStream> _openFiles = new List<MpqFileStream>();
|
||||
private FileAccess _accessType;
|
||||
private List<MpqArchiveCompactingEventHandler> _compactCallbacks = new List<MpqArchiveCompactingEventHandler>();
|
||||
private SFILE_COMPACT_CALLBACK _compactCallback;
|
||||
|
||||
#region Constructors / Factories
|
||||
public MpqArchive(string filePath, FileAccess accessType)
|
||||
{
|
||||
_accessType = accessType;
|
||||
SFileOpenArchiveFlags flags = SFileOpenArchiveFlags.TypeIsFile;
|
||||
if (accessType == FileAccess.Read)
|
||||
flags |= SFileOpenArchiveFlags.AccessReadOnly;
|
||||
else
|
||||
flags |= SFileOpenArchiveFlags.AccessReadWriteShare;
|
||||
|
||||
// constant 2 = SFILE_OPEN_HARD_DISK_FILE
|
||||
if (!NativeMethods.SFileOpenArchive(filePath, 2, flags, out _handle))
|
||||
throw new Win32Exception(); // Implicitly calls GetLastError
|
||||
}
|
||||
|
||||
public MpqArchive(MemoryMappedFile file, FileAccess accessType)
|
||||
{
|
||||
_accessType = accessType;
|
||||
string fileName = Win32Methods.GetFileNameOfMemoryMappedFile(file);
|
||||
if (fileName == null)
|
||||
throw new ArgumentException("Could not retrieve the name of the file to initialize.");
|
||||
|
||||
SFileOpenArchiveFlags flags = SFileOpenArchiveFlags.TypeIsMemoryMapped;
|
||||
if (accessType == FileAccess.Read)
|
||||
flags |= SFileOpenArchiveFlags.AccessReadOnly;
|
||||
else
|
||||
flags |= SFileOpenArchiveFlags.AccessReadWriteShare;
|
||||
|
||||
// constant 2 = SFILE_OPEN_HARD_DISK_FILE
|
||||
if (!NativeMethods.SFileOpenArchive(fileName, 2, flags, out _handle))
|
||||
throw new Win32Exception(); // Implicitly calls GetLastError
|
||||
}
|
||||
|
||||
private MpqArchive(string filePath, MpqArchiveVersion version, MpqFileStreamAttributes listfileAttributes, MpqFileStreamAttributes attributesFileAttributes, int maxFileCount)
|
||||
{
|
||||
if (maxFileCount < 0)
|
||||
throw new ArgumentException("maxFileCount");
|
||||
|
||||
SFileOpenArchiveFlags flags = SFileOpenArchiveFlags.TypeIsFile | SFileOpenArchiveFlags.AccessReadWriteShare;
|
||||
flags |= (SFileOpenArchiveFlags)version;
|
||||
|
||||
//SFILE_CREATE_MPQ create = new SFILE_CREATE_MPQ()
|
||||
//{
|
||||
// cbSize = unchecked((uint)Marshal.SizeOf(typeof(SFILE_CREATE_MPQ))),
|
||||
// dwMaxFileCount = unchecked((uint)maxFileCount),
|
||||
// dwMpqVersion = (uint)version,
|
||||
// dwFileFlags1 = (uint)listfileAttributes,
|
||||
// dwFileFlags2 = (uint)attributesFileAttributes,
|
||||
// dwStreamFlags = (uint)flags,
|
||||
//};
|
||||
|
||||
//if (!NativeMethods.SFileCreateArchive2(filePath, ref create, out _handle))
|
||||
// throw new Win32Exception();
|
||||
if (!NativeMethods.SFileCreateArchive(filePath, (uint)flags, int.MaxValue, out _handle))
|
||||
throw new Win32Exception();
|
||||
}
|
||||
|
||||
public static MpqArchive CreateNew(string mpqPath, MpqArchiveVersion version)
|
||||
{
|
||||
return CreateNew(mpqPath, version, MpqFileStreamAttributes.None, MpqFileStreamAttributes.None, int.MaxValue);
|
||||
}
|
||||
|
||||
public static MpqArchive CreateNew(string mpqPath, MpqArchiveVersion version, MpqFileStreamAttributes listfileAttributes,
|
||||
MpqFileStreamAttributes attributesFileAttributes, int maxFileCount)
|
||||
{
|
||||
return new MpqArchive(mpqPath, version, listfileAttributes, attributesFileAttributes, maxFileCount);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
// TODO: Move to common location.
|
||||
// This is a global setting, not per-archive setting.
|
||||
|
||||
//public int Locale
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
// set
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
//}
|
||||
|
||||
public long MaxFileCount
|
||||
{
|
||||
get
|
||||
{
|
||||
VerifyHandle();
|
||||
return NativeMethods.SFileGetMaxFileCount(_handle);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value < 0 || value > uint.MaxValue)
|
||||
throw new ArgumentException("value");
|
||||
VerifyHandle();
|
||||
|
||||
if (!NativeMethods.SFileSetMaxFileCount(_handle, unchecked((uint)value)))
|
||||
throw new Win32Exception();
|
||||
}
|
||||
}
|
||||
|
||||
private void VerifyHandle()
|
||||
{
|
||||
if (_handle == null || _handle.IsInvalid)
|
||||
throw new ObjectDisposedException("MpqArchive");
|
||||
}
|
||||
|
||||
public bool IsPatchedArchive
|
||||
{
|
||||
get
|
||||
{
|
||||
VerifyHandle();
|
||||
return NativeMethods.SFileIsPatchedArchive(_handle);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
VerifyHandle();
|
||||
if (!NativeMethods.SFileFlushArchive(_handle))
|
||||
throw new Win32Exception();
|
||||
}
|
||||
|
||||
public int AddListFile(string listfileContents)
|
||||
{
|
||||
VerifyHandle();
|
||||
return NativeMethods.SFileAddListFile(_handle, listfileContents);
|
||||
}
|
||||
|
||||
public void AddFileFromDisk(string filePath, string archiveName)
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
if (!NativeMethods.SFileAddFile(_handle, filePath, archiveName, 0))
|
||||
throw new Win32Exception();
|
||||
}
|
||||
|
||||
public void Compact(string listfile)
|
||||
{
|
||||
VerifyHandle();
|
||||
if (!NativeMethods.SFileCompactArchive(_handle, listfile, false))
|
||||
throw new Win32Exception();
|
||||
}
|
||||
|
||||
private void _OnCompact(IntPtr pvUserData, uint dwWorkType, ulong bytesProcessed, ulong totalBytes)
|
||||
{
|
||||
MpqArchiveCompactingEventArgs args = new MpqArchiveCompactingEventArgs(dwWorkType, bytesProcessed, totalBytes);
|
||||
OnCompacting(args);
|
||||
}
|
||||
|
||||
protected virtual void OnCompacting(MpqArchiveCompactingEventArgs e)
|
||||
{
|
||||
foreach (var cb in _compactCallbacks)
|
||||
{
|
||||
cb(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
public event MpqArchiveCompactingEventHandler Compacting
|
||||
{
|
||||
add
|
||||
{
|
||||
VerifyHandle();
|
||||
_compactCallback = _OnCompact;
|
||||
if (!NativeMethods.SFileSetCompactCallback(_handle, _compactCallback, IntPtr.Zero))
|
||||
throw new Win32Exception();
|
||||
|
||||
_compactCallbacks.Add(value);
|
||||
}
|
||||
remove
|
||||
{
|
||||
_compactCallbacks.Remove(value);
|
||||
|
||||
VerifyHandle();
|
||||
if (_compactCallbacks.Count == 0)
|
||||
{
|
||||
if (!NativeMethods.SFileSetCompactCallback(_handle, null, IntPtr.Zero))
|
||||
{
|
||||
// Don't do anything here. Remove shouldn't fail hard.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Determine if SFileGetAttributes/SFileSetAttributes/SFileUpdateFileAttributes deserves a projection.
|
||||
// It's unclear - these seem to affect the (attributes) file but I can't figure out exactly what that means.
|
||||
|
||||
public void AddPatchArchive(string patchPath)
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
if (!NativeMethods.SFileOpenPatchArchive(_handle, patchPath, null, 0))
|
||||
throw new Win32Exception();
|
||||
}
|
||||
|
||||
public void AddPatchArchives(IEnumerable<string> patchPaths)
|
||||
{
|
||||
if (patchPaths == null)
|
||||
throw new ArgumentNullException("patchPaths");
|
||||
|
||||
VerifyHandle();
|
||||
|
||||
foreach (string path in patchPaths)
|
||||
{
|
||||
// Don't sublet to AddPatchArchive to avoid having to repeatedly call VerifyHandle()
|
||||
if (!NativeMethods.SFileOpenPatchArchive(_handle, path, null, 0))
|
||||
throw new Win32Exception();
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasFile(string fileToFind)
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
return NativeMethods.SFileHasFile(_handle, fileToFind);
|
||||
}
|
||||
|
||||
public MpqFileStream OpenFile(string fileName)
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
MpqFileSafeHandle fileHandle;
|
||||
if (!NativeMethods.SFileOpenFileEx(_handle, fileName, 0, out fileHandle))
|
||||
throw new Win32Exception();
|
||||
|
||||
MpqFileStream fs = new MpqFileStream(fileHandle, _accessType, this);
|
||||
_openFiles.Add(fs);
|
||||
return fs;
|
||||
}
|
||||
|
||||
public void ExtractFile(string fileToExtract, string destinationPath)
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
if (!NativeMethods.SFileExtractFile(_handle, fileToExtract, destinationPath, 0))
|
||||
throw new Win32Exception();
|
||||
}
|
||||
|
||||
public MpqFileVerificationResults VerifyFile(string fileToVerify)
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
return (MpqFileVerificationResults)NativeMethods.SFileVerifyFile(_handle, fileToVerify, 0);
|
||||
}
|
||||
|
||||
// TODO: Consider SFileVerifyRawData
|
||||
|
||||
public MpqArchiveVerificationResult VerifyArchive()
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
return (MpqArchiveVerificationResult)NativeMethods.SFileVerifyArchive(_handle);
|
||||
}
|
||||
|
||||
|
||||
#region IDisposable implementation
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
~MpqArchive()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// Release owned files first.
|
||||
if (_openFiles != null)
|
||||
{
|
||||
foreach (var file in _openFiles)
|
||||
{
|
||||
file.Dispose();
|
||||
}
|
||||
|
||||
_openFiles.Clear();
|
||||
_openFiles = null;
|
||||
}
|
||||
|
||||
// Release
|
||||
if (_handle != null && !_handle.IsInvalid)
|
||||
{
|
||||
_handle.Close();
|
||||
_handle = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void RemoveOwnedFile(MpqFileStream file)
|
||||
{
|
||||
_openFiles.Remove(file);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public enum MpqArchiveVersion
|
||||
{
|
||||
Version1 = 0,
|
||||
Version2 = 0x01000000,
|
||||
Version3 = 0x02000000,
|
||||
Version4 = 0x03000000,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum MpqFileStreamAttributes
|
||||
{
|
||||
None = 0x0,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum MpqFileVerificationResults
|
||||
{
|
||||
/// <summary>
|
||||
/// There were no errors with the file.
|
||||
/// </summary>
|
||||
Verified = 0,
|
||||
/// <summary>
|
||||
/// Failed to open the file
|
||||
/// </summary>
|
||||
Error = 0x1,
|
||||
/// <summary>
|
||||
/// Failed to read all data from the file
|
||||
/// </summary>
|
||||
ReadError = 0x2,
|
||||
/// <summary>
|
||||
/// File has sector CRC
|
||||
/// </summary>
|
||||
HasSectorCrc = 0x4,
|
||||
/// <summary>
|
||||
/// Sector CRC check failed
|
||||
/// </summary>
|
||||
SectorCrcError = 0x8,
|
||||
/// <summary>
|
||||
/// File has CRC32
|
||||
/// </summary>
|
||||
HasChecksum = 0x10,
|
||||
/// <summary>
|
||||
/// CRC32 check failed
|
||||
/// </summary>
|
||||
ChecksumError = 0x20,
|
||||
/// <summary>
|
||||
/// File has data MD5
|
||||
/// </summary>
|
||||
HasMd5 = 0x40,
|
||||
/// <summary>
|
||||
/// MD5 check failed
|
||||
/// </summary>
|
||||
Md5Error = 0x80,
|
||||
/// <summary>
|
||||
/// File has raw data MD5
|
||||
/// </summary>
|
||||
HasRawMd5 = 0x100,
|
||||
/// <summary>
|
||||
/// Raw MD5 check failed
|
||||
/// </summary>
|
||||
RawMd5Error = 0x200,
|
||||
}
|
||||
|
||||
public enum MpqArchiveVerificationResult
|
||||
{
|
||||
/// <summary>
|
||||
/// There is no signature in the MPQ
|
||||
/// </summary>
|
||||
NoSignature = 0,
|
||||
/// <summary>
|
||||
/// There was an error during verifying signature (like no memory)
|
||||
/// </summary>
|
||||
VerificationFailed = 1,
|
||||
/// <summary>
|
||||
/// There is a weak signature and sign check passed
|
||||
/// </summary>
|
||||
WeakSignatureVerified = 2,
|
||||
/// <summary>
|
||||
/// There is a weak signature but sign check failed
|
||||
/// </summary>
|
||||
WeakSignatureFailed = 3,
|
||||
/// <summary>
|
||||
/// There is a strong signature and sign check passed
|
||||
/// </summary>
|
||||
StrongSignatureVerified = 4,
|
||||
/// <summary>
|
||||
/// There is a strong signature but sign check failed
|
||||
/// </summary>
|
||||
StrongSignatureFailed = 5,
|
||||
}
|
||||
}
|
||||
49
BurnOutSharp/External/StormLibSharp/MpqArchiveCompactingEventArgs.cs
vendored
Normal file
49
BurnOutSharp/External/StormLibSharp/MpqArchiveCompactingEventArgs.cs
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace StormLibSharp
|
||||
{
|
||||
public delegate void MpqArchiveCompactingEventHandler(MpqArchive sender, MpqArchiveCompactingEventArgs e);
|
||||
|
||||
public class MpqArchiveCompactingEventArgs : EventArgs
|
||||
{
|
||||
internal MpqArchiveCompactingEventArgs(uint dwWorkType, ulong processed, ulong total)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
WorkType = (MpqCompactingWorkType)dwWorkType;
|
||||
BytesProcessed = (long)processed;
|
||||
TotalBytes = (long)total;
|
||||
}
|
||||
}
|
||||
|
||||
public MpqCompactingWorkType WorkType
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public long BytesProcessed
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public long TotalBytes
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
}
|
||||
|
||||
public enum MpqCompactingWorkType
|
||||
{
|
||||
CheckingFiles = 1,
|
||||
CheckingHashTable = 2,
|
||||
CopyingNonMpqData = 3,
|
||||
CompactingFiles = 4,
|
||||
ClosingArchive = 5,
|
||||
}
|
||||
}
|
||||
185
BurnOutSharp/External/StormLibSharp/MpqFileStream.cs
vendored
Normal file
185
BurnOutSharp/External/StormLibSharp/MpqFileStream.cs
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
using StormLibSharp.Native;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace StormLibSharp
|
||||
{
|
||||
public class MpqFileStream : Stream
|
||||
{
|
||||
private MpqFileSafeHandle _handle;
|
||||
private FileAccess _accessType;
|
||||
private MpqArchive _owner;
|
||||
|
||||
internal MpqFileStream(MpqFileSafeHandle handle, FileAccess accessType, MpqArchive owner)
|
||||
{
|
||||
_handle = handle;
|
||||
_accessType = accessType;
|
||||
_owner = owner;
|
||||
}
|
||||
|
||||
private void VerifyHandle()
|
||||
{
|
||||
if (_handle == null || _handle.IsInvalid || _handle.IsClosed)
|
||||
throw new ObjectDisposedException("MpqFileStream");
|
||||
}
|
||||
|
||||
public override bool CanRead
|
||||
{
|
||||
get { VerifyHandle(); return true; }
|
||||
}
|
||||
|
||||
public override bool CanSeek
|
||||
{
|
||||
get { VerifyHandle(); return true; }
|
||||
}
|
||||
|
||||
public override bool CanWrite
|
||||
{
|
||||
get { VerifyHandle(); return _accessType != FileAccess.Read; }
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
_owner.Flush();
|
||||
}
|
||||
|
||||
public override long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
uint high = 0;
|
||||
uint low = NativeMethods.SFileGetFileSize(_handle, ref high);
|
||||
|
||||
ulong val = (high << 32) | low;
|
||||
return unchecked((long)val);
|
||||
}
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
return NativeMethods.SFileGetFilePointer(_handle);
|
||||
}
|
||||
set
|
||||
{
|
||||
Seek(value, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
|
||||
public override unsafe int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (buffer == null)
|
||||
throw new ArgumentNullException("buffer");
|
||||
if (offset > buffer.Length || (offset + count) > buffer.Length)
|
||||
throw new ArgumentException();
|
||||
if (count < 0)
|
||||
throw new ArgumentOutOfRangeException("count");
|
||||
|
||||
VerifyHandle();
|
||||
|
||||
bool success;
|
||||
uint read;
|
||||
fixed (byte* pb = &buffer[offset])
|
||||
{
|
||||
NativeOverlapped overlapped = default(NativeOverlapped);
|
||||
success = NativeMethods.SFileReadFile(_handle, new IntPtr(pb), unchecked((uint)count), out read, ref overlapped);
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
int lastError = Win32Methods.GetLastError();
|
||||
if (lastError != 38) // EOF
|
||||
throw new Win32Exception(lastError);
|
||||
}
|
||||
|
||||
return unchecked((int)read);
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
uint low, high;
|
||||
low = unchecked((uint)(offset & 0xffffffffu));
|
||||
high = unchecked((uint)(offset >> 32));
|
||||
return NativeMethods.SFileSetFilePointer(_handle, low, ref high, (uint)origin);
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override unsafe void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
if (buffer == null)
|
||||
throw new ArgumentNullException("buffer");
|
||||
if (offset > buffer.Length || (offset + count) > buffer.Length)
|
||||
throw new ArgumentException();
|
||||
if (count < 0)
|
||||
throw new ArgumentOutOfRangeException("count");
|
||||
|
||||
VerifyHandle();
|
||||
|
||||
bool success;
|
||||
fixed (byte* pb = &buffer[offset])
|
||||
{
|
||||
success = NativeMethods.SFileWriteFile(_handle, new IntPtr(pb), unchecked((uint)count), 0u);
|
||||
}
|
||||
|
||||
if (!success)
|
||||
throw new Win32Exception();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (_handle != null && !_handle.IsInvalid)
|
||||
{
|
||||
_handle.Close();
|
||||
_handle = null;
|
||||
}
|
||||
|
||||
if (_owner != null)
|
||||
{
|
||||
_owner.RemoveOwnedFile(this);
|
||||
_owner = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Seems like the right place for SFileGetFileInfo, but will need to determine
|
||||
// what value add these features have except for sophisticated debugging purposes
|
||||
// (like in Ladis' MPQ Editor app).
|
||||
|
||||
public int ChecksumCrc32
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] GetMd5Hash()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
17
BurnOutSharp/External/StormLibSharp/Native/Callbacks.cs
vendored
Normal file
17
BurnOutSharp/External/StormLibSharp/Native/Callbacks.cs
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace StormLibSharp.Native
|
||||
{
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
internal delegate void SFILE_DOWNLOAD_CALLBACK(IntPtr pvUserData, ulong byteOffset, uint dwTotalBytes);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
internal delegate void SFILE_COMPACT_CALLBACK(IntPtr pvUserData, uint dwWorkType, ulong bytesProcessed, ulong totalBytes);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
internal delegate void SFILE_ADDFILE_CALLBACK(IntPtr pvUserData, uint dwBytesWritte, uint dwTotalBytes, bool bFinalCall);
|
||||
}
|
||||
26
BurnOutSharp/External/StormLibSharp/Native/MpqArchiveSafeHandle.cs
vendored
Normal file
26
BurnOutSharp/External/StormLibSharp/Native/MpqArchiveSafeHandle.cs
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace StormLibSharp.Native
|
||||
{
|
||||
internal sealed class MpqArchiveSafeHandle : SafeHandleZeroOrMinusOneIsInvalid
|
||||
{
|
||||
public MpqArchiveSafeHandle(IntPtr handle)
|
||||
: base(true)
|
||||
{
|
||||
this.SetHandle(handle);
|
||||
}
|
||||
|
||||
public MpqArchiveSafeHandle()
|
||||
: base(true) { }
|
||||
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
return NativeMethods.SFileCloseArchive(this.handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
27
BurnOutSharp/External/StormLibSharp/Native/MpqFileSafeHandle.cs
vendored
Normal file
27
BurnOutSharp/External/StormLibSharp/Native/MpqFileSafeHandle.cs
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace StormLibSharp.Native
|
||||
{
|
||||
internal sealed class MpqFileSafeHandle : SafeHandleZeroOrMinusOneIsInvalid
|
||||
{
|
||||
public MpqFileSafeHandle(IntPtr handle)
|
||||
: base(true)
|
||||
{
|
||||
this.SetHandle(handle);
|
||||
}
|
||||
|
||||
public MpqFileSafeHandle()
|
||||
: base(true)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
return NativeMethods.SFileCloseFile(this.handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
497
BurnOutSharp/External/StormLibSharp/Native/NativeMethods.cs
vendored
Normal file
497
BurnOutSharp/External/StormLibSharp/Native/NativeMethods.cs
vendored
Normal file
@@ -0,0 +1,497 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace StormLibSharp.Native
|
||||
{
|
||||
internal static class NativeMethods
|
||||
{
|
||||
private const string STORMLIB = "stormlib.dll";
|
||||
|
||||
#region Functions for manipulation with StormLib global flags
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern uint SFileGetLocale();
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern uint SFileSetLocale(uint lcNewLocale);
|
||||
#endregion
|
||||
|
||||
#region Functions for archive manipulation
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileOpenArchive(
|
||||
[MarshalAs(UnmanagedType.LPTStr)] string szMpqName,
|
||||
uint dwPriority,
|
||||
SFileOpenArchiveFlags dwFlags,
|
||||
out MpqArchiveSafeHandle phMpq
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileCreateArchive(
|
||||
[MarshalAs(UnmanagedType.LPTStr)] string szMpqName,
|
||||
uint dwCreateFlags,
|
||||
uint dwMaxFileCount,
|
||||
out MpqArchiveSafeHandle phMpq
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileCreateArchive2(
|
||||
[MarshalAs(UnmanagedType.LPTStr)] string szMpqName,
|
||||
ref SFILE_CREATE_MPQ pCreateInfo,
|
||||
out MpqArchiveSafeHandle phMpq
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileSetDownloadCallback(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.FunctionPtr)] SFILE_DOWNLOAD_CALLBACK pfnCallback,
|
||||
IntPtr pvUserData
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileFlushArchive(MpqArchiveSafeHandle hMpq);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileCloseArchive(IntPtr hMpq);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileCloseArchive(MpqArchiveSafeHandle hMpq);
|
||||
#endregion
|
||||
|
||||
#region Adds another listfile into MPQ.
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern int SFileAddListFile(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szListFile
|
||||
);
|
||||
#endregion
|
||||
|
||||
#region Archive compacting
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileSetCompactCallback(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
SFILE_COMPACT_CALLBACK compactCB,
|
||||
IntPtr pvUserData
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileCompactArchive(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szListFile,
|
||||
bool bReserved
|
||||
);
|
||||
#endregion
|
||||
|
||||
#region Maximum file count
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern uint SFileGetMaxFileCount(MpqArchiveSafeHandle hMpq);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileSetMaxFileCount(MpqArchiveSafeHandle hMpq, uint dwMaxFileCount);
|
||||
#endregion
|
||||
|
||||
#region Changing (attributes) file
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern uint SFileGetAttributes(MpqArchiveSafeHandle hMpq);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileSetAttributes(MpqArchiveSafeHandle hMpq, uint dwFlags);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileUpdateFileAttributes(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szFileName
|
||||
);
|
||||
#endregion
|
||||
|
||||
#region Functions for manipulation with patch archives
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileOpenPatchArchive(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPTStr)] string szPatchMpqName,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szPatchPathPrefix,
|
||||
uint dwFlags
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileIsPatchedArchive(MpqArchiveSafeHandle hMpq);
|
||||
#endregion
|
||||
|
||||
#region Functions for file manipulation
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileHasFile(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szFileName
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileOpenFileEx(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szFileName,
|
||||
uint dwSearchScope,
|
||||
out MpqFileSafeHandle phFile
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern uint SFileGetFileSize(MpqFileSafeHandle hFile, ref uint pdwFileSizeHigh);
|
||||
|
||||
public static unsafe uint SFileGetFilePointer(
|
||||
MpqFileSafeHandle hFile
|
||||
)
|
||||
{
|
||||
if (hFile.IsInvalid || hFile.IsClosed)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
IntPtr handle = hFile.DangerousGetHandle();
|
||||
_TMPQFileHeader* header = (_TMPQFileHeader*)handle.ToPointer();
|
||||
return header->dwFilePos;
|
||||
}
|
||||
|
||||
//public static unsafe uint SFileGetFileSize(
|
||||
// MpqFileSafeHandle hFile
|
||||
// )
|
||||
//{
|
||||
// if (hFile.IsInvalid || hFile.IsClosed)
|
||||
// throw new InvalidOperationException();
|
||||
|
||||
// IntPtr handle = hFile.DangerousGetHandle();
|
||||
// _TMPQFileHeader* header = (_TMPQFileHeader*)handle.ToPointer();
|
||||
// return header->pFileEntry->dwFileSize;
|
||||
//}
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern uint SFileSetFilePointer(
|
||||
MpqFileSafeHandle hFile,
|
||||
uint lFilePos,
|
||||
ref uint plFilePosHigh,
|
||||
uint dwMoveMethod
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileReadFile(
|
||||
MpqFileSafeHandle hFile,
|
||||
IntPtr lpBuffer,
|
||||
uint dwToRead,
|
||||
out uint pdwRead,
|
||||
ref System.Threading.NativeOverlapped lpOverlapped
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileCloseFile(IntPtr hFile);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileCloseFile(MpqFileSafeHandle hFile);
|
||||
|
||||
#region Retrieving info about a file in the archive
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileGetFileInfo(
|
||||
IntPtr hMpqOrFile,
|
||||
SFileInfoClass InfoClass,
|
||||
IntPtr pvFileInfo,
|
||||
uint cbFileInfoSize,
|
||||
out uint pcbLengthNeeded
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileGetFileInfo(
|
||||
MpqArchiveSafeHandle hMpqOrFile,
|
||||
SFileInfoClass InfoClass,
|
||||
IntPtr pvFileInfo,
|
||||
uint cbFileInfoSize,
|
||||
out uint pcbLengthNeeded
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileGetFileInfo(
|
||||
MpqFileSafeHandle hMpqOrFile,
|
||||
SFileInfoClass InfoClass,
|
||||
IntPtr pvFileInfo,
|
||||
uint cbFileInfoSize,
|
||||
out uint pcbLengthNeeded
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileGetFileName(
|
||||
MpqFileSafeHandle hFile,
|
||||
[MarshalAs(UnmanagedType.LPStr)] out string szFileName
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileFreeFileInfo(
|
||||
IntPtr pvFileInfo,
|
||||
SFileInfoClass infoClass
|
||||
);
|
||||
#endregion
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileExtractFile(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szToExtract,
|
||||
[MarshalAs(UnmanagedType.LPTStr)] string szExtracted,
|
||||
uint dwSearchScope
|
||||
);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Functions for file and archive verification
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileGetFileChecksums(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szFileName,
|
||||
out uint pdwCrc32,
|
||||
IntPtr pMD5
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern uint SFileVerifyFile(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szFileName,
|
||||
uint dwFlags
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern int SFileVerifyRawData(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
uint dwWhatToVerify,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szFileName
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern uint SFileVerifyArchive(MpqArchiveSafeHandle hMpq);
|
||||
#endregion
|
||||
|
||||
#region Functions for file searching
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern IntPtr SFileFindFirstFile(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szMask,
|
||||
out _SFILE_FIND_DATA lpFindFileData,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szListFile
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileFindNextFile(
|
||||
IntPtr hFind,
|
||||
[In, Out] ref _SFILE_FIND_DATA lpFindFileData
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileFindClose(IntPtr hFind);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern IntPtr SListFileFindFirstFile(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szListFile,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szMask,
|
||||
[In, Out] ref _SFILE_FIND_DATA lpFindFileData
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SListFileFindNextFile(
|
||||
IntPtr hFind,
|
||||
[In, Out] ref _SFILE_FIND_DATA lpFindFileData
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SListFileFindClose(IntPtr hFind);
|
||||
#endregion
|
||||
|
||||
#region Locale support
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern int SFileEnumLocales(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szFileName,
|
||||
IntPtr plcLocales,
|
||||
ref uint pdwMaxLocales,
|
||||
uint dwSearchScope
|
||||
);
|
||||
#endregion
|
||||
|
||||
#region Support for adding files to the MPQ
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileCreateFile(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szArchiveName,
|
||||
ulong fileTime,
|
||||
uint dwFileSize,
|
||||
uint lcLocale,
|
||||
uint dwFlags,
|
||||
out IntPtr phFile
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileWriteFile(
|
||||
MpqFileSafeHandle hFile,
|
||||
IntPtr pvData,
|
||||
uint dwSize,
|
||||
uint dwCompression
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileFinishFile(MpqFileSafeHandle hFile);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileAddFileEx(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPTStr)] string szFileName,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szArchivedName,
|
||||
uint dwFlags,
|
||||
uint dwCompression,
|
||||
uint dwCompressionNext
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileAddFile(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPTStr)] string szFileName,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szArchivedName,
|
||||
uint dwFlags
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileAddWave(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPTStr)] string szFileName,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szArchivedName,
|
||||
uint dwFlags,
|
||||
uint dwQuality
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileRemoveFile(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szFileName,
|
||||
uint dwSearchScope
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileRenameFile(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szOldFileName,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szNewFileName
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileSetFileLocale(
|
||||
MpqFileSafeHandle hFile,
|
||||
uint lcNewLocale
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileSetDataCompression(uint DataCompression);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileSetAddFileCallback(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
SFILE_ADDFILE_CALLBACK AddFileCB,
|
||||
IntPtr pvUserData
|
||||
);
|
||||
#endregion
|
||||
|
||||
#region Compression and decompression
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern int SCompImplode(
|
||||
IntPtr pvOutBuffer,
|
||||
ref int pcbOutBuffer,
|
||||
IntPtr pvInBuffer,
|
||||
int cbInBuffer
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern int SCompExplode(
|
||||
IntPtr pvOutBuffer,
|
||||
ref int pcbOutBuffer,
|
||||
IntPtr pvInBuffer,
|
||||
int cbInBuffer
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern int SCompCompress(
|
||||
IntPtr pvOutBuffer,
|
||||
ref int pcbOutBuffer,
|
||||
IntPtr pvInBuffer,
|
||||
int cbInBuffer,
|
||||
uint uCompressionMask,
|
||||
int nCmpType,
|
||||
int nCmpLevel
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern int SCompDecompress(
|
||||
IntPtr pvOutBuffer,
|
||||
ref int pcbOutBuffer,
|
||||
IntPtr pvInBuffer,
|
||||
int cbInBuffer
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern int SCompDecompress2(
|
||||
IntPtr pvOutBuffer,
|
||||
ref int pcbOutBuffer,
|
||||
IntPtr pvInBuffer,
|
||||
int cbInBuffer
|
||||
);
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#pragma warning disable 0169,0649
|
||||
internal struct SFILE_CREATE_MPQ
|
||||
{
|
||||
public uint cbSize;
|
||||
public uint dwMpqVersion;
|
||||
private IntPtr pvUserData;
|
||||
private uint cbUserData;
|
||||
public uint dwStreamFlags;
|
||||
public uint dwFileFlags1;
|
||||
public uint dwFileFlags2;
|
||||
public uint dwAttrFlags;
|
||||
public uint dwSectorSize;
|
||||
public uint dwRawChunkSize;
|
||||
public uint dwMaxFileCount;
|
||||
}
|
||||
|
||||
internal unsafe struct _SFILE_FIND_DATA
|
||||
{
|
||||
public fixed char cFileName[260]; // Full name of the found file
|
||||
|
||||
public IntPtr szPlainName; // Plain name of the found file
|
||||
public uint dwHashIndex; // Hash table index for the file
|
||||
public uint dwBlockIndex; // Block table index for the file
|
||||
public uint dwFileSize; // File size in bytes
|
||||
public uint dwFileFlags; // MPQ file flags
|
||||
public uint dwCompSize; // Compressed file size
|
||||
public uint dwFileTimeLo; // Low 32-bits of the file time (0 if not present)
|
||||
public uint dwFileTimeHi; // High 32-bits of the file time (0 if not present)
|
||||
public uint lcLocale; // Locale version
|
||||
}
|
||||
|
||||
internal unsafe struct _TFileEntry
|
||||
{
|
||||
public ulong FileNameHash;
|
||||
public ulong ByteOffset;
|
||||
public ulong FileTime;
|
||||
public uint dwHashIndex;
|
||||
public uint dwFileSize;
|
||||
public uint dwCmpSize;
|
||||
public uint dwFlags;
|
||||
public ushort lcLocale;
|
||||
public ushort wPlatform;
|
||||
public uint dwCrc32;
|
||||
public fixed byte md5[16];
|
||||
public IntPtr szFileName;
|
||||
}
|
||||
|
||||
// Provides enough of _TMPQFile to get to the file size and current position.
|
||||
internal unsafe struct _TMPQFileHeader
|
||||
{
|
||||
public IntPtr pStream;
|
||||
public IntPtr ha;
|
||||
public _TFileEntry* pFileEntry;
|
||||
public uint dwFileKey;
|
||||
public uint dwFilePos;
|
||||
}
|
||||
#pragma warning restore 0169,0649
|
||||
|
||||
}
|
||||
70
BurnOutSharp/External/StormLibSharp/Native/SFileInfoClass.cs
vendored
Normal file
70
BurnOutSharp/External/StormLibSharp/Native/SFileInfoClass.cs
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace StormLibSharp.Native
|
||||
{
|
||||
internal enum SFileInfoClass
|
||||
{
|
||||
// Info classes for archives
|
||||
SFileMpqFileName, // Name of the archive file (TCHAR [])
|
||||
SFileMpqStreamBitmap, // Array of bits, each bit means availability of one block (BYTE [])
|
||||
SFileMpqUserDataOffset, // Offset of the user data header (ULONGLONG)
|
||||
SFileMpqUserDataHeader, // Raw (unfixed) user data header (TMPQUserData)
|
||||
SFileMpqUserData, // MPQ USer data, without the header (BYTE [])
|
||||
SFileMpqHeaderOffset, // Offset of the MPQ header (ULONGLONG)
|
||||
SFileMpqHeaderSize, // Fixed size of the MPQ header
|
||||
SFileMpqHeader, // Raw (unfixed) archive header (TMPQHeader)
|
||||
SFileMpqHetTableOffset, // Offset of the HET table, relative to MPQ header (ULONGLONG)
|
||||
SFileMpqHetTableSize, // Compressed size of the HET table (ULONGLONG)
|
||||
SFileMpqHetHeader, // HET table header (TMPQHetHeader)
|
||||
SFileMpqHetTable, // HET table as pointer. Must be freed using SFileFreeFileInfo
|
||||
SFileMpqBetTableOffset, // Offset of the BET table, relative to MPQ header (ULONGLONG)
|
||||
SFileMpqBetTableSize, // Compressed size of the BET table (ULONGLONG)
|
||||
SFileMpqBetHeader, // BET table header, followed by the flags (TMPQBetHeader + DWORD[])
|
||||
SFileMpqBetTable, // BET table as pointer. Must be freed using SFileFreeFileInfo
|
||||
SFileMpqHashTableOffset, // Hash table offset, relative to MPQ header (ULONGLONG)
|
||||
SFileMpqHashTableSize64, // Compressed size of the hash table (ULONGLONG)
|
||||
SFileMpqHashTableSize, // Size of the hash table, in entries (DWORD)
|
||||
SFileMpqHashTable, // Raw (unfixed) hash table (TMPQBlock [])
|
||||
SFileMpqBlockTableOffset, // Block table offset, relative to MPQ header (ULONGLONG)
|
||||
SFileMpqBlockTableSize64, // Compressed size of the block table (ULONGLONG)
|
||||
SFileMpqBlockTableSize, // Size of the block table, in entries (DWORD)
|
||||
SFileMpqBlockTable, // Raw (unfixed) block table (TMPQBlock [])
|
||||
SFileMpqHiBlockTableOffset, // Hi-block table offset, relative to MPQ header (ULONGLONG)
|
||||
SFileMpqHiBlockTableSize64, // Compressed size of the hi-block table (ULONGLONG)
|
||||
SFileMpqHiBlockTable, // The hi-block table (USHORT [])
|
||||
SFileMpqSignatures, // Signatures present in the MPQ (DWORD)
|
||||
SFileMpqStrongSignatureOffset, // Byte offset of the strong signature, relative to begin of the file (ULONGLONG)
|
||||
SFileMpqStrongSignatureSize, // Size of the strong signature (DWORD)
|
||||
SFileMpqStrongSignature, // The strong signature (BYTE [])
|
||||
SFileMpqArchiveSize64, // Archive size from the header (ULONGLONG)
|
||||
SFileMpqArchiveSize, // Archive size from the header (DWORD)
|
||||
SFileMpqMaxFileCount, // Max number of files in the archive (DWORD)
|
||||
SFileMpqFileTableSize, // Number of entries in the file table (DWORD)
|
||||
SFileMpqSectorSize, // Sector size (DWORD)
|
||||
SFileMpqNumberOfFiles, // Number of files (DWORD)
|
||||
SFileMpqRawChunkSize, // Size of the raw data chunk for MD5
|
||||
SFileMpqStreamFlags, // Stream flags (DWORD)
|
||||
SFileMpqIsReadOnly, // Nonzero if the MPQ is read only (DWORD)
|
||||
|
||||
// Info classes for files
|
||||
SFileInfoPatchChain, // Chain of patches where the file is (TCHAR [])
|
||||
SFileInfoFileEntry, // The file entry for the file (TFileEntry)
|
||||
SFileInfoHashEntry, // Hash table entry for the file (TMPQHash)
|
||||
SFileInfoHashIndex, // Index of the hash table entry (DWORD)
|
||||
SFileInfoNameHash1, // The first name hash in the hash table (DWORD)
|
||||
SFileInfoNameHash2, // The second name hash in the hash table (DWORD)
|
||||
SFileInfoNameHash3, // 64-bit file name hash for the HET/BET tables (ULONGLONG)
|
||||
SFileInfoLocale, // File locale (DWORD)
|
||||
SFileInfoFileIndex, // Block index (DWORD)
|
||||
SFileInfoByteOffset, // File position in the archive (ULONGLONG)
|
||||
SFileInfoFileTime, // File time (ULONGLONG)
|
||||
SFileInfoFileSize, // Size of the file (DWORD)
|
||||
SFileInfoCompressedSize, // Compressed file size (DWORD)
|
||||
SFileInfoFlags, // File flags from (DWORD)
|
||||
SFileInfoEncryptionKey, // File encryption key
|
||||
SFileInfoEncryptionKeyRaw, // Unfixed value of the file key
|
||||
}
|
||||
}
|
||||
26
BurnOutSharp/External/StormLibSharp/Native/SFileOpenArchiveFlags.cs
vendored
Normal file
26
BurnOutSharp/External/StormLibSharp/Native/SFileOpenArchiveFlags.cs
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace StormLibSharp.Native
|
||||
{
|
||||
[Flags]
|
||||
internal enum SFileOpenArchiveFlags : uint
|
||||
{
|
||||
None = 0,
|
||||
TypeIsFile = None,
|
||||
TypeIsMemoryMapped = 1,
|
||||
TypeIsHttp = 2,
|
||||
|
||||
AccessReadOnly = 0x100,
|
||||
AccessReadWriteShare = 0x200,
|
||||
AccessUseBitmap = 0x400,
|
||||
|
||||
DontOpenListfile = 0x10000,
|
||||
DontOpenAttributes = 0x20000,
|
||||
DontSearchHeader = 0x40000,
|
||||
ForceVersion1 = 0x80000,
|
||||
CheckSectorCRC = 0x100000,
|
||||
}
|
||||
}
|
||||
60
BurnOutSharp/External/StormLibSharp/Native/Win32Methods.cs
vendored
Normal file
60
BurnOutSharp/External/StormLibSharp/Native/Win32Methods.cs
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO.MemoryMappedFiles;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace StormLibSharp.Native
|
||||
{
|
||||
internal static class Win32Methods
|
||||
{
|
||||
[DllImport("kernel32", ExactSpelling = false, SetLastError = true)]
|
||||
public static extern uint GetMappedFileName(
|
||||
IntPtr hProcess,
|
||||
IntPtr fileHandle,
|
||||
IntPtr lpFilename,
|
||||
uint nSize
|
||||
);
|
||||
|
||||
[DllImport("kernel32", ExactSpelling = false, SetLastError = true)]
|
||||
public static extern uint GetFinalPathNameByHandle(
|
||||
IntPtr hFile,
|
||||
IntPtr lpszFilePath,
|
||||
uint cchFilePath,
|
||||
uint dwFlags
|
||||
);
|
||||
|
||||
[DllImport("kernel32", SetLastError = false, ExactSpelling = false)]
|
||||
public static extern int GetLastError();
|
||||
|
||||
public static string GetFileNameOfMemoryMappedFile(MemoryMappedFile file)
|
||||
{
|
||||
const uint size = 522;
|
||||
IntPtr path = Marshal.AllocCoTaskMem(unchecked((int)size)); // MAX_PATH + 1 char
|
||||
|
||||
string result = null;
|
||||
try
|
||||
{
|
||||
// constant 0x2 = VOLUME_NAME_NT
|
||||
uint test = GetFinalPathNameByHandle(file.SafeMemoryMappedFileHandle.DangerousGetHandle(), path, size, 0x2);
|
||||
if (test != 0)
|
||||
throw new Win32Exception();
|
||||
|
||||
result = Marshal.PtrToStringAuto(path);
|
||||
}
|
||||
catch
|
||||
{
|
||||
uint test = GetMappedFileName(Process.GetCurrentProcess().Handle, file.SafeMemoryMappedFileHandle.DangerousGetHandle(), path, size);
|
||||
if (test != 0)
|
||||
throw new Win32Exception();
|
||||
|
||||
result = Marshal.PtrToStringAuto(path);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
217
BurnOutSharp/External/psxt001z/LibCrypt.cs
vendored
217
BurnOutSharp/External/psxt001z/LibCrypt.cs
vendored
@@ -1,139 +1,128 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace BurnOutSharp.External.psxt001z
|
||||
{
|
||||
/// <summary>
|
||||
/// LibCrypt detection code
|
||||
/// Originally written by Dremora: https://github.com/Dremora/psxt001z
|
||||
/// Ported and changed by darksabre76
|
||||
/// </summary>
|
||||
public class LibCrypt
|
||||
/// <summary>
|
||||
/// LibCrypt detection code
|
||||
/// Originally written by Dremora: https://github.com/Dremora/psxt001z
|
||||
/// Ported and changed by darksabre76
|
||||
/// </summary>
|
||||
public class LibCrypt
|
||||
{
|
||||
public static bool CheckSubfile(string subFilePath)
|
||||
{
|
||||
// opening .sub
|
||||
FileStream subfile;
|
||||
try
|
||||
{
|
||||
subfile = File.OpenRead(subFilePath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine($"Error opening {subFilePath}");
|
||||
return false;
|
||||
}
|
||||
// Check the file exists first
|
||||
if (!File.Exists(subFilePath))
|
||||
return false;
|
||||
|
||||
// checking extension
|
||||
string ext = Path.GetExtension(subFilePath).TrimStart('.').ToLowerInvariant();
|
||||
if (ext != "sub")
|
||||
{
|
||||
Console.WriteLine($"{ext}: unknown file extension");
|
||||
return false;
|
||||
}
|
||||
|
||||
// filesize
|
||||
long size = subfile.Length;
|
||||
if (size % 96 != 0)
|
||||
{
|
||||
Console.WriteLine($"{subFilePath}: wrong size");
|
||||
return false;
|
||||
}
|
||||
// Check the extension is a subfile
|
||||
string ext = Path.GetExtension(subFilePath).TrimStart('.').ToLowerInvariant();
|
||||
if (ext != "sub")
|
||||
return false;
|
||||
|
||||
return CheckSubfile(subfile);
|
||||
}
|
||||
// Open and check the subfile for LibCrypt
|
||||
try
|
||||
{
|
||||
using (FileStream subfile = File.OpenRead(subFilePath))
|
||||
{
|
||||
return CheckSubfile(subfile);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CheckSubfile(Stream subfile)
|
||||
{
|
||||
// Variables
|
||||
byte[] buffer = new byte[16];
|
||||
byte[] sub = new byte[16];
|
||||
int tpos = 0;
|
||||
uint sector, psectors = 0;
|
||||
long size = subfile.Length;
|
||||
public static bool CheckSubfile(Stream subfile)
|
||||
{
|
||||
// Check the length is valid for subfiles
|
||||
long size = subfile.Length;
|
||||
if (size % 96 != 0)
|
||||
return false;
|
||||
|
||||
for (sector = 150; sector < ((size / 96) + 150); sector++)
|
||||
{
|
||||
subfile.Seek(12, SeekOrigin.Current);
|
||||
if (subfile.Read(buffer, 0, 12) == 0)
|
||||
return true;
|
||||
// Persistent values
|
||||
byte[] buffer = new byte[16];
|
||||
byte[] sub = new byte[16];
|
||||
int tpos = 0;
|
||||
int modifiedSectors = 0;
|
||||
|
||||
subfile.Seek(72, SeekOrigin.Current);
|
||||
// Check each sector for modifications
|
||||
for (uint sector = 150; sector < ((size / 96) + 150); sector++)
|
||||
{
|
||||
subfile.Seek(12, SeekOrigin.Current);
|
||||
if (subfile.Read(buffer, 0, 12) == 0)
|
||||
return modifiedSectors != 0;
|
||||
|
||||
// New track
|
||||
if ((btoi(buffer[1]) == (btoi(sub[1]) + 1)) && (buffer[2] == 0 || buffer[2] == 1))
|
||||
{
|
||||
Array.Copy(buffer, sub, 6);
|
||||
tpos = ((btoi((byte)(buffer[3] * 60)) + btoi(buffer[4])) * 75) + btoi(buffer[5]);
|
||||
}
|
||||
subfile.Seek(72, SeekOrigin.Current);
|
||||
|
||||
// New index
|
||||
else if (btoi(buffer[2]) == (btoi(sub[2]) + 1) && buffer[1] == sub[1])
|
||||
{
|
||||
Array.Copy(buffer, 2, sub, 2, 4);
|
||||
tpos = ((btoi((byte)(buffer[3] * 60)) + btoi(buffer[4])) * 75) + btoi(buffer[5]);
|
||||
}
|
||||
// New track
|
||||
if ((btoi(buffer[1]) == (btoi(sub[1]) + 1)) && (buffer[2] == 0 || buffer[2] == 1))
|
||||
{
|
||||
Array.Copy(buffer, sub, 6);
|
||||
tpos = ((btoi((byte)(buffer[3] * 60)) + btoi(buffer[4])) * 75) + btoi(buffer[5]);
|
||||
}
|
||||
|
||||
// MSF1 [3-5]
|
||||
else
|
||||
{
|
||||
if (sub[2] == 0)
|
||||
tpos--;
|
||||
else
|
||||
tpos++;
|
||||
// New index
|
||||
else if (btoi(buffer[2]) == (btoi(sub[2]) + 1) && buffer[1] == sub[1])
|
||||
{
|
||||
Array.Copy(buffer, 2, sub, 2, 4);
|
||||
tpos = ((btoi((byte)(buffer[3] * 60)) + btoi(buffer[4])) * 75) + btoi(buffer[5]);
|
||||
}
|
||||
|
||||
sub[3] = itob((byte)(tpos / 60 / 75));
|
||||
sub[4] = itob((byte)((tpos / 75) % 60));
|
||||
sub[5] = itob((byte)(tpos % 75));
|
||||
}
|
||||
// MSF1 [3-5]
|
||||
else
|
||||
{
|
||||
if (sub[2] == 0)
|
||||
tpos--;
|
||||
else
|
||||
tpos++;
|
||||
|
||||
// MSF2 [7-9]
|
||||
sub[7] = itob((byte)(sector / 60 / 75));
|
||||
sub[8] = itob((byte)((sector / 75) % 60));
|
||||
sub[9] = itob((byte)(sector % 75));
|
||||
sub[3] = itob((byte)(tpos / 60 / 75));
|
||||
sub[4] = itob((byte)((tpos / 75) % 60));
|
||||
sub[5] = itob((byte)(tpos % 75));
|
||||
}
|
||||
|
||||
// CRC-16 [10-11]
|
||||
ushort crc = CRC16.Calculate(sub, 0, 10);
|
||||
byte[] crcBytes = BitConverter.GetBytes(crc);
|
||||
sub[10] = crcBytes[0];
|
||||
sub[11] = crcBytes[1];
|
||||
// MSF2 [7-9]
|
||||
sub[7] = itob((byte)(sector / 60 / 75));
|
||||
sub[8] = itob((byte)((sector / 75) % 60));
|
||||
sub[9] = itob((byte)(sector % 75));
|
||||
|
||||
// TODO: This *was* a memcmp, but that's harder to do. Fix this for C# later
|
||||
if (buffer[10] != sub[10] && buffer[11] != sub[11] && (buffer[3] != sub[3] || buffer[7] != sub[7] || buffer[4] != sub[4] || buffer[8] != sub[8] || buffer[5] != sub[5] || buffer[9] != sub[9]))
|
||||
{
|
||||
if (buffer[10] != sub[10] || buffer[11] != sub[11] || buffer[3] != sub[3] || buffer[7] != sub[7] || buffer[4] != sub[4] || buffer[8] != sub[8] || buffer[5] != sub[5] || buffer[9] != sub[9])
|
||||
{
|
||||
Console.Write($"MSF: {sub[7]:x}:{sub[8]:x}:{sub[9]:x} Q-Data: {buffer[0]:x}{buffer[1]:x}{buffer[2]:x} {buffer[3]:x}:{buffer[4]:x}:{buffer[5]:x} {buffer[6]:x} {buffer[7]:x}:{buffer[8]:x}:{buffer[9]:x} {buffer[10]:x}{buffer[11]:x} xor {crc ^ ((buffer[10] << 8) + buffer[11]):x} % {CRC16.Calculate(buffer, 0, 10) ^ ((buffer[10] << 8) + buffer[11]):x}");
|
||||
//Console.Write("\nMSF: %02x:%02x:%02x Q-Data: %02x%02x%02x %02x:%02x:%02x %02x %02x:%02x:%02x %02x%02x", sub[7], sub[8], sub[9], sub[0], sub[1], sub[2], sub[3], sub[4], sub[5], sub[6], sub[7], sub[8], sub[9], sub[10], sub[11]);
|
||||
if (buffer[3] != sub[3] && buffer[7] != sub[7] && buffer[4] == sub[4] && buffer[8] == sub[8] && buffer[5] == sub[5] && buffer[9] == sub[9])
|
||||
Console.Write($" P1 xor {buffer[3] ^ sub[3]:x} {buffer[7] ^ sub[7]:x}");
|
||||
else if (buffer[3] == sub[3] && buffer[7] == sub[7] && buffer[4] != sub[4] && buffer[8] != sub[8] && buffer[5] == sub[5] && buffer[9] == sub[9])
|
||||
Console.Write($" P2 xor {buffer[4] ^ sub[4]:x} {buffer[8] ^ sub[8]:x}");
|
||||
else if (buffer[3] == sub[3] && buffer[7] == sub[7] && buffer[4] == sub[4] && buffer[8] == sub[8] && buffer[5] != sub[5] && buffer[9] != sub[9])
|
||||
Console.Write($" P3 xor {buffer[5] ^ sub[5]:x} {buffer[9] ^ sub[9]:x}");
|
||||
else
|
||||
Console.Write(" ?");
|
||||
// CRC-16 [10-11]
|
||||
ushort crc = CRC16.Calculate(sub, 0, 10);
|
||||
byte[] crcBytes = BitConverter.GetBytes(crc);
|
||||
sub[10] = crcBytes[0];
|
||||
sub[11] = crcBytes[1];
|
||||
|
||||
Console.Write("\n");
|
||||
psectors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If any byte (except position 6) is different, it's a modified sector
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
if (i == 6)
|
||||
continue;
|
||||
|
||||
Console.WriteLine($"Number of modified sectors: {psectors}");
|
||||
return true;
|
||||
}
|
||||
if (buffer[i] != sub[i])
|
||||
{
|
||||
modifiedSectors++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static byte btoi(byte b)
|
||||
{
|
||||
/* BCD to u_char */
|
||||
return (byte)((b) / 16 * 10 + (b) % 16);
|
||||
}
|
||||
return modifiedSectors != 0;
|
||||
}
|
||||
|
||||
private static byte itob(byte i)
|
||||
{
|
||||
/* u_char to BCD */
|
||||
return (byte)((i) / 10 * 16 + (i) % 10);
|
||||
}
|
||||
}
|
||||
private static byte btoi(byte b)
|
||||
{
|
||||
/* BCD to u_char */
|
||||
return (byte)((b) / 16 * 10 + (b) % 16);
|
||||
}
|
||||
|
||||
private static byte itob(byte i)
|
||||
{
|
||||
/* u_char to BCD */
|
||||
return (byte)((i) / 10 * 16 + (i) % 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
115
BurnOutSharp/FileType/BFPK.cs
Normal file
115
BurnOutSharp/FileType/BFPK.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using SharpCompress.Compressors;
|
||||
using SharpCompress.Compressors.Deflate;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class BFPK
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
if (magic.StartsWith(new byte[] { 0x42, 0x46, 0x50, 0x4b }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream)
|
||||
{
|
||||
// If the BFPK file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true))
|
||||
{
|
||||
br.ReadBytes(4); // Skip magic number
|
||||
|
||||
int version = br.ReadInt32();
|
||||
int files = br.ReadInt32();
|
||||
long current = br.BaseStream.Position;
|
||||
|
||||
for (int i = 0; i < files; i++)
|
||||
{
|
||||
br.BaseStream.Seek(current, SeekOrigin.Begin);
|
||||
|
||||
int nameSize = br.ReadInt32();
|
||||
string name = new string(br.ReadChars(nameSize));
|
||||
|
||||
uint uncompressedSize = br.ReadUInt32();
|
||||
int offset = br.ReadInt32();
|
||||
|
||||
current = br.BaseStream.Position;
|
||||
|
||||
br.BaseStream.Seek(offset, SeekOrigin.Begin);
|
||||
uint compressedSize = br.ReadUInt32();
|
||||
|
||||
// Some files can lack the length prefix
|
||||
if (compressedSize > br.BaseStream.Length)
|
||||
{
|
||||
br.BaseStream.Seek(-4, SeekOrigin.Current);
|
||||
compressedSize = uncompressedSize;
|
||||
}
|
||||
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
string tempFile = Path.Combine(tempPath, name);
|
||||
if (!Directory.Exists(Path.GetDirectoryName(tempFile)))
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(tempFile));
|
||||
|
||||
if (compressedSize == uncompressedSize)
|
||||
{
|
||||
using (FileStream fs = File.OpenWrite(tempFile))
|
||||
{
|
||||
fs.Write(br.ReadBytes((int)uncompressedSize), 0, (int)uncompressedSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (FileStream fs = File.OpenWrite(tempFile))
|
||||
{
|
||||
try
|
||||
{
|
||||
ZlibStream zs = new ZlibStream(br.BaseStream, CompressionMode.Decompress);
|
||||
zs.CopyTo(fs);
|
||||
}
|
||||
catch (ZlibException)
|
||||
{
|
||||
br.BaseStream.Seek(offset + 4, SeekOrigin.Begin);
|
||||
fs.Write(br.ReadBytes((int)compressedSize), 0, (int)compressedSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
br.BaseStream.Seek(current, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
|
||||
// Collect and format all found protections
|
||||
var protections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Remove temporary path references
|
||||
Utilities.StripFromKeys(protections, tempPath);
|
||||
|
||||
return protections;
|
||||
}
|
||||
catch { }
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
62
BurnOutSharp/FileType/BZip2.cs
Normal file
62
BurnOutSharp/FileType/BZip2.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SharpCompress.Compressors;
|
||||
using SharpCompress.Compressors.BZip2;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class BZip2
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
if (magic.StartsWith(new byte[] { 0x42, 0x52, 0x68 }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream)
|
||||
{
|
||||
// If the 7-zip file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (BZip2Stream bz2File = new BZip2Stream(stream, CompressionMode.Decompress, true))
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
string tempFile = Path.Combine(tempPath, Guid.NewGuid().ToString());
|
||||
using (FileStream fs = File.OpenWrite(tempFile))
|
||||
{
|
||||
bz2File.CopyTo(fs);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// Collect and format all found protections
|
||||
var protections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Remove temporary path references
|
||||
Utilities.StripFromKeys(protections, tempPath);
|
||||
|
||||
return protections;
|
||||
}
|
||||
catch { }
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
298
BurnOutSharp/FileType/Executable.cs
Normal file
298
BurnOutSharp/FileType/Executable.cs
Normal file
@@ -0,0 +1,298 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BurnOutSharp.PackerType;
|
||||
using BurnOutSharp.ProtectionType;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class Executable
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
// DOS MZ executable file format (and descendants)
|
||||
if (magic.StartsWith(new byte[] { 0x4d, 0x5a }))
|
||||
return true;
|
||||
|
||||
// Executable and Linkable Format
|
||||
if (magic.StartsWith(new byte[] { 0x7f, 0x45, 0x4c, 0x46 }))
|
||||
return true;
|
||||
|
||||
// Mach-O binary (32-bit)
|
||||
if (magic.StartsWith(new byte[] { 0xfe, 0xed, 0xfa, 0xce }))
|
||||
return true;
|
||||
|
||||
// Mach-O binary (32-bit, reverse byte ordering scheme)
|
||||
if (magic.StartsWith(new byte[] { 0xce, 0xfa, 0xed, 0xfe }))
|
||||
return true;
|
||||
|
||||
// Mach-O binary (64-bit)
|
||||
if (magic.StartsWith(new byte[] { 0xfe, 0xed, 0xfa, 0xcf }))
|
||||
return true;
|
||||
|
||||
// Mach-O binary (64-bit, reverse byte ordering scheme)
|
||||
if (magic.StartsWith(new byte[] { 0xcf, 0xfa, 0xed, 0xfe }))
|
||||
return true;
|
||||
|
||||
// Prefrred Executable File Format
|
||||
if (magic.StartsWith(new byte[] { 0x4a, 0x6f, 0x79, 0x21, 0x70, 0x65, 0x66, 0x66 }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file = null)
|
||||
{
|
||||
// Load the current file content
|
||||
byte[] fileContent = null;
|
||||
using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true))
|
||||
{
|
||||
fileContent = br.ReadBytes((int)stream.Length);
|
||||
}
|
||||
|
||||
// If we can, seek to the beginning of the stream
|
||||
if (stream.CanSeek)
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
// Files can be protected in multiple ways
|
||||
var protections = new Dictionary<string, List<string>>();
|
||||
var subProtections = new Dictionary<string, List<string>>();
|
||||
string protection;
|
||||
|
||||
#region Protections
|
||||
|
||||
// 3PLock
|
||||
protection = ThreePLock.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// 321Studios Online Activation
|
||||
protection = ThreeTwoOneStudios.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// ActiveMARK
|
||||
protection = ActiveMARK.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// Alpha-ROM
|
||||
protection = AlphaROM.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// Cactus Data Shield
|
||||
protection = CactusDataShield.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// CD-Cops
|
||||
protection = CDCops.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// CD-Lock
|
||||
protection = CDLock.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// CDSHiELD SE
|
||||
protection = CDSHiELDSE.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// CD Check
|
||||
protection = CDCheck.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// Cenega ProtectDVD
|
||||
protection = CengaProtectDVD.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// Code Lock
|
||||
protection = CodeLock.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// CopyKiller
|
||||
protection = CopyKiller.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// DVD-Cops
|
||||
protection = DVDCops.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// EA Protections
|
||||
protection = ElectronicArts.CheckContents(file, fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// Games for Windows - Live
|
||||
protection = GFWL.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// Impulse Reactor
|
||||
protection = ImpulseReactor.CheckContents(file, fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// Inno Setup
|
||||
protection = InnoSetup.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// INTENIUM Trial & Buy Protection
|
||||
protection = Intenium.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// JoWooD X-Prot
|
||||
protection = JoWooDXProt.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// Key-Lock (Dongle)
|
||||
protection = KeyLock.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// LaserLock
|
||||
protection = LaserLock.CheckContents(file, fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// MediaMax CD-3
|
||||
protection = MediaMaxCD3.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// ProtectDisc
|
||||
protection = ProtectDisc.CheckContents(file, fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// Ring PROTECH
|
||||
protection = RingPROTECH.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// SafeDisc / SafeCast
|
||||
protection = SafeDisc.CheckContents(file, fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// SafeLock
|
||||
protection = SafeLock.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// SecuROM
|
||||
protection = SecuROM.CheckContents(file, fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// SmartE
|
||||
protection = SmartE.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// SolidShield
|
||||
protection = SolidShield.CheckContents(file, fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// StarForce
|
||||
protection = StarForce.CheckContents(file, fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// SVK Protector
|
||||
protection = SVKProtector.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// Sysiphus / Sysiphus DVD
|
||||
protection = Sysiphus.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// TAGES
|
||||
protection = Tages.CheckContents(file, fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// VOB ProtectCD/DVD
|
||||
protection = VOBProtectCDDVD.CheckContents(file, fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// Wise Installer
|
||||
subProtections = WiseInstaller.CheckContents(scanner, file, fileContent);
|
||||
if (subProtections != null && subProtections.Count > 0)
|
||||
Utilities.AppendToDictionary(protections, subProtections);
|
||||
|
||||
// WTM CD Protect
|
||||
protection = WTMCDProtect.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// XCP 1/2
|
||||
protection = XCP.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// Xtreme-Protector
|
||||
protection = XtremeProtector.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Packers
|
||||
|
||||
// If we're looking for packers too, run scans
|
||||
if (scanner.ScanPackers)
|
||||
{
|
||||
|
||||
// Armadillo
|
||||
protection = Armadillo.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// dotFuscator
|
||||
protection = dotFuscator.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// EXE Stealth
|
||||
protection = EXEStealth.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// NSIS
|
||||
protection = NSIS.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// PE Compact
|
||||
protection = PECompact.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// UPX
|
||||
protection = UPX.CheckContents(fileContent, scanner.IncludePosition);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
}
|
||||
65
BurnOutSharp/FileType/GZIP.cs
Normal file
65
BurnOutSharp/FileType/GZIP.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.GZip;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class GZIP
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
if (magic.StartsWith(new byte[] { 0x1f, 0x8b }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream)
|
||||
{
|
||||
// If the gzip file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (GZipArchive zipFile = GZipArchive.Open(stream))
|
||||
{
|
||||
foreach (var entry in zipFile.Entries)
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
// Collect and format all found protections
|
||||
var protections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Remove temporary path references
|
||||
Utilities.StripFromKeys(protections, tempPath);
|
||||
|
||||
return protections;
|
||||
}
|
||||
catch { }
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
296
BurnOutSharp/FileType/IniFile.cs
Normal file
296
BurnOutSharp/FileType/IniFile.cs
Normal file
@@ -0,0 +1,296 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
public class IniFile : IDictionary<string, string>
|
||||
{
|
||||
private Dictionary<string, string> _keyValuePairs = new Dictionary<string, string>();
|
||||
|
||||
public string this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_keyValuePairs == null)
|
||||
_keyValuePairs = new Dictionary<string, string>();
|
||||
|
||||
key = key.ToLowerInvariant();
|
||||
if (_keyValuePairs.ContainsKey(key))
|
||||
return _keyValuePairs[key];
|
||||
|
||||
return null;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_keyValuePairs == null)
|
||||
_keyValuePairs = new Dictionary<string, string>();
|
||||
|
||||
key = key.ToLowerInvariant();
|
||||
_keyValuePairs[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an empty INI file
|
||||
/// </summary>
|
||||
public IniFile()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populate an INI file from path
|
||||
/// </summary>
|
||||
public IniFile(string path)
|
||||
{
|
||||
this.Parse(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populate an INI file from stream
|
||||
/// </summary>
|
||||
public IniFile(Stream stream)
|
||||
{
|
||||
this.Parse(stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add or update a key and value to the INI file
|
||||
/// </summary>
|
||||
public void AddOrUpdate(string key, string value)
|
||||
{
|
||||
_keyValuePairs[key.ToLowerInvariant()] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a key from the INI file
|
||||
/// </summary>
|
||||
public void Remove(string key)
|
||||
{
|
||||
_keyValuePairs.Remove(key.ToLowerInvariant());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read an INI file based on the path
|
||||
/// </summary>
|
||||
public bool Parse(string path)
|
||||
{
|
||||
// If we don't have a file, we can't read it
|
||||
if (!File.Exists(path))
|
||||
return false;
|
||||
|
||||
using (var fileStream = File.OpenRead(path))
|
||||
{
|
||||
return Parse(fileStream);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read an INI file from a stream
|
||||
/// </summary>
|
||||
public bool Parse(Stream stream)
|
||||
{
|
||||
// If the stream is invalid or unreadable, we can't process it
|
||||
if (stream == null || !stream.CanRead || stream.Position >= stream.Length - 1)
|
||||
return false;
|
||||
|
||||
// Keys are case-insensitive by default
|
||||
try
|
||||
{
|
||||
using (StreamReader sr = new StreamReader(stream))
|
||||
{
|
||||
string section = string.Empty;
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
string line = sr.ReadLine().Trim();
|
||||
|
||||
// Comments start with ';'
|
||||
if (line.StartsWith(";"))
|
||||
{
|
||||
// No-op, we don't process comments
|
||||
}
|
||||
|
||||
// Section titles are surrounded by square brackets
|
||||
else if (line.StartsWith("["))
|
||||
{
|
||||
section = line.TrimStart('[').TrimEnd(']');
|
||||
}
|
||||
|
||||
// Valid INI lines are in the format key=value
|
||||
else if (line.Contains("="))
|
||||
{
|
||||
// Split the line by '=' for key-value pairs
|
||||
string[] data = line.Split('=');
|
||||
|
||||
// If the value field contains an '=', we need to put them back in
|
||||
string key = data[0].Trim();
|
||||
string value = string.Join("=", data.Skip(1)).Trim();
|
||||
|
||||
// Section names are prepended to the key with a '.' separating
|
||||
if (!string.IsNullOrEmpty(section))
|
||||
key = $"{section}.{key}";
|
||||
|
||||
// Set or overwrite keys in the returned dictionary
|
||||
_keyValuePairs[key.ToLowerInvariant()] = value;
|
||||
}
|
||||
|
||||
// All other lines are ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was, just catch and return
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write an INI file to a path
|
||||
/// </summary>
|
||||
public bool Write(string path)
|
||||
{
|
||||
// If we don't have a valid dictionary with values, we can't write out
|
||||
if (_keyValuePairs == null || _keyValuePairs.Count == 0)
|
||||
return false;
|
||||
|
||||
using (var fileStream = File.OpenWrite(path))
|
||||
{
|
||||
return Write(fileStream);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write an INI file to a stream
|
||||
/// </summary>
|
||||
public bool Write(Stream stream)
|
||||
{
|
||||
// If we don't have a valid dictionary with values, we can't write out
|
||||
if (_keyValuePairs == null || _keyValuePairs.Count == 0)
|
||||
return false;
|
||||
|
||||
// If the stream is invalid or unwritable, we can't output to it
|
||||
if (stream == null || !stream.CanWrite || stream.Position >= stream.Length - 1)
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
using (StreamWriter sw = new StreamWriter(stream))
|
||||
{
|
||||
// Order the dictionary by keys to link sections together
|
||||
var orderedKeyValuePairs = _keyValuePairs.OrderBy(kvp => kvp.Key);
|
||||
|
||||
string section = string.Empty;
|
||||
foreach (var keyValuePair in orderedKeyValuePairs)
|
||||
{
|
||||
// Extract the key and value
|
||||
string key = keyValuePair.Key;
|
||||
string value = keyValuePair.Value;
|
||||
|
||||
// We assume '.' is a section name separator
|
||||
if (key.Contains('.'))
|
||||
{
|
||||
// Split the key by '.'
|
||||
string[] data = keyValuePair.Key.Split('.');
|
||||
|
||||
// If the key contains an '.', we need to put them back in
|
||||
string newSection = data[0].Trim();
|
||||
key = string.Join(".", data.Skip(1)).Trim();
|
||||
|
||||
// If we have a new section, write it out
|
||||
if (!string.Equals(newSection, section, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sw.WriteLine($"[{newSection}]");
|
||||
section = newSection;
|
||||
}
|
||||
}
|
||||
|
||||
// Now write out the key and value in a standardized way
|
||||
sw.WriteLine($"{key}={value}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was, just catch and return
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#region IDictionary Impelementations
|
||||
|
||||
public ICollection<string> Keys => ((IDictionary<string, string>)_keyValuePairs).Keys;
|
||||
|
||||
public ICollection<string> Values => ((IDictionary<string, string>)_keyValuePairs).Values;
|
||||
|
||||
public int Count => ((ICollection<KeyValuePair<string, string>>)_keyValuePairs).Count;
|
||||
|
||||
public bool IsReadOnly => ((ICollection<KeyValuePair<string, string>>)_keyValuePairs).IsReadOnly;
|
||||
|
||||
public void Add(string key, string value)
|
||||
{
|
||||
((IDictionary<string, string>)_keyValuePairs).Add(key.ToLowerInvariant(), value);
|
||||
}
|
||||
|
||||
bool IDictionary<string, string>.Remove(string key)
|
||||
{
|
||||
return ((IDictionary<string, string>)_keyValuePairs).Remove(key.ToLowerInvariant());
|
||||
}
|
||||
|
||||
public bool TryGetValue(string key, out string value)
|
||||
{
|
||||
return ((IDictionary<string, string>)_keyValuePairs).TryGetValue(key.ToLowerInvariant(), out value);
|
||||
}
|
||||
|
||||
public void Add(KeyValuePair<string, string> item)
|
||||
{
|
||||
var newItem = new KeyValuePair<string, string>(item.Key.ToLowerInvariant(), item.Value);
|
||||
((ICollection<KeyValuePair<string, string>>)_keyValuePairs).Add(newItem);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
((ICollection<KeyValuePair<string, string>>)_keyValuePairs).Clear();
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<string, string> item)
|
||||
{
|
||||
var newItem = new KeyValuePair<string, string>(item.Key.ToLowerInvariant(), item.Value);
|
||||
return ((ICollection<KeyValuePair<string, string>>)_keyValuePairs).Contains(newItem);
|
||||
}
|
||||
|
||||
public bool ContainsKey(string key)
|
||||
{
|
||||
return _keyValuePairs.ContainsKey(key.ToLowerInvariant());
|
||||
}
|
||||
|
||||
public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex)
|
||||
{
|
||||
((ICollection<KeyValuePair<string, string>>)_keyValuePairs).CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
public bool Remove(KeyValuePair<string, string> item)
|
||||
{
|
||||
var newItem = new KeyValuePair<string, string>(item.Key.ToLowerInvariant(), item.Value);
|
||||
return ((ICollection<KeyValuePair<string, string>>)_keyValuePairs).Remove(newItem);
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable<KeyValuePair<string, string>>)_keyValuePairs).GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable)_keyValuePairs).GetEnumerator();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
75
BurnOutSharp/FileType/InstallShieldCAB.cs
Normal file
75
BurnOutSharp/FileType/InstallShieldCAB.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnshieldSharp;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class InstallShieldCAB
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
if (magic.StartsWith(new byte[] { 0x49, 0x53, 0x63 }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Add stream opening support
|
||||
public static Dictionary<string, List<string>> Scan(Scanner scanner, string file)
|
||||
{
|
||||
// Get the name of the first cabinet file or header
|
||||
string directory = Path.GetDirectoryName(file);
|
||||
string noExtension = Path.GetFileNameWithoutExtension(file);
|
||||
string filenamePattern = Path.Combine(directory, noExtension);
|
||||
filenamePattern = new Regex(@"\d+$").Replace(filenamePattern, string.Empty);
|
||||
|
||||
bool cabinetHeaderExists = File.Exists(Path.Combine(directory, filenamePattern + "1.hdr"));
|
||||
bool shouldScanCabinet = cabinetHeaderExists
|
||||
? file.Equals(Path.Combine(directory, filenamePattern + "1.hdr"), StringComparison.OrdinalIgnoreCase)
|
||||
: file.Equals(Path.Combine(directory, filenamePattern + "1.cab"), StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
// If we have the first file
|
||||
if (shouldScanCabinet)
|
||||
{
|
||||
// If the cab file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
UnshieldCabinet cabfile = UnshieldCabinet.Open(file);
|
||||
for (int i = 0; i < cabfile.FileCount; i++)
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
string tempFile = Path.Combine(tempPath, cabfile.FileName(i));
|
||||
cabfile.FileSave(i, tempFile);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// Collect and format all found protections
|
||||
var protections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Remove temporary path references
|
||||
Utilities.StripFromKeys(protections, tempPath);
|
||||
|
||||
return protections;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
80
BurnOutSharp/FileType/MPQ.cs
Normal file
80
BurnOutSharp/FileType/MPQ.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using StormLibSharp;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class MPQ
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
if (magic.StartsWith(new byte[] { 0x4d, 0x50, 0x51, 0x1a }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Add stream opening support
|
||||
public static Dictionary<string, List<string>> Scan(Scanner scanner, string file)
|
||||
{
|
||||
// If the mpq file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (MpqArchive mpqArchive = new MpqArchive(file, FileAccess.Read))
|
||||
{
|
||||
// Try to open the listfile
|
||||
string listfile = null;
|
||||
MpqFileStream listStream = mpqArchive.OpenFile("(listfile)");
|
||||
|
||||
// If we can't read the listfile, we just return
|
||||
if (!listStream.CanRead)
|
||||
return null;
|
||||
|
||||
// Read the listfile in for processing
|
||||
using (StreamReader sr = new StreamReader(listStream))
|
||||
{
|
||||
listfile = sr.ReadToEnd();
|
||||
}
|
||||
|
||||
// Split the listfile by newlines
|
||||
string[] listfileLines = listfile.Replace("\r\n", "\n").Split('\n');
|
||||
|
||||
// Loop over each entry
|
||||
foreach (string sub in listfileLines)
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
string tempFile = Path.Combine(tempPath, sub);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(tempFile));
|
||||
mpqArchive.ExtractFile(sub, tempFile);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
// Collect and format all found protections
|
||||
var protections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Remove temporary path references
|
||||
Utilities.StripFromKeys(protections, tempPath);
|
||||
|
||||
return protections;
|
||||
}
|
||||
catch { }
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
58
BurnOutSharp/FileType/MSI.cs
Normal file
58
BurnOutSharp/FileType/MSI.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
#if NET_FRAMEWORK
|
||||
using Microsoft.Deployment.WindowsInstaller;
|
||||
#endif
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class MSI
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
#if NET_FRAMEWORK
|
||||
if (magic.StartsWith(new byte[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }))
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Add stream opening support
|
||||
public static Dictionary<string, List<string>> Scan(Scanner scanner, string file)
|
||||
{
|
||||
#if NET_FRAMEWORK
|
||||
// If the MSI file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (Database msidb = new Database(file, DatabaseOpenMode.ReadOnly))
|
||||
{
|
||||
msidb.ExportAll(tempPath);
|
||||
}
|
||||
|
||||
// Collect and format all found protections
|
||||
var protections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Remove temporary path references
|
||||
Utilities.StripFromKeys(protections, tempPath);
|
||||
|
||||
return protections;
|
||||
}
|
||||
catch { }
|
||||
#endif
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
69
BurnOutSharp/FileType/MicrosoftCAB.cs
Normal file
69
BurnOutSharp/FileType/MicrosoftCAB.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
#if NET_FRAMEWORK
|
||||
using LibMSPackN;
|
||||
#endif
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
// Specification available at http://download.microsoft.com/download/5/0/1/501ED102-E53F-4CE0-AA6B-B0F93629DDC6/Exchange/%5BMS-CAB%5D.pdf
|
||||
internal class MicrosoftCAB
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
#if NET_FRAMEWORK
|
||||
if (magic.StartsWith(new byte[] { 0x4d, 0x53, 0x43, 0x46 }))
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Add stream opening support
|
||||
public static Dictionary<string, List<string>> Scan(Scanner scanner, string file)
|
||||
{
|
||||
#if NET_FRAMEWORK
|
||||
// If the cab file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (MSCabinet cabfile = new MSCabinet(file))
|
||||
{
|
||||
foreach (var sub in cabfile.GetFiles())
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
// The trim here is for some very odd and stubborn files
|
||||
string tempFile = Path.Combine(tempPath, sub.Filename.TrimEnd('.'));
|
||||
sub.ExtractTo(tempFile);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
// Collect and format all found protections
|
||||
var protections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Remove temporary path references
|
||||
Utilities.StripFromKeys(protections, tempPath);
|
||||
|
||||
return protections;
|
||||
}
|
||||
catch { }
|
||||
#endif
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
74
BurnOutSharp/FileType/PKZIP.cs
Normal file
74
BurnOutSharp/FileType/PKZIP.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Zip;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class PKZIP
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
// PKZIP
|
||||
if (magic.StartsWith(new byte[] { 0x50, 0x4b, 0x03, 0x04 }))
|
||||
return true;
|
||||
|
||||
// PKZIP (Empty Archive)
|
||||
if (magic.StartsWith(new byte[] { 0x50, 0x4b, 0x05, 0x06 }))
|
||||
return true;
|
||||
|
||||
// PKZIP (Spanned Archive)
|
||||
if (magic.StartsWith(new byte[] { 0x50, 0x4b, 0x07, 0x08 }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream)
|
||||
{
|
||||
// If the zip file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (ZipArchive zipFile = ZipArchive.Open(stream))
|
||||
{
|
||||
foreach (var entry in zipFile.Entries)
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
// Collect and format all found protections
|
||||
var protections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Remove temporary path references
|
||||
Utilities.StripFromKeys(protections, tempPath);
|
||||
|
||||
return protections;
|
||||
}
|
||||
catch { }
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
70
BurnOutSharp/FileType/RAR.cs
Normal file
70
BurnOutSharp/FileType/RAR.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Rar;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class RAR
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
// RAR archive version 1.50 onwards
|
||||
if (magic.StartsWith(new byte[] { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 }))
|
||||
return true;
|
||||
|
||||
// RAR archive version 5.0 onwards
|
||||
if (magic.StartsWith(new byte[] { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0x00 }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream)
|
||||
{
|
||||
// If the rar file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (RarArchive zipFile = RarArchive.Open(stream))
|
||||
{
|
||||
foreach (var entry in zipFile.Entries)
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
// Collect and format all found protections
|
||||
var protections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Remove temporary path references
|
||||
Utilities.StripFromKeys(protections, tempPath);
|
||||
|
||||
return protections;
|
||||
}
|
||||
catch { }
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
65
BurnOutSharp/FileType/SevenZip.cs
Normal file
65
BurnOutSharp/FileType/SevenZip.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.SevenZip;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class SevenZip
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
if (magic.StartsWith(new byte[] { 0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream)
|
||||
{
|
||||
// If the 7-zip file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (SevenZipArchive sevenZipFile = SevenZipArchive.Open(stream))
|
||||
{
|
||||
foreach (var entry in sevenZipFile.Entries)
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// Collect and format all found protections
|
||||
var protections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Remove temporary path references
|
||||
Utilities.StripFromKeys(protections, tempPath);
|
||||
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
68
BurnOutSharp/FileType/TapeArchive.cs
Normal file
68
BurnOutSharp/FileType/TapeArchive.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Tar;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class TapeArchive
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
if (magic.StartsWith(new byte[] { 0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x30, 0x30 }))
|
||||
return true;
|
||||
|
||||
if (magic.StartsWith(new byte[] { 0x75, 0x73, 0x74, 0x61, 0x72, 0x20, 0x20, 0x00 }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream)
|
||||
{
|
||||
// If the tar file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (TarArchive tarFile = TarArchive.Open(stream))
|
||||
{
|
||||
foreach (var entry in tarFile.Entries)
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
// Collect and format all found protections
|
||||
var protections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Remove temporary path references
|
||||
Utilities.StripFromKeys(protections, tempPath);
|
||||
|
||||
return protections;
|
||||
}
|
||||
catch { }
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
66
BurnOutSharp/FileType/Textfile.cs
Normal file
66
BurnOutSharp/FileType/Textfile.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class Textfile
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic, string extension)
|
||||
{
|
||||
// Rich Text File
|
||||
if (magic.StartsWith(new byte[] { 0x7b, 0x5c, 0x72, 0x74, 0x66, 0x31 }))
|
||||
return true;
|
||||
|
||||
// HTML
|
||||
if (magic.StartsWith(new byte[] { 0x3c, 0x68, 0x74, 0x6d, 0x6c }))
|
||||
return true;
|
||||
|
||||
// HTML and XML
|
||||
if (magic.StartsWith(new byte[] { 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45 }))
|
||||
return true;
|
||||
|
||||
// Microsoft Office File (old)
|
||||
if (magic.StartsWith(new byte[] { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 }))
|
||||
return true;
|
||||
|
||||
// Generic textfile (no header)
|
||||
if (string.Equals(extension.TrimStart('.'), "txt", StringComparison.OrdinalIgnoreCase))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<string> Scan(Stream stream)
|
||||
{
|
||||
List<string> protections = new List<string>();
|
||||
|
||||
try
|
||||
{
|
||||
// Load the current file content
|
||||
string fileContent = null;
|
||||
using (var sr = new StreamReader(stream, Encoding.Default, true, 1024 * 1024, true))
|
||||
{
|
||||
fileContent = sr.ReadToEnd();
|
||||
}
|
||||
|
||||
// CD-Key
|
||||
if (fileContent.Contains("a valid serial number is required"))
|
||||
protections.Add("CD-Key / Serial");
|
||||
else if (fileContent.Contains("serial number is located"))
|
||||
protections.Add("CD-Key / Serial");
|
||||
|
||||
// MediaMax
|
||||
if (fileContent.Contains("MediaMax technology"))
|
||||
protections.Add("MediaMax CD-3");
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
}
|
||||
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
}
|
||||
68
BurnOutSharp/FileType/Valve.cs
Normal file
68
BurnOutSharp/FileType/Valve.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using HLExtract.Net;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class Valve
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
// GCF
|
||||
if (magic.StartsWith(new byte[] { 0x01, 0x00, 0x00, 0x00 }))
|
||||
return true;
|
||||
|
||||
// PAK
|
||||
if (magic.StartsWith(new byte[] { 0x50, 0x41, 0x43, 0x4b }))
|
||||
return true;
|
||||
|
||||
// SGA
|
||||
if (magic.StartsWith(new byte[] { 0x5f, 0x41, 0x52, 0x43, 0x48, 0x49, 0x56, 0x45 }))
|
||||
return true;
|
||||
|
||||
// VPK
|
||||
if (magic.StartsWith(new byte[] { 0x55, 0xaa, 0x12, 0x34 }))
|
||||
return true;
|
||||
|
||||
// WAD
|
||||
if (magic.StartsWith(new byte[] { 0x57, 0x41, 0x44, 0x33 }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Add stream opening support
|
||||
public static Dictionary<string, List<string>> Scan(Scanner scanner, string file)
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
string[] args = new string[]
|
||||
{
|
||||
"-p", file,
|
||||
"-x", "root",
|
||||
"-x", "'extract .'",
|
||||
"-x", "exit",
|
||||
"-d", tempPath,
|
||||
};
|
||||
|
||||
HLExtractProgram.Process(args);
|
||||
|
||||
// Collect and format all found protections
|
||||
var protections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Remove temporary path references
|
||||
Utilities.StripFromKeys(protections, tempPath);
|
||||
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
}
|
||||
60
BurnOutSharp/FileType/XZ.cs
Normal file
60
BurnOutSharp/FileType/XZ.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Compressors.Xz;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class XZ
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
if (magic.StartsWith(new byte[] { 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00 }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream)
|
||||
{
|
||||
// If the xz file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (XZStream xzFile = new XZStream(stream))
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
string tempFile = Path.Combine(tempPath, Guid.NewGuid().ToString());
|
||||
using (FileStream fs = File.OpenWrite(tempFile))
|
||||
{
|
||||
xzFile.CopyTo(fs);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// Collect and format all found protections
|
||||
var protections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Remove temporary path references
|
||||
Utilities.StripFromKeys(protections, tempPath);
|
||||
|
||||
return protections;
|
||||
}
|
||||
catch { }
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
BurnOutSharp/HLLib.x64.dll
Normal file
BIN
BurnOutSharp/HLLib.x64.dll
Normal file
Binary file not shown.
BIN
BurnOutSharp/HLLib.x86.dll
Normal file
BIN
BurnOutSharp/HLLib.x86.dll
Normal file
Binary file not shown.
674
BurnOutSharp/LICENSE.txt
Normal file
674
BurnOutSharp/LICENSE.txt
Normal file
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
20
BurnOutSharp/PackerType/Armadillo.cs
Normal file
20
BurnOutSharp/PackerType/Armadillo.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
public class Armadillo
|
||||
{
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
// ".nicode" + (char)0x00
|
||||
byte[] check = new byte[] { 0x2E, 0x6E, 0x69, 0x63, 0x6F, 0x64, 0x65, 0x00 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"Armadillo" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
// "ARMDEBUG"
|
||||
check = new byte[] { 0x41, 0x52, 0x4D, 0x44, 0x45, 0x42, 0x55, 0x47 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"Armadillo" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
BurnOutSharp/PackerType/EXEStealth.cs
Normal file
15
BurnOutSharp/PackerType/EXEStealth.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
public class EXEStealth
|
||||
{
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
// "??[[__[[_" + (char)0x00 + "{{" + (char)0x0 + (char)0x00 + "{{" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x0 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + "?;??;??"
|
||||
byte[] check = new byte[] { 0x3F, 0x3F, 0x5B, 0x5B, 0x5F, 0x5F, 0x5B, 0x5B, 0x5F, 0x00, 0x7B, 0x7B, 0x00, 0x00, 0x7B, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x3B, 0x3F, 0x3F, 0x3B, 0x3F, 0x3F };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"EXE Stealth" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
47
BurnOutSharp/PackerType/NSIS.cs
Normal file
47
BurnOutSharp/PackerType/NSIS.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
public class NSIS
|
||||
{
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
// Nullsoft Install System
|
||||
byte[] check = new byte[] { 0x4e, 0x75, 0x6c, 0x6c, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
{
|
||||
string version = GetVersion(fileContent, position);
|
||||
return $"NSIS {version}" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
}
|
||||
|
||||
// NullsoftInst
|
||||
check = new byte[] { 0x4e, 0x75, 0x6c, 0x6c, 0x73, 0x6f, 0x66, 0x74, 0x49, 0x6e, 0x73, 0x74 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
{
|
||||
return $"NSIS" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetVersion(byte[] fileContent, int index)
|
||||
{
|
||||
try
|
||||
{
|
||||
index += 24;
|
||||
if (fileContent[index] != 'v')
|
||||
return "(Unknown Version)";
|
||||
|
||||
var versionBytes = new ReadOnlySpan<byte>(fileContent, index, 16).ToArray();
|
||||
var onlyVersion = versionBytes.TakeWhile(b => b != '<').ToArray();
|
||||
return Encoding.ASCII.GetString(onlyVersion);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return "(Unknown Version)";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
BurnOutSharp/PackerType/PECompact.cs
Normal file
15
BurnOutSharp/PackerType/PECompact.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
public class PECompact
|
||||
{
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
// "PEC2"
|
||||
byte[] check = new byte[] { 0x50, 0x45, 0x43, 0x32 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return "PE Compact 2" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
10
BurnOutSharp/PackerType/Petite.cs
Normal file
10
BurnOutSharp/PackerType/Petite.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
public class Petite
|
||||
{
|
||||
/*
|
||||
* Possible strings for PEtite Win32 Executable Compressor (Unknown how to get version)
|
||||
* - petite - 40 70 65 74 69 74 65 (Made with Version 2.4, Compression Level 1-9)
|
||||
*/
|
||||
}
|
||||
}
|
||||
37
BurnOutSharp/PackerType/UPX.cs
Normal file
37
BurnOutSharp/PackerType/UPX.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Text;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
public class UPX
|
||||
{
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
// UPX!
|
||||
byte[] check = new byte[] { 0x55, 0x50, 0x58, 0x21 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
{
|
||||
string version = GetVersion(fileContent, position);
|
||||
return $"UPX {version}" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetVersion(byte[] fileContent, int index)
|
||||
{
|
||||
try
|
||||
{
|
||||
index -= 5;
|
||||
string versionString = Encoding.ASCII.GetString(fileContent, index, 4);
|
||||
if (!char.IsNumber(versionString[0]))
|
||||
return "(Unknown Version)";
|
||||
|
||||
return versionString;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return "(Unknown Version)";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
BurnOutSharp/PackerType/dotFuscator.cs
Normal file
15
BurnOutSharp/PackerType/dotFuscator.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
public class dotFuscator
|
||||
{
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
// "DotfuscatorAttribute"
|
||||
byte[] check = new byte[] { 0x44, 0x6F, 0x74, 0x66, 0x75, 0x73, 0x63, 0x61, 0x74, 0x6F, 0x72, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return "dotFuscator" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("BurnOutSharp")]
|
||||
[assembly: AssemblyDescription("Port of BurnOut to C#, with additions")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Matt Nadareski, Gernot Knippen")]
|
||||
[assembly: AssemblyProduct("BurnOutSharp")]
|
||||
[assembly: AssemblyCopyright("Copyright (c)2005-2010 Gernot Knippen, Copyright (c)2018 Matt Nadareski")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("1da4212e-6071-4951-b45d-bb74a7838246")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.03.9.0")]
|
||||
[assembly: AssemblyFileVersion("1.03.9.0")]
|
||||
@@ -1,923 +0,0 @@
|
||||
//this file is part of BurnOut
|
||||
//Copyright (C)2005-2010 Gernot Knippen
|
||||
//Ported code with augments Copyright (C)2018 Matt Nadareski
|
||||
//
|
||||
//This program is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU General Public License
|
||||
//as published by the Free Software Foundation; either
|
||||
//version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This program is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
//GNU General Public License for more details.
|
||||
//
|
||||
//You can get a copy of the GNU General Public License
|
||||
//by writing to the Free Software
|
||||
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using BurnOutSharp.ProtectionType;
|
||||
using LibMSPackN;
|
||||
using UnshieldSharp;
|
||||
|
||||
namespace BurnOutSharp
|
||||
{
|
||||
public static class ProtectionFind
|
||||
{
|
||||
/// <summary>
|
||||
/// Scan a path to find any known copy protection(s)
|
||||
/// </summary>
|
||||
/// <param name="path">Path to scan for protection(s)</param>
|
||||
/// <param name="progress">Optional progress indicator that will return a float in the range from 0 to 1</param>
|
||||
/// <returns>Dictionary of filename to protection mappings, if possible</returns>
|
||||
public static Dictionary<string, string> Scan(string path, IProgress<FileProtection> progress = null)
|
||||
{
|
||||
var protections = new Dictionary<string, string>();
|
||||
|
||||
// Checkpoint
|
||||
progress?.Report(new FileProtection(null, 0, null));
|
||||
|
||||
// If we have a file
|
||||
if (File.Exists(path))
|
||||
{
|
||||
// Try using just the file first to get protection info
|
||||
string fileProtection = ScanPath(path, false);
|
||||
if (!string.IsNullOrWhiteSpace(fileProtection))
|
||||
protections[path] = fileProtection;
|
||||
|
||||
// Now check to see if the file contains any additional information
|
||||
string contentProtection = ScanInFile(path)?.Replace("" + (char)0x00, "");
|
||||
if (!string.IsNullOrWhiteSpace(contentProtection))
|
||||
{
|
||||
if (protections.ContainsKey(path))
|
||||
protections[path] += $", {contentProtection}";
|
||||
else
|
||||
protections[path] = contentProtection;
|
||||
}
|
||||
|
||||
// Checkpoint
|
||||
progress?.Report(new FileProtection(path, 1, contentProtection));
|
||||
}
|
||||
// If we have a directory
|
||||
else if (Directory.Exists(path))
|
||||
{
|
||||
// Get the lists of files to be used
|
||||
var files = Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories);
|
||||
|
||||
// Try using just the path first to get protection info
|
||||
string pathProtection = ScanPath(path, true);
|
||||
if (!string.IsNullOrWhiteSpace(pathProtection))
|
||||
protections[path] = pathProtection;
|
||||
|
||||
// Loop through all files and scan their contents
|
||||
for (int i = 0; i < files.Count(); i++)
|
||||
{
|
||||
// Get the current file
|
||||
string file = files.ElementAt(i);
|
||||
|
||||
// Try using just the file first to get protection info
|
||||
string fileProtection = ScanPath(file, false);
|
||||
if (!string.IsNullOrWhiteSpace(fileProtection))
|
||||
protections[file] = fileProtection;
|
||||
|
||||
// Now check to see if the file contains any additional information
|
||||
string contentProtection = ScanInFile(file)?.Replace("" + (char)0x00, "");
|
||||
if (!string.IsNullOrWhiteSpace(contentProtection))
|
||||
{
|
||||
if (protections.ContainsKey(file))
|
||||
protections[file] += $", {contentProtection}";
|
||||
else
|
||||
protections[file] = contentProtection;
|
||||
}
|
||||
|
||||
// Checkpoint
|
||||
progress?.Report(new FileProtection(file, i / (float)files.Count(), contentProtection));
|
||||
}
|
||||
}
|
||||
|
||||
// If we have an empty list, we need to take care of that
|
||||
if (protections.Count(p => !string.IsNullOrWhiteSpace(p.Value)) == 0)
|
||||
{
|
||||
protections = new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
return protections;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scan a path for indications of copy protection
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="isDirectory"></param>
|
||||
/// <returns></returns>
|
||||
public static string ScanPath(string path, bool isDirectory)
|
||||
{
|
||||
List<string> protections = new List<string>();
|
||||
string protection;
|
||||
|
||||
// If we have a directory, get the files in the directory for searching
|
||||
IEnumerable<string> files = null;
|
||||
if (isDirectory)
|
||||
files = Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories);
|
||||
|
||||
// AACS
|
||||
protection = AACS.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Alpha-DVD
|
||||
protection = AlphaDVD.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Bitpool
|
||||
protection = Bitpool.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// ByteShield
|
||||
protection = ByteShield.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Cactus Data Shield
|
||||
protection = CactusDataShield.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// CD-Cops
|
||||
protection = CDCops.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// CD-Lock
|
||||
protection = CDLock.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// CD-Protector
|
||||
protection = CDProtector.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// CD-X
|
||||
protection = CDX.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
/*
|
||||
// CopyKiller
|
||||
protection = CopyKiller.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
*/
|
||||
|
||||
// DiscGuard
|
||||
protection = DiscGuard.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// DVD Crypt
|
||||
protection = DVDCrypt.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// DVD-Movie-PROTECT
|
||||
protection = DVDMoviePROTECT.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// FreeLock
|
||||
protection = FreeLock.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Games for Windows - Live
|
||||
protection = GFWL.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Hexalock AutoLock
|
||||
protection = HexalockAutoLock.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Impulse Reactor
|
||||
protection = ImpulseReactor.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// IndyVCD
|
||||
protection = IndyVCD.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Key2Audio XS
|
||||
protection = Key2AudioXS.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// LaserLock
|
||||
protection = LaserLock.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// MediaCloQ
|
||||
protection = MediaCloQ.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// MediaMax CD3
|
||||
protection = MediaMaxCD3.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Origin
|
||||
protection = Origin.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Protect DVD-Video
|
||||
protection = ProtectDVDVideo.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// PSX Anti-modchip
|
||||
protection = PSXAntiModchip.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SafeCast
|
||||
protection = SafeCast.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SafeDisc
|
||||
protection = SafeDisc.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SafeDisc Lite
|
||||
protection = SafeDiscLite.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SafeLock
|
||||
protection = SafeLock.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SecuROM
|
||||
protection = SecuROM.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SmartE
|
||||
protection = SmartE.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SoftLock
|
||||
protection = SoftLock.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SolidShield
|
||||
protection = SolidShield.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// StarForce
|
||||
protection = StarForce.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Steam
|
||||
protection = Steam.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// TAGES
|
||||
protection = Tages.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// TZCopyProtector
|
||||
protection = TZCopyProtector.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Uplay
|
||||
protection = Uplay.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// VOB ProtectCD/DVD
|
||||
protection = VOBProtectCDDVD.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Winlock
|
||||
protection = Winlock.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// WTM CD Protect
|
||||
protection = WTMCDProtect.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// XCP
|
||||
protection = XCP.CheckPath(path, files, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Zzxzz
|
||||
protection = Zzxzz.CheckPath(path, isDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Now combine any found protections, or null if empty
|
||||
if (protections.Count() == 0)
|
||||
return null;
|
||||
else
|
||||
return string.Join(", ", protections);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scan an individual file for copy protection
|
||||
/// </summary>
|
||||
/// <param name="file">File path for scanning</param>
|
||||
public static string ScanInFile(string file)
|
||||
{
|
||||
// Get the extension for certain checks
|
||||
string extension = Path.GetExtension(file).ToLower().TrimStart('.');
|
||||
|
||||
// Read the first 8 bytes to get the file type
|
||||
string magic = "";
|
||||
try
|
||||
{
|
||||
using (BinaryReader br = new BinaryReader(File.OpenRead(file)))
|
||||
{
|
||||
magic = new string(br.ReadChars(8));
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the issue was, we can't open the file
|
||||
return null;
|
||||
}
|
||||
|
||||
// Files can be protected in multiple ways
|
||||
List<string> protections = new List<string>();
|
||||
|
||||
#region Executable Content Checks
|
||||
|
||||
if (magic.StartsWith("MZ") // Windows Executable and DLL
|
||||
|| magic.StartsWith((char)0x7f + "ELF") // Unix binaries
|
||||
|| magic.StartsWith("" + (char)0xfe + (char)0xed + (char)0xfa + (char)0xce) // Macintosh
|
||||
|| magic.StartsWith("" + (char)0xce + (char)0xfa + (char)0xed + (char)0xfe) // Macintosh
|
||||
|| magic.StartsWith("Joy!peff")) // Macintosh
|
||||
{
|
||||
try
|
||||
{
|
||||
// Load the current file content
|
||||
string fileContent = null;
|
||||
using (StreamReader sr = new StreamReader(file, Encoding.Default))
|
||||
{
|
||||
fileContent = sr.ReadToEnd();
|
||||
}
|
||||
|
||||
protections.AddRange(ScanFileContent(file, fileContent));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Textfile Content Checks
|
||||
|
||||
if (magic.StartsWith("{\rtf") // Rich Text File
|
||||
|| magic.StartsWith("" + (char)0xd0 + (char)0xcf + (char)0x11 + (char)0xe0 + (char)0xa1 + (char)0xb1 + (char)0x1a + (char)0xe1) // Microsoft Office File (old)
|
||||
|| extension == "txt") // Generic textfile (no header)
|
||||
{
|
||||
try
|
||||
{
|
||||
StreamReader sr = File.OpenText(file);
|
||||
string FileContent = sr.ReadToEnd().ToLower();
|
||||
sr.Close();
|
||||
|
||||
// CD-Key
|
||||
if (FileContent.Contains("a valid serial number is required")
|
||||
|| FileContent.Contains("serial number is located"))
|
||||
{
|
||||
protections.Add("CD-Key / Serial");
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Archive Content Checks
|
||||
|
||||
// 7-zip
|
||||
if (magic.StartsWith("7z" + (char)0xbc + (char)0xaf + (char)0x27 + (char)0x1c))
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
|
||||
// InstallShield CAB
|
||||
else if (magic.StartsWith("ISc"))
|
||||
{
|
||||
// Get the name of the first cabinet file or header
|
||||
string directory = Path.GetDirectoryName(file);
|
||||
string noExtension = Path.GetFileNameWithoutExtension(file);
|
||||
string filenamePattern = Path.Combine(directory, noExtension);
|
||||
filenamePattern = new Regex(@"\d+$").Replace(filenamePattern, string.Empty);
|
||||
|
||||
bool cabinetHeaderExists = File.Exists(Path.Combine(directory, filenamePattern + "1.hdr"));
|
||||
bool shouldScanCabinet = cabinetHeaderExists
|
||||
? file.Equals(Path.Combine(directory, filenamePattern + "1.hdr"), StringComparison.OrdinalIgnoreCase)
|
||||
: file.Equals(Path.Combine(directory, filenamePattern + "1.cab"), StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
// If we have the first file
|
||||
if (shouldScanCabinet)
|
||||
{
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
UnshieldCabinet cabfile = UnshieldCabinet.Open(file);
|
||||
for (int i = 0; i < cabfile.FileCount; i++)
|
||||
{
|
||||
string tempFileName = Path.Combine(tempPath, cabfile.FileName(i));
|
||||
if (cabfile.FileSave(i, tempFileName))
|
||||
{
|
||||
string protection = ScanInFile(tempFileName);
|
||||
try
|
||||
{
|
||||
File.Delete(tempFileName);
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (!string.IsNullOrEmpty(protection))
|
||||
protections.Add(protection);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
// Microsoft CAB
|
||||
else if (magic.StartsWith("MSCF"))
|
||||
{
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (MSCabinet cabfile = new MSCabinet(file))
|
||||
{
|
||||
foreach (var sub in cabfile.GetFiles())
|
||||
{
|
||||
string tempfile = Path.Combine(tempPath, sub.Filename);
|
||||
sub.ExtractTo(tempfile);
|
||||
string protection = ScanInFile(tempfile);
|
||||
File.Delete(tempfile);
|
||||
|
||||
if (!string.IsNullOrEmpty(protection))
|
||||
protections.Add(protection);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// PKZIP
|
||||
else if (magic.StartsWith("PK" + (char)03 + (char)04)
|
||||
|| magic.StartsWith("PK" + (char)05 + (char)06)
|
||||
|| magic.StartsWith("PK" + (char)07 + (char)08))
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
|
||||
// RAR
|
||||
else if (magic.StartsWith("Rar!"))
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// Return blank if nothing found, or comma-separated list of protections
|
||||
if (protections.Count() == 0)
|
||||
return string.Empty;
|
||||
else
|
||||
return string.Join(", ", protections);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scan an individual stream for copy protection
|
||||
/// </summary>
|
||||
/// <param name="stream">Generic stream to scan</param>
|
||||
/// <param name="file">File path to be used for name checks (optional)</param>
|
||||
public static string ScanInFile(Stream stream, string file = null)
|
||||
{
|
||||
// Assume the first part of the stream is the start of a file
|
||||
string magic = "";
|
||||
try
|
||||
{
|
||||
using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true))
|
||||
{
|
||||
magic = new string(br.ReadChars(8));
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the issue was, we can't open the file
|
||||
return null;
|
||||
}
|
||||
|
||||
// If we can, seek to the beginning of the stream
|
||||
if (stream.CanSeek)
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
// Files can be protected in multiple ways
|
||||
List<string> protections = new List<string>();
|
||||
|
||||
#region Executable Content Checks
|
||||
|
||||
// Windows Executable and DLL
|
||||
if (magic.StartsWith("MZ"))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Load the current file content
|
||||
string fileContent = null;
|
||||
using (StreamReader sr = new StreamReader(stream, Encoding.Default))
|
||||
{
|
||||
fileContent = sr.ReadToEnd();
|
||||
}
|
||||
|
||||
protections.AddRange(ScanFileContent(file, fileContent));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Textfile Content Checks
|
||||
|
||||
if (magic.StartsWith("{\rtf") // Rich Text File
|
||||
|| magic.StartsWith("" + (char)0xd0 + (char)0xcf + (char)0x11 + (char)0xe0 + (char)0xa1 + (char)0xb1 + (char)0x1a + (char)0xe1)) // Microsoft Office File (old)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Load the current file content
|
||||
string fileContent = null;
|
||||
using (StreamReader sr = new StreamReader(stream))
|
||||
{
|
||||
fileContent = sr.ReadToEnd();
|
||||
}
|
||||
|
||||
// CD-Key
|
||||
if (fileContent.Contains("a valid serial number is required")
|
||||
|| fileContent.Contains("serial number is located"))
|
||||
{
|
||||
protections.Add("CD-Key / Serial");
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Archive Content Checks
|
||||
|
||||
// 7-zip
|
||||
if (magic.StartsWith("7z" + (char)0xbc + (char)0xaf + (char)0x27 + (char)0x1c))
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
|
||||
// InstallShield CAB
|
||||
else if (magic.StartsWith("ISc"))
|
||||
{
|
||||
// TODO: Update UnshieldSharp to include generic stream support
|
||||
}
|
||||
|
||||
// Microsoft CAB
|
||||
else if (magic.StartsWith("MSCF"))
|
||||
{
|
||||
// TODO: See if LibMSPackN can use generic streams
|
||||
}
|
||||
|
||||
// PKZIP
|
||||
else if (magic.StartsWith("PK" + (char)03 + (char)04)
|
||||
|| magic.StartsWith("PK" + (char)05 + (char)06)
|
||||
|| magic.StartsWith("PK" + (char)07 + (char)08))
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
|
||||
// RAR
|
||||
else if (magic.StartsWith("Rar!"))
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// Return blank if nothing found, or comma-separated list of protections
|
||||
if (protections.Count() == 0)
|
||||
return string.Empty;
|
||||
else
|
||||
return string.Join(", ", protections);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scan the contents of a file for protection
|
||||
/// </summary>
|
||||
/// TODO: This needs to work on a byte array of file content instead of string
|
||||
private static List<string> ScanFileContent(string file, string fileContent)
|
||||
{
|
||||
// Files can be protected in multiple ways
|
||||
List<string> protections = new List<string>();
|
||||
string protection;
|
||||
|
||||
// 3PLock
|
||||
protection = ThreePLock.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// ActiveMARK
|
||||
protection = ActiveMARK.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Alpha-ROM
|
||||
protection = AlphaROM.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Armadillo
|
||||
protection = Armadillo.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// CD-Cops
|
||||
protection = CDCops.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// CD-Lock
|
||||
protection = CDLock.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// CDSHiELD SE
|
||||
protection = CDSHiELDSE.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// CD Check
|
||||
protection = CDCheck.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Cenega ProtectDVD
|
||||
protection = CengaProtectDVD.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Code Lock
|
||||
protection = CodeLock.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// CopyKiller
|
||||
protection = CopyKiller.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Cucko (EA Custom)
|
||||
protection = Cucko.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// dotFuscator
|
||||
protection = dotFuscator.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// DVD-Cops
|
||||
protection = DVDCops.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// EA CdKey Registration Module
|
||||
protection = EACdKey.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// EXE Stealth
|
||||
protection = EXEStealth.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Games for Windows - Live
|
||||
protection = GFWL.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Impulse Reactor
|
||||
protection = ImpulseReactor.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Inno Setup
|
||||
protection = InnoSetup.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// JoWooD X-Prot
|
||||
protection = JoWooDXProt.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Key-Lock (Dongle)
|
||||
protection = KeyLock.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// LaserLock
|
||||
protection = LaserLock.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// PE Compact
|
||||
protection = PECompact.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// ProtectDisc
|
||||
protection = ProtectDisc.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Ring PROTECH
|
||||
protection = RingPROTECH.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SafeDisc / SafeCast
|
||||
protection = SafeDisc.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SafeLock
|
||||
protection = SafeLock.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SecuROM
|
||||
protection = SecuROM.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SmartE
|
||||
protection = SmartE.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SolidShield
|
||||
protection = SolidShield.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// StarForce
|
||||
protection = StarForce.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SVK Protector
|
||||
protection = SVKProtector.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Sysiphus / Sysiphus DVD
|
||||
protection = Sysiphus.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// TAGES
|
||||
protection = Tages.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// VOB ProtectCD/DVD
|
||||
protection = VOBProtectCDDVD.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// WTM CD Protect
|
||||
protection = WTMCDProtect.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Xtreme-Protector
|
||||
protection = XtremeProtector.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
return protections;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scan a disc sector by sector for protection
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// https://stackoverflow.com/questions/8819188/c-sharp-classes-to-undelete-files/8820157#8820157
|
||||
/// TODO: Finish implementation
|
||||
/// </remarks>
|
||||
private static string ScanSectors(char driveLetter, int sectorsize)
|
||||
{
|
||||
string fsName = Utilities.GetFileSystemName(driveLetter);
|
||||
|
||||
// Gets a handle to the physical disk
|
||||
IntPtr hDisk = Utilities.CreateFile($"\\\\.\\{driveLetter}:",
|
||||
FileAccess.Read,
|
||||
FileShare.ReadWrite,
|
||||
IntPtr.Zero,
|
||||
FileMode.Open,
|
||||
0,
|
||||
IntPtr.Zero);
|
||||
|
||||
// If we have a good pointer
|
||||
if (hDisk.ToInt32() != -1)
|
||||
{
|
||||
// Setup vars
|
||||
byte[] buffer = new byte[sectorsize];
|
||||
IntPtr pt = IntPtr.Zero;
|
||||
NativeOverlapped no = new NativeOverlapped();
|
||||
|
||||
// Set initial offset
|
||||
Utilities.SetFilePointerEx(
|
||||
hDisk,
|
||||
0,
|
||||
ref pt,
|
||||
Utilities.FileBegin);
|
||||
|
||||
// Read a whole sector
|
||||
while (true)
|
||||
{
|
||||
buffer = new byte[sectorsize];
|
||||
Utilities.ReadFileEx(
|
||||
hDisk,
|
||||
buffer,
|
||||
(uint)sectorsize,
|
||||
ref no,
|
||||
null);
|
||||
|
||||
Utilities.SetFilePointerEx(
|
||||
hDisk,
|
||||
sectorsize,
|
||||
ref pt,
|
||||
Utilities.FileCurrent);
|
||||
}
|
||||
}
|
||||
|
||||
Utilities.CloseHandle(hDisk);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
namespace BurnOutSharp
|
||||
{
|
||||
public class FileProtection
|
||||
public class ProtectionProgress
|
||||
{
|
||||
public string Filename { get; private set; }
|
||||
public float Percentage { get; private set; }
|
||||
public string Protection { get; private set; }
|
||||
|
||||
public FileProtection(string filename, float percentage, string protection)
|
||||
public ProtectionProgress(string filename, float percentage, string protection)
|
||||
{
|
||||
this.Filename = filename;
|
||||
this.Percentage = percentage;
|
||||
@@ -11,8 +11,8 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
if (isDirectory)
|
||||
{
|
||||
if (files.Count(f => f.Contains(Path.Combine("aacs", "VTKF000.AACS"))) > 0
|
||||
&& files.Count(f => f.Contains(Path.Combine("AACS", "CPSUnit00001.cci"))) > 0)
|
||||
if (files.Any(f => f.Contains(Path.Combine("aacs", "VTKF000.AACS")))
|
||||
&& files.Any(f => f.Contains(Path.Combine("AACS", "CPSUnit00001.cci"))))
|
||||
{
|
||||
return "AACS";
|
||||
}
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
{
|
||||
public class ActiveMARK
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
if (fileContent.Contains("TMSAMVOF"))
|
||||
return "ActiveMARK";
|
||||
// "TMSAMVOF"
|
||||
byte[] check = new byte[] { 0x54, 0x4D, 0x53, 0x41, 0x4D, 0x56, 0x4F, 0x46 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return "ActiveMARK" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
if (fileContent.Contains(" " + (char)0xC2 + (char)0x16 + (char)0x00 + (char)0xA8 + (char)0xC1 + (char)0x16
|
||||
+ (char)0x00 + (char)0xB8 + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0x86 + (char)0xC8 + (char)0x16 + (char)0x0
|
||||
+ (char)0x9A + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0x10 + (char)0xC2 + (char)0x16 + (char)0x00))
|
||||
{
|
||||
return "ActiveMARK 5";
|
||||
}
|
||||
// " " + (char)0xC2 + (char)0x16 + (char)0x00 + (char)0xA8 + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0xB8 + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0x86 + (char)0xC8 + (char)0x16 + (char)0x0 + (char)0x9A + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0x10 + (char)0xC2 + (char)0x16 + (char)0x00
|
||||
check = new byte[] { 0x20, 0xC2, 0x16, 0x00, 0xA8, 0xC1, 0x16, 0x00, 0xB8, 0xC1, 0x16, 0x00, 0x86, 0xC8, 0x16, 0x0, 0x9A, 0xC1, 0x16, 0x00, 0x10, 0xC2, 0x16, 0x00 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return "ActiveMARK 5" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
if (isDirectory)
|
||||
{
|
||||
if (files.Count(f => Path.GetFileName(f).Equals("PlayDVD.exe", StringComparison.OrdinalIgnoreCase)) > 0)
|
||||
if (files.Any(f => Path.GetFileName(f).Equals("PlayDVD.exe", StringComparison.OrdinalIgnoreCase)))
|
||||
return "Alpha-DVD";
|
||||
}
|
||||
else
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
{
|
||||
public class AlphaROM
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
if (fileContent.Contains("SETTEC"))
|
||||
return "Alpha-ROM";
|
||||
// "SETTEC"
|
||||
byte[] check = new byte[] { 0x53, 0x45, 0x54, 0x54, 0x45, 0x43 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return "Alpha-ROM" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class Armadillo
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
{
|
||||
if (fileContent.Contains(".nicode" + (char)0x00)
|
||||
|| fileContent.Contains("ARMDEBUG"))
|
||||
return "Armadillo";
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
if (isDirectory)
|
||||
{
|
||||
if (files.Count(f => Path.GetFileName(f).Equals("bitpool.rsc", StringComparison.OrdinalIgnoreCase)) > 0)
|
||||
if (files.Any(f => Path.GetFileName(f).Equals("bitpool.rsc", StringComparison.OrdinalIgnoreCase)))
|
||||
return "Bitpool";
|
||||
}
|
||||
else
|
||||
|
||||
@@ -11,8 +11,8 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
if (isDirectory)
|
||||
{
|
||||
if (files.Count(f => Path.GetFileName(f).Equals("Byteshield.dll", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetExtension(f).Trim('.').Equals("bbz", StringComparison.OrdinalIgnoreCase)) > 0)
|
||||
if (files.Any(f => Path.GetFileName(f).Equals("Byteshield.dll", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetExtension(f).Trim('.').Equals("bbz", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return "ByteShield";
|
||||
}
|
||||
|
||||
@@ -2,11 +2,33 @@
|
||||
{
|
||||
public class CDCheck
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
if (fileContent.Contains("GetDriveType")
|
||||
|| fileContent.Contains("GetVolumeInformation"))
|
||||
return "CD Check";
|
||||
// MGS CDCheck
|
||||
byte[] check = new byte[] { 0x4D, 0x47, 0x53, 0x20, 0x43, 0x44, 0x43, 0x68, 0x65, 0x63, 0x6B };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return "Microsoft Game Studios CD Check" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
// CDCheck
|
||||
check = new byte[] { 0x43, 0x44, 0x43, 0x68, 0x65, 0x63, 0x6B };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return "Executable-Based CD Check" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// These content checks are too broad to be useful
|
||||
private static string CheckContentsBroad(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
// GetDriveType
|
||||
byte[] check = new byte[] { 0x47, 0x65, 0x74, 0x44, 0x72, 0x69, 0x76, 0x65, 0x54, 0x79, 0x70, 0x65 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return "CD Check" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
// GetVolumeInformation
|
||||
check = new byte[] { 0x47, 0x65, 0x74, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x49, 0x6E, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x69, 0x6F, 0x6E };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return "CD Check" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -7,14 +7,17 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class CDCops
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
int position;
|
||||
if ((position = fileContent.IndexOf("CD-Cops, ver. ")) > -1)
|
||||
return "CD-Cops " + GetVersion(file, position);
|
||||
// "CD-Cops, ver. "
|
||||
byte[] check = new byte[] { 0x43, 0x44, 0x2D, 0x43, 0x6F, 0x70, 0x73, 0x2C, 0x20, 0x20, 0x76, 0x65, 0x72, 0x2E, 0x20 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"CD-Cops {GetVersion(fileContent, position)}" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
if (fileContent.Contains(".grand" + (char)0x00))
|
||||
return "CD-Cops";
|
||||
// ".grand" + (char)0x00
|
||||
check = new byte[] { 0x2E, 0x67, 0x72, 0x61, 0x6E, 0x64, 0x00};
|
||||
if (fileContent.Contains(check, out position))
|
||||
return "CD-Cops" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -23,11 +26,11 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
if (isDirectory)
|
||||
{
|
||||
if (files.Count(f => Path.GetFileName(f).Equals("CDCOPS.DLL", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
&& (files.Count(f => Path.GetExtension(f).Trim('.').Equals("GZ_", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetExtension(f).Trim('.').Equals("W_X", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetExtension(f).Trim('.').Equals("Qz", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetExtension(f).Trim('.').Equals("QZ_", StringComparison.OrdinalIgnoreCase)) > 0))
|
||||
if (files.Any(f => Path.GetFileName(f).Equals("CDCOPS.DLL", StringComparison.OrdinalIgnoreCase))
|
||||
&& (files.Any(f => Path.GetExtension(f).Trim('.').Equals("GZ_", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetExtension(f).Trim('.').Equals("W_X", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetExtension(f).Trim('.').Equals("Qz", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetExtension(f).Trim('.').Equals("QZ_", StringComparison.OrdinalIgnoreCase))))
|
||||
{
|
||||
return "CD-Cops";
|
||||
}
|
||||
@@ -47,21 +50,13 @@ namespace BurnOutSharp.ProtectionType
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetVersion(string file, int position)
|
||||
private static string GetVersion(byte[] fileContent, int position)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
char[] version = new ArraySegment<byte>(fileContent, position + 15, 4).Select(b => (char)b).ToArray();
|
||||
if (version[0] == 0x00)
|
||||
return "";
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
{
|
||||
br.BaseStream.Seek(position + 15, SeekOrigin.Begin); // Begin reading after "CD-Cops, ver."
|
||||
char[] version = br.ReadChars(4);
|
||||
if (version[0] == 0x00)
|
||||
return "";
|
||||
|
||||
return new string(version);
|
||||
}
|
||||
return new string(version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,14 +7,12 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class CDLock
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
if (fileContent.Contains("2" + (char)0xF2 + (char)0x02 + (char)0x82 + (char)0xC3 + (char)0xBC + (char)0x0B
|
||||
+ "$" + (char)0x99 + (char)0xAD + "'C" + (char)0xE4 + (char)0x9D + "st"
|
||||
+ (char)0x99 + (char)0xFA + "2$" + (char)0x9D + ")4" + (char)0xFF + "t"))
|
||||
{
|
||||
return "CD-Lock";
|
||||
}
|
||||
// "2" + (char)0xF2 + (char)0x02 + (char)0x82 + (char)0xC3 + (char)0xBC + (char)0x0B + "$" + (char)0x99 + (char)0xAD + "'C" + (char)0xE4 + (char)0x9D + "st" + (char)0x99 + (char)0xFA + "2$" + (char)0x9D + ")4" + (char)0xFF + "t"
|
||||
byte[] check = new byte[] { 0x32, 0xF2, 0x02, 0x82, 0xC3, 0xBC, 0x0B, 0x24, 0x99, 0xAD, 0x27, 0x43, 0xE4, 0x9D, 0x73, 0x74, 0x99, 0xFA, 0x32, 0x24, 0x9D, 0x29, 0x34, 0xFF, 0x74 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return "CD-Lock" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -23,7 +21,7 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
if (isDirectory)
|
||||
{
|
||||
if (files.Count(f => Path.GetExtension(f).Trim('.').Equals("AFP", StringComparison.OrdinalIgnoreCase)) > 0)
|
||||
if (files.Any(f => Path.GetExtension(f).Trim('.').Equals("AFP", StringComparison.OrdinalIgnoreCase)))
|
||||
return "CD-Lock";
|
||||
}
|
||||
else
|
||||
|
||||
@@ -12,10 +12,10 @@ namespace BurnOutSharp.ProtectionType
|
||||
if (isDirectory)
|
||||
{
|
||||
// TODO: Verify if these are OR or AND
|
||||
if (files.Count(f => Path.GetFileName(f).Equals("_cdp16.dat", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetFileName(f).Equals("_cdp16.dll", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetFileName(f).Equals("_cdp32.dat", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetFileName(f).Equals("_cdp32.dll", StringComparison.OrdinalIgnoreCase)) > 0)
|
||||
if (files.Any(f => Path.GetFileName(f).Equals("_cdp16.dat", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetFileName(f).Equals("_cdp16.dll", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetFileName(f).Equals("_cdp32.dat", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetFileName(f).Equals("_cdp32.dll", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return "CD-Protector";
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
{
|
||||
public class CDSHiELDSE
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
if (fileContent.Contains("~0017.tmp"))
|
||||
return "CDSHiELD SE";
|
||||
// "~0017.tmp"
|
||||
byte[] check = new byte[] { 0x7E, 0x30, 0x30, 0x31, 0x37, 0x2E, 0x74, 0x6D, 0x70 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return "CDSHiELD SE" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -12,9 +12,9 @@ namespace BurnOutSharp.ProtectionType
|
||||
if (isDirectory)
|
||||
{
|
||||
// TODO: Verify if these are OR or AND
|
||||
if (files.Count(f => Path.GetFileName(f).Equals("CHKCDX16.DLL", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetFileName(f).Equals("CHKCDX32.DLL", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetFileName(f).Equals("CHKCDXNT.DLL", StringComparison.OrdinalIgnoreCase)) > 0)
|
||||
if (files.Any(f => Path.GetFileName(f).Equals("CHKCDX16.DLL", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetFileName(f).Equals("CHKCDX32.DLL", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetFileName(f).Equals("CHKCDXNT.DLL", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return "CD-X";
|
||||
}
|
||||
|
||||
@@ -8,15 +8,22 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class CactusDataShield
|
||||
{
|
||||
public static string CheckContents(string file)
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
if (Path.GetFileName(file) == "CDSPlayer.app")
|
||||
{
|
||||
using (var sr = new StreamReader(file, Encoding.Default))
|
||||
{
|
||||
return "Cactus Data Shield " + sr.ReadLine().Substring(3) + "(" + sr.ReadLine() + ")";
|
||||
}
|
||||
}
|
||||
// DATA.CDS
|
||||
byte[] check = new byte[] { 0x44, 0x41, 0x54, 0x41, 0x2E, 0x43, 0x44, 0x53 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return "Cactus Data Shield 200" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
// \*.CDS
|
||||
check = new byte[] { 0x5C, 0x2A, 0x2E, 0x43, 0x44, 0x53 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return "Cactus Data Shield 200" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
// CDSPlayer
|
||||
check = new byte[] { 0x43, 0x44, 0x53, 0x50, 0x6C, 0x61, 0x79, 0x65, 0x72 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return "Cactus Data Shield 200" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -25,34 +32,30 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
if (isDirectory)
|
||||
{
|
||||
// TODO: Verify if these are OR or AND
|
||||
if (files.Count(f => Path.GetFileName(f).Equals("CDSPlayer.app", StringComparison.OrdinalIgnoreCase)) > 0)
|
||||
{
|
||||
string file = files.First(f => Path.GetFileName(f).Equals("CDSPlayer.app", StringComparison.OrdinalIgnoreCase));
|
||||
string protection = CheckContents(file);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
return protection;
|
||||
}
|
||||
else if (files.Count(f => Path.GetFileName(f).Equals("yucca.cds", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetFileName(f).Equals("wmmp.exe", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetFileName(f).Equals("PJSTREAM.DLL", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetFileName(f).Equals("CACTUSPJ.exe", StringComparison.OrdinalIgnoreCase)) > 0)
|
||||
if (files.Any(f => Path.GetFileName(f).Equals("CACTUSPJ.exe", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetFileName(f).Equals("CDSPlayer.app", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetFileName(f).Equals("PJSTREAM.DLL", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetFileName(f).Equals("wmmp.exe", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetExtension(f).Trim('.').Equals("cds", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
string versionPath = files.FirstOrDefault(f => Path.GetFileName(f).Equals("version.txt", StringComparison.OrdinalIgnoreCase));
|
||||
if (!string.IsNullOrWhiteSpace(versionPath))
|
||||
{
|
||||
string version = GetVersion(versionPath);
|
||||
if (!string.IsNullOrWhiteSpace(version))
|
||||
return $"Cactus Data Shield {version}";
|
||||
}
|
||||
|
||||
return "Cactus Data Shield 200";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Path.GetFileName(path).Equals("CDSPlayer.app", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
string protection = CheckContents(path);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
return protection;
|
||||
}
|
||||
else if (Path.GetFileName(path).Equals("yucca.cds", StringComparison.OrdinalIgnoreCase)
|
||||
|| Path.GetFileName(path).Equals("wmmp.exe", StringComparison.OrdinalIgnoreCase)
|
||||
if (Path.GetFileName(path).Equals("CACTUSPJ.exe", StringComparison.OrdinalIgnoreCase)
|
||||
|| Path.GetFileName(path).Equals("CDSPlayer.app", StringComparison.OrdinalIgnoreCase)
|
||||
|| Path.GetFileName(path).Equals("PJSTREAM.DLL", StringComparison.OrdinalIgnoreCase)
|
||||
|| Path.GetFileName(path).Equals("CACTUSPJ.exe", StringComparison.OrdinalIgnoreCase))
|
||||
|| Path.GetFileName(path).Equals("wmmp.exe", StringComparison.OrdinalIgnoreCase)
|
||||
|| Path.GetExtension(path).Trim('.').Equals("cds", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return "Cactus Data Shield 200";
|
||||
}
|
||||
@@ -60,5 +63,23 @@ namespace BurnOutSharp.ProtectionType
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetVersion(string path)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
using (var sr = new StreamReader(path, Encoding.Default))
|
||||
{
|
||||
return $"{sr.ReadLine().Substring(3)} ({sr.ReadLine()})";
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
{
|
||||
public class CengaProtectDVD
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
if (fileContent.Contains(".cenega"))
|
||||
return "Cenega ProtectDVD";
|
||||
// ".cenega"
|
||||
byte[] check = new byte[] { 0x2E, 0x63, 0x65, 0x6E, 0x65, 0x67, 0x61 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return "Cenega ProtectDVD" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2,15 +2,23 @@
|
||||
{
|
||||
public class CodeLock
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
// TODO: Verify if these are OR or AND
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
// TODO: Verify if these are OR or AND
|
||||
if (fileContent.Contains("icd1" + (char)0x00)
|
||||
|| fileContent.Contains("icd2" + (char)0x00)
|
||||
|| fileContent.Contains("CODE-LOCK.OCX"))
|
||||
{
|
||||
return "Code Lock";
|
||||
}
|
||||
// "icd1" + (char)0x00
|
||||
byte[] check = new byte[] { 0x69, 0x63, 0x64, 0x31, 0x00 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return "Code Lock" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
// "icd2" + (char)0x00
|
||||
check = new byte[] { 0x69, 0x63, 0x64, 0x32, 0x00 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return "Code Lock" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
// "CODE-LOCK.OCX"
|
||||
check = new byte[] { 0x43, 0x4F, 0x44, 0x45, 0x2D, 0x4C, 0x4F, 0x43, 0x4B, 0x2E, 0x4F, 0x43, 0x58 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return "Code Lock" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -7,10 +7,12 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class CopyKiller
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
if (fileContent.Contains("Tom Commander"))
|
||||
return "CopyKiller";
|
||||
// "Tom Commander"
|
||||
byte[] check = new byte[] { 0x54, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x61, 0x6E, 0x64, 0x65, 0x72 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return "CopyKiller" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -19,7 +21,7 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
if (isDirectory)
|
||||
{
|
||||
if (files.Count(f => Path.GetFileName(f).Equals("Autorun.dat", StringComparison.OrdinalIgnoreCase)) > 0)
|
||||
if (files.Any(f => Path.GetFileName(f).Equals("Autorun.dat", StringComparison.OrdinalIgnoreCase)))
|
||||
return "CopyKiller";
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class Cucko
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
{
|
||||
// TODO: Verify this doesn't over-match
|
||||
if (fileContent.Contains("EASTL"))
|
||||
return "Cucko (EA Custom)";
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +1,27 @@
|
||||
using System.IO;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class DVDCops
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
int position;
|
||||
if ((position = fileContent.IndexOf("DVD-Cops, ver. ")) > -1)
|
||||
return "DVD-Cops " + GetVersion(file, position);
|
||||
// "DVD-Cops, ver. "
|
||||
byte[] check = new byte[] { 0x44, 0x56, 0x44, 0x2D, 0x43, 0x6F, 0x70, 0x73, 0x2C, 0x20, 0x20, 0x76, 0x65, 0x72, 0x2E, 0x20 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"DVD-Cops {GetVersion(fileContent, position)}" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetVersion(string file, int position)
|
||||
private static string GetVersion(byte[] fileContent, int position)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
char[] version = new ArraySegment<byte>(fileContent, position + 15, 4).Select(b => (char)b).ToArray();
|
||||
if (version[0] == 0x00)
|
||||
return "";
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
{
|
||||
br.BaseStream.Seek(position + 15, SeekOrigin.Begin); // Begin reading after "CD-Cops, ver."
|
||||
char[] version = br.ReadChars(4);
|
||||
if (version[0] == 0x00)
|
||||
return "";
|
||||
|
||||
return new string(version);
|
||||
}
|
||||
return new string(version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
if (isDirectory)
|
||||
{
|
||||
if (files.Count(f => Path.GetFileName(f).Equals("DvdCrypt.pdb", StringComparison.OrdinalIgnoreCase)) > 0)
|
||||
if (files.Any(f => Path.GetFileName(f).Equals("DvdCrypt.pdb", StringComparison.OrdinalIgnoreCase)))
|
||||
return "DVD Crypt";
|
||||
}
|
||||
else
|
||||
|
||||
@@ -11,8 +11,8 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
if (isDirectory)
|
||||
{
|
||||
if (files.Count(f => Path.GetFileName(f).Equals("IOSLINK.VXD", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
&& files.Count(f => Path.GetFileName(f).Equals("IOSLINK.SYS", StringComparison.OrdinalIgnoreCase)) > 0)
|
||||
if (files.Any(f => Path.GetFileName(f).Equals("IOSLINK.VXD", StringComparison.OrdinalIgnoreCase))
|
||||
&& files.Any(f => Path.GetFileName(f).Equals("IOSLINK.SYS", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return "DiscGuard";
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class EACdKey
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
{
|
||||
if (fileContent.Contains("ereg.ea-europe.com"))
|
||||
return "EA CdKey Registration Module";
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class EXEStealth
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
{
|
||||
if (fileContent.Contains("??[[__[[_" + (char)0x00 + "{{" + (char)0x0
|
||||
+ (char)0x00 + "{{" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x0
|
||||
+ (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + "?;??;??"))
|
||||
{
|
||||
return "EXE Stealth";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
46
BurnOutSharp/ProtectionType/ElectronicArts.cs
Normal file
46
BurnOutSharp/ProtectionType/ElectronicArts.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class ElectronicArts
|
||||
{
|
||||
// TODO: Verify this doesn't over-match
|
||||
public static string CheckContents(string file, byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
// EASTL
|
||||
byte[] check = new byte[] { 0x45, 0x41, 0x53, 0x54, 0x4C };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return "Cucko (EA Custom)" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
// R + (char)0x00 + e + (char)0x00 + g + (char)0x00 + i + (char)0x00 + s + (char)0x00 + t + (char)0x00 + r + (char)0x00 + a + (char)0x00 + t + (char)0x00 + i + (char)0x00 + o + (char)0x00 + n + (char)0x00 + + (char)0x00 + C + (char)0x00 + o + (char)0x00 + d + (char)0x00 + e + (char)0x00
|
||||
check = new byte[] { 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6F, 0x00, 0x64, 0x00, 0x65, 0x00 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"EA CdKey Registration Module {Utilities.GetFileVersion(file)}" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
// R + (char)0x00 + e + (char)0x00 + g + (char)0x00 + i + (char)0x00 + s + (char)0x00 + t + (char)0x00 + r + (char)0x00 + a + (char)0x00 + t + (char)0x00 + i + (char)0x00 + o + (char)0x00 + n + (char)0x00 + + (char)0x00 + c + (char)0x00 + o + (char)0x00 + d + (char)0x00 + e + (char)0x00
|
||||
check = new byte[] { 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6F, 0x00, 0x64, 0x00, 0x65, 0x00 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"EA CdKey Registration Module {Utilities.GetFileVersion(file)}" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
// C + (char)0x00 + D + (char)0x00 + K + (char)0x00 + e + (char)0x00 + y + (char)0x00
|
||||
check = new byte[] { 0x43, 0x00, 0x44, 0x00, 0x4B, 0x00, 0x65, 0x00, 0x79, 0x00 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"EA CdKey Registration Module {Utilities.GetFileVersion(file)}" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
// ereg.ea-europe.com
|
||||
check = new byte[] { 0x65, 0x72, 0x65, 0x67, 0x2E, 0x65, 0x61, 0x2D, 0x65, 0x75, 0x72, 0x6F, 0x70, 0x65, 0x2E, 0x63, 0x6F, 0x6D };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"EA CdKey Registration Module {Utilities.GetFileVersion(file)}" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
// GenericEA + (char)0x00 + (char)0x00 + (char)0x00 + Activation
|
||||
check = new byte[] { 0x47, 0x65, 0x6E, 0x65, 0x72, 0x69, 0x63, 0x45, 0x41, 0x00, 0x00, 0x00, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6F, 0x6E };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return "EA DRM Protection" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
// E + (char)0x00 + A + (char)0x00 + + (char)0x00 + D + (char)0x00 + R + (char)0x00 + M + (char)0x00 + + (char)0x00 + H + (char)0x00 + e + (char)0x00 + l + (char)0x00 + p + (char)0x00 + e + (char)0x00 + r
|
||||
check = new byte[] { 0x45, 0x00, 0x41, 0x00, 0x20, 0x00, 0x44, 0x00, 0x52, 0x00, 0x4D, 0x00, 0x20, 0x00, 0x48, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x70, 0x00, 0x65, 0x00, 0x72 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return "EA DRM Protection" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
if (isDirectory)
|
||||
{
|
||||
if (files.Count(f => Path.GetFileName(f).Equals("FREELOCK.IMG", StringComparison.OrdinalIgnoreCase)) > 0)
|
||||
if (files.Any(f => Path.GetFileName(f).Equals("FREELOCK.IMG", StringComparison.OrdinalIgnoreCase)))
|
||||
return "FreeLock";
|
||||
}
|
||||
else
|
||||
|
||||
@@ -7,10 +7,12 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class GFWL
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
if (fileContent.Contains("xlive.dll"))
|
||||
return "Games for Windows - Live";
|
||||
// "xlive.dll"
|
||||
byte[] check = new byte[] { 0x78, 0x6C, 0x69, 0x76, 0x65, 0x2E, 0x64, 0x6C, 0x6C };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return "Games for Windows - Live" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -19,7 +21,7 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
if (isDirectory)
|
||||
{
|
||||
if (files.Count(f => Path.GetFileName(f).Equals("XLiveRedist.msi", StringComparison.OrdinalIgnoreCase)) > 0)
|
||||
if (files.Any(f => Path.GetFileName(f).Equals("XLiveRedist.msi", StringComparison.OrdinalIgnoreCase)))
|
||||
return "Games for Windows - Live";
|
||||
}
|
||||
else
|
||||
|
||||
@@ -12,10 +12,10 @@ namespace BurnOutSharp.ProtectionType
|
||||
if (isDirectory)
|
||||
{
|
||||
// TODO: Verify if these are OR or AND
|
||||
if (files.Count(f => Path.GetFileName(f).Equals("Start_Here.exe", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetFileName(f).Equals("HCPSMng.exe", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetFileName(f).Equals("MFINT.DLL", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetFileName(f).Equals("MFIMP.DLL", StringComparison.OrdinalIgnoreCase)) > 0)
|
||||
if (files.Any(f => Path.GetFileName(f).Equals("Start_Here.exe", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetFileName(f).Equals("HCPSMng.exe", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetFileName(f).Equals("MFINT.DLL", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetFileName(f).Equals("MFIMP.DLL", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return "Hexalock AutoLock";
|
||||
}
|
||||
|
||||
@@ -7,22 +7,18 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class ImpulseReactor
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
public static string CheckContents(string file, byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
if (fileContent.Contains("CVPInitializeClient"))
|
||||
// "CVPInitializeClient"
|
||||
byte[] check = new byte[] { 0x43, 0x56, 0x50, 0x49, 0x6E, 0x69, 0x74, 0x69, 0x61, 0x6C, 0x69, 0x7A, 0x65, 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
{
|
||||
if (fileContent.Contains("A" + (char)0x00 + "T" + (char)0x00 + "T" + (char)0x00 + "L" + (char)0x00 + "I"
|
||||
+ (char)0x00 + "S" + (char)0x00 + "T" + (char)0x00 + (char)0x00 + (char)0x00 + "E" + (char)0x00 + "L"
|
||||
+ (char)0x00 + "E" + (char)0x00 + "M" + (char)0x00 + "E" + (char)0x00 + "N" + (char)0x00 + "T" + (char)0x00
|
||||
+ (char)0x00 + (char)0x00 + "N" + (char)0x00 + "O" + (char)0x00 + "T" + (char)0x00 + "A" + (char)0x00 + "T"
|
||||
+ (char)0x00 + "I" + (char)0x00 + "O" + (char)0x00 + "N"))
|
||||
{
|
||||
return "Impulse Reactor " + Utilities.GetFileVersion(file);
|
||||
}
|
||||
// "A" + (char)0x00 + "T" + (char)0x00 + "T" + (char)0x00 + "L" + (char)0x00 + "I" + (char)0x00 + "S" + (char)0x00 + "T" + (char)0x00 + (char)0x00 + (char)0x00 + "E" + (char)0x00 + "L" + (char)0x00 + "E" + (char)0x00 + "M" + (char)0x00 + "E" + (char)0x00 + "N" + (char)0x00 + "T" + (char)0x00 + (char)0x00 + (char)0x00 + "N" + (char)0x00 + "O" + (char)0x00 + "T" + (char)0x00 + "A" + (char)0x00 + "T" + (char)0x00 + "I" + (char)0x00 + "O" + (char)0x00 + "N"
|
||||
byte[] check2 = new byte[] { 0x41, 0x00, 0x54, 0x00, 0x54, 0x00, 0x4C, 0x00, 0x49, 0x00, 0x53, 0x00, 0x54, 0x00, 0x00, 0x00, 0x45, 0x00, 0x4C, 0x00, 0x45, 0x00, 0x4D, 0x00, 0x45, 0x00, 0x4E, 0x00, 0x54, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x4F, 0x00, 0x54, 0x00, 0x41, 0x00, 0x54, 0x00, 0x49, 0x00, 0x4F, 0x00, 0x4E };
|
||||
if (fileContent.Contains(check2, out int position2))
|
||||
return $"Impulse Reactor {Utilities.GetFileVersion(file)}" + (includePosition ? $" (Index {position}, {position2})" : string.Empty);
|
||||
else
|
||||
{
|
||||
return "Impulse Reactor";
|
||||
}
|
||||
return "Impulse Reactor" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -32,7 +28,7 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
if (isDirectory)
|
||||
{
|
||||
if (files.Count(f => Path.GetFileName(f).Equals("ImpulseReactor.dll", StringComparison.OrdinalIgnoreCase)) > 0)
|
||||
if (files.Any(f => Path.GetFileName(f).Equals("ImpulseReactor.dll", StringComparison.OrdinalIgnoreCase)))
|
||||
return "Impulse Reactor " + Utilities.GetFileVersion(files.First(f => Path.GetFileName(f).Equals("ImpulseReactor.dll", StringComparison.OrdinalIgnoreCase)));
|
||||
}
|
||||
else
|
||||
|
||||
@@ -12,8 +12,8 @@ namespace BurnOutSharp.ProtectionType
|
||||
if (isDirectory)
|
||||
{
|
||||
// TODO: Verify if these are OR or AND
|
||||
if (files.Count(f => Path.GetFileName(f).Equals("INDYVCD.AX", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetFileName(f).Equals("INDYMP3.idt", StringComparison.OrdinalIgnoreCase)) > 0)
|
||||
if (files.Any(f => Path.GetFileName(f).Equals("INDYVCD.AX", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetFileName(f).Equals("INDYMP3.idt", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return "IndyVCD";
|
||||
}
|
||||
|
||||
@@ -1,48 +1,55 @@
|
||||
using System.IO;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class InnoSetup
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
// TOOO: Add Inno Setup extraction
|
||||
// https://github.com/dscharrer/InnoExtract
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
if (fileContent.IndexOf("Inno") == 0x30)
|
||||
{
|
||||
// TOOO: Add Inno Setup extraction
|
||||
return "Inno Setup " + GetVersion(file);
|
||||
}
|
||||
// "Inno"
|
||||
byte[] check = new byte[] { 0x49, 0x6E, 0x6E, 0x6F };
|
||||
if (fileContent.Contains(check, out int position) && position == 0x30)
|
||||
return $"Inno Setup {GetVersion(fileContent)}" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetVersion(string file)
|
||||
private static string GetVersion(byte[] fileContent)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
byte[] signature = new ArraySegment<byte>(fileContent, 0x30, 12).ToArray();
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
{
|
||||
br.BaseStream.Seek(0x30, SeekOrigin.Begin);
|
||||
string signature = new string(br.ReadChars(12));
|
||||
// "rDlPtS02" + (char)0x87 + "eVx"
|
||||
if (signature.SequenceEqual( new byte[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0x30, 0x32, 0x87, 0x65, 0x56, 0x78 }))
|
||||
return "1.2.10";
|
||||
|
||||
if (signature == "rDlPtS02" + (char)0x87 + "eVx")
|
||||
return "1.2.10";
|
||||
else if (signature == "rDlPtS04" + (char)0x87 + "eVx")
|
||||
return "4.0.0";
|
||||
else if (signature == "rDlPtS05" + (char)0x87 + "eVx")
|
||||
return "4.0.3";
|
||||
else if (signature == "rDlPtS06" + (char)0x87 + "eVx")
|
||||
return "4.0.10";
|
||||
else if (signature == "rDlPtS07" + (char)0x87 + "eVx")
|
||||
return "4.1.6";
|
||||
else if (signature == "rDlPtS" + (char)0xcd + (char)0xe6 + (char)0xd7 + "{" + (char)0x0b + "*")
|
||||
return "5.1.5";
|
||||
else if (signature == "nS5W7dT" + (char)0x83 + (char)0xaa + (char)0x1b + (char)0x0f + "j")
|
||||
return "5.1.5";
|
||||
// "rDlPtS04" + (char)0x87 + "eVx"
|
||||
else if (signature.SequenceEqual(new byte[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0x30, 0x34, 0x87, 0x65, 0x56, 0x78 }))
|
||||
return "4.0.0";
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
// "rDlPtS05" + (char)0x87 + "eVx"
|
||||
else if (signature.SequenceEqual(new byte[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0x30, 0x35, 0x87, 0x65, 0x56, 0x78 }))
|
||||
return "4.0.3";
|
||||
|
||||
// "rDlPtS06" + (char)0x87 + "eVx"
|
||||
else if (signature.SequenceEqual(new byte[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0x30, 0x36, 0x87, 0x65, 0x56, 0x78 }))
|
||||
return "4.0.10";
|
||||
|
||||
// "rDlPtS07" + (char)0x87 + "eVx"
|
||||
else if (signature.SequenceEqual(new byte[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0x30, 0x37, 0x87, 0x65, 0x56, 0x78 }))
|
||||
return "4.1.6";
|
||||
|
||||
// "rDlPtS" + (char)0xcd + (char)0xe6 + (char)0xd7 + "{" + (char)0x0b + "*"
|
||||
else if (signature.SequenceEqual(new byte[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0xCD, 0xE6, 0xD7, 0x7B, 0x0b, 0x2A }))
|
||||
return "5.1.5";
|
||||
|
||||
// "nS5W7dT" + (char)0x83 + (char)0xaa + (char)0x1b + (char)0x0f + "j"
|
||||
else if (signature.SequenceEqual(new byte[] { 0x6E, 0x53, 0x35, 0x57, 0x37, 0x64, 0x54, 0x83, 0xAA, 0x1B, 0x0F, 0x6A }))
|
||||
return "5.1.5";
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
31
BurnOutSharp/ProtectionType/Intenium.cs
Normal file
31
BurnOutSharp/ProtectionType/Intenium.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class Intenium
|
||||
{
|
||||
/*
|
||||
* Possible strings for finding INTENIUM Trial & Buy Protection
|
||||
*
|
||||
* Luxor Only:
|
||||
* - command_buyNowCb - 63 6F 6D 6D 61 6E 64 5F 62 75 79 4E 6F 77 43 62
|
||||
* - command_testTrialCb - 63 6F 6D 6D 61 6E 64 5F 74 65 73 74 54 72 69 61 6C 43 62
|
||||
* - PHRASE_TRIAL - 50 48 52 41 53 45 5F 54 52 49 41 4C
|
||||
* - V_TRIAL_GAME - 56 5F 54 52 49 41 4C 5F 47 41 4D 45
|
||||
* - V_FULL_GAME - 56 5F 46 55 4C 4C 5F 47 41 4D 45
|
||||
*
|
||||
* Luxor, World, Cradle, and Kingdom:
|
||||
* - Trial + (char)0x00 + P - 54 72 69 61 6C 00 50
|
||||
* + This is possibly followed by a version number. Undetermined if it's the software or protection version.
|
||||
* - NO NESTED PRMS SUPPORTED - 4E 4F 20 4E 45 53 54 45 44 20 50 52 4D 53 20 53 55 50 50 4F 52 54 45 44
|
||||
*/
|
||||
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
// Trial + (char)0x00 + P
|
||||
byte[] check = new byte[] { 0x54, 0x72, 0x69, 0x61, 0x6C, 0x00, 0x50 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return "INTENIUM Trial & Buy Protection" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,51 +1,36 @@
|
||||
using System.IO;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class JoWooDXProt
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
int position;
|
||||
if (fileContent.Contains(".ext "))
|
||||
// ".ext "
|
||||
byte[] check = new byte[] { 0x2E, 0x65, 0x78, 0x74, 0x20, 0x20, 0x20, 0x20 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
{
|
||||
if ((position = fileContent.IndexOf("kernel32.dll" + (char)0x00 + (char)0x00 + (char)0x00 + "VirtualProtect")) > -1)
|
||||
{
|
||||
return "JoWooD X-Prot " + GetVersion(file, --position);
|
||||
}
|
||||
// "kernel32.dll" + (char)0x00 + (char)0x00 + (char)0x00 + "VirtualProtect"
|
||||
byte[] check2 = new byte[] { 0x6B, 0x65, 0x72, 0x6E, 0x65, 0x6C, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6C, 0x50, 0x72, 0x6F, 0x74, 0x65, 0x63, 0x74 };
|
||||
if (fileContent.Contains(check2, out int position2))
|
||||
return $"JoWooD X-Prot {GetVersion(fileContent, --position2)}" + (includePosition ? $" (Index {position}, {position2})" : string.Empty);
|
||||
else
|
||||
{
|
||||
return "JoWooD X-Prot v1";
|
||||
}
|
||||
return $"JoWooD X-Prot v1" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
}
|
||||
|
||||
if (fileContent.Contains("@HC09 "))
|
||||
return "JoWooD X-Prot v2";
|
||||
// "@HC09 "
|
||||
check = new byte[] { 0x40, 0x48, 0x43, 0x30, 0x39, 0x20, 0x20, 0x20, 0x20 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"JoWooD X-Prot v2" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetVersion(string file, int position)
|
||||
private static string GetVersion(byte[] fileContent, int position)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
{
|
||||
char[] version = new char[5];
|
||||
br.BaseStream.Seek(position + 67, SeekOrigin.Begin);
|
||||
version[0] = br.ReadChar();
|
||||
br.ReadByte();
|
||||
version[1] = br.ReadChar();
|
||||
br.ReadByte();
|
||||
version[2] = br.ReadChar();
|
||||
br.ReadByte();
|
||||
version[3] = br.ReadChar();
|
||||
version[4] = br.ReadChar();
|
||||
|
||||
return version[0] + "." + version[1] + "." + version[2] + "." + version[3] + version[4];
|
||||
}
|
||||
char[] version = new ArraySegment<byte>(fileContent, position + 67, 8).Select(b => (char)b).ToArray();
|
||||
return $"{version[0]}.{version[2]}.{version[4]}.{version[6]}{version[7]}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,10 +12,10 @@ namespace BurnOutSharp.ProtectionType
|
||||
if (isDirectory)
|
||||
{
|
||||
// TODO: Verify if these are OR or AND
|
||||
if (files.Count(f => Path.GetFileName(f).Equals("SDKHM.EXE", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetFileName(f).Equals("SDKHM.DLL", StringComparison.OrdinalIgnoreCase)) > 0)
|
||||
if (files.Any(f => Path.GetFileName(f).Equals("SDKHM.EXE", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetFileName(f).Equals("SDKHM.DLL", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return "Key2Audio XS";
|
||||
return "key2AudioXS";
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -23,7 +23,7 @@ namespace BurnOutSharp.ProtectionType
|
||||
if (Path.GetFileName(path).Equals("SDKHM.EXE", StringComparison.OrdinalIgnoreCase)
|
||||
|| Path.GetFileName(path).Equals("SDKHM.DLL", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return "Key2Audio XS";
|
||||
return "key2AudioXS";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
{
|
||||
public class KeyLock
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
if (fileContent.Contains("KEY-LOCK COMMAND"))
|
||||
return "Key-Lock (Dongle)";
|
||||
// "KEY-LOCK COMMAND"
|
||||
byte[] check = new byte[] { 0x4B, 0x45, 0x59, 0x2D, 0x4C, 0x4F, 0x43, 0x4B, 0x20, 0x43, 0x4F, 0x4D, 0x4D, 0x41, 0x4E, 0x44 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"Key-Lock (Dongle)" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -7,38 +7,35 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class LaserLock
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
public static string CheckContents(string file, byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
int position;
|
||||
if (fileContent.Contains("Packed by SPEEnc V2 Asterios Parlamentas.PE")
|
||||
&& (position = fileContent.IndexOf("GetModuleHandleA" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00
|
||||
+ "GetProcAddress" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + "LoadLibraryA" + (char)0x00 + (char)0x00
|
||||
+ "KERNEL32.dll" + (char)0x00 + "ëy" + (char)0x01 + "SNIF")) > -1)
|
||||
{
|
||||
return "LaserLock " + GetVersion(fileContent, position) + " " + GetBuild(fileContent, true);
|
||||
}
|
||||
// "Packed by SPEEnc V2 Asterios Parlamentas.PE"
|
||||
byte[] check = new byte[] { 0x50, 0x61, 0x63, 0x6B, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x53, 0x50, 0x45, 0x45, 0x6E, 0x63, 0x20, 0x56, 0x32, 0x20, 0x41, 0x73, 0x74, 0x65, 0x72, 0x69, 0x6F, 0x73, 0x20, 0x50, 0x61, 0x72, 0x6C, 0x61, 0x6D, 0x65, 0x6E, 0x74, 0x61, 0x73, 0x2E, 0x50, 0x45 };
|
||||
bool containsCheck = fileContent.Contains(check, out int position);
|
||||
|
||||
if (fileContent.Contains("Packed by SPEEnc V2 Asterios Parlamentas.PE"))
|
||||
return "LaserLock Marathon " + GetBuild(fileContent, false);
|
||||
// "GetModuleHandleA" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + "GetProcAddress" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + "LoadLibraryA" + (char)0x00 + (char)0x00 + "KERNEL32.dll" + (char)0x00 + "ëy" + (char)0x01 + "SNIF"
|
||||
byte[] check2 = { 0x47, 0x65, 0x74, 0x4D, 0x6F, 0x64, 0x75, 0x6C, 0x65, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x41, 0x00, 0x00, 0x00, 0x00, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6F, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x6F, 0x61, 0x64, 0x4C, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x41, 0x00, 0x00, 0x4B, 0x45, 0x52, 0x4E, 0x45, 0x4C, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0xEB, 0x79, 0x01, 0x53, 0x4E, 0x49, 0x46 };
|
||||
bool containsCheck2 = fileContent.Contains(check2, out int position2);
|
||||
|
||||
if ((position = fileContent.IndexOf("GetModuleHandleA" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00
|
||||
+ "GetProcAddress" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + "LoadLibraryA" + (char)0x00 + (char)0x00
|
||||
+ "KERNEL32.dll" + (char)0x00 + "ëy" + (char)0x01 + "SNIF")) > -1)
|
||||
{
|
||||
return "LaserLock " + GetVersion(fileContent, --position) + " " + GetBuild(fileContent, false);
|
||||
}
|
||||
if (containsCheck && containsCheck2)
|
||||
return $"LaserLock {GetVersion(fileContent, position2)} {GetBuild(fileContent, true)}" + (includePosition ? $" (Index {position}, {position2})" : string.Empty);
|
||||
else if (containsCheck && !containsCheck2)
|
||||
return $"LaserLock Marathon {GetBuild(fileContent, false)}" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
else if (!containsCheck && containsCheck2)
|
||||
return $"LaserLock {GetVersion(fileContent, --position2)} {GetBuild(fileContent, false)}" + (includePosition ? $" (Index {position2})" : string.Empty);
|
||||
|
||||
if (file != null && Path.GetFileName(file) == "NOMOUSE.SP")
|
||||
return "LaserLock " + GetVersion16Bit(file);
|
||||
if (file != null && string.Equals(Path.GetFileName(file), "NOMOUSE.SP", StringComparison.OrdinalIgnoreCase))
|
||||
return $"LaserLock {GetVersion16Bit(fileContent)}" + (includePosition ? $" (Index 71)" : string.Empty);
|
||||
|
||||
if (fileContent.Contains(":\\LASERLOK\\LASERLOK.IN" + (char)0x00 + "C:\\NOMOUSE.SP"))
|
||||
return "LaserLock 3";
|
||||
// ":\\LASERLOK\\LASERLOK.IN" + (char)0x00 + "C:\\NOMOUSE.SP"
|
||||
check = new byte[] { 0x3A, 0x5C, 0x5C, 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x5C, 0x5C, 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x2E, 0x49, 0x4E, 0x00, 0x43, 0x3A, 0x5C, 0x5C, 0x4E, 0x4F, 0x4D, 0x4F, 0x55, 0x53, 0x45, 0x2E, 0x53, 0x50 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return "LaserLock 3" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
if (fileContent.Contains("LASERLOK_INIT" + (char)0xC + "LASERLOK_RUN" + (char)0xE + "LASERLOK_CHECK"
|
||||
+ (char)0xF + "LASERLOK_CHECK2" + (char)0xF + "LASERLOK_CHECK3"))
|
||||
{
|
||||
return "LaserLock 5";
|
||||
}
|
||||
// "LASERLOK_INIT" + (char)0xC + "LASERLOK_RUN" + (char)0xE + "LASERLOK_CHECK" + (char)0xF + "LASERLOK_CHECK2" + (char)0xF + "LASERLOK_CHECK3"
|
||||
check = new byte[] { 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x5F, 0x49, 0x4E, 0x49, 0x54, 0x0C, 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x5F, 0x52, 0x55, 0x4E, 0x0E, 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x5F, 0x43, 0x48, 0x45, 0x43, 0x4B, 0x0F, 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x5F, 0x43, 0x48, 0x45, 0x43, 0x4B, 0x32, 0x0F, 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x5F, 0x43, 0x48, 0x45, 0x43, 0x4B, 0x33 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return "LaserLock 5" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -53,18 +50,21 @@ namespace BurnOutSharp.ProtectionType
|
||||
}
|
||||
|
||||
// TODO: Verify if these are OR or AND
|
||||
else if (files.Count(f => Path.GetFileName(f).Equals("NOMOUSE.SP", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetFileName(f).Equals("NOMOUSE.COM", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetFileName(f).Equals("l16dll.dll", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetFileName(f).Equals("laserlok.in", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetFileName(f).Equals("laserlok.o10", StringComparison.OrdinalIgnoreCase)) > 0
|
||||
|| files.Count(f => Path.GetFileName(f).Equals("laserlok.011", StringComparison.OrdinalIgnoreCase)) > 0)
|
||||
else if (files.Any(f => Path.GetFileName(f).Equals("NOMOUSE.SP", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetFileName(f).Equals("NOMOUSE.COM", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetFileName(f).Equals("l16dll.dll", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetFileName(f).Equals("laserlok.in", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetFileName(f).Equals("laserlok.o10", StringComparison.OrdinalIgnoreCase))
|
||||
|| files.Any(f => Path.GetFileName(f).Equals("laserlok.011", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return "LaserLock";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (path != null && string.Equals(Path.GetFileName(path), "NOMOUSE.SP", StringComparison.OrdinalIgnoreCase))
|
||||
return $"LaserLock {GetVersion16Bit(path)}";
|
||||
|
||||
if (Path.GetFileName(path).Equals("NOMOUSE.SP", StringComparison.OrdinalIgnoreCase)
|
||||
|| Path.GetFileName(path).Equals("NOMOUSE.COM", StringComparison.OrdinalIgnoreCase)
|
||||
|| Path.GetFileName(path).Equals("l16dll.dll", StringComparison.OrdinalIgnoreCase)
|
||||
@@ -79,30 +79,37 @@ namespace BurnOutSharp.ProtectionType
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetBuild(string fileContent, bool versionTwo)
|
||||
private static string GetBuild(byte[] fileContent, bool versionTwo)
|
||||
{
|
||||
// TODO: Is this supposed to be "Unknown"?
|
||||
int position = fileContent.IndexOf("Unkown" + (char)0 + "Unkown");
|
||||
// "Unkown" + (char)0x00 + "Unkown" // TODO: Is this supposed to be "Unknown"?
|
||||
byte[] check = new byte[] { 0x55, 0x6E, 0x6B, 0x6F, 0x77, 0x6E, 0x00, 0x55, 0x6E, 0x6B, 0x6F, 0x77, 0x6E };
|
||||
fileContent.Contains(check, out int position);
|
||||
string year, month, day;
|
||||
if (versionTwo)
|
||||
{
|
||||
day = fileContent.Substring(position + 14, 2);
|
||||
month = fileContent.Substring(position + 14 + 3, 2);
|
||||
year = "20" + fileContent.Substring(position + 14 + 6, 2);
|
||||
int index = position + 14;
|
||||
day = new string(new ArraySegment<byte>(fileContent, index, 2).Select(b => (char)b).ToArray());
|
||||
index += 3;
|
||||
month = new string(new ArraySegment<byte>(fileContent, index, 2).Select(b => (char)b).ToArray());
|
||||
index += 3;
|
||||
year = "20" + new string(new ArraySegment<byte>(fileContent, index, 2).Select(b => (char)b).ToArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
day = fileContent.Substring(position + 13, 2);
|
||||
month = fileContent.Substring(position + 13 + 3, 2);
|
||||
year = "20" + fileContent.Substring(position + 13 + 6, 2);
|
||||
int index = position + 13;
|
||||
day = new string(new ArraySegment<byte>(fileContent, index, 2).Select(b => (char)b).ToArray());
|
||||
index += 3;
|
||||
month = new string(new ArraySegment<byte>(fileContent, index, 2).Select(b => (char)b).ToArray());
|
||||
index += 3;
|
||||
year = "20" + new string(new ArraySegment<byte>(fileContent, index, 2).Select(b => (char)b).ToArray());
|
||||
}
|
||||
|
||||
return "(Build " + year + "-" + month + "-" + day + ")";
|
||||
return $"(Build {year}-{month}-{day})";
|
||||
}
|
||||
|
||||
private static string GetVersion(string FileContent, int position)
|
||||
private static string GetVersion(byte[] fileContent, int position)
|
||||
{
|
||||
return FileContent.Substring(position + 76, 4);
|
||||
return new string(new ArraySegment<byte>(fileContent, position + 76, 4).Select(b => (char)b).ToArray());
|
||||
}
|
||||
|
||||
private static string GetVersion16Bit(string file)
|
||||
@@ -110,18 +117,17 @@ namespace BurnOutSharp.ProtectionType
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
{
|
||||
char[] version = new char[3];
|
||||
br.BaseStream.Seek(71, SeekOrigin.Begin);
|
||||
version[0] = br.ReadChar();
|
||||
br.ReadByte();
|
||||
version[1] = br.ReadChar();
|
||||
version[2] = br.ReadChar();
|
||||
|
||||
if (char.IsNumber(version[0]) && char.IsNumber(version[1]) && char.IsNumber(version[2]))
|
||||
return version[0] + "." + version[1] + version[2];
|
||||
|
||||
return "";
|
||||
return GetVersion16Bit(br.ReadBytes((int)fs.Length));
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetVersion16Bit(byte[] fileContent)
|
||||
{
|
||||
char[] version = new ArraySegment<byte>(fileContent, 71, 4).Select(b => (char)b).ToArray();
|
||||
if (char.IsNumber(version[0]) && char.IsNumber(version[2]) && char.IsNumber(version[3]))
|
||||
return $"{version[0]}.{version[2]}{version[3]}";
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
if (isDirectory)
|
||||
{
|
||||
if (files.Count(f => Path.GetFileName(f).Equals("sunncomm.ico", StringComparison.OrdinalIgnoreCase)) > 0)
|
||||
if (files.Any(f => Path.GetFileName(f).Equals("sunncomm.ico", StringComparison.OrdinalIgnoreCase)))
|
||||
return "MediaCloQ";
|
||||
}
|
||||
else
|
||||
|
||||
@@ -7,17 +7,32 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class MediaMaxCD3
|
||||
{
|
||||
public static string CheckContents(byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
// Cd3Ctl
|
||||
byte[] check = new byte[] { 0x43, 0x64, 0x33, 0x43, 0x74, 0x6C };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return "MediaMax CD-3" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
// DllInstallSbcp
|
||||
check = new byte[] { 0x44, 0x6C, 0x6C, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6C, 0x6C, 0x53, 0x62, 0x63, 0x70 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return "MediaMax CD-3" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string CheckPath(string path, IEnumerable<string> files, bool isDirectory)
|
||||
{
|
||||
if (isDirectory)
|
||||
{
|
||||
if (files.Count(f => Path.GetFileName(f).Equals("LaunchCd.exe", StringComparison.OrdinalIgnoreCase)) > 0)
|
||||
return "MediaMax CD3";
|
||||
if (files.Any(f => Path.GetFileName(f).Equals("LaunchCd.exe", StringComparison.OrdinalIgnoreCase)))
|
||||
return "MediaMax CD-3";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Path.GetFileName(path).Equals("LaunchCd.exe", StringComparison.OrdinalIgnoreCase))
|
||||
return "MediaMax CD3";
|
||||
return "MediaMax CD-3";
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
if (isDirectory)
|
||||
{
|
||||
if (files.Count(f => Path.GetFileName(f).Equals("OriginSetup.exe", StringComparison.OrdinalIgnoreCase)) > 0)
|
||||
if (files.Any(f => Path.GetFileName(f).Equals("OriginSetup.exe", StringComparison.OrdinalIgnoreCase)))
|
||||
return "Origin";
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class PECompact
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
{
|
||||
if (fileContent.Contains("PEC2"))
|
||||
return "PE Compact 2";
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,45 +1,20 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class PSXAntiModchip
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
// TODO: Figure out PSX binary header so this can be checked explicitly
|
||||
// TODO: Detect Red Hand protection
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
// TODO: Detect Red Hand protection
|
||||
if (fileContent.Contains(" SOFTWARE TERMINATED\nCONSOLE MAY HAVE BEEN MODIFIED\n CALL 1-888-780-7690"))
|
||||
return "PlayStation Anti-modchip (English)";
|
||||
// " SOFTWARE TERMINATED\nCONSOLE MAY HAVE BEEN MODIFIED\n CALL 1-888-780-7690"
|
||||
byte[] check = new byte[] { 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x4F, 0x46, 0x54, 0x57, 0x41, 0x52, 0x45, 0x20, 0x54, 0x45, 0x52, 0x4D, 0x49, 0x4E, 0x41, 0x54, 0x45, 0x44, 0x5C, 0x6E, 0x43, 0x4F, 0x4E, 0x53, 0x4F, 0x4C, 0x45, 0x20, 0x4D, 0x41, 0x59, 0x20, 0x48, 0x41, 0x56, 0x45, 0x20, 0x42, 0x45, 0x45, 0x4E, 0x20, 0x4D, 0x4F, 0x44, 0x49, 0x46, 0x49, 0x45, 0x44, 0x5C, 0x6E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x41, 0x4C, 0x4C, 0x20, 0x31, 0x2D, 0x38, 0x38, 0x38, 0x2D, 0x37, 0x38, 0x30, 0x2D, 0x37, 0x36, 0x39, 0x30 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"PlayStation Anti-modchip (English) (Index {position})";
|
||||
|
||||
if (fileContent.Contains("強制終了しました。\n本体が改造されている\nおそれがあります。"))
|
||||
return "PlayStation Anti-modchip (Japanese)";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string CheckPath(string path, IEnumerable<string> files, bool isDirectory)
|
||||
{
|
||||
if (isDirectory)
|
||||
{
|
||||
if (files.Where(s => s.ToLowerInvariant().EndsWith(".cnf")).Count() > 0)
|
||||
{
|
||||
foreach (string file in files)
|
||||
{
|
||||
// Load the current file content
|
||||
string fileContent = null;
|
||||
using (StreamReader sr = new StreamReader(file, Encoding.Default))
|
||||
{
|
||||
fileContent = sr.ReadToEnd();
|
||||
}
|
||||
|
||||
string protection = CheckContents(path, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
return protection;
|
||||
}
|
||||
}
|
||||
}
|
||||
// "強制終了しました。\n本体が改造されている\nおそれがあります。"
|
||||
check = new byte[] { 0x5F, 0x37, 0x52, 0x36, 0x7D, 0x42, 0x4E, 0x86, 0x30, 0x57, 0x30, 0x7E, 0x30, 0x57, 0x30, 0x5F, 0x30, 0x02, 0x5C, 0x6E, 0x67, 0x2C, 0x4F, 0x53, 0x30, 0x4C, 0x65, 0x39, 0x90, 0x20, 0x30, 0x55, 0x30, 0x8C, 0x30, 0x66, 0x30, 0x44, 0x30, 0x8B, 0x5C, 0x6E, 0x30, 0x4A, 0x30, 0x5D, 0x30, 0x8C, 0x30, 0x4C, 0x30, 0x42, 0x30, 0x8A, 0x30, 0x7E, 0x30, 0x59, 0x30, 0x02 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"PlayStation Anti-modchip (Japanese) (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,164 +1,336 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class ProtectDisc
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
public static string CheckContents(string file, byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
int position;
|
||||
if ((position = fileContent.IndexOf("HúMETINF")) > -1)
|
||||
// "HúMETINF"
|
||||
byte[] check = new byte[] { 0x48, 0xFA, 0x4D, 0x45, 0x54, 0x49, 0x4E, 0x46 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
{
|
||||
string version = EVORE.SearchProtectDiscVersion(file);
|
||||
string version = SearchProtectDiscVersion(file, fileContent);
|
||||
if (version.Length > 0)
|
||||
{
|
||||
string[] astrVersionArray = version.Split('.');
|
||||
if (astrVersionArray[0] == "9")
|
||||
{
|
||||
if (GetVersionBuild76till10(file, position, out int ibuild).Length > 0)
|
||||
return "ProtectDisc " + astrVersionArray[0] + "." + astrVersionArray[1] + astrVersionArray[2] + "." + astrVersionArray[3] + " (Build " + ibuild + ")";
|
||||
if (GetVersionBuild76till10(fileContent, position, out int ibuild).Length > 0)
|
||||
return $"ProtectDisc {astrVersionArray[0]}.{astrVersionArray[1]}{astrVersionArray[2]}.{astrVersionArray[3]} (Build {ibuild})" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
}
|
||||
else
|
||||
return "ProtectDisc " + astrVersionArray[0] + "." + astrVersionArray[1] + "." + astrVersionArray[2] + " (Build " + astrVersionArray[3] + ")";
|
||||
{
|
||||
return $"ProtectDisc {astrVersionArray[0]}.{astrVersionArray[1]}.{astrVersionArray[2]} (Build {astrVersionArray[3]})" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((position = fileContent.IndexOf("ACE-PCD")) > -1)
|
||||
// "ACE-PCD"
|
||||
check = new byte[] { 0x41, 0x43, 0x45, 0x2D, 0x50, 0x43, 0x44 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
{
|
||||
string version = EVORE.SearchProtectDiscVersion(file);
|
||||
string version = SearchProtectDiscVersion(file, fileContent);
|
||||
if (version.Length > 0)
|
||||
{
|
||||
string[] astrVersionArray = version.Split('.');
|
||||
return "ProtectDisc " + astrVersionArray[0] + "." + astrVersionArray[1] + "." + astrVersionArray[2] + " (Build " + astrVersionArray[3] + ")";
|
||||
return $"ProtectDisc {astrVersionArray[0]}.{astrVersionArray[1]}.{astrVersionArray[2]} (Build {astrVersionArray[3]})" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
}
|
||||
|
||||
return "ProtectDisc " + GetVersionBuild6till8(file, position);
|
||||
return $"ProtectDisc {GetVersionBuild6till8(fileContent, position)}" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetVersionBuild6till8(string file, int position)
|
||||
private static string GetVersionBuild6till8(byte[] fileContent, int position)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
string version;
|
||||
string strBuild;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
int index = position - 12;
|
||||
if (new ArraySegment<byte>(fileContent, index, 4).SequenceEqual(new byte[] { 0x0A, 0x0D, 0x0A, 0x0D })) // ProtectDisc 6-7 with Build Number in plain text
|
||||
{
|
||||
string version;
|
||||
string strBuild;
|
||||
index = position - 12 - 6;
|
||||
|
||||
br.BaseStream.Seek(position - 12, SeekOrigin.Begin);
|
||||
if (br.ReadByte() == 0xA && br.ReadByte() == 0xD && br.ReadByte() == 0xA && br.ReadByte() == 0xD) // ProtectDisc 6-7 with Build Number in plain text
|
||||
// ProtectDisc 7
|
||||
if (new string(new ArraySegment<byte>(fileContent, index, 6).Select(b => (char)b).ToArray()) == "Henrik")
|
||||
{
|
||||
br.BaseStream.Seek(position - 12 - 6, SeekOrigin.Begin);
|
||||
if (new string(br.ReadChars(6)) == "Henrik") // ProtectDisc 7
|
||||
{
|
||||
version = "7.1-7.5";
|
||||
br.BaseStream.Seek(position - 12 - 6 - 6, SeekOrigin.Begin);
|
||||
}
|
||||
else // ProtectDisc 6
|
||||
{
|
||||
version = "6";
|
||||
br.BaseStream.Seek(position - 12 - 10, SeekOrigin.Begin);
|
||||
while (true) //search for e.g. "Build 050913 - September 2005"
|
||||
{
|
||||
if (Char.IsNumber(br.ReadChar()))
|
||||
break;
|
||||
br.BaseStream.Seek(-2, SeekOrigin.Current); //search upwards
|
||||
}
|
||||
|
||||
br.BaseStream.Seek(-5, SeekOrigin.Current);
|
||||
}
|
||||
version = "7.1-7.5";
|
||||
index = position - 12 - 6 - 6;
|
||||
}
|
||||
|
||||
// ProtectDisc 6
|
||||
else
|
||||
{
|
||||
br.BaseStream.Seek(position + 28, SeekOrigin.Begin);
|
||||
if (br.ReadByte() == 0xFB)
|
||||
version = "6";
|
||||
index = position - 12 - 10;
|
||||
while (true) //search for e.g. "Build 050913 - September 2005"
|
||||
{
|
||||
return "7.6-7.x";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "8.0";
|
||||
if (Char.IsNumber((char)fileContent[index]))
|
||||
break;
|
||||
|
||||
index -= 1; //search upwards
|
||||
}
|
||||
|
||||
index -= 5;
|
||||
}
|
||||
strBuild = "" + br.ReadChar() + br.ReadChar() + br.ReadChar() + br.ReadChar() + br.ReadChar();
|
||||
return version + " (Build " + strBuild + ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
index = position + 28;
|
||||
if (fileContent[index] == 0xFB)
|
||||
return "7.6-7.x";
|
||||
else
|
||||
return "8.0";
|
||||
}
|
||||
|
||||
strBuild = new string(new ArraySegment<byte>(fileContent, index, 5).Select(b => (char)b).ToArray());
|
||||
return $"{version} (Build {strBuild})";
|
||||
}
|
||||
|
||||
private static string GetVersionBuild76till10(string file, int position, out int irefBuild)
|
||||
private static string GetVersionBuild76till10(byte[] fileContent, int position, out int irefBuild)
|
||||
{
|
||||
irefBuild = 0;
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
int index = position + 37;
|
||||
byte subversion = fileContent[index];
|
||||
index++;
|
||||
index++;
|
||||
byte version = fileContent[index];
|
||||
index = position + 49;
|
||||
irefBuild = BitConverter.ToInt32(fileContent, index);
|
||||
index = position + 53;
|
||||
byte versionindicatorPD9 = fileContent[index];
|
||||
index = position + 0x40;
|
||||
byte subsubversionPD9x = fileContent[index];
|
||||
index++;
|
||||
byte subversionPD9x2 = fileContent[index];
|
||||
index++;
|
||||
byte subversionPD9x1 = fileContent[index];
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
// version 7
|
||||
if (version == 0xAC)
|
||||
return $"7.{subversion ^ 0x43} (Build {irefBuild})";
|
||||
|
||||
// version 8
|
||||
else if (version == 0xA2)
|
||||
{
|
||||
br.BaseStream.Seek(position + 37, SeekOrigin.Begin);
|
||||
byte subversion = br.ReadByte();
|
||||
br.ReadByte();
|
||||
byte version = br.ReadByte();
|
||||
br.BaseStream.Seek(position + 49, SeekOrigin.Begin);
|
||||
irefBuild = br.ReadInt32();
|
||||
br.BaseStream.Seek(position + 53, SeekOrigin.Begin);
|
||||
byte versionindicatorPD9 = br.ReadByte();
|
||||
br.BaseStream.Seek(position + 0x40, SeekOrigin.Begin);
|
||||
byte subsubversionPD9x = br.ReadByte();
|
||||
byte subversionPD9x2 = br.ReadByte();
|
||||
byte subversionPD9x1 = br.ReadByte();
|
||||
|
||||
// version 7
|
||||
if (version == 0xAC)
|
||||
return "7." + (subversion ^ 0x43) + " (Build " + irefBuild + ")";
|
||||
// version 8
|
||||
else if (version == 0xA2)
|
||||
if (subversion == 0x46)
|
||||
{
|
||||
if (subversion == 0x46)
|
||||
{
|
||||
if ((irefBuild & 0x3A00) == 0x3A00)
|
||||
return "8.2" + " (Build " + irefBuild + ")";
|
||||
else
|
||||
return "8.1" + " (Build " + irefBuild + ")";
|
||||
}
|
||||
return "8." + (subversion ^ 0x47) + " (Build " + irefBuild + ")";
|
||||
}
|
||||
// version 9
|
||||
else if (version == 0xA3)
|
||||
{
|
||||
// version removed or not given
|
||||
if ((subversionPD9x2 == 0x5F && subversionPD9x1 == 0x61) || (subversionPD9x1 == 0 && subversionPD9x2 == 0))
|
||||
{
|
||||
if (versionindicatorPD9 == 0xB)
|
||||
return "9.0-9.4" + " (Build " + irefBuild + ")";
|
||||
else if (versionindicatorPD9 == 0xC)
|
||||
{
|
||||
if (subversionPD9x2 == 0x5F && subversionPD9x1 == 0x61)
|
||||
return "9.5-9.11" + " (Build " + irefBuild + ")";
|
||||
else if (subversionPD9x1 == 0 && subversionPD9x2 == 0)
|
||||
return "9.11-9.20" + " (Build " + irefBuild + ")";
|
||||
}
|
||||
else
|
||||
return "9." + subversionPD9x1 + subversionPD9x2 + "." + subsubversionPD9x + " (Build " + irefBuild + ")";
|
||||
}
|
||||
}
|
||||
else if (version == 0xA0)
|
||||
{
|
||||
// version removed
|
||||
if (subversionPD9x1 != 0 || subversionPD9x2 != 0)
|
||||
return "10." + subversionPD9x1 + "." + subsubversionPD9x + " (Build " + irefBuild + ")";
|
||||
if ((irefBuild & 0x3A00) == 0x3A00)
|
||||
return $"8.2 (Build {irefBuild})";
|
||||
else
|
||||
return "10.x (Build " + irefBuild + ")";
|
||||
return $"8.1 (Build {irefBuild})";
|
||||
}
|
||||
|
||||
return $"8.{subversion ^ 0x47} (Build {irefBuild})";
|
||||
}
|
||||
|
||||
// version 9
|
||||
else if (version == 0xA3)
|
||||
{
|
||||
// version removed or not given
|
||||
if ((subversionPD9x2 == 0x5F && subversionPD9x1 == 0x61) || (subversionPD9x1 == 0 && subversionPD9x2 == 0))
|
||||
{
|
||||
if (versionindicatorPD9 == 0xB)
|
||||
{
|
||||
return $"9.0-9.4 (Build {irefBuild})";
|
||||
}
|
||||
else if (versionindicatorPD9 == 0xC)
|
||||
{
|
||||
if (subversionPD9x2 == 0x5F && subversionPD9x1 == 0x61)
|
||||
return $"9.5-9.11 (Build {irefBuild})";
|
||||
else if (subversionPD9x1 == 0 && subversionPD9x2 == 0)
|
||||
return $"9.11-9.20 (Build {irefBuild})";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"9.{subversionPD9x1}{subversionPD9x2}.{subsubversionPD9x} (Build {irefBuild})";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// version 10
|
||||
else if (version == 0xA0)
|
||||
{
|
||||
// version removed
|
||||
if (subversionPD9x1 != 0 || subversionPD9x2 != 0)
|
||||
return $"10.{subversionPD9x1}.{subsubversionPD9x} (Build {irefBuild})";
|
||||
else
|
||||
return $"10.x (Build {irefBuild})";
|
||||
}
|
||||
|
||||
// unknown version
|
||||
else
|
||||
{
|
||||
return $"7.6-10.x (Build {irefBuild})";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
// TODO: Analyze this method and figure out if this can be done without attempting execution
|
||||
private static string SearchProtectDiscVersion(string file, byte[] fileContent)
|
||||
{
|
||||
string version = "";
|
||||
DateTime timestart;
|
||||
if (!EVORE.IsEXE(fileContent))
|
||||
return "";
|
||||
|
||||
string tempexe = EVORE.MakeTempFile(fileContent);
|
||||
string[] DependentDlls = EVORE.CopyDependentDlls(file, fileContent);
|
||||
try
|
||||
{
|
||||
File.Delete(Path.Combine(Path.GetTempPath(), "a*.tmp"));
|
||||
}
|
||||
catch { }
|
||||
try
|
||||
{
|
||||
File.Delete(Path.Combine(Path.GetTempPath(), "PCD*.sys"));
|
||||
}
|
||||
catch { }
|
||||
if (Directory.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ProtectDisc")))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ProtectDisc", "p*.dll"));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
Process exe = EVORE.StartSafe(tempexe);
|
||||
if (exe == null)
|
||||
return "";
|
||||
|
||||
Process[] processes = new Process[0];
|
||||
timestart = DateTime.Now;
|
||||
do
|
||||
{
|
||||
exe.Refresh();
|
||||
string[] files = null;
|
||||
|
||||
//check for ProtectDisc 8.2-x
|
||||
if (Directory.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ProtectDisc")))
|
||||
{
|
||||
files = Directory.GetFiles(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ProtectDisc"), "p*.dll");
|
||||
}
|
||||
|
||||
if (files != null)
|
||||
{
|
||||
if (files.Length > 0)
|
||||
{
|
||||
FileVersionInfo fvinfo = FileVersionInfo.GetVersionInfo(files[0]);
|
||||
if (fvinfo.FileVersion != "")
|
||||
{
|
||||
version = fvinfo.FileVersion.Replace(" ", "").Replace(",", ".");
|
||||
//ProtectDisc 9 uses a ProtectDisc-Core dll version 8.0.x
|
||||
if (version.StartsWith("8.0"))
|
||||
version = "";
|
||||
fvinfo = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//check for ProtectDisc 7.1-8.1
|
||||
files = Directory.GetFiles(Path.GetTempPath(), "a*.tmp");
|
||||
if (files.Length > 0)
|
||||
{
|
||||
FileVersionInfo fvinfo = FileVersionInfo.GetVersionInfo(files[0]);
|
||||
if (fvinfo.FileVersion != "")
|
||||
{
|
||||
version = fvinfo.FileVersion.Replace(" ", "").Replace(",", ".");
|
||||
fvinfo = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (exe.HasExited)
|
||||
break;
|
||||
|
||||
processes = Process.GetProcessesByName(exe.ProcessName);
|
||||
if (processes.Length == 2)
|
||||
{
|
||||
processes[0].Refresh();
|
||||
processes[1].Refresh();
|
||||
if (processes[1].WorkingSet64 > exe.WorkingSet64)
|
||||
exe = processes[1];
|
||||
else if (processes[0].WorkingSet64 > exe.WorkingSet64) //else if (processes[0].Modules.Count > exe.Modules.Count)
|
||||
exe = processes[0];
|
||||
}
|
||||
} while (processes.Length > 0 && DateTime.Now.Subtract(timestart).TotalSeconds < 20);
|
||||
|
||||
Thread.Sleep(500);
|
||||
if (!exe.HasExited)
|
||||
{
|
||||
processes = Process.GetProcessesByName(exe.ProcessName);
|
||||
if (processes.Length == 2)
|
||||
{
|
||||
try
|
||||
{
|
||||
processes[0].Kill();
|
||||
}
|
||||
catch { }
|
||||
processes[0].Close();
|
||||
try
|
||||
{
|
||||
processes[1].Kill();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
else
|
||||
return "7.6-10.x (Build " + irefBuild + ")";
|
||||
|
||||
return "";
|
||||
{
|
||||
exe.Refresh();
|
||||
try
|
||||
{
|
||||
exe.Kill();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
exe.Close();
|
||||
Thread.Sleep(500);
|
||||
if (Directory.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ProtectDisc")))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ProtectDisc", "p*.dll"));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
File.Delete(Path.Combine(Path.GetTempPath(), "a*.tmp"));
|
||||
}
|
||||
catch { }
|
||||
|
||||
try
|
||||
{
|
||||
File.Delete(Path.Combine(Path.GetTempPath(), "PCD*.sys"));
|
||||
}
|
||||
catch { }
|
||||
File.Delete(tempexe);
|
||||
if (DependentDlls != null)
|
||||
{
|
||||
for (int i = 0; i < DependentDlls.Length; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(DependentDlls[i]);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("!error while deleting file " + DependentDlls[i] + "; " + ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user