84 Commits
Author SHA1 Message Date
Gustave Monce d270cace79 Fix: device being null 2026-04-22 18:36:50 +02:00
Gustave Monce af61c9ad29 Preliminary support for UFP 2026-04-16 18:46:00 +02:00
Gustave Monce de4d5e577a Add preliminary SimpleIO support 2026-04-16 18:11:13 +02:00
Gustave Monce df02025a31 Update timebomb 2026-01-03 23:26:37 +01:00
Gustave Monce ad92ecdab3 Restructure assets into their own dedicated folders 2025-11-01 11:06:33 +01:00
Gustave Monce b3b037a3c8 Remove deprecated download command line options 2025-11-01 11:06:17 +01:00
Gustave Monce be15155c39 Deprecate MSR download fully as the MSR and repair avoidance services are fully deprecated as of 2025 2025-11-01 11:06:02 +01:00
Gustave Monce a17dae3931 Update project structure 2025-11-01 09:44:23 +01:00
Gustave Monce 7646e3fc76 Bump timebomb date 2025-11-01 09:42:59 +01:00
Gustave Monce 933e9e53b6 Migrate DiscUtils fat code to a standalone project dependency 2025-11-01 09:42:52 +01:00
Gustave Monce e838168127 Migrate 7zip code to a standalone project dependency 2025-11-01 09:31:14 +01:00
Gustave Monce 058cde0d91 Migrate WinUSBNet code to a standalone project dependency 2025-11-01 09:28:08 +01:00
Gustave Monce 1cc7a5cee4 Update Timebomb 2024-12-23 15:14:30 +01:00
Gustave Monce 132e21e58a Patcher: fix: broken go to labels in script engine 2024-10-22 21:22:30 +02:00
Gustave Monce 1e5da5452b Small fixes 2024-10-21 23:52:08 +02:00
Gustave Monce 6992ed3f70 Remove references to dead website 2024-10-21 23:30:50 +02:00
Gustave Monce bb9702a3c3 Patcher: fix compilation with dotnet 8 2024-10-21 23:25:50 +02:00
Gustave Monce 3c66688303 Add Patcher Project
The other Patcher repository is locked from future modifications
2024-10-21 08:57:39 +02:00
Gustave Monce bc77e8b589 Fixes 2024-10-21 08:56:11 +02:00
Gustave Monce 6be24faee0 Update ci.yml 2024-10-13 00:26:53 +02:00
Gustave Monce e078bb10ed Fixes for Spec A unlocking
In memories of the cyan RM-821 from a fellow care center

Rest in peace, 12th of October 2024
2024-10-13 00:25:01 +02:00
Gustave Monce 605b19aede Fixes 2024-10-12 21:22:07 +02:00
Gustave Monce d9da49915e Some changes 2024-10-12 19:44:11 +02:00
Gustave Monce 7c18a168fa Various Fixes 2024-10-12 19:15:41 +02:00
Gustave Monce 303c2d4b5a Some cleanup 2024-10-12 18:38:39 +02:00
Gustave Monce d700ae5911 Add the ability to add Secure WIMs to the store 2024-10-12 17:19:47 +02:00
Gustave Monce 14bf607111 Remove Defunct MSR Downloads 2024-10-12 17:14:06 +02:00
Gustave Monce 57c9595d86 Some cleanup 2024-10-12 16:56:36 +02:00
Gustave Monce 7fc332e912 Cleanup using directives 2024-10-12 13:46:34 +02:00
Gustave Monce bcec0a72e6 Nokia Flash Model -> Nokia UEFI Model 2024-10-12 13:45:51 +02:00
Gustave Monce 00407d6f24 Cleanup 2024-10-12 13:40:24 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2d5b0fd3db Bump System.Text.Json from 8.0.4 to 8.0.5 in /WPinternals (#79)
Bumps [System.Text.Json](https://github.com/dotnet/runtime) from 8.0.4 to 8.0.5.
- [Release notes](https://github.com/dotnet/runtime/releases)
- [Commits](https://github.com/dotnet/runtime/compare/v8.0.4...v8.0.5)

---
updated-dependencies:
- dependency-name: System.Text.Json
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-09 09:03:31 +02:00
Gustave Monce a982c119fb Bump timebomb 2024-09-09 21:08:35 +02:00
Gustave Monce c6dee3fe33 workaround older phone fw issues when retrieving via json rpc and gpt get function failures 2024-09-01 16:49:36 +02:00
Gustave Monce 91961b0e7b fix issues with downloading files 2024-09-01 12:45:46 +02:00
Gustave Monce 29c6ab06d4 fix: Download issues with ENOSW 2024-09-01 10:38:47 +02:00
Gustave Monce b03b561724 fix a few TODOs 2024-08-31 23:17:34 +02:00
Gustave Monce 91f534a7c3 fix: Merge issues from previous commit 2024-08-31 21:58:23 +02:00
Gustave Monce f0f3268924 Split phone info structures for each app type 2024-08-31 21:52:20 +02:00
Gustave Monce c269cfe839 Enable downloading ENOSW via Download Page 2024-08-31 19:45:24 +02:00
Gustave Monce 7d8aad0e88 fix: Modern Flash App Label mode switching 2024-08-31 18:31:56 +02:00
Gustave Monce 310d0b97c5 fix: Mode change detection on specb
resolves a few issues but not all due to the combined app
2024-08-31 17:50:18 +02:00
Gustave Monce 8e50c46357 wip: Refactor FlashApp Logic to account for the 3 split app states 2024-08-31 16:39:44 +02:00
Gustave Monce e6555741b0 fix: PhoneInfo app handling + label parsing issues 2024-08-31 11:00:04 +02:00
Gustave Monce c21692491d fix: Log all silent exceptions 2024-08-30 21:43:30 +02:00
Gustave Monce 350b6e8f1e fix: add missing raise can execute changed for unlock v1 with supported ffu field 2024-08-30 20:42:52 +02:00
Gustave Monce 0101477830 fix: Handle empty flash part list
This is used to clear the red flashing status we need to handle this differently for spec A
2024-08-30 20:42:37 +02:00
Gustave Monce a6c017986b fix: Handle loaders with new lines at the top instead of intel hex style right at the start 2024-08-30 20:42:16 +02:00
Gustave Monce 0174fc8b30 QCParts: Check if signatures are available 2024-08-30 20:41:57 +02:00
Gustave Monce c6f6ef4429 Rework Qualcomm Partition to also work with modern day ed loaders 2024-08-27 10:08:47 +02:00
Gustave Monce ab0c35e879 fix: revert qualcomm partition code changes to account for older ed payloads 2024-08-27 09:55:52 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
676a95dd97 Bump System.Text.Json from 8.0.0 to 8.0.4 in /WPinternals (#74)
Bumps System.Text.Json from 8.0.0 to 8.0.4.

---
updated-dependencies:
- dependency-name: System.Text.Json
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-13 14:53:12 +02:00
Gustave Monce 8981fd02e9 Enable Preview Build 2023-11-26 18:50:46 +01:00
Gustave Monce 16d3f95971 WPinternals v3.0 2023-11-26 18:39:49 +01:00
Gustave Monce 293c649edb Refactor Qualcomm Sahara and Qualcomm Firehose code 2023-11-26 18:37:14 +01:00
Gustave Monce 88efc77887 Cleanup Sahara Implementation 2023-11-26 18:08:50 +01:00
Gustave Monce dc6085f185 Sahara: Implement getting the RKH 2023-11-26 16:51:29 +01:00
Gustave Monce e2cbb9c6fc Alter the list of OS partitions 2023-11-26 14:19:05 +01:00
Gustave Monce 4b7b9621b4 Rebuild the Backup to Custom ROM zip functionality to handle more partitions and be more flexible 2023-11-26 14:04:13 +01:00
Gustave Monce 96c42a29b5 Adopt new C# syntax for array init 2023-11-26 14:03:46 +01:00
Gustave Monce 742c89b9bf CI: Use .NET 8 SDK 2023-11-26 13:09:49 +01:00
Gustave Monce dbd303fd07 Add new feature to generate a GPT xml file from a binary or backup 2023-11-26 13:08:33 +01:00
Gustave Monce 8d35be447a Project: Update to .NET 8 2023-11-26 12:25:14 +01:00
Gustave Monce 83c09bdc81 Improve RKH Reading from Qualcomm Images 2023-03-09 21:40:23 +01:00
Gustave MonceandGitHub 93a5064751 Merge pull request #47 from ungeskriptet/fix-typo 2022-12-23 09:31:24 +01:00
David Wronek ef6a962a01 Fix typo in MassStorageView 2022-12-19 20:35:47 +01:00
Gustave Monce d32788198d Project: Migrate to .NET 7 2022-11-11 02:26:45 -08:00
Gustave Monce 7798dd1c34 RKH: Fix an issue retrieving modern day RKH 2022-11-11 02:22:17 -08:00
Gustave Monce 57cd052d61 About: Show Build and Revision in the version field 2021-11-15 15:06:13 +01:00
Gustave Monce 5eb523530c Remove the Lumia 535 from the supported phone list 2021-11-15 14:53:34 +01:00
Gustave Monce 8a17b05398 Project: Update to .NET 6 2021-11-15 14:47:29 +01:00
Gustave Monce dc5ac1e7d4 CI: Make CI always fetch latest .NET 5 SDK 2021-08-26 09:09:47 +02:00
Gustave Monce 1d14d79fab Flash: Custom ROM: Fix incorrect unlocked check for EFIESP 2021-08-16 11:40:58 +02:00
Gustave Monce 846ea41883 Project: Add SDK 2021-08-14 11:24:02 +02:00
Gustave Monce 452393aaa7 Project: Add RootAccessTestUWP 2021-08-14 11:14:56 +02:00
Gustave Monce 17bc763761 Project: Move WPinternals code to a WPinternals folder 2021-08-14 11:04:37 +02:00
Gustave Monce 668a9b7fe2 Fix an issue with incorrect logging of secure boot state 2021-08-13 13:21:15 +02:00
Gustave Monce 8293c18406 Merge branch 'master' of https://github.com/ReneLergner/WPinternals 2021-08-12 17:43:45 +02:00
Gustave Monce 48fbfa77df Project: remove references to hijacked website/domain to prevent potential malicious activity due to us not controlling the domain anymore. 2021-08-12 17:43:38 +02:00
Gustave MonceandGitHub 709c91cec5 Create bug_report.yml 2021-08-12 08:59:16 +02:00
Gustave MonceandGitHub 611ad122f9 Create README.md 2021-08-12 08:52:54 +02:00
Gustave Monce d8fd0aa516 Fix more hyperlink issues 2021-08-12 08:37:20 +02:00
Gustave Monce 7f3c8b1777 Merge branch 'master' of https://github.com/ReneLergner/WPinternals 2021-08-12 08:32:27 +02:00
Gustave Monce 087457fa0d FIx an issue with hyperlinks 2021-08-12 08:31:36 +02:00
405 changed files with 72037 additions and 48595 deletions
+60
View File
@@ -0,0 +1,60 @@
name: Bug Report
description: Create a bug report to help improve WPinternals
labels: [bug]
body:
- type: textarea
attributes:
label: Description
description: A clear and concise description of what the bug is.
validations:
required: true
- type: textarea
attributes:
label: Steps To Reproduce
description: Steps to reproduce the behavior.
placeholder: |
1. Go to '....'
2. Click on '....'
3. Scroll down to '....'
4. See the error
validations:
required: false
- type: textarea
attributes:
label: Expected behavior
description: A clear and concise description of what you expected to happen.
validations:
required: true
- type: input
id: wpi-version
attributes:
label: WPinternals Version
description: What version of WPinternals are you using?
placeholder: v2.9.2
validations:
required: true
- type: input
attributes:
label: Windows Version
description: What version of Windows are you using? Press <kbd>Win</kbd> + <kbd>Pause/Break</kbd> and copy.
placeholder: e.g. Windows 11 21H2 22000.132
validations:
required: true
- type: input
attributes:
label: Phone model
description: What phone model did you reproduce the bug on (if applicable)
placeholder: e.g. Lumia 950 XL (RM-1085)
validations:
required: false
- type: textarea
attributes:
label: Relevant Assets
description: |
A list of assets (logs, screenshots) relevant to this bug.
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
placeholder: |
To upload the log
- Copy the `WPinternals.log` files from `%ALLUSERSPROFILE%\WPinternals`
- Drag and drop them into this text area.
+4 -4
View File
@@ -11,16 +11,16 @@ jobs:
runs-on: windows-latest
strategy:
matrix:
architecture: [x86, x64]
architecture: [x86, x64, arm64]
platform: [win]
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Install .NET SDK
uses: actions/setup-dotnet@v1
with:
dotnet-version: "5.0.400"
dotnet-version: "8.0.x"
- name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@v1.0.2
@@ -31,7 +31,7 @@ jobs:
msbuild /m /t:restore,wpinternals:publish /p:Platform=${{ matrix.architecture }} /p:RuntimeIdentifier=${{ matrix.platform }}-${{ matrix.architecture }} /p:PublishDir=${{ github.workspace }}/artifacts/${{ matrix.platform }}-${{ matrix.architecture }} /p:PublishSingleFile=true /p:PublishTrimmed=false WPinternals.sln
- name: Upload artifact
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.platform }}-${{ matrix.architecture }}
path: ${{ github.workspace }}/artifacts/${{ matrix.platform }}-${{ matrix.architecture }}
+10
View File
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>_7zip</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
+2 -2
View File
@@ -47,7 +47,7 @@ namespace SevenZip.CommandLineParser
{
public bool ThereIs;
public bool WithMinus;
public ArrayList PostStrings = new();
public ArrayList PostStrings = [];
public int PostCharIndex;
public SwitchResult()
{
@@ -57,7 +57,7 @@ namespace SevenZip.CommandLineParser
public class Parser
{
public ArrayList NonSwitchStrings = new();
public ArrayList NonSwitchStrings = [];
private readonly SwitchResult[] _switches;
public Parser(int numSwitches)
+2 -2
View File
@@ -1518,10 +1518,10 @@ namespace SevenZip.Compression.LZMA
}
private static readonly string[] kMatchFinderIDs =
{
[
"BT2",
"BT4",
};
];
private static int FindMatchFinder(string s)
{
@@ -4,7 +4,7 @@ using System.Text;
namespace DiscUtils.CoreCompat
{
internal static class EncodingHelper
public static class EncodingHelper
{
private static bool _registered;
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DiscUtils.Core" Version="0.16.13" />
</ItemGroup>
</Project>
@@ -28,7 +28,7 @@ using System.Text.RegularExpressions;
namespace DiscUtils.Internal
{
internal static class Utilities
public static class Utilities
{
/// <summary>
/// Converts between two arrays.
@@ -61,14 +61,14 @@ namespace DiscUtils.Internal
/// <returns>The resultant array.</returns>
public static U[] Map<T, U>(IEnumerable<T> source, Func<T, U> func)
{
List<U> result = new();
List<U> result = [];
foreach (T sVal in source)
{
result.Add(func(sVal));
}
return result.ToArray();
return [.. result];
}
/// <summary>
+1 -9
View File
@@ -48,15 +48,7 @@ namespace DiscUtils.Fat
_fat = fileSystem.Fat;
_length = length;
_knownClusters = new List<uint>();
if (firstCluster != 0)
{
_knownClusters.Add(firstCluster);
}
else
{
_knownClusters.Add(FatBuffer.EndOfChain);
}
_knownClusters = [firstCluster != 0 ? firstCluster : FatBuffer.EndOfChain];
if (_length == uint.MaxValue)
{
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\DiscUtils.Core\DiscUtils.Core.WPI.csproj" />
</ItemGroup>
</Project>
+2 -2
View File
@@ -64,7 +64,7 @@ namespace DiscUtils.Fat
{
_type = type;
_buffer = buffer;
_dirtySectors = new Dictionary<uint, uint>();
_dirtySectors = [];
}
internal int NumEntries
@@ -220,7 +220,7 @@ namespace DiscUtils.Fat
internal List<uint> GetChain(uint head)
{
List<uint> result = new();
List<uint> result = [];
if (head != 0)
{
+4 -4
View File
@@ -31,15 +31,15 @@ namespace DiscUtils.Fat
private const byte SpaceByte = 0x20;
public static readonly FileName SelfEntryName =
new(new byte[] { 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }, 0);
new([0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20], 0);
public static readonly FileName ParentEntryName =
new(new byte[] { 0x2E, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }, 0);
new([0x2E, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20], 0);
public static readonly FileName Null =
new(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0);
new([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], 0);
private static readonly byte[] InvalidBytes = { 0x22, 0x2A, 0x2B, 0x2C, 0x2E, 0x2F, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x5B, 0x5C, 0x5D, 0x7C };
private static readonly byte[] InvalidBytes = [0x22, 0x2A, 0x2B, 0x2C, 0x2E, 0x2F, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x5B, 0x5C, 0x5D, 0x7C];
private readonly byte[] _raw;
+2 -2
View File
@@ -33,10 +33,10 @@ namespace DiscUtils.Fat
{
if (FatFileSystem.Detect(stream))
{
return new FileSystemInfo[] { new VfsFileSystemInfo("FAT", "Microsoft FAT", Open) };
return [new VfsFileSystemInfo("FAT", "Microsoft FAT", Open)];
}
return System.Array.Empty<FileSystemInfo>();
return [];
}
private DiscFileSystem Open(Stream stream, VolumeInfo volumeInfo, FileSystemParameters parameters)
+20 -20
View File
@@ -80,22 +80,22 @@ namespace DiscUtils.Fat
{
// see http://home.teleport.com/~brainy/lfn.htm
// NOTE: we assume ordinals are ok here.
char[] chars = new char[13];
chars[0] = (char)((256 * buffer[2]) + buffer[1]);
chars[1] = (char)((256 * buffer[4]) + buffer[3]);
chars[2] = (char)((256 * buffer[6]) + buffer[5]);
chars[3] = (char)((256 * buffer[8]) + buffer[7]);
chars[4] = (char)((256 * buffer[10]) + buffer[9]);
chars[5] = (char)((256 * buffer[15]) + buffer[14]);
chars[6] = (char)((256 * buffer[17]) + buffer[16]);
chars[7] = (char)((256 * buffer[19]) + buffer[18]);
chars[8] = (char)((256 * buffer[21]) + buffer[20]);
chars[9] = (char)((256 * buffer[23]) + buffer[22]);
chars[10] = (char)((256 * buffer[25]) + buffer[24]);
chars[11] = (char)((256 * buffer[29]) + buffer[28]);
chars[12] = (char)((256 * buffer[31]) + buffer[30]);
char[] chars =
[
(char)((256 * buffer[2]) + buffer[1]),
(char)((256 * buffer[4]) + buffer[3]),
(char)((256 * buffer[6]) + buffer[5]),
(char)((256 * buffer[8]) + buffer[7]),
(char)((256 * buffer[10]) + buffer[9]),
(char)((256 * buffer[15]) + buffer[14]),
(char)((256 * buffer[17]) + buffer[16]),
(char)((256 * buffer[19]) + buffer[18]),
(char)((256 * buffer[21]) + buffer[20]),
(char)((256 * buffer[23]) + buffer[22]),
(char)((256 * buffer[25]) + buffer[24]),
(char)((256 * buffer[29]) + buffer[28]),
(char)((256 * buffer[31]) + buffer[30]),
];
string chunk = new(chars);
int zero = chunk.IndexOf('\0');
return zero >= 0 ? chunk.Substring(0, zero) : chunk;
@@ -201,7 +201,7 @@ namespace DiscUtils.Fat
}
}
return dirs.ToArray();
return [.. dirs];
}
public DirectoryEntry[] GetFiles()
@@ -215,7 +215,7 @@ namespace DiscUtils.Fat
}
}
return files.ToArray();
return [.. files];
}
public DirectoryEntry GetEntry(long id)
@@ -452,8 +452,8 @@ namespace DiscUtils.Fat
private void LoadEntries()
{
_entries = new Dictionary<long, DirectoryEntry>();
_freeEntries = new List<long>();
_entries = [];
_freeEntries = [];
_selfEntryLocation = -1;
_parentEntryLocation = -1;
@@ -94,7 +94,7 @@ namespace DiscUtils.Fat
public FatFileSystem(Stream data)
: base(new FatFileSystemOptions())
{
_dirCache = new Dictionary<uint, Directory>();
_dirCache = [];
_timeConverter = DefaultTimeConverter;
Initialize(data);
}
@@ -111,7 +111,7 @@ namespace DiscUtils.Fat
public FatFileSystem(Stream data, Ownership ownsData)
: base(new FatFileSystemOptions())
{
_dirCache = new Dictionary<uint, Directory>();
_dirCache = [];
_timeConverter = DefaultTimeConverter;
Initialize(data);
_ownsData = ownsData;
@@ -125,7 +125,7 @@ namespace DiscUtils.Fat
public FatFileSystem(Stream data, TimeConverter timeConverter)
: base(new FatFileSystemOptions())
{
_dirCache = new Dictionary<uint, Directory>();
_dirCache = [];
_timeConverter = timeConverter;
Initialize(data);
}
@@ -140,7 +140,7 @@ namespace DiscUtils.Fat
public FatFileSystem(Stream data, Ownership ownsData, TimeConverter timeConverter)
: base(new FatFileSystemOptions())
{
_dirCache = new Dictionary<uint, Directory>();
_dirCache = [];
_timeConverter = timeConverter;
Initialize(data);
_ownsData = ownsData;
@@ -156,7 +156,7 @@ namespace DiscUtils.Fat
public FatFileSystem(Stream data, Ownership ownsData, FileSystemParameters parameters)
: base(new FatFileSystemOptions(parameters))
{
_dirCache = new Dictionary<uint, Directory>();
_dirCache = [];
if (parameters?.TimeConverter != null)
{
@@ -1258,7 +1258,7 @@ namespace DiscUtils.Fat
dirs.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding)));
}
return dirs.ToArray();
return [.. dirs];
}
/// <summary>
@@ -1273,9 +1273,9 @@ namespace DiscUtils.Fat
{
Regex re = Utilities.ConvertWildcardsToRegEx(searchPattern);
List<string> dirs = new();
List<string> dirs = [];
DoSearch(dirs, path, re, searchOption == SearchOption.AllDirectories, true, false);
return dirs.ToArray();
return [.. dirs];
}
/// <summary>
@@ -1294,7 +1294,7 @@ namespace DiscUtils.Fat
files.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding)));
}
return files.ToArray();
return [.. files];
}
/// <summary>
@@ -1309,9 +1309,9 @@ namespace DiscUtils.Fat
{
Regex re = Utilities.ConvertWildcardsToRegEx(searchPattern);
List<string> results = new();
List<string> results = [];
DoSearch(results, path, re, searchOption == SearchOption.AllDirectories, false, true);
return results.ToArray();
return [.. results];
}
/// <summary>
@@ -1330,7 +1330,7 @@ namespace DiscUtils.Fat
result.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding)));
}
return result.ToArray();
return [.. result];
}
/// <summary>
@@ -1356,7 +1356,7 @@ namespace DiscUtils.Fat
}
}
return result.ToArray();
return [.. result];
}
/// <summary>
@@ -1915,9 +1915,7 @@ namespace DiscUtils.Fat
throw new DirectoryNotFoundException(string.Format(CultureInfo.InvariantCulture, "The directory '{0}' was not found", path));
}
DirectoryEntry[] entries = dir.Entries;
foreach (DirectoryEntry de in entries)
foreach (DirectoryEntry de in dir.Entries)
{
bool isDir = (de.Attributes & FatAttributes.Directory) != 0;
-2353
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
-860
View File
@@ -1,860 +0,0 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
namespace WPinternals
{
internal static class LumiaDownloadModel
{
internal static string SearchFFU(string ProductType, string ProductCode, string OperatorCode)
{
return SearchFFU(ProductType, ProductCode, OperatorCode, out string FoundProductType);
}
internal static string SearchFFU(string ProductType, string ProductCode, string OperatorCode, out string FoundProductType)
{
if (ProductType?.Length == 0)
{
ProductType = null;
}
if (ProductCode?.Length == 0)
{
ProductCode = null;
}
if (OperatorCode?.Length == 0)
{
OperatorCode = null;
}
if (ProductCode != null)
{
ProductCode = ProductCode.ToUpper();
ProductType = null;
OperatorCode = null;
}
if (ProductType != null)
{
ProductType = ProductType.ToUpper();
if (ProductType.StartsWith("RM") && !ProductType.StartsWith("RM-"))
{
ProductType = "RM-" + ProductType[2..];
}
}
if (OperatorCode != null)
{
OperatorCode = OperatorCode.ToUpper();
}
DiscoveryQueryParameters DiscoveryQueryParams = new()
{
manufacturerName = "Microsoft",
manufacturerProductLine = "Lumia",
packageType = "Firmware",
packageClass = "Public",
manufacturerHardwareModel = ProductType,
manufacturerHardwareVariant = ProductCode,
operatorName = OperatorCode
};
DiscoveryParameters DiscoveryParams = new()
{
query = DiscoveryQueryParams
};
DataContractJsonSerializer Serializer1 = new(typeof(DiscoveryParameters));
MemoryStream JsonStream1 = new();
Serializer1.WriteObject(JsonStream1, DiscoveryParams);
JsonStream1.Seek(0L, SeekOrigin.Begin);
string JsonContent = new StreamReader(JsonStream1).ReadToEnd();
Uri RequestUri = new("https://api.swrepository.com/rest-api/discovery/1/package");
HttpClient HttpClient = new();
HttpClient.DefaultRequestHeaders.UserAgent.TryParseAdd("SoftwareRepository");
HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Task<HttpResponseMessage> HttpPostTask = HttpClient.PostAsync(RequestUri, new StringContent(JsonContent, Encoding.UTF8, "application/json"));
HttpPostTask.Wait();
HttpResponseMessage Response = HttpPostTask.Result;
string JsonResultString = "";
if (Response.StatusCode == HttpStatusCode.OK)
{
Task<string> ReadResponseTask = Response.Content.ReadAsStringAsync();
ReadResponseTask.Wait();
JsonResultString = ReadResponseTask.Result;
}
SoftwarePackage Package = null;
using (MemoryStream JsonStream2 = new(Encoding.UTF8.GetBytes(JsonResultString)))
{
DataContractJsonSerializer Serializer2 = new(typeof(SoftwarePackages));
SoftwarePackages SoftwarePackages = (SoftwarePackages)Serializer2.ReadObject(JsonStream2);
if (SoftwarePackages != null)
{
Package = SoftwarePackages.softwarePackages.FirstOrDefault();
}
}
if (Package == null)
{
throw new WPinternalsException("FFU not found", "No FFU has been found in the remote software repository for the requested model.");
}
FoundProductType = Package.manufacturerHardwareModel[0];
SoftwareFile FileInfo = Package.files.First(f => f.fileName.EndsWith(".ffu", StringComparison.OrdinalIgnoreCase));
Uri FileInfoUri = new("https://api.swrepository.com/rest-api/discovery/fileurl/1/" + Package.id + "/" + FileInfo.fileName);
Task<string> GetFileInfoTask = HttpClient.GetStringAsync(FileInfoUri);
GetFileInfoTask.Wait();
string FileInfoString = GetFileInfoTask.Result;
string FfuUrl = "";
FileUrlResult FileUrl = null;
using (MemoryStream JsonStream3 = new(Encoding.UTF8.GetBytes(FileInfoString)))
{
DataContractJsonSerializer Serializer3 = new(typeof(FileUrlResult));
FileUrl = (FileUrlResult)Serializer3.ReadObject(JsonStream3);
if (FileUrl != null)
{
FfuUrl = FileUrl.url.Replace("sr.azureedge.net", "softwarerepo.blob.core.windows.net");
}
}
HttpClient.Dispose();
return FfuUrl;
}
internal static string SearchENOSW(string ProductType, string PhoneFirmwareRevision)
{
if (ProductType?.Length == 0)
{
ProductType = null;
}
if (ProductType != null)
{
ProductType = ProductType.ToUpper();
if (ProductType.StartsWith("RM") && !ProductType.StartsWith("RM-"))
{
ProductType = "RM-" + ProductType[2..];
}
}
DiscoveryQueryParameters DiscoveryQueryParams = new()
{
manufacturerName = "Microsoft",
manufacturerProductLine = "Lumia",
packageType = "Test Mode",
packageClass = "Public",
manufacturerHardwareModel = ProductType
};
DiscoveryParameters DiscoveryParams = new()
{
query = DiscoveryQueryParams
};
DataContractJsonSerializer Serializer1 = new(typeof(DiscoveryParameters));
MemoryStream JsonStream1 = new();
Serializer1.WriteObject(JsonStream1, DiscoveryParams);
JsonStream1.Seek(0L, SeekOrigin.Begin);
string JsonContent = new StreamReader(JsonStream1).ReadToEnd();
Uri RequestUri = new("https://api.swrepository.com/rest-api/discovery/1/package");
HttpClient HttpClient = new();
HttpClient.DefaultRequestHeaders.UserAgent.TryParseAdd("SoftwareRepository");
HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Task<HttpResponseMessage> HttpPostTask = HttpClient.PostAsync(RequestUri, new StringContent(JsonContent, Encoding.UTF8, "application/json"));
HttpPostTask.Wait();
HttpResponseMessage Response = HttpPostTask.Result;
string JsonResultString = "";
if (Response.StatusCode == HttpStatusCode.OK)
{
Task<string> ReadResponseTask = Response.Content.ReadAsStringAsync();
ReadResponseTask.Wait();
JsonResultString = ReadResponseTask.Result;
}
SoftwarePackage Package = null;
using (MemoryStream JsonStream2 = new(Encoding.UTF8.GetBytes(JsonResultString)))
{
DataContractJsonSerializer Serializer2 = new(typeof(SoftwarePackages));
SoftwarePackages SoftwarePackages = (SoftwarePackages)Serializer2.ReadObject(JsonStream2);
if (SoftwarePackages != null)
{
foreach (SoftwarePackage pkg in SoftwarePackages.softwarePackages)
{
Package = SoftwarePackages.softwarePackages.FirstOrDefault();
}
}
}
if (Package == null)
{
throw new WPinternalsException("ENOSW package not found", "No ENOSW package has been found in the remote software repository for the requested model.");
}
SoftwareFile FileInfo = Package.files.First(f => f.fileName.EndsWith(".secwim", StringComparison.OrdinalIgnoreCase));
SoftwareFile DPLF = Package.files.First(f => f.fileName.EndsWith(".dpl", StringComparison.OrdinalIgnoreCase));
Uri DPLUri = new("https://api.swrepository.com/rest-api/discovery/fileurl/1/" + Package.id + "/" + DPLF.fileName);
Task<string> GetDPLTask = HttpClient.GetStringAsync(DPLUri);
GetDPLTask.Wait();
string DPLString = GetDPLTask.Result;
string DPLUrl = "";
FileUrlResult FileUrlDPL = null;
using (MemoryStream JsonStream3 = new(Encoding.UTF8.GetBytes(DPLString)))
{
DataContractJsonSerializer Serializer3 = new(typeof(FileUrlResult));
FileUrlDPL = (FileUrlResult)Serializer3.ReadObject(JsonStream3);
if (FileUrlDPL != null)
{
DPLUrl = FileUrlDPL.url.Replace("sr.azureedge.net", "softwarerepo.blob.core.windows.net");
}
}
if (DPLUrl?.Length == 0)
{
throw new WPinternalsException("DPL not found", "No DPL has been found in the remote software repository for the requested model.");
}
Task<string> GetDPLStrTask = HttpClient.GetStringAsync(DPLUrl);
GetDPLStrTask.Wait();
string DPLStrString = GetDPLStrTask.Result;
DPL.Package dpl;
XmlSerializer serializer = new(typeof(DPL.Package));
using (StringReader reader = new(DPLStrString.Replace("ft:", "").Replace("dpl:", "").Replace("typedes:", "")))
{
dpl = (DPL.Package)serializer.Deserialize(reader);
}
foreach (DPL.File file in dpl.Content.Files.File)
{
string name = file.Name;
DPL.Range range = file.Extensions.MmosWimFile.UseCaseCompatibilities.Compatibility.FirstOrDefault().Range;
if (IsFirmwareBetween(PhoneFirmwareRevision, range.From, range.To))
{
FileInfo = Package.files.First(f => f.fileName.EndsWith(name, StringComparison.OrdinalIgnoreCase));
}
}
Uri FileInfoUri = new("https://api.swrepository.com/rest-api/discovery/fileurl/1/" + Package.id + "/" + FileInfo.fileName);
Task<string> GetFileInfoTask = HttpClient.GetStringAsync(FileInfoUri);
GetFileInfoTask.Wait();
string FileInfoString = GetFileInfoTask.Result;
string ENOSWUrl = "";
FileUrlResult FileUrl = null;
using (MemoryStream JsonStream3 = new(Encoding.UTF8.GetBytes(FileInfoString)))
{
DataContractJsonSerializer Serializer3 = new(typeof(FileUrlResult));
FileUrl = (FileUrlResult)Serializer3.ReadObject(JsonStream3);
if (FileUrl != null)
{
ENOSWUrl = FileUrl.url.Replace("sr.azureedge.net", "softwarerepo.blob.core.windows.net");
}
}
HttpClient.Dispose();
return ENOSWUrl;
}
private static bool IsFirmwareBetween(string PhoneFirmwareRevision, string Limit1, string Limit2)
{
var version = new Version(PhoneFirmwareRevision);
var version1 = new Version(Limit1);
var version2 = new Version(Limit2);
var result = version.CompareTo(version1);
var result2 = version.CompareTo(version2);
return result >= 0 && result2 <= 0;
}
internal static string[] SearchEmergencyFiles(string ProductType)
{
ProductType = ProductType.ToUpper();
if (ProductType.StartsWith("RM") && !ProductType.StartsWith("RM-"))
{
ProductType = "RM-" + ProductType[2..];
}
LogFile.Log("Getting Emergency files for: " + ProductType, LogType.FileAndConsole);
if ((ProductType == "RM-1072") || (ProductType == "RM-1073"))
{
LogFile.Log("Due to mix-up in online-repository, redirecting to emergency files of RM-1113", LogType.FileAndConsole);
ProductType = "RM-1113";
}
List<string> Result = new();
WebClient Client = new();
string Src;
string FileName;
string Config = null;
try
{
Config = Client.DownloadString("https://repairavoidance.blob.core.windows.net/packages/EmergencyFlash/" + ProductType + "/emergency_flash_config.xml");
}
catch
{
LogFile.Log("Emergency files for " + ProductType + " not found", LogType.FileAndConsole);
return null;
}
Client.Dispose();
XmlDocument Doc = new();
Doc.LoadXml(Config);
// Hex
XmlNode Node = Doc.SelectSingleNode("//emergency_flash_config/hex_flasher");
if (Node != null)
{
FileName = Node.Attributes["image_path"].InnerText;
Src = "https://repairavoidance.blob.core.windows.net/packages/EmergencyFlash/" + ProductType + "/" + FileName;
LogFile.Log("Hex-file: " + Src);
Result.Add(Src);
}
// Mbn
Node = Doc.SelectSingleNode("//emergency_flash_config/mbn_image");
if (Node != null)
{
FileName = Node.Attributes["image_path"].InnerText;
Src = "https://repairavoidance.blob.core.windows.net/packages/EmergencyFlash/" + ProductType + "/" + FileName;
LogFile.Log("Mbn-file: " + Src);
Result.Add(Src);
}
// Ede
foreach (XmlNode SubNode in Doc.SelectNodes("//emergency_flash_config/first_boot_images/first_boot_image"))
{
FileName = SubNode.Attributes["image_path"].InnerText;
Src = "https://repairavoidance.blob.core.windows.net/packages/EmergencyFlash/" + ProductType + "/" + FileName;
LogFile.Log("Firehose-programmer-file: " + Src);
Result.Add(Src);
}
// Edp
foreach (XmlNode SubNode in Doc.SelectNodes("//emergency_flash_config/second_boot_firehose_single_image/firehose_image"))
{
FileName = SubNode.Attributes["image_path"].InnerText;
Src = "https://repairavoidance.blob.core.windows.net/packages/EmergencyFlash/" + ProductType + "/" + FileName;
LogFile.Log("Firehose-payload-file: " + Src);
Result.Add(Src);
}
return Result.ToArray();
}
}
#pragma warning disable 0649
[DataContract]
internal class FileUrlResult
{
[DataMember]
internal string url;
[DataMember]
internal List<string> alternateUrl;
[DataMember]
internal long fileSize;
[DataMember]
internal List<SoftwareFileChecksum> checksum;
}
#pragma warning restore 0649
[DataContract]
public class DiscoveryQueryParameters
{
[DataMember(EmitDefaultValue = false)]
public string customerName;
[DataMember(EmitDefaultValue = false)]
public ExtendedAttributes extendedAttributes;
[DataMember(EmitDefaultValue = false)]
public string manufacturerHardwareModel;
[DataMember(EmitDefaultValue = false)]
public string manufacturerHardwareVariant;
[DataMember(EmitDefaultValue = false)]
public string manufacturerModelName;
[DataMember]
public string manufacturerName;
[DataMember(EmitDefaultValue = false)]
public string manufacturerPackageId;
[DataMember(EmitDefaultValue = false)]
public string manufacturerPlatformId;
[DataMember]
public string manufacturerProductLine;
[DataMember(EmitDefaultValue = false)]
public string manufacturerVariantName;
[DataMember(EmitDefaultValue = false)]
public string operatorName;
[DataMember]
public string packageClass;
[DataMember(EmitDefaultValue = false)]
public string packageRevision;
[DataMember(EmitDefaultValue = false)]
public string packageState;
[DataMember(EmitDefaultValue = false)]
public string packageSubRevision;
[DataMember(EmitDefaultValue = false)]
public string packageSubtitle;
[DataMember(EmitDefaultValue = false)]
public string packageTitle;
[DataMember]
public string packageType;
}
[DataContract]
public class DiscoveryParameters
{
[DataMember(Name = "api-version")]
public string apiVersion;
[DataMember]
public DiscoveryQueryParameters query;
[DataMember]
public List<string> condition;
[DataMember]
public List<string> response;
public DiscoveryParameters() : this(DiscoveryCondition.Default)
{
}
public DiscoveryParameters(DiscoveryCondition Condition)
{
this.apiVersion = "1";
this.query = new DiscoveryQueryParameters();
this.condition = new List<string>();
if (Condition == DiscoveryCondition.All)
{
this.condition.Add("all");
return;
}
if (Condition == DiscoveryCondition.Latest)
{
this.condition.Add("latest");
return;
}
this.condition.Add("default");
}
}
public enum DiscoveryCondition
{
Default,
All,
Latest
}
[Serializable]
public class ExtendedAttributes : ISerializable
{
public Dictionary<string, string> Dictionary;
public ExtendedAttributes()
{
this.Dictionary = new Dictionary<string, string>();
}
protected ExtendedAttributes(SerializationInfo info, StreamingContext context)
{
if (info != null)
{
this.Dictionary = new Dictionary<string, string>();
SerializationInfoEnumerator Enumerator = info.GetEnumerator();
while (Enumerator.MoveNext())
{
this.Dictionary.Add(Enumerator.Current.Name, (string)Enumerator.Current.Value);
}
}
}
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info != null)
{
foreach (string Current in this.Dictionary.Keys)
{
info.AddValue(Current, this.Dictionary[Current]);
}
}
}
}
[DataContract]
public class SoftwareFileChecksum
{
[DataMember]
public string type;
[DataMember]
public string value;
}
[DataContract]
public class SoftwarePackages
{
[DataMember]
public List<SoftwarePackage> softwarePackages;
}
[DataContract]
public class SoftwarePackage
{
[DataMember]
public List<string> customerName;
[DataMember]
public ExtendedAttributes extendedAttributes;
[DataMember]
public List<SoftwareFile> files;
[DataMember]
public string id;
[DataMember]
public List<string> manufacturerHardwareModel;
[DataMember]
public List<string> manufacturerHardwareVariant;
[DataMember]
public List<string> manufacturerModelName;
[DataMember]
public string manufacturerName;
[DataMember]
public string manufacturerPackageId;
[DataMember]
public List<string> manufacturerPlatformId;
[DataMember]
public string manufacturerProductLine;
[DataMember]
public List<string> manufacturerVariantName;
[DataMember]
public List<string> operatorName;
[DataMember]
public List<string> packageClass;
[DataMember]
public string packageDescription;
[DataMember]
public string packageRevision;
[DataMember]
public string packageState;
[DataMember]
public string packageSubRevision;
[DataMember]
public string packageSubtitle;
[DataMember]
public string packageTitle;
[DataMember]
public string packageType;
}
[DataContract]
public class SoftwareFile
{
[DataMember]
public List<SoftwareFileChecksum> checksum;
[DataMember]
public string fileName;
[DataMember]
public long fileSize;
[DataMember]
public string fileType;
}
public static class DPL
{
[XmlRoot(ElementName = "BasicProductCodes")]
public class BasicProductCodes
{
[XmlElement(ElementName = "BasicProductCode")]
public List<string> BasicProductCode { get; set; }
}
[XmlRoot(ElementName = "Identification")]
public class Identification
{
[XmlElement(ElementName = "TypeDesignator")]
public string TypeDesignator { get; set; }
[XmlElement(ElementName = "BasicProductCodes")]
public BasicProductCodes BasicProductCodes { get; set; }
[XmlElement(ElementName = "Purpose")]
public string Purpose { get; set; }
}
[XmlRoot(ElementName = "Extensions")]
public class Extensions
{
[XmlElement(ElementName = "PackageType")]
public string PackageType { get; set; }
[XmlElement(ElementName = "Identification")]
public Identification Identification { get; set; }
[XmlElement(ElementName = "FileType")]
public string FileType { get; set; }
[XmlElement(ElementName = "MmosWimFile")]
public MmosWimFile MmosWimFile { get; set; }
}
[XmlRoot(ElementName = "PackageDescription")]
public class PackageDescription
{
[XmlElement(ElementName = "Identifier")]
public string Identifier { get; set; }
[XmlElement(ElementName = "Revision")]
public string Revision { get; set; }
[XmlElement(ElementName = "Extensions")]
public Extensions Extensions { get; set; }
}
[XmlRoot(ElementName = "Digest")]
public class Digest
{
[XmlAttribute(AttributeName = "method")]
public string Method { get; set; }
[XmlAttribute(AttributeName = "encoding")]
public string Encoding { get; set; }
[XmlText]
public string Text { get; set; }
}
[XmlRoot(ElementName = "Digests")]
public class Digests
{
[XmlElement(ElementName = "Digest")]
public List<Digest> Digest { get; set; }
}
[XmlRoot(ElementName = "Range")]
public class Range
{
[XmlAttribute(AttributeName = "from")]
public string From { get; set; }
[XmlAttribute(AttributeName = "to")]
public string To { get; set; }
}
[XmlRoot(ElementName = "Compatibility")]
public class Compatibility
{
[XmlElement(ElementName = "Range")]
public Range Range { get; set; }
[XmlAttribute(AttributeName = "useCase")]
public string UseCase { get; set; }
}
[XmlRoot(ElementName = "UseCaseCompatibilities")]
public class UseCaseCompatibilities
{
[XmlElement(ElementName = "Compatibility")]
public List<Compatibility> Compatibility { get; set; }
}
[XmlRoot(ElementName = "MmosWimFile")]
public class MmosWimFile
{
[XmlElement(ElementName = "UseCaseCompatibilities")]
public UseCaseCompatibilities UseCaseCompatibilities { get; set; }
}
[XmlRoot(ElementName = "File")]
public class File
{
[XmlElement(ElementName = "Name")]
public string Name { get; set; }
[XmlElement(ElementName = "Digests")]
public Digests Digests { get; set; }
[XmlElement(ElementName = "Revision")]
public string Revision { get; set; }
[XmlElement(ElementName = "Extensions")]
public Extensions Extensions { get; set; }
}
[XmlRoot(ElementName = "Files")]
public class Files
{
[XmlElement(ElementName = "File")]
public List<File> File { get; set; }
}
[XmlRoot(ElementName = "Content")]
public class Content
{
[XmlElement(ElementName = "PackageDescription")]
public PackageDescription PackageDescription { get; set; }
[XmlElement(ElementName = "Files")]
public Files Files { get; set; }
}
[XmlRoot(ElementName = "CanonicalizationMethod", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public class CanonicalizationMethod
{
[XmlAttribute(AttributeName = "Algorithm")]
public string Algorithm { get; set; }
}
[XmlRoot(ElementName = "SignatureMethod", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public class SignatureMethod
{
[XmlAttribute(AttributeName = "Algorithm")]
public string Algorithm { get; set; }
}
[XmlRoot(ElementName = "Transform", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public class Transform
{
[XmlAttribute(AttributeName = "Algorithm")]
public string Algorithm { get; set; }
}
[XmlRoot(ElementName = "Transforms", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public class Transforms
{
[XmlElement(ElementName = "Transform", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public Transform Transform { get; set; }
}
[XmlRoot(ElementName = "DigestMethod", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public class DigestMethod
{
[XmlAttribute(AttributeName = "Algorithm")]
public string Algorithm { get; set; }
}
[XmlRoot(ElementName = "Reference", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public class Reference
{
[XmlElement(ElementName = "Transforms", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public Transforms Transforms { get; set; }
[XmlElement(ElementName = "DigestMethod", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public DigestMethod DigestMethod { get; set; }
[XmlElement(ElementName = "DigestValue", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public string DigestValue { get; set; }
[XmlAttribute(AttributeName = "URI")]
public string URI { get; set; }
}
[XmlRoot(ElementName = "SignedInfo", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public class SignedInfo
{
[XmlElement(ElementName = "CanonicalizationMethod", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public CanonicalizationMethod CanonicalizationMethod { get; set; }
[XmlElement(ElementName = "SignatureMethod", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public SignatureMethod SignatureMethod { get; set; }
[XmlElement(ElementName = "Reference", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public Reference Reference { get; set; }
}
[XmlRoot(ElementName = "KeyInfo", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public class KeyInfo
{
[XmlElement(ElementName = "KeyName", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public string KeyName { get; set; }
}
[XmlRoot(ElementName = "Signature", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public class Signature
{
[XmlElement(ElementName = "SignedInfo", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public SignedInfo SignedInfo { get; set; }
[XmlElement(ElementName = "SignatureValue", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public string SignatureValue { get; set; }
[XmlElement(ElementName = "KeyInfo", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public KeyInfo KeyInfo { get; set; }
[XmlAttribute(AttributeName = "xmlns")]
public string Xmlns { get; set; }
}
[XmlRoot(ElementName = "Package")]
public class Package
{
[XmlElement(ElementName = "Content")]
public Content Content { get; set; }
[XmlElement(ElementName = "Signature", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public Signature Signature { get; set; }
}
}
}
+334
View File
@@ -0,0 +1,334 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
# *.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>
+301
View File
@@ -0,0 +1,301 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Gee.External.Capstone;
using Gee.External.Capstone.Arm;
//using PeNet;
namespace Patcher
{
public static class ArmDisassembler
{
public static AnalyzedFile Analyze(string FilePath, string AsmPath = null)
{
PeFile File = new(FilePath);
SortedList<UInt32, ArmInstruction> AnalyzedCode = new(0x1000000); // Default capacity of 0x100000 was not enough for analyzing ntoskrnl.exe
if ((AsmPath != null) && System.IO.File.Exists(AsmPath))
{
using StreamReader Reader = new(AsmPath);
while (Reader.Peek() >= 0)
{
ArmInstruction Instruction = new(Reader.ReadLine());
AnalyzedCode.Add(Instruction.Address, Instruction);
}
}
else
{
CapstoneArmDisassembler Disassembler = CapstoneDisassembler.CreateArmDisassembler(ArmDisassembleMode.Thumb);
// Initially use a Dictionary and sort it afterwards. For analyzing ntoskrnl.exe this is about 60 times faster than using a SortedList from the start.
// Default capacity of 0x100000 was not enough for analyzing ntoskrnl.exe
Dictionary<UInt32, ArmInstruction> TempCode = new(0x1000000);
// Analyze from entrypoint
Analyze(Disassembler, File.Sections, TempCode, (UInt32)(File.ImageBase + File.EntryPoint));
// Analyze from exports
foreach (FunctionDescriptor Function in File.Exports)
Analyze(Disassembler, File.Sections, TempCode, (UInt32)Function.VirtualAddress);
// Analyze from imports
foreach (FunctionDescriptor Function in File.Imports)
Analyze(Disassembler, File.Sections, TempCode, (UInt32)Function.VirtualAddress);
// Analyze from runtime-functions
foreach (FunctionDescriptor Function in File.RuntimeFunctions)
Analyze(Disassembler, File.Sections, TempCode, (UInt32)Function.VirtualAddress);
// Sort the instructions.
// SortedList is used, because it can be indexed by value (not only by key).
List<UInt32> Keys = TempCode.Keys.ToList();
Keys.Sort();
foreach (UInt32 Key in Keys)
AnalyzedCode.Add(Key, TempCode[Key]);
if (AsmPath != null)
{
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(AsmPath));
using StreamWriter Writer = new(AsmPath, false);
for (int i = 0; i < AnalyzedCode.Count; i++)
{
Writer.WriteLine(AnalyzedCode.Values[i].ToString());
}
}
}
return new AnalyzedFile() { File = File, Code = AnalyzedCode };
}
public static void Analyze(CapstoneArmDisassembler Disassembler, List<Section> Sections, Dictionary<UInt32, ArmInstruction> AnalyzedCode, UInt32 VirtualAddress)
{
VirtualAddress -= (VirtualAddress % 2);
List<UInt32> AddressesToAnalyze = new();
AddressesToAnalyze.Add(VirtualAddress);
Section CurrentSection = null;
while (AddressesToAnalyze.Count > 0)
{
UInt32 CurrentAddress = AddressesToAnalyze[0];
if ((CurrentSection == null) || (CurrentAddress < CurrentSection.VirtualAddress) || (CurrentAddress > (CurrentSection.VirtualAddress + CurrentSection.VirtualSize)))
{
CurrentSection = Sections.Find(s => (CurrentAddress >= s.VirtualAddress) && (CurrentAddress < (s.VirtualAddress + s.VirtualSize)) && s.IsCode);
if (CurrentSection == null)
{
// throw new Exception("Address 0x" + CurrentAddress.ToString("X8") + " is not inside boundaries of code-sections");
// Probably jumped to this address because data was disassembled as if it were code. Ignore this.
// return;
AddressesToAnalyze.RemoveAt(0);
continue;
}
}
if (AnalyzedCode.ContainsKey(CurrentAddress))
{
// return;
AddressesToAnalyze.RemoveAt(0);
continue;
}
Gee.External.Capstone.Arm.ArmInstruction[] NewInstructions = Disassembler.Disassemble(CurrentSection.Buffer.Skip((int)CurrentAddress - (int)CurrentSection.VirtualAddress).ToArray(), CurrentAddress);
if (NewInstructions.Any())
{
UInt32 StartAddress = (UInt32)NewInstructions.First().Address;
UInt32 EndAddress = (UInt32)NewInstructions.Last().Address;
ArmInstruction PreviousInstruction = null;
foreach (Gee.External.Capstone.Arm.ArmInstruction DisassemblerInstruction in NewInstructions)
{
// ArmInstruction Instruction = new ArmInstruction(DisassemblerInstruction);
ArmInstruction Instruction = new()
{
Address = (UInt32)DisassemblerInstruction.Address,
Bytes = DisassemblerInstruction.Bytes,
Mnemonic = DisassemblerInstruction.Mnemonic,
Operand = DisassemblerInstruction.Operand.Replace("sb", "r9").Replace("sl", "r10").Replace("fp", "r11").Replace("ip", "r12")
};
if (AnalyzedCode.ContainsKey((UInt32)Instruction.Address))
break;
// Merge movw + movt into one command
// movw r3, #0x6010 + movt r3, #0x1000 = mov r3, #0x10006010
UInt32 HighPart, LowPart;
string HighString, LowString;
if ((PreviousInstruction?.Mnemonic == "movt") && (Instruction.Mnemonic == "movw") && (PreviousInstruction.Operand.Split(new char[] { ',' })[0] == Instruction.Operand.Split(new char[] { ',' })[0]))
{
byte[] Combined = new byte[8];
System.Buffer.BlockCopy(PreviousInstruction.Bytes, 0, Combined, 0, 4);
System.Buffer.BlockCopy(Instruction.Bytes, 0, Combined, 4, 4);
PreviousInstruction.Bytes = Combined;
PreviousInstruction.Mnemonic = "mov";
HighString = PreviousInstruction.Operand[(PreviousInstruction.Operand.IndexOf('#') + 1)..];
HighPart = (HighString.Length >= 2) && (HighString.Substring(0, 2) == "0x")
? UInt32.Parse(HighString[2..], System.Globalization.NumberStyles.HexNumber)
: UInt32.Parse(HighString);
LowString = Instruction.Operand[(Instruction.Operand.IndexOf('#') + 1)..];
LowPart = (LowString.Length >= 2) && (LowString.Substring(0, 2) == "0x")
? UInt32.Parse(LowString[2..], System.Globalization.NumberStyles.HexNumber)
: UInt32.Parse(LowString);
PreviousInstruction.Operand = string.Concat(PreviousInstruction.Operand.AsSpan(0, PreviousInstruction.Operand.IndexOf('#') + 1), "0x", ((HighPart << 16) + LowPart).ToString("X8"));
continue;
}
if ((PreviousInstruction?.Mnemonic == "movw") && (Instruction.Mnemonic == "movt") && (PreviousInstruction.Operand.Split(new char[] { ',' })[0] == Instruction.Operand.Split(new char[] { ',' })[0]))
{
byte[] Combined = new byte[8];
System.Buffer.BlockCopy(PreviousInstruction.Bytes, 0, Combined, 0, 4);
System.Buffer.BlockCopy(Instruction.Bytes, 0, Combined, 4, 4);
PreviousInstruction.Bytes = Combined;
PreviousInstruction.Mnemonic = "mov";
HighString = Instruction.Operand[(Instruction.Operand.IndexOf('#') + 1)..];
HighPart = (HighString.Length >= 2) && (HighString.Substring(0, 2) == "0x")
? UInt32.Parse(HighString[2..], System.Globalization.NumberStyles.HexNumber)
: UInt32.Parse(HighString);
LowString = PreviousInstruction.Operand[(PreviousInstruction.Operand.IndexOf('#') + 1)..];
LowPart = (LowString.Length >= 2) && (LowString.Substring(0, 2) == "0x")
? UInt32.Parse(LowString[2..], System.Globalization.NumberStyles.HexNumber)
: UInt32.Parse(LowString);
PreviousInstruction.Operand = string.Concat(PreviousInstruction.Operand.AsSpan(0, PreviousInstruction.Operand.IndexOf('#') + 1), "0x", ((HighPart << 16) + LowPart).ToString("X8"));
continue;
}
AnalyzedCode.Add((UInt32)Instruction.Address, Instruction);
int IndexOfIndirectConstant = Instruction.Operand.IndexOf("[pc, #0x");
if (IndexOfIndirectConstant >= 0)
{
int IndexOfEnd = Instruction.Operand.IndexOf("]", IndexOfIndirectConstant);
string PCOffsetString = Instruction.Operand.Substring(IndexOfIndirectConstant + 8, IndexOfEnd - IndexOfIndirectConstant - 8);
UInt32 PCOffset = UInt32.Parse(PCOffsetString, System.Globalization.NumberStyles.HexNumber);
UInt32 PC = (UInt32)Instruction.Address + 4;
UInt32 PCforIndirect = PC - (PC % 4);
UInt32 VirtualAddressOfIndirectConstant = PCforIndirect + PCOffset;
// If the address is outside the range of the section, then this is probably data which is compiled as code.
// In this case we will ignore this and not do this part of the analysis.
if ((VirtualAddressOfIndirectConstant >= CurrentSection.VirtualAddress) && (VirtualAddressOfIndirectConstant < (CurrentSection.VirtualAddress + CurrentSection.VirtualSize)))
{
UInt32 RawOffsetOfIndirectConstant = VirtualAddressOfIndirectConstant - CurrentSection.VirtualAddress;
UInt32 IndirectConstant = BitConverter.ToUInt32(CurrentSection.Buffer, (int)RawOffsetOfIndirectConstant);
Instruction.Operand = Instruction.Operand.Substring(0, IndexOfIndirectConstant) + "#0x" + IndirectConstant.ToString("x8") + Instruction.Operand[(IndexOfEnd + 1)..];
}
}
if (JumpCommands.Contains(Instruction.Mnemonic))
{
UInt32 NewAddress = UInt32.Parse(Instruction.Operand[(Instruction.Operand.IndexOf("#0x") + 3)..], System.Globalization.NumberStyles.HexNumber);
NewAddress -= (NewAddress % 2);
if (((NewAddress < StartAddress) || (NewAddress > EndAddress)) && !AddressesToAnalyze.Any(a => a == NewAddress))
AddressesToAnalyze.Add(NewAddress);
}
PreviousInstruction = Instruction;
}
}
AddressesToAnalyze.RemoveAt(0);
}
}
public static string[] JumpCommands = new string[]
{
"b", "b.w", "bl", "bl.w", "beq", "beq.w", "bne", "bne.w", "bhs", "bhs.w", "blo", "blo.w",
"bmi", "bmi.w", "bpl", "bpl.w", "bvs", "bvs.w", "bvc", "bvc.w", "bhi", "bhi.w", "bls", "bls.w",
"bge", "bge.w", "blt", "blt.w", "bgt", "bgt.w", "ble", "ble.w", "bal", "bal.w", "cbnz", "cbz"
};
public static string[] ConditionalJumpInstructions = new string[]
{
"beq", "beq.w", "bne", "bne.w", "bhs", "bhs.w", "blo", "blo.w", "bmi", "bmi.w",
"bpl", "bpl.w", "bvs", "bvs.w", "bvc", "bvc.w", "bhi", "bhi.w", "bls", "bls.w",
"bge", "bge.w", "blt", "blt.w", "bgt", "bgt.w", "ble", "ble.w", "bal", "bal.w", "cbnz", "cbz"
};
public static string WriteCode(SortedDictionary<UInt32, ArmInstruction> AnalyzedCode)
{
StringBuilder Code = new(1000);
foreach (var Instruction in AnalyzedCode)
{
Code.AppendFormat("{0:X}: \t {1} \t {2}\r\n", Instruction.Value.Address, Instruction.Value.Mnemonic, Instruction.Value.Operand);
}
return Code.ToString();
}
}
public class ArmInstruction
{
public UInt32 Address;
public byte[] Bytes;
public string Mnemonic;
public string Operand;
public ArmInstruction()
{
}
public ArmInstruction(string Assembly)
{
Address = UInt32.Parse(Assembly.Substring(0, 8), System.Globalization.NumberStyles.HexNumber);
string Hex = Assembly.Substring(12, 24).Trim();
Bytes = new byte[(Hex.Length + 1) / 3];
for (int i = 0; i < Bytes.Length; i++)
Bytes[i] = byte.Parse(Hex.Substring(i * 3, 2), System.Globalization.NumberStyles.HexNumber);
Mnemonic = Assembly.Substring(39, 16).Trim();
Operand = Assembly[55..];
}
public override string ToString()
{
StringBuilder Result = new();
Result.Append(Address.ToString("X8")); // 0
Result.Append(" ");
for (int i = 0; i < Bytes.Length; i++) // 12
{
Result.Append(Bytes[i].ToString("X2"));
Result.Append(' ');
}
Result.Append(new String(' ', (8 - Bytes.Length) * 3));
Result.Append(" ");
Result.Append(Mnemonic.PadRight(16)); // 39
Result.Append(Operand); // 55
return Result.ToString();
}
}
public class AnalyzedFile
{
public PeFile File;
public SortedList<UInt32, ArmInstruction> Code;
}
}
+39
View File
@@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<OutputType>WinExe</OutputType>
<RootNamespace>Patcher</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<UseWindowsForms>true</UseWindowsForms>
<Platforms>x86</Platforms>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Patcher\ArmCompiler.cs">
<Link>ArmCompiler.cs</Link>
</Compile>
<Compile Include="..\Patcher\ByteOperations.cs">
<Link>ByteOperations.cs</Link>
</Compile>
<Compile Include="..\Patcher\HelperClasses.cs">
<Link>HelperClasses.cs</Link>
</Compile>
<Compile Include="..\Patcher\ObjectFileParser.cs">
<Link>ObjectFileParser.cs</Link>
</Compile>
<Compile Include="..\Patcher\PatchEngine.cs">
<Link>PatchEngine.cs</Link>
</Compile>
<Compile Include="..\Patcher\PeFile.cs">
<Link>PeFile.cs</Link>
</Compile>
<None Include="..\Patcher\LICENSE">
<Link>LICENSE</Link>
</None>
<None Update="BootUnllockAndRootAccessPatchScript.pds">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Gee.External.Capstone" Version="2.0.2" />
</ItemGroup>
</Project>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
<ItemGroup>
<Compile Update="MainForm.cs">
<SubType>Form</SubType>
</Compile>
</ItemGroup>
</Project>
@@ -0,0 +1,698 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Patch Definition Script for Boot Unlock and Root Access on Windows Mobile
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
PatchDefinition Name="RootAccess-MainOS" VersionFrom="EFIESP\Windows\System32\Boot\mobilestartup.efi"
PatchFile Path="Windows\System32\sspisrv.dll"
JumpToImport "RpcImpersonateClient"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "CheckLowboxAccess" // Optional here
PatchCode
MOVS R1, #1
STR R1, [R0]
MOVS R0, #0
BX LR
EndPatch
PatchChecksum
PatchFile Path="Windows\System32\NtlmShared.dll"
JumpToExport "MsvpPasswordValidate"
PatchCode
MOVS R0, #1
BX LR
EndPatch
PatchChecksum
PatchFile Path="Windows\System32\pacmanserver.dll"
FindFirstUnicode "GetMaxCountForDeployedApp"
JumpToReference
FindPreviousInstruction "PUSH.W"
PatchCode
LDR R1, =0x7FFFFFFF
STR R1, [R0]
MOVS R0, #0
BX LR
EndPatch
PatchChecksum
PatchFile Path="Windows\System32\mscoree.dll"
JumpToImport "GetModuleFileNameW"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "CompareWithWhiteList" // Optional here
PatchCode
MOVS R0, #0
BX LR
EndPatch
PatchChecksum
PatchFile Path="Windows\System32\DeploymentExt.dll"
FindFirstUnicode "MaxUnsignedApp"
JumpToReference
FindValue 0x800413A0
FindPreviousConditionalJump
MakeJumpUnconditional
PatchChecksum
PatchFile Path="Windows\System32\ntoskrnl.exe"
// Phase 1: find all kernel-functions
JumpToExport "SeAccessCheckWithHint"
CreateLabel "SeAccessCheckWithHint"
FindFunctionCall R0 = "ADD R0, SP, #0x7C" R1 = "MOV R1, R?"
JumpToTarget
CreateLabel "SepFilterToDiscretionary"
JumpToReference R0 = "ADDS R0, R?, #0xD0"
FindPreviousInstruction "PUSH"
FindPreviousInstruction "PUSH"
CreateLabel "SeAccessCheckByType"
FindFunctionCall R0 = "ADDS R0, R?, #0xF8" R1 = "MOV R1, R?" R2 = "LDR R2, [R?,#0x28]" R3 = "MOV R3, R?"
JumpToTarget
CreateLabel "SepConstrainByMandatory"
JumpBack // to SeAccessCheckByType
JumpBack // to SepFilterToDiscretionary
JumpToReference R1 = "LDR R1, [R?,#8]"
FindPreviousInstruction "PUSH"
CreateLabel "SepCommonAccessCheckEx"
FindFunctionCall Result = "STR R0, [SP,#0xD4]"
JumpToTarget
CreateLabel "SepAccessCheckEx"
JumpBack // to SepCommonAccessCheckEx
JumpBack // to SepFilterToDiscretionary
JumpToReference R0 = "ADDS R0, R?, #0x130"
FindPreviousInstruction "PUSH"
FindPreviousInstruction "PUSH"
CreateLabel "SepAccessCheckAndAuditAlarm"
FindFunctionCall R0 = "LDR R0, [R?,#0x130]" R1 = "MOV R1, R?" R2 = "LDR R2, [R?,#0x50]" R3 = "MOV R3, R?"
JumpToTarget
CreateLabel "SepConstrainByConstraintMask"
FindNextConditionalJump
JumpToTarget
CreateLabel "SepConstrainByConstraintMask_FunctionChunk01"
JumpBack // to SepConstrainByConstraintMask
JumpBack // to SepAccessCheckAndAuditAlarm
JumpBack // to SepFilterToDiscretionary
JumpBack // to SeAccessCheckWithHint
FindFunctionCall R0 = "ADD R0, SP, #0x88" R1 = "MOV R1, R?"
JumpToTarget
CreateLabel "SepMandatoryToDiscretionary"
JumpBack
FindFunctionCall Result = "STR R0, [SP,#0x70]"
JumpToTarget
CreateLabel "SepAccessCheck"
JumpToExport "SePrivilegeCheck"
FindFunctionCall
JumpToTarget
CreateLabel "SepPrivilegeCheck"
JumpToExport "SeSinglePrivilegeCheck"
CreateLabel "SeSinglePrivilegeCheck"
JumpToExport "ObReferenceObjectByHandleWithTag"
CreateLabel "ObReferenceObjectByHandleWithTag"
// Phase 2: patches
JumpToLabel "SeAccessCheckByType"
// Patch 1:
FindNextValue 0xC0000022
FindPreviousConditionalJump
FindPreviousConditionalJump
FindPreviousConditionalJump
FindPreviousConditionalJump
MakeJumpUnconditional
FindNextValue 0xC0000022
// Patch 2:
FindNextValue 0xC0000022
FindStore
FindPreviousConditionalJump
MakeJumpUnconditional
// Patch 3:
FindNextValue 0xC0000022
FindPreviousConditionalJump
MakeJumpUnconditional // This jump is right above the value 0xC0000022. After patch the pointer is back on that value.
// FindNextValue 0xC0000022
// Patch 4:
FindNextValue 0xC0000022
FindPreviousConditionalJump
MakeJumpUnconditional // This jump is right above the value 0xC0000022. After patch the pointer is back on that value.
// FindNextValue 0xC0000022
// Patch 5:
FindNextValue 0xC0000022
FindNextInstruction "BNE"
JumpToTarget
CreateLabel "TargetPatch5"
JumpBack
FindPreviousInstruction "BEQ"
PatchCode
B TargetPatch5
EndPatch
// Patch 6:
FindNextValue 0xC0000022
FindNextConditionalJump
MakeJumpUnconditional
// Patch 7:
FindNextValue 0xC0000022
FindStore
FindPreviousConditionalJump
MakeJumpUnconditional
// Patch 8:
FindNextValue 0xC0000022
JumpToReference
ClearInstruction
JumpBack
// Patch 9:
FindNextValue 0xC0000022
JumpToReference
ClearInstruction
JumpBack
JumpToLabel "SepAccessCheckAndAuditAlarm"
// Patch 10:
FindNextValue 0xC0000022
FindPreviousConditionalJump
MakeJumpUnconditional
FindNextValue 0xC0000022
// Patch 11:
FindNextValue 0xC0000022
FindStore
CreateLabel "Patch11"
FindNextConditionalJump
JumpToTarget
CreateLabel "TargetPatch11"
JumpToLabel "Patch11"
PatchCode
B TargetPatch11
EndPatch
// Patch 12:
FindNextValue 0xC0000022
PatchCode
MOV.W R2, #0
EndPatch
JumpToLabel "SepCommonAccessCheckEx"
// Patch 13:
FindNextInstruction "TST"
FindNextInstruction "TST"
FindPreviousConditionalJump
ClearInstruction
JumpToLabel "SeAccessCheckWithHint"
// Patch 14:
FindNextInstruction "BEQ"
MakeJumpUnconditional
JumpToLabel "SeSinglePrivilegeCheck"
// Patch 15:
PatchCode
MOVS R0, #1
BX LR
EndPatch
JumpToLabel "ObReferenceObjectByHandleWithTag"
FindFunctionCall
JumpToTarget
CreateLabel "ObpReferenceObjectByHandleWithTag"
FindInstructionPattern "LDR R?, [R?,#0x74]; CMP R?, #0; BNE ?" InstructionIndex = 2
JumpToTarget
// Patch 16:
FindNextConditionalJump
MakeJumpUnconditional // This jump is right above the value 0xC0000022. After patch the pointer is on the error-value.
// Patch 17:
JumpToReference
ClearInstruction
JumpBack
JumpBack
// Patch 18:
FindNextValue 0xC0000022
JumpToReference
ClearInstruction
JumpToLabel "SepPrivilegeCheck"
// Patch 19:
PatchCode
MOVS R0, #1
BX LR
EndPatch
JumpToLabel "SepMandatoryToDiscretionary"
// Patch 20:
PatchCode
MOVS R0, #0
BX LR
EndPatch
JumpToLabel "SepAccessCheckEx"
// Patch 21:
FindNextValue 0x2000000
CreateLabel "Patch21"
FindNextInstruction "B"
JumpToTarget
CreateLabel "TargetPatch21"
JumpToLabel "Patch21"
PatchCode
B TargetPatch21
EndPatch
FindNextValue 0xC0000022
// Patch 22:
FindNextValue 0xC0000022
FindPreviousConditionalJump
MakeJumpUnconditional // This jump is right above the value 0xC0000022. After patch the pointer is back on that value.
// FindNextValue 0xC0000022
// Patch 23:
JumpToReference 0
ClearInstruction
JumpBack
// Patch 24:
JumpToReference 1
ClearInstruction
JumpBack
// Patch 25:
JumpToReference 2
ClearInstruction
JumpBack
// Patch 26:
FindNextValue 0xC0000022
FindPreviousConditionalJump
MakeJumpUnconditional
FindNextValue 0xC0000022
// Patch 27:
FindNextValue 0xC0000022
FindPreviousConditionalJump
MakeJumpUnconditional
FindNextValue 0xC0000022
// Patch 28:
JumpToReference
ClearInstruction
JumpToLabel "SepAccessCheck"
// Patch 29:
FindFunctionCall R0 = "LDR R0, [SP,#0x28]"
JumpToTarget
CreateLabel "SepNormalAccessCheck"
JumpBack
FindNextInstruction "TST"
FindNextConditionalJump
ClearInstruction
// Patch 30:
FindFunctionCall R0 = "MOV R0, R?" R1 = "MOV R1, R?" R2 = "MOV R2, R?" R3 = "LDR R3, [SP,#0x38]"
JumpToTarget
CreateLabel "SepMaximumAccessCheck"
JumpBack
FindNextConditionalJump
ClearInstruction
// Patch 31:
FindNextConditionalJump
ClearInstruction
// Patch 32:
FindNextValue 0xC0000022
JumpToReference 1
ClearInstruction
JumpBack
// Patch 33:
JumpToReference 2
ClearInstruction
JumpBack
// Patch 34:
FindNextValue 0xC0000022
FindPreviousInstruction "MOVS"
FindPreviousInstruction "MOVS"
JumpToReference
ClearInstruction
JumpBack
FindNextValue 0xC0000022
// Patch 35:
JumpToReference CodePattern = "BEQ"
ClearInstruction
JumpBack
// Patch 36:
JumpToReference CodePattern = "MOVS; B"
FindPreviousInstruction "B"
JumpToTarget
CreateLabel "TargetPatch36"
JumpBack
FindPreviousInstruction "CMP"
PatchCode
B.W TargetPatch36
EndPatch
JumpBack
// Patch 37:
JumpToReference CodePattern = "STR; B"
FindPreviousConditionalJump
MakeJumpUnconditional
// Patch 38:
// Stay in function-chunk. Error-code is between previous two patches.
FindPreviousValue 0xC0000022
FindPreviousConditionalJump
MakeJumpUnconditional
JumpToLabel "SepConstrainByMandatory"
// Patch 39:
FindNextInstruction "BNE"
JumpToTarget
FindNextInstruction "CBNZ"
JumpToTarget
CreateLabel "TargetPatch39"
JumpBack
FindPreviousInstruction "BEQ"
PatchCode
B TargetPatch39
EndPatch
JumpBack
// Patch 40:
FindNextInstruction "B"
JumpToTarget
FindNextInstruction "CBNZ"
JumpToTarget
CreateLabel "TargetPatch40"
JumpBack
FindPreviousInstruction "BEQ"
PatchCode
B TargetPatch40
EndPatch
JumpToLabel "SepFilterToDiscretionary"
// Patch 41:
PatchCode
MOVS R0, #0
BX LR
EndPatch
JumpToLabel "SepConstrainByConstraintMask_FunctionChunk01"
// Patch 42:
FindNextInstruction "TST"
FindNextInstruction "CBNZ"
JumpToTarget
CreateLabel "TargetPatch42"
JumpBack
FindPreviousInstruction "BEQ"
PatchCode
B TargetPatch42
EndPatch
// Patch 43:
FindNextInstruction "TST"
FindNextInstruction "CBNZ"
JumpToTarget
CreateLabel "TargetPatch43"
JumpBack
FindPreviousInstruction "BEQ"
FindPreviousInstruction "BEQ" // This one is actually not necessary. Kept here for consistency.
PatchCode
B TargetPatch43
EndPatch
PatchChecksum
PatchDefinition Name="SecureBootHack-MainOS" VersionFrom="EFIESP\Windows\System32\Boot\mobilestartup.efi"
PatchFile Path="Windows\System32\BOOT\winload.efi"
FindFirstAscii "1.3.6.1.4.1.311.61.4.1"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "ImgpValidateImageHash"
PatchCode
MOVS R0, #0
BX LR
EndPatch
PatchChecksum
PatchFile Path="Windows\System32\ci.dll"
JumpToImport "PsGetProcessSignatureLevel"
JumpToReference
CreateLabel "PsGetProcessSignatureLevelWrapper"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "CipReportAndReprieveUMCIFailure"
FindNextInstruction "TST.W"
FindNextConditionalJump
MakeJumpUnconditional "BNE" // BNE -> B, BEQ -> NOP
PatchChecksum
PatchDefinition Name="SecureBootHack-V1-EFIESP" VersionFrom="EFIESP\Windows\System32\Boot\mobilestartup.efi" RelativePath="EFIESP" RelativeOutputPath="SecureBootHack-V1"
PatchFile Path="Windows\System32\boot\mobilestartup.efi" // Symbols taken from pdb from version 10.0.10586.107
FindFirstAscii "1.3.6.1.4.1.311.61.4.1"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "ImgpValidateImageHash"
PatchCode
MOVS R0, #0
BX LR
EndPatch
FindFirstUnicode "BootDebugPolicyApplied"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "ApplyBootDebugPolicy"
PatchCode // This patch is for the new unlock for Lumia Spec A
MOVS R0, #0
BX LR
EndPatch
PatchChecksum
PatchFile Path="efi\boot\bootarm.efi"
FindFirstAscii "1.3.6.1.4.1.311.61.4.1"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "ImgpValidateImageHash"
PatchCode
MOVS R0, #0
BX LR
EndPatch
PatchChecksum
PatchDefinition Name="SecureBootHack-V2-EFIESP" VersionFrom="EFIESP\Windows\System32\Boot\mobilestartup.efi" RelativePath="EFIESP"
PatchFile Path="Windows\System32\boot\mobilestartup.efi"
FindFirstAscii "MZ"
CreateLabel "ImageBase"
FindFirstAscii "1.3.6.1.4.1.311.61.4.1"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "ImgpValidateImageHash"
PatchCode
MOVS R0, #0
BX LR
EndPatch
FindFirstUnicode "BootDebugPolicyApplied"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "ApplyBootDebugPolicy"
PatchCode
MOVS R0, #0
BX LR
EndPatch
CreateLabel "EnterMassStorageModeShellCode" // Use the left-over space of the ApplyBootDebugPolicy-function to insert shell-code later on
FindFirstUnicode "MassStorageFlag"
CreateLabel "MassStorageName"
PatchUnicode "Heathcliff74MSM"
FindFirstBytes "41 E5 C1 A0 CE 73 7F 46 88 EC D4 4F 92 34 50 4A"
CreateLabel "MassStorageGuid"
JumpToLabel "MassStorageName"
JumpToReference
FindNextInstruction "BL"
JumpToTarget
CreateLabel "EfiGetVariableVolatile"
FindValue 2
FindNextConditionalJump
MakeJumpUnconditional "BEQ"
FindFirstUnicode "\Windows\System32\boot\ui\boot.ums.waiting.bmpx"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "EnterMassStorageMode"
JumpToReference
PatchCode
B.W EnterMassStorageModeShellCode
EndPatch
CreateLabel ReturnFromMassStorageMode
FindFirstValue 0x26000145
IfNotFoundGo PatchForSetErrorDone
FindPreviousInstruction "PUSH.W"
CreateLabel "SetError"
PatchCode
MOVS R0, #1
BX LR
EndPatch
PatchForSetErrorDone:
FindFirstUnicode "DeviceIDVersion"
JumpToReference
FindNextInstruction "BL"
JumpToTarget
CreateLabel "EfiSetVariable"
FindFirstAscii "charge: DisplayPowerState protocol successfully loaded"
JumpToReference
FindPreviousInstruction "PUSH.W"
CreateLabel "InitGraphicsSubsystem"
FindNextInstruction "BL"
JumpToTarget
CreateLabel "BlpArchQueryCurrentContextType"
JumpBack
FindNextInstruction "BL"
FindNextInstruction "BL"
FindNextInstruction "BL"
JumpToTarget
CreateLabel "BlpArchSwitchContext"
JumpBack
FindNextInstruction "LDR"
JumpToTarget
CreateLabel "EfiBS"
JumpToLabel "EnterMassStorageModeShellCode"
PatchCode
MOV R0, PC
LDR R1, =(ApplyBootDebugPolicy - ImageBase + 8) // Subtract (Offset of shell-code + 4)
SUB R0, R0, R1 // R0 = relocated base of mobilestartup.efi
PUSH {R4-R6}
SUB SP, SP, #4
MOV R4, R0 // R4 = relocated base of mobilestartup.efi
LDR R3, =(MassStorageName - ImageBase) // Offset of NV var name (which is patched to "Heathcliff74MSM")
ADD R0, R4, R3
LDR R3, =(MassStorageGuid - ImageBase) // Offset of NV var Guid
ADD R1, R4, R3
MOVS R2, #3 // Non-volatile, boot-services
MOVS R3, #0 // Data-size
STR R3, [SP] // Pointer to data-buffer = NULL
LDR R6, =(EfiSetVariable - ImageBase + 1) // Offset of SetVariable + 1
ADD R5, R4, R6
BLX R5 // EfiSetVariable -> Delete variable
LDR R1, =(BlpArchQueryCurrentContextType - ImageBase + 1) // Offset to first thread-function + 1
ADD R5, R4, R1
BLX R5
MOV R6, R0
CMP R6, #1
BEQ ContextSwitchDone1
MOVS R0, #1
LDR R1, =(BlpArchSwitchContext - ImageBase + 1) // Offset to second thread-function + 1
ADD R5, R4, R1
BLX R5
ContextSwitchDone1:
LDR R0, =(EfiBS - ImageBase) // Offset of pointer to BootServices function-table
ADD R1, R4, R0 // R1 = pointer to pointer to BootServices function-table
LDR R1, [R1] // R1 = pointer to BootServices function-table
LDR.W R5, [R1,#0xAC] // LocateProtocol
ADR R0, VarServicesGuid // This is relative, no need to relocate
MOVS R1, #0
MOV R2, SP
BLX R5 // LocateProtocol - pVarServices in [SP]
LDR R5, [SP] // R5 = Pointer to VariableServices interface
LDR R5, [R5,#4] // R5 = pointer to FlushVariableNV()
CMP R5, #0
BNE PointerFound
LDR R5, [SP] // R5 = Pointer to VariableServices interface
LDR R5, [R5,#8] // R5 = pointer to FlushVariableNV()
PointerFound:
BLX R5 // FlushVariableNV()
CMP R6, #1
BEQ ContextSwitchDone2
MOV R0, R6
LDR R1, =(BlpArchSwitchContext - ImageBase + 1) // Offset to second thread-function + 1
ADD R5, R4, R1
BLX R5
ContextSwitchDone2:
LDR R6, =(EnterMassStorageMode - ImageBase + 1) // Offset of EnterMassStorageMode + 1
ADD R5, R4, R6
BLX R5 // EnterMassStorageMode
LDR R6, =(ReturnFromMassStorageMode - ImageBase + 1) // Offset of return address + 1
ADD R0, R4, R6
ADD SP, SP, #4
POP {R4-R6}
BX R0
VarServicesGuid:
DCD 0xf9085b9d
DCW 0x9304, 0x40fb
DCB 0x8f, 0xe0, 0x4a, 0xee, 0x3b, 0x1a, 0x78, 0x4b
EndPatch
PatchChecksum
+423
View File
@@ -0,0 +1,423 @@
namespace Patcher
{
partial class MainForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.txtVisualStudioPath = new System.Windows.Forms.TextBox();
this.FolderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog();
this.OpenFileDialog = new System.Windows.Forms.OpenFileDialog();
this.SaveFileDialog = new System.Windows.Forms.SaveFileDialog();
this.cmdVisualStudioPath = new System.Windows.Forms.Button();
this.cmdInputFolder = new System.Windows.Forms.Button();
this.txtInputFolder = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.cmdOutputFolder = new System.Windows.Forms.Button();
this.txtOutputFolder = new System.Windows.Forms.TextBox();
this.label3 = new System.Windows.Forms.Label();
this.cmdPatchDefinitionsFile = new System.Windows.Forms.Button();
this.txtPatchDefinitionsFile = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.txtConsole = new System.Windows.Forms.TextBox();
this.label9 = new System.Windows.Forms.Label();
this.cmdCompile = new System.Windows.Forms.Button();
this.cmdPatch = new System.Windows.Forms.Button();
this.cmdScriptFile = new System.Windows.Forms.Button();
this.txtScriptFile = new System.Windows.Forms.TextBox();
this.label5 = new System.Windows.Forms.Label();
this.cmdBackupFolder = new System.Windows.Forms.Button();
this.txtBackupFolder = new System.Windows.Forms.TextBox();
this.label6 = new System.Windows.Forms.Label();
this.label7 = new System.Windows.Forms.Label();
this.CapstoneLink = new System.Windows.Forms.LinkLabel();
this.label8 = new System.Windows.Forms.Label();
this.CapstoneNetLink = new System.Windows.Forms.LinkLabel();
this.label10 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(15, 13);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(191, 13);
this.label1.TabIndex = 0;
this.label1.Text = "Path to Visual Studio with ARM32 SDK";
//
// txtVisualStudioPath
//
this.txtVisualStudioPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtVisualStudioPath.Location = new System.Drawing.Point(18, 29);
this.txtVisualStudioPath.Name = "txtVisualStudioPath";
this.txtVisualStudioPath.Size = new System.Drawing.Size(665, 20);
this.txtVisualStudioPath.TabIndex = 1;
//
// OpenFileDialog
//
this.OpenFileDialog.FileName = "openFileDialog1";
//
// cmdVisualStudioPath
//
this.cmdVisualStudioPath.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cmdVisualStudioPath.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.cmdVisualStudioPath.Location = new System.Drawing.Point(689, 28);
this.cmdVisualStudioPath.Name = "cmdVisualStudioPath";
this.cmdVisualStudioPath.Size = new System.Drawing.Size(35, 22);
this.cmdVisualStudioPath.TabIndex = 2;
this.cmdVisualStudioPath.Text = "...";
this.cmdVisualStudioPath.UseVisualStyleBackColor = true;
this.cmdVisualStudioPath.Click += new System.EventHandler(this.cmdVisualStudioPath_Click);
//
// cmdInputFolder
//
this.cmdInputFolder.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cmdInputFolder.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.cmdInputFolder.Location = new System.Drawing.Point(689, 224);
this.cmdInputFolder.Name = "cmdInputFolder";
this.cmdInputFolder.Size = new System.Drawing.Size(35, 22);
this.cmdInputFolder.TabIndex = 8;
this.cmdInputFolder.Text = "...";
this.cmdInputFolder.UseVisualStyleBackColor = true;
this.cmdInputFolder.Click += new System.EventHandler(this.cmdInputFolder_Click);
//
// txtInputFolder
//
this.txtInputFolder.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtInputFolder.Location = new System.Drawing.Point(18, 225);
this.txtInputFolder.Name = "txtInputFolder";
this.txtInputFolder.Size = new System.Drawing.Size(665, 20);
this.txtInputFolder.TabIndex = 7;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(15, 209);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(71, 13);
this.label2.TabIndex = 12;
this.label2.Text = "Input location";
//
// cmdOutputFolder
//
this.cmdOutputFolder.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cmdOutputFolder.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.cmdOutputFolder.Location = new System.Drawing.Point(689, 322);
this.cmdOutputFolder.Name = "cmdOutputFolder";
this.cmdOutputFolder.Size = new System.Drawing.Size(35, 22);
this.cmdOutputFolder.TabIndex = 12;
this.cmdOutputFolder.Text = "...";
this.cmdOutputFolder.UseVisualStyleBackColor = true;
this.cmdOutputFolder.Click += new System.EventHandler(this.cmdOutputFolder_Click);
//
// txtOutputFolder
//
this.txtOutputFolder.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtOutputFolder.Location = new System.Drawing.Point(18, 323);
this.txtOutputFolder.Name = "txtOutputFolder";
this.txtOutputFolder.Size = new System.Drawing.Size(665, 20);
this.txtOutputFolder.TabIndex = 11;
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(15, 307);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(125, 13);
this.label3.TabIndex = 15;
this.label3.Text = "Output location (optional)";
//
// cmdPatchDefinitionsFile
//
this.cmdPatchDefinitionsFile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cmdPatchDefinitionsFile.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.cmdPatchDefinitionsFile.Location = new System.Drawing.Point(689, 91);
this.cmdPatchDefinitionsFile.Name = "cmdPatchDefinitionsFile";
this.cmdPatchDefinitionsFile.Size = new System.Drawing.Size(35, 22);
this.cmdPatchDefinitionsFile.TabIndex = 4;
this.cmdPatchDefinitionsFile.Text = "...";
this.cmdPatchDefinitionsFile.UseVisualStyleBackColor = true;
this.cmdPatchDefinitionsFile.Click += new System.EventHandler(this.cmdPatchDefinitionsFile_Click);
//
// txtPatchDefinitionsFile
//
this.txtPatchDefinitionsFile.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtPatchDefinitionsFile.Location = new System.Drawing.Point(18, 92);
this.txtPatchDefinitionsFile.Name = "txtPatchDefinitionsFile";
this.txtPatchDefinitionsFile.Size = new System.Drawing.Size(665, 20);
this.txtPatchDefinitionsFile.TabIndex = 3;
this.txtPatchDefinitionsFile.Leave += new System.EventHandler(this.txtPatchDefinitionsFile_Leave);
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(15, 76);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(117, 13);
this.label4.TabIndex = 3;
this.label4.Text = "Patch definitions xml-file";
//
// txtConsole
//
this.txtConsole.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtConsole.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.txtConsole.Location = new System.Drawing.Point(18, 383);
this.txtConsole.Multiline = true;
this.txtConsole.Name = "txtConsole";
this.txtConsole.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.txtConsole.Size = new System.Drawing.Size(706, 392);
this.txtConsole.TabIndex = 13;
//
// label9
//
this.label9.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label9.AutoSize = true;
this.label9.Location = new System.Drawing.Point(15, 367);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(78, 13);
this.label9.TabIndex = 24;
this.label9.Text = "Console output";
//
// cmdCompile
//
this.cmdCompile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.cmdCompile.Location = new System.Drawing.Point(470, 792);
this.cmdCompile.Name = "cmdCompile";
this.cmdCompile.Size = new System.Drawing.Size(120, 33);
this.cmdCompile.TabIndex = 14;
this.cmdCompile.Text = "Compile";
this.cmdCompile.UseVisualStyleBackColor = true;
this.cmdCompile.Click += new System.EventHandler(this.cmdCompile_Click);
//
// cmdPatch
//
this.cmdPatch.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.cmdPatch.Location = new System.Drawing.Point(604, 792);
this.cmdPatch.Name = "cmdPatch";
this.cmdPatch.Size = new System.Drawing.Size(120, 33);
this.cmdPatch.TabIndex = 15;
this.cmdPatch.Text = "Patch";
this.cmdPatch.UseVisualStyleBackColor = true;
this.cmdPatch.Click += new System.EventHandler(this.cmdPatch_Click);
//
// cmdScriptFile
//
this.cmdScriptFile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cmdScriptFile.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.cmdScriptFile.Location = new System.Drawing.Point(689, 155);
this.cmdScriptFile.Name = "cmdScriptFile";
this.cmdScriptFile.Size = new System.Drawing.Size(35, 22);
this.cmdScriptFile.TabIndex = 6;
this.cmdScriptFile.Text = "...";
this.cmdScriptFile.UseVisualStyleBackColor = true;
this.cmdScriptFile.Click += new System.EventHandler(this.cmdScriptFile_Click);
//
// txtScriptFile
//
this.txtScriptFile.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtScriptFile.Location = new System.Drawing.Point(18, 156);
this.txtScriptFile.Name = "txtScriptFile";
this.txtScriptFile.Size = new System.Drawing.Size(665, 20);
this.txtScriptFile.TabIndex = 5;
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(15, 140);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(50, 13);
this.label5.TabIndex = 28;
this.label5.Text = "Script-file";
//
// cmdBackupFolder
//
this.cmdBackupFolder.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cmdBackupFolder.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.cmdBackupFolder.Location = new System.Drawing.Point(689, 273);
this.cmdBackupFolder.Name = "cmdBackupFolder";
this.cmdBackupFolder.Size = new System.Drawing.Size(35, 22);
this.cmdBackupFolder.TabIndex = 10;
this.cmdBackupFolder.Text = "...";
this.cmdBackupFolder.UseVisualStyleBackColor = true;
this.cmdBackupFolder.Click += new System.EventHandler(this.cmdBackupFolder_Click);
//
// txtBackupFolder
//
this.txtBackupFolder.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtBackupFolder.Location = new System.Drawing.Point(18, 274);
this.txtBackupFolder.Name = "txtBackupFolder";
this.txtBackupFolder.Size = new System.Drawing.Size(665, 20);
this.txtBackupFolder.TabIndex = 9;
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(15, 258);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(130, 13);
this.label6.TabIndex = 31;
this.label6.Text = "Backup location (optional)";
//
// label7
//
this.label7.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(20, 807);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(66, 13);
this.label7.TabIndex = 32;
this.label7.Text = "Powered by ";
//
// CapstoneLink
//
this.CapstoneLink.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.CapstoneLink.AutoSize = true;
this.CapstoneLink.Location = new System.Drawing.Point(80, 807);
this.CapstoneLink.Name = "CapstoneLink";
this.CapstoneLink.Size = new System.Drawing.Size(52, 13);
this.CapstoneLink.TabIndex = 33;
this.CapstoneLink.TabStop = true;
this.CapstoneLink.Text = "Capstone";
this.CapstoneLink.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.CapstoneLink_LinkClicked);
//
// label8
//
this.label8.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.label8.AutoSize = true;
this.label8.Location = new System.Drawing.Point(129, 807);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(28, 13);
this.label8.TabIndex = 34;
this.label8.Text = "and ";
//
// CapstoneNetLink
//
this.CapstoneNetLink.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.CapstoneNetLink.AutoSize = true;
this.CapstoneNetLink.Location = new System.Drawing.Point(151, 807);
this.CapstoneNetLink.Name = "CapstoneNetLink";
this.CapstoneNetLink.Size = new System.Drawing.Size(77, 13);
this.CapstoneNetLink.TabIndex = 35;
this.CapstoneNetLink.TabStop = true;
this.CapstoneNetLink.Text = "Capstone.NET";
this.CapstoneNetLink.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.CapstoneNetLink_LinkClicked);
//
// label10
//
this.label10.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.label10.AutoSize = true;
this.label10.Location = new System.Drawing.Point(225, 807);
this.label10.Name = "label10";
this.label10.Size = new System.Drawing.Size(42, 13);
this.label10.TabIndex = 36;
this.label10.Text = "libraries";
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(742, 840);
this.Controls.Add(this.label10);
this.Controls.Add(this.CapstoneNetLink);
this.Controls.Add(this.label8);
this.Controls.Add(this.CapstoneLink);
this.Controls.Add(this.label7);
this.Controls.Add(this.cmdBackupFolder);
this.Controls.Add(this.txtBackupFolder);
this.Controls.Add(this.label6);
this.Controls.Add(this.cmdScriptFile);
this.Controls.Add(this.txtScriptFile);
this.Controls.Add(this.label5);
this.Controls.Add(this.cmdPatch);
this.Controls.Add(this.cmdCompile);
this.Controls.Add(this.txtConsole);
this.Controls.Add(this.label9);
this.Controls.Add(this.cmdPatchDefinitionsFile);
this.Controls.Add(this.txtPatchDefinitionsFile);
this.Controls.Add(this.label4);
this.Controls.Add(this.cmdOutputFolder);
this.Controls.Add(this.txtOutputFolder);
this.Controls.Add(this.label3);
this.Controls.Add(this.cmdInputFolder);
this.Controls.Add(this.txtInputFolder);
this.Controls.Add(this.label2);
this.Controls.Add(this.cmdVisualStudioPath);
this.Controls.Add(this.txtVisualStudioPath);
this.Controls.Add(this.label1);
this.Name = "MainForm";
this.Text = "ARM Auto-patcher by Rene Lergner";
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.MainForm_FormClosed);
this.Load += new System.EventHandler(this.MainForm_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox txtVisualStudioPath;
private System.Windows.Forms.FolderBrowserDialog FolderBrowserDialog;
private System.Windows.Forms.OpenFileDialog OpenFileDialog;
private System.Windows.Forms.SaveFileDialog SaveFileDialog;
private System.Windows.Forms.Button cmdVisualStudioPath;
private System.Windows.Forms.Button cmdInputFolder;
private System.Windows.Forms.TextBox txtInputFolder;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button cmdOutputFolder;
private System.Windows.Forms.TextBox txtOutputFolder;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Button cmdPatchDefinitionsFile;
private System.Windows.Forms.TextBox txtPatchDefinitionsFile;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.TextBox txtConsole;
private System.Windows.Forms.Label label9;
private System.Windows.Forms.Button cmdCompile;
private System.Windows.Forms.Button cmdPatch;
private System.Windows.Forms.Button cmdScriptFile;
private System.Windows.Forms.TextBox txtScriptFile;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Button cmdBackupFolder;
private System.Windows.Forms.TextBox txtBackupFolder;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.LinkLabel CapstoneLink;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.LinkLabel CapstoneNetLink;
private System.Windows.Forms.Label label10;
}
}
+371
View File
@@ -0,0 +1,371 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using WPinternals;
namespace Patcher
{
public partial class MainForm : Form
{
private PatchEngine PatchEngine = null;
public MainForm()
{
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
LoadPaths();
CenterToScreen();
}
private void LoadPaths()
{
RegistryKey Key = Registry.CurrentUser.OpenSubKey(@"Software\Patcher", true) ?? Registry.CurrentUser.CreateSubKey(@"Software\Patcher");
txtVisualStudioPath.Text = (string)Key.GetValue("VisualStudioPath", "");
if (txtVisualStudioPath.Text.Length == 0)
txtVisualStudioPath.Text = FindVisualStudioPath();
txtPatchDefinitionsFile.Text = (string)Key.GetValue("PatchDefinitionsFilePath", "");
txtScriptFile.Text = (string)Key.GetValue("ScriptFilePath", "");
txtInputFolder.Text = (string)Key.GetValue("InputFolderPath", "");
txtOutputFolder.Text = (string)Key.GetValue("OutputFolderPath", "");
txtBackupFolder.Text = (string)Key.GetValue("BackupFolderPath", "");
LoadPatchDefinitions();
}
public static string[] FindMSVCBinaryPaths(string s)
{
string LegacyPath = Path.Combine(s, @"VC\bin");
if (Directory.Exists(LegacyPath))
{
return new string[] { LegacyPath };
}
if (Directory.Exists(Path.Combine(s, @"VC\Tools\MSVC")))
{
IEnumerable<string> MSVCs = Directory.EnumerateDirectories(Path.Combine(s, @"VC\Tools\MSVC"));
IEnumerable<string> Bins = MSVCs.Select(s => Path.Combine(s, "bin")).Where(s => Directory.Exists(s));
return Bins.ToArray();
}
return Array.Empty<string>();
}
public static string FindArmAsmPath(string s)
{
foreach (string MSVCBin in FindMSVCBinaryPaths(s))
{
string path1 = Path.Combine(MSVCBin, "x86_arm");
string path2 = Path.Combine(MSVCBin, @"Hostx86\arm");
if (File.Exists(Path.Combine(path1, "armasm.exe")))
{
return path1;
}
if (File.Exists(Path.Combine(path2, "armasm.exe")))
{
return path2;
}
}
return "";
}
private static string FindVisualStudioPath()
{
IEnumerable<string> MainX86VSDirectories = Directory.EnumerateDirectories(@"C:\Program Files (x86)\", "Microsoft Visual Studio*");
IEnumerable<string> MainX64VSDirectories = Directory.EnumerateDirectories(@"C:\Program Files\", "Microsoft Visual Studio*");
IEnumerable<string> MainVSDirectories = MainX86VSDirectories.Union(MainX64VSDirectories);
IEnumerable<string> SubMainVSDirectories = MainVSDirectories.SelectMany(s => Directory.EnumerateDirectories(s));
IEnumerable<string> SubSubMainVSDirectories = SubMainVSDirectories.SelectMany(s => Directory.EnumerateDirectories(s));
IEnumerable<string> Directories = MainVSDirectories.Union(SubMainVSDirectories).Union(SubSubMainVSDirectories);
string attempt1 = Directories.Where(s => FindArmAsmPath(s) != "").OrderByDescending(s => File.GetCreationTime(Path.Combine(s, @"VC\bin\x86_arm\armasm.exe"))).FirstOrDefault() ?? "";
if (attempt1 != "")
return attempt1;
return Directories.Where(s => Directory.Exists(Path.Combine(s, @"VC\Tools\MSVC"))).Select(s => Path.Combine(s, @"VC\Tools\MSVC")).SelectMany(s => Directory.EnumerateDirectories(s)).Where(s => File.Exists(Path.Combine(s, @"bin\Hostx86\arm\armasm.exe"))).OrderByDescending(s => File.GetCreationTime(Path.Combine(s, @"bin\Hostx86\arm\armasm.exe"))).FirstOrDefault() ?? "";
}
private void StorePaths()
{
RegistryKey Key = Registry.CurrentUser.OpenSubKey(@"Software\Patcher", true) ?? Registry.CurrentUser.CreateSubKey(@"Software\Patcher");
string VisualStudioPath = txtVisualStudioPath.Text.Trim();
if (VisualStudioPath.Length == 0)
{
if (Key.GetValue("VisualStudioPath") != null)
Key.DeleteValue("VisualStudioPath");
}
else
{
Key.SetValue("VisualStudioPath", VisualStudioPath);
}
string PatchDefinitionsFilePath = txtPatchDefinitionsFile.Text.Trim();
if (PatchDefinitionsFilePath.Length == 0)
{
if (Key.GetValue("PatchDefinitionsFilePath") != null)
Key.DeleteValue("PatchDefinitionsFilePath");
}
else
{
Key.SetValue("PatchDefinitionsFilePath", PatchDefinitionsFilePath);
}
string ScriptFilePath = txtScriptFile.Text.Trim();
if (ScriptFilePath.Length == 0)
{
if (Key.GetValue("ScriptFilePath") != null)
Key.DeleteValue("ScriptFilePath");
}
else
{
Key.SetValue("ScriptFilePath", ScriptFilePath);
}
string InputFolderPath = txtInputFolder.Text.Trim();
if (InputFolderPath.Length == 0)
{
if (Key.GetValue("InputFolderPath") != null)
Key.DeleteValue("InputFolderPath");
}
else
{
Key.SetValue("InputFolderPath", InputFolderPath);
}
string OutputFolderPath = txtOutputFolder.Text.Trim();
if (OutputFolderPath.Length == 0)
{
if (Key.GetValue("OutputFolderPath") != null)
Key.DeleteValue("OutputFolderPath");
}
else
{
Key.SetValue("OutputFolderPath", OutputFolderPath);
}
string BackupFolderPath = txtBackupFolder.Text.Trim();
if (BackupFolderPath.Length == 0)
{
if (Key.GetValue("BackupFolderPath") != null)
Key.DeleteValue("BackupFolderPath");
}
else
{
Key.SetValue("BackupFolderPath", BackupFolderPath);
}
}
private bool LoadingPatchDefinitions = false;
private void LoadPatchDefinitions()
{
if (LoadingPatchDefinitions)
return;
LoadingPatchDefinitions = true;
try
{
string Definitions = File.ReadAllText(txtPatchDefinitionsFile.Text);
PatchEngine = new PatchEngine(Definitions);
}
catch
{
PatchEngine = new PatchEngine();
}
LoadingPatchDefinitions = false;
}
private void cmdVisualStudioPath_Click(object sender, EventArgs e)
{
FolderBrowserDialog.SelectedPath = txtVisualStudioPath.Text;
FolderBrowserDialog.Description = "Select path to Visual Studio with ARM32 SDK";
System.Windows.Forms.DialogResult Result = FolderBrowserDialog.ShowDialog();
if (Result == System.Windows.Forms.DialogResult.OK)
txtVisualStudioPath.Text = FolderBrowserDialog.SelectedPath;
}
private void cmdPatchDefinitionsFile_Click(object sender, EventArgs e)
{
OpenFileDialog.CheckFileExists = false;
OpenFileDialog.DefaultExt = "xml";
try
{
OpenFileDialog.FileName = Path.GetFileName(txtPatchDefinitionsFile.Text);
OpenFileDialog.InitialDirectory = Path.GetDirectoryName(txtPatchDefinitionsFile.Text);
}
catch { }
OpenFileDialog.Multiselect = false;
OpenFileDialog.Title = "Open patch-definitions file";
System.Windows.Forms.DialogResult Result = OpenFileDialog.ShowDialog();
if (Result == System.Windows.Forms.DialogResult.OK)
{
txtPatchDefinitionsFile.Text = OpenFileDialog.FileName;
WindowsFormsSynchronizationContext.Current.Post(s => LoadPatchDefinitions(), null);
}
}
private void txtPatchDefinitionsFile_Leave(object sender, EventArgs e)
{
WindowsFormsSynchronizationContext.Current.Post(s => LoadPatchDefinitions(), null);
}
private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
{
StorePaths();
}
private void cmdInputFolder_Click(object sender, EventArgs e)
{
FolderSelectDialog Dialog = new();
Dialog.Title = "Select input location";
Dialog.InitialDirectory = txtInputFolder.Text;
try
{
Dialog.InitialDirectory = txtInputFolder.Text;
}
catch { }
bool Result = Dialog.ShowDialog();
if (Result)
{
txtInputFolder.Text = Dialog.FileName;
txtOutputFolder.Text = "";
}
}
private void cmdOutputFolder_Click(object sender, EventArgs e)
{
FolderSelectDialog Dialog = new();
Dialog.Title = "Select output location";
Dialog.InitialDirectory = txtOutputFolder.Text;
try
{
Dialog.InitialDirectory = txtOutputFolder.Text;
}
catch { }
bool Result = Dialog.ShowDialog();
if (Result)
{
txtOutputFolder.Text = Dialog.FileName;
}
}
private void cmdScriptFile_Click(object sender, EventArgs e)
{
OpenFileDialog.CheckFileExists = true;
OpenFileDialog.DefaultExt = "pds";
try
{
OpenFileDialog.FileName = Path.GetFileName(txtScriptFile.Text);
OpenFileDialog.InitialDirectory = Path.GetDirectoryName(txtScriptFile.Text);
}
catch { }
OpenFileDialog.Multiselect = false;
OpenFileDialog.Title = "Open patch-definition-script-file";
System.Windows.Forms.DialogResult Result = OpenFileDialog.ShowDialog();
if (Result == System.Windows.Forms.DialogResult.OK)
{
txtScriptFile.Text = OpenFileDialog.FileName;
}
}
private void cmdCompile_Click(object sender, EventArgs e)
{
ClearLog();
StorePaths();
ScriptEngine.ExecuteScript(txtVisualStudioPath.Text.Trim(), txtScriptFile.Text.Trim(), txtInputFolder.Text.Trim(), PatchEngine: PatchEngine, WriteLog: WriteLog);
}
private void cmdPatch_Click(object sender, EventArgs e)
{
ClearLog();
StorePaths();
ScriptEngine.ExecuteScript(txtVisualStudioPath.Text.Trim(), txtScriptFile.Text.Trim(), txtInputFolder.Text.Trim(), PatchEngine, txtOutputFolder.Text.Trim(), txtBackupFolder.Text.Trim().Length == 0 ? null : txtBackupFolder.Text.Trim(), WriteLog);
PatchEngine.WriteDefinitions(txtPatchDefinitionsFile.Text);
WriteLog("Patch-definitions written to: " + txtPatchDefinitionsFile.Text);
}
private void ClearLog()
{
txtConsole.Clear();
}
private void WriteLog(string Line)
{
if (txtConsole.InvokeRequired)
{
txtConsole.Invoke((MethodInvoker)delegate { WriteLog(Line); });
}
else
{
txtConsole.AppendText(Line + Environment.NewLine);
txtConsole.Select(txtConsole.Text.Length, 0);
txtConsole.ScrollToCaret();
System.Diagnostics.Debug.WriteLine(Line);
}
}
private void cmdBackupFolder_Click(object sender, EventArgs e)
{
FolderSelectDialog Dialog = new();
Dialog.Title = "Select backup location";
Dialog.InitialDirectory = txtBackupFolder.Text;
try
{
Dialog.InitialDirectory = txtBackupFolder.Text;
}
catch { }
bool Result = Dialog.ShowDialog();
if (Result)
{
txtBackupFolder.Text = Dialog.FileName;
}
}
private void CapstoneLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
System.Diagnostics.Process.Start("https://github.com/aquynh/capstone/blob/master/LICENSE.TXT");
}
private void CapstoneNetLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
System.Diagnostics.Process.Start("https://github.com/9ee1/Capstone.NET/blob/master/LICENSE");
}
}
}
+129
View File
@@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="FolderBrowserDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="OpenFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>182, 17</value>
</metadata>
<metadata name="SaveFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>317, 17</value>
</metadata>
</root>
+39
View File
@@ -0,0 +1,39 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Windows.Forms;
namespace Patcher
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
private static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
}
@@ -0,0 +1,35 @@
using System.Reflection;
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("ARM Auto-patcher")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("WPinternals.net")]
[assembly: AssemblyProduct("ARM Auto-patcher")]
[assembly: AssemblyCopyright("Copyright © 2018 by Rene Lergner")]
[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("95cf9509-c1c4-40f5-a60e-9d93ea6f438c")]
// 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.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
+63
View File
@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Patcher.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Patcher.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}
+26
View File
@@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Patcher.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.8.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}
@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>
File diff suppressed because it is too large Load Diff
+41
View File
@@ -0,0 +1,41 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.12.35323.107
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Patcher", "Patcher\Patcher.csproj", "{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoPatcher", "AutoPatcher\AutoPatcher.csproj", "{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
.NET45Debug|x86 = .NET45Debug|x86
.NET45Release|x86 = .NET45Release|x86
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}..NET45Debug|x86.ActiveCfg = Debug|x86
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}..NET45Debug|x86.Build.0 = Debug|x86
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}..NET45Release|x86.ActiveCfg = Release|x86
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}..NET45Release|x86.Build.0 = Release|x86
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}.Debug|x86.ActiveCfg = Debug|x86
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}.Debug|x86.Build.0 = Debug|x86
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}.Release|x86.ActiveCfg = Release|Any CPU
{B67C62AE-86C4-4C18-99AB-4E94A3E09D36}.Release|x86.Build.0 = Release|Any CPU
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}..NET45Debug|x86.ActiveCfg = Debug|x86
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}..NET45Debug|x86.Build.0 = Debug|x86
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}..NET45Release|x86.ActiveCfg = Release|x86
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}..NET45Release|x86.Build.0 = Release|x86
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}.Debug|x86.ActiveCfg = Debug|x86
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}.Debug|x86.Build.0 = Debug|x86
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}.Release|x86.ActiveCfg = Release|x86
{95CF9509-C1C4-40F5-A60E-9D93EA6F438C}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6763D5C5-7BCE-437C-9FD0-67BDD8D79FD2}
EndGlobalSection
EndGlobal
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
+229
View File
@@ -0,0 +1,229 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
namespace Patcher
{
public enum CodeType
{
ARM,
Thumb,
Thumb2
}
public static class ArmCompiler
{
public static Int32 LastErrorCode;
public static string Output;
public static byte[] Compile(string PathToVisualStudio, UInt32 Origin, CodeType CodeType, string ArmCodeFragment)
{
if (PathToVisualStudio.Length == 0)
{
Output = "ARM SDK is missing.";
return null;
}
string AssemblyFilePath = Path.GetTempFileName();
string ObjectFilePathTmp = Path.GetTempFileName();
string ObjectFilePath = ObjectFilePathTmp.Replace(".tmp", ".obj");
File.Move(ObjectFilePathTmp, ObjectFilePath);
string CodeTypeDirective = null;
switch (CodeType)
{
case Patcher.CodeType.ARM:
CodeTypeDirective = "CODE32";
break;
case Patcher.CodeType.Thumb:
CodeTypeDirective = "CODE16";
break;
case Patcher.CodeType.Thumb2:
CodeTypeDirective = "THUMB";
break;
}
string FullAssemblyCode =
" AREA ARM_AREA, CODE, READONLY" + Environment.NewLine +
" " + CodeTypeDirective + Environment.NewLine;
string ProcessedAssembly = ProcessArmCodeFragment(ArmCodeFragment, Origin, out uint Padding);
if (Padding > 0)
FullAssemblyCode += " SPACE " + Padding.ToString() + Environment.NewLine;
FullAssemblyCode +=
"start" + Environment.NewLine +
ProcessedAssembly;
FullAssemblyCode += " end" + Environment.NewLine;
File.WriteAllText(AssemblyFilePath, FullAssemblyCode);
string ArmAsmPath = MainForm.FindArmAsmPath(PathToVisualStudio);
string BinPath = MainForm.FindMSVCBinaryPaths(PathToVisualStudio).FirstOrDefault() ?? "";
ProcessStartInfo psi = new(Path.Combine(ArmAsmPath, "armasm.exe"));
psi.EnvironmentVariables["PATH"] += ";" + Path.Combine(PathToVisualStudio, @"Common7\IDE\");
psi.EnvironmentVariables["PATH"] += ";" + Path.Combine(PathToVisualStudio, @"Common7\Tools\");
psi.EnvironmentVariables["PATH"] += ";" + BinPath;
psi.EnvironmentVariables["PATH"] += ";" + ArmAsmPath;
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.CreateNoWindow = true;
psi.Arguments = "-g \"" + AssemblyFilePath + "\" \"" + ObjectFilePath + "\"";
Process ArmAsmProcess = Process.Start(psi);
ArmAsmProcess.WaitForExit();
LastErrorCode = ArmAsmProcess.ExitCode;
if (ArmAsmProcess.ExitCode != 0)
{
using StreamReader reader = ArmAsmProcess.StandardOutput;
Output = reader.ReadToEnd();
string[] Lines = Output.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
Output = "";
foreach (string Line in Lines)
{
string Out = Line.Trim();
if (Out.Length == 0) continue;
if (Out.StartsWith("Microsoft (R) ARM Macro Assembler")) continue;
if (Out.StartsWith("Copyright (C) Microsoft Corporation")) continue;
if (Out.StartsWith(AssemblyFilePath))
{
Out = Out[AssemblyFilePath.Length..];
int P = Out.IndexOf(':');
Out = Out[(P + 1)..].Trim();
}
Output += Out + Environment.NewLine;
}
}
byte[] Result = null;
if (LastErrorCode == 0)
Result = COFF.ObjectFileParser.ParseObjectFile(ObjectFilePath).SectionHeaders.First(h => h.Name == "ARM_AREA").RawData;
File.Delete(AssemblyFilePath);
File.Delete(ObjectFilePath);
if ((Result != null) && (Padding > 0))
{
byte[] RemovedPadding = new byte[Result.Length - Padding];
Buffer.BlockCopy(Result, (int)Padding, RemovedPadding, 0, RemovedPadding.Length);
Result = RemovedPadding;
}
return Result;
}
private static string ProcessArmCodeFragment(string ArmCodeFragment, UInt32 Origin, out UInt32 Padding)
{
string[] BranchOpcodes = new string[] { "B", "BEQ", "BNE", "BCS", "BHS", "BCC", "BLO", "BMI", "BPL", "BVS", "BVC", "BHI", "BLS", "BGE", "BLT", "BGT", "BLE", "BAL"};
StringBuilder Result = new(1000);
Padding = 0;
string[] Lines = ArmCodeFragment.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
List<Tuple<string, string>> Labels = new();
foreach (string Line in Lines)
{
string Code = Line;
if (Line.Contains(':'))
{
string Label = Line.Substring(0, Line.IndexOf(':'));
Label = Label.Trim();
if (Label.Length > 0)
Result.AppendLine(Label);
Code = Line[(Line.IndexOf(':') + 1)..];
}
int EquPos = Code.IndexOf("EQU", StringComparison.OrdinalIgnoreCase);
if ((EquPos > 0) && (EquPos > 0) && (EquPos < (Code.Length - 3)))
{
if (new char[] { '\t', ' ' }.Contains(Line[EquPos - 1]) &&
new char[] { '\t', ' ' }.Contains(Line[EquPos + 3]))
{
Result.AppendLine(Line.Trim());
Labels.Add(new Tuple<string, string>(Line.Substring(0, EquPos).Trim(), Line[(EquPos + 3)..].Trim()));
continue;
}
}
Code = Code.Trim();
bool IsAbsoluteAddress = false;
int OpcodeLength = Code.IndexOfAny(new char [] { '\t', ' ', '.' });
if (OpcodeLength > 0)
{
string Opcode = Code.Substring(0, OpcodeLength).ToUpper();
string PossibleAddress = null;
if (Opcode == "LDR")
{
PossibleAddress = Code[(Code.IndexOf(',') + 1)..].Trim();
}
else if (BranchOpcodes.Contains(Opcode))
{
PossibleAddress = Code[(Code.IndexOfAny(new char[] { '\t', ' ' }) + 1)..].Trim();
}
if (PossibleAddress != null)
{
foreach (Tuple<string, string> Label in Labels)
{
if (string.Equals(Label.Item1, PossibleAddress, StringComparison.CurrentCultureIgnoreCase))
{
PossibleAddress = Label.Item2;
break;
}
}
if (PossibleAddress.StartsWith("0x"))
PossibleAddress = PossibleAddress[2..];
IsAbsoluteAddress = UInt32.TryParse(PossibleAddress, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out uint ParsedValue);
if (IsAbsoluteAddress && (ParsedValue < Origin))
Padding = Math.Max(Padding, Origin - ParsedValue);
}
}
Result.Append(' ');
Result.Append(Code);
if (IsAbsoluteAddress)
{
Result.Append(" + start - 0x");
Result.Append(Origin.ToString("X8"));
}
Result.Append(Environment.NewLine);
}
return Result.ToString();
}
}
}
+382
View File
@@ -0,0 +1,382 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.IO;
namespace WPinternals
{
internal static class ByteOperations
{
internal static string ReadAsciiString(byte[] ByteArray, UInt32 Offset)
{
UInt32 Length = 0;
while (((Offset + Length) < ByteArray.Length) && (ByteArray[Offset + Length] != 0))
Length++;
byte[] Bytes = new byte[Length];
Buffer.BlockCopy(ByteArray, (int)Offset, Bytes, 0, (int)Length);
return System.Text.Encoding.ASCII.GetString(Bytes);
}
internal static string ReadAsciiString(byte[] ByteArray, UInt32 Offset, UInt32 Length)
{
byte[] Bytes = new byte[Length];
Buffer.BlockCopy(ByteArray, (int)Offset, Bytes, 0, (int)Length);
return System.Text.Encoding.ASCII.GetString(Bytes);
}
internal static string ReadUnicodeString(byte[] ByteArray, UInt32 Offset, UInt32 Length)
{
byte[] Bytes = new byte[Length];
Buffer.BlockCopy(ByteArray, (int)Offset, Bytes, 0, (int)Length);
return System.Text.Encoding.Unicode.GetString(Bytes);
}
internal static void WriteUnicodeString(byte[] ByteArray, UInt32 Offset, string Text, UInt32? MaxBufferLength = null)
{
if (MaxBufferLength != null)
Array.Clear(ByteArray, (int)Offset, (int)MaxBufferLength);
byte[] TextBytes = System.Text.UnicodeEncoding.Unicode.GetBytes(Text);
int WriteLength = TextBytes.Length;
if (WriteLength > MaxBufferLength)
WriteLength = (int)MaxBufferLength;
Buffer.BlockCopy(TextBytes, 0, ByteArray, (int)Offset, WriteLength);
}
internal static UInt32 ReadUInt32(byte[] ByteArray, UInt32 Offset)
{
// Assume CPU and FFU are both Little Endian
return BitConverter.ToUInt32(ByteArray, (int)Offset);
}
internal static void WriteUInt32(byte[] ByteArray, UInt32 Offset, UInt32 Value)
{
System.Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 4);
}
internal static Int32 ReadInt32(byte[] ByteArray, UInt32 Offset)
{
// Assume CPU and FFU are both Little Endian
return BitConverter.ToInt32(ByteArray, (int)Offset);
}
internal static void WriteInt32(byte[] ByteArray, UInt32 Offset, Int32 Value)
{
System.Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 4);
}
internal static UInt16 ReadUInt16(byte[] ByteArray, UInt32 Offset)
{
// Assume CPU and FFU are both Little Endian
return BitConverter.ToUInt16(ByteArray, (int)Offset);
}
internal static void WriteUInt16(byte[] ByteArray, UInt32 Offset, UInt16 Value)
{
System.Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 2);
}
internal static Int16 ReadInt16(byte[] ByteArray, UInt32 Offset)
{
// Assume CPU and FFU are both Little Endian
return BitConverter.ToInt16(ByteArray, (int)Offset);
}
internal static void WriteInt16(byte[] ByteArray, UInt32 Offset, Int16 Value)
{
System.Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 2);
}
internal static byte ReadUInt8(byte[] ByteArray, UInt32 Offset)
{
return ByteArray[Offset];
}
internal static void WriteUInt8(byte[] ByteArray, UInt32 Offset, byte Value)
{
ByteArray[Offset] = Value;
}
internal static UInt32 ReadUInt24(byte[] ByteArray, UInt32 Offset)
{
return (UInt32)(ByteArray[Offset] + (ByteArray[Offset + 1] << 8) + (ByteArray[Offset + 2] << 16));
}
internal static void WriteUInt24(byte[] ByteArray, UInt32 Offset, UInt32 Value)
{
System.Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 3);
}
internal static UInt64 ReadUInt64(byte[] ByteArray, UInt32 Offset)
{
// Assume CPU and FFU are both Little Endian
return BitConverter.ToUInt64(ByteArray, (int)Offset);
}
internal static void WriteUInt64(byte[] ByteArray, UInt32 Offset, UInt64 Value)
{
System.Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 8);
}
internal static Guid ReadGuid(byte[] ByteArray, UInt32 Offset)
{
byte[] GuidBuffer = new byte[0x10];
Buffer.BlockCopy(ByteArray, (int)Offset, GuidBuffer, 0, 0x10);
return new Guid(GuidBuffer);
}
internal static void WriteGuid(byte[] ByteArray, UInt32 Offset, Guid Value)
{
Buffer.BlockCopy(Value.ToByteArray(), 0, ByteArray, (int)Offset, 0x10);
}
internal static UInt32 Align(UInt32 Base, UInt32 Offset, UInt32 Alignment)
{
if (((Offset - Base) % Alignment) == 0)
return Offset;
else
return ((((Offset - Base) / Alignment) + 1) * Alignment) + Base;
}
internal static UInt32? FindPatternInFile(string FileName, byte[] Pattern, byte[] Mask, out byte[] OutPattern)
{
// The mask is optional.
// In the mask 0x00 means the value must match, and 0xFF means that this position is a wildcard.
UInt32? Result = null;
FileStream Stream = new(FileName, FileMode.Open, FileAccess.Read);
byte[] Buffer = new byte[0x10000 + Pattern.Length - 1];
UInt32 BytesInBuffer = 0;
UInt32 BytesRead;
UInt32 SearchPositionFile = 0;
UInt32 SearchPositionBuffer = 0;
UInt32 BufferFileOffset = 0; // Offset in file where data from buffer is located.
int i;
OutPattern = null;
while (SearchPositionFile <= (Stream.Length - Pattern.Length))
{
if ((SearchPositionBuffer + Pattern.Length) > BytesInBuffer)
{
// Need to read next chunk
if ((BytesInBuffer - SearchPositionBuffer) > 0)
{
System.Buffer.BlockCopy(Buffer, (int)SearchPositionBuffer, Buffer, 0, (int)(BytesInBuffer - SearchPositionBuffer));
}
uint BufferReadPosition = BytesInBuffer - SearchPositionBuffer;
BytesInBuffer -= SearchPositionBuffer;
BufferFileOffset += SearchPositionBuffer;
SearchPositionBuffer = 0;
BytesRead = (UInt32)Stream.Read(Buffer, (int)BufferReadPosition, Buffer.Length - (int)BufferReadPosition);
BytesInBuffer += BytesRead;
}
bool Match = true;
for (i = 0; i < Pattern.Length; i++)
{
if (Buffer[SearchPositionBuffer + i] != Pattern[i])
{
if ((Mask == null) || (Mask[i] == 0))
{
Match = false;
break;
}
}
}
if (Match)
{
Result = SearchPositionFile;
OutPattern = new byte[Pattern.Length];
System.Buffer.BlockCopy(Buffer, (int)SearchPositionBuffer, OutPattern, 0, Pattern.Length);
break;
}
SearchPositionBuffer++;
SearchPositionFile++;
}
Stream.Close();
return Result;
}
internal static UInt32? FindAscii(byte[] SourceBuffer, string Pattern)
{
return FindPattern(SourceBuffer, System.Text.ASCIIEncoding.ASCII.GetBytes((string)Pattern), null, null);
}
internal static UInt32? FindAscii(byte[] SourceBuffer, uint SourceOffset, string Pattern)
{
return FindPattern(SourceBuffer, SourceOffset, null, System.Text.ASCIIEncoding.ASCII.GetBytes((string)Pattern), null, null);
}
internal static UInt32? FindUnicode(byte[] SourceBuffer, string Pattern)
{
return FindPattern(SourceBuffer, System.Text.UnicodeEncoding.Unicode.GetBytes((string)Pattern), null, null);
}
internal static UInt32? FindUnicode(byte[] SourceBuffer, uint SourceOffset, string Pattern)
{
return FindPattern(SourceBuffer, SourceOffset, null, System.Text.UnicodeEncoding.Unicode.GetBytes((string)Pattern), null, null);
}
internal static UInt32? FindUint(byte[] SourceBuffer, UInt32 Pattern)
{
return FindPattern(SourceBuffer, BitConverter.GetBytes((UInt32)Pattern), null, null);
}
internal static UInt32? FindPattern(byte[] SourceBuffer, byte[] Pattern, byte[] Mask, byte[] OutPattern)
{
return FindPattern(SourceBuffer, 0, null, Pattern, Mask, OutPattern);
}
internal static UInt32? FindPattern(byte[] SourceBuffer, uint SourceOffset, uint? SourceSize, byte[] Pattern, byte[] Mask, byte[] OutPattern)
{
// The mask is optional.
// In the mask 0x00 means the value must match, and 0xFF means that this position is a wildcard.
UInt32? Result = null;
UInt32 SearchPosition = SourceOffset;
int i;
while ((SearchPosition <= (SourceBuffer.Length - Pattern.Length)) && ((SourceSize == null) || (SearchPosition <= (SourceOffset + SourceSize - Pattern.Length))))
{
bool Match = true;
for (i = 0; i < Pattern.Length; i++)
{
if (SourceBuffer[SearchPosition + i] != Pattern[i])
{
if ((Mask == null) || (Mask[i] == 0))
{
Match = false;
break;
}
}
}
if (Match)
{
Result = SearchPosition;
if (OutPattern != null)
System.Buffer.BlockCopy(SourceBuffer, (int)SearchPosition, OutPattern, 0, Pattern.Length);
break;
}
SearchPosition++;
}
return Result;
}
internal static byte CalculateChecksum8(byte[] Buffer, UInt32 Offset, UInt32 Size)
{
byte Checksum = 0;
for (UInt32 i = Offset; i < (Offset + Size); i++)
Checksum += Buffer[i];
return (byte)(0x100 - Checksum);
}
internal static UInt16 CalculateChecksum16(byte[] Buffer, UInt32 Offset, UInt32 Size)
{
UInt16 Checksum = 0;
for (UInt32 i = Offset; i < (Offset + Size - 1); i += 2)
Checksum += BitConverter.ToUInt16(Buffer, (int)i);
return (UInt16)(0x10000 - Checksum);
}
private static readonly UInt32[] CRC32Table = new UInt32[] {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
internal static UInt32 CRC32(byte[] Input, UInt32 Offset, UInt32 Length)
{
if ((Input == null) || ((Offset + Length) > Input.Length))
throw new ArgumentException();
unchecked
{
uint crc = (uint)(((uint)0) ^ (-1));
for (var i = Offset; i < (Offset + Length); i++)
{
crc = (crc >> 8) ^ CRC32Table[ (crc ^ Input[i]) & 0xFF ];
}
crc = (uint)(crc ^ (-1));
return crc;
}
}
}
}
+66
View File
@@ -0,0 +1,66 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Text;
namespace WPinternals
{
public static class Converter
{
public static string ConvertHexToString(byte[] Bytes, string Separator)
{
StringBuilder s = new(1000);
for (int i = Bytes.GetLowerBound(0); i <= Bytes.GetUpperBound(0); i++)
{
if (i != Bytes.GetLowerBound(0))
s.Append(Separator);
s.Append(Bytes[i].ToString("X2"));
}
return s.ToString();
}
public static byte[] ConvertStringToHex(string HexString)
{
if (HexString.Length % 2 == 1)
throw new Exception("The binary key cannot have an odd number of digits");
byte[] arr = new byte[HexString.Length >> 1];
for (int i = 0; i < (HexString.Length >> 1); ++i)
{
arr[i] = (byte)((GetHexVal(HexString[i << 1]) << 4) + GetHexVal(HexString[(i << 1) + 1]));
}
return arr;
}
public static int GetHexVal(char hex)
{
int val = (int)hex;
//For uppercase A-F letters:
//return val - (val < 58 ? 48 : 55);
//For lowercase a-f letters:
//return val - (val < 58 ? 48 : 87);
//Or the two combined, but a bit slower:
return val - (val < 58 ? 48 : (val < 97 ? 55 : 87));
}
}
}
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+426
View File
@@ -0,0 +1,426 @@
namespace Patcher
{
partial class MainForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.txtVisualStudioPath = new System.Windows.Forms.TextBox();
this.FolderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog();
this.OpenFileDialog = new System.Windows.Forms.OpenFileDialog();
this.SaveFileDialog = new System.Windows.Forms.SaveFileDialog();
this.cmdVisualStudioPath = new System.Windows.Forms.Button();
this.cmdInputFile = new System.Windows.Forms.Button();
this.txtInputFile = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.cmdOutputFile = new System.Windows.Forms.Button();
this.txtOutputFile = new System.Windows.Forms.TextBox();
this.label3 = new System.Windows.Forms.Label();
this.cmdPatchDefinitionsFile = new System.Windows.Forms.Button();
this.txtPatchDefinitionsFile = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.cmbPatchDefinitionName = new System.Windows.Forms.ComboBox();
this.cmbTargetVersion = new System.Windows.Forms.ComboBox();
this.label6 = new System.Windows.Forms.Label();
this.cmbTargetPath = new System.Windows.Forms.ComboBox();
this.label7 = new System.Windows.Forms.Label();
this.label8 = new System.Windows.Forms.Label();
this.txtAssemblyCode = new System.Windows.Forms.TextBox();
this.txtCompiledOpcodes = new System.Windows.Forms.TextBox();
this.label9 = new System.Windows.Forms.Label();
this.txtVirtualOffset = new System.Windows.Forms.TextBox();
this.label10 = new System.Windows.Forms.Label();
this.cmbCodeType = new System.Windows.Forms.ComboBox();
this.label11 = new System.Windows.Forms.Label();
this.cmdCompile = new System.Windows.Forms.Button();
this.cmdPatch = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(15, 13);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(191, 13);
this.label1.TabIndex = 0;
this.label1.Text = "Path to Visual Studio with ARM32 SDK";
//
// txtVisualStudioPath
//
this.txtVisualStudioPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtVisualStudioPath.Location = new System.Drawing.Point(18, 29);
this.txtVisualStudioPath.Name = "txtVisualStudioPath";
this.txtVisualStudioPath.Size = new System.Drawing.Size(665, 20);
this.txtVisualStudioPath.TabIndex = 1;
//
// OpenFileDialog
//
this.OpenFileDialog.FileName = "openFileDialog1";
//
// cmdVisualStudioPath
//
this.cmdVisualStudioPath.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cmdVisualStudioPath.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.cmdVisualStudioPath.Location = new System.Drawing.Point(689, 28);
this.cmdVisualStudioPath.Name = "cmdVisualStudioPath";
this.cmdVisualStudioPath.Size = new System.Drawing.Size(35, 22);
this.cmdVisualStudioPath.TabIndex = 2;
this.cmdVisualStudioPath.Text = "...";
this.cmdVisualStudioPath.UseVisualStyleBackColor = true;
this.cmdVisualStudioPath.Click += new System.EventHandler(this.cmdVisualStudioPath_Click);
//
// cmdInputFile
//
this.cmdInputFile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cmdInputFile.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.cmdInputFile.Location = new System.Drawing.Point(689, 301);
this.cmdInputFile.Name = "cmdInputFile";
this.cmdInputFile.Size = new System.Drawing.Size(35, 22);
this.cmdInputFile.TabIndex = 14;
this.cmdInputFile.Text = "...";
this.cmdInputFile.UseVisualStyleBackColor = true;
this.cmdInputFile.Click += new System.EventHandler(this.cmdInputFile_Click);
//
// txtInputFile
//
this.txtInputFile.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtInputFile.Location = new System.Drawing.Point(18, 302);
this.txtInputFile.Name = "txtInputFile";
this.txtInputFile.Size = new System.Drawing.Size(665, 20);
this.txtInputFile.TabIndex = 13;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(15, 286);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(47, 13);
this.label2.TabIndex = 12;
this.label2.Text = "Input file";
//
// cmdOutputFile
//
this.cmdOutputFile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cmdOutputFile.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.cmdOutputFile.Location = new System.Drawing.Point(689, 349);
this.cmdOutputFile.Name = "cmdOutputFile";
this.cmdOutputFile.Size = new System.Drawing.Size(35, 22);
this.cmdOutputFile.TabIndex = 17;
this.cmdOutputFile.Text = "...";
this.cmdOutputFile.UseVisualStyleBackColor = true;
this.cmdOutputFile.Click += new System.EventHandler(this.cmdOutputFile_Click);
//
// txtOutputFile
//
this.txtOutputFile.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtOutputFile.Location = new System.Drawing.Point(18, 350);
this.txtOutputFile.Name = "txtOutputFile";
this.txtOutputFile.Size = new System.Drawing.Size(665, 20);
this.txtOutputFile.TabIndex = 16;
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(15, 334);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(101, 13);
this.label3.TabIndex = 15;
this.label3.Text = "Output file (optional)";
//
// cmdPatchDefinitionsFile
//
this.cmdPatchDefinitionsFile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cmdPatchDefinitionsFile.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.cmdPatchDefinitionsFile.Location = new System.Drawing.Point(689, 91);
this.cmdPatchDefinitionsFile.Name = "cmdPatchDefinitionsFile";
this.cmdPatchDefinitionsFile.Size = new System.Drawing.Size(35, 22);
this.cmdPatchDefinitionsFile.TabIndex = 5;
this.cmdPatchDefinitionsFile.Text = "...";
this.cmdPatchDefinitionsFile.UseVisualStyleBackColor = true;
this.cmdPatchDefinitionsFile.Click += new System.EventHandler(this.cmdPatchDefinitionsFile_Click);
//
// txtPatchDefinitionsFile
//
this.txtPatchDefinitionsFile.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtPatchDefinitionsFile.Location = new System.Drawing.Point(18, 92);
this.txtPatchDefinitionsFile.Name = "txtPatchDefinitionsFile";
this.txtPatchDefinitionsFile.Size = new System.Drawing.Size(665, 20);
this.txtPatchDefinitionsFile.TabIndex = 4;
this.txtPatchDefinitionsFile.Leave += new System.EventHandler(this.txtPatchDefinitionsFile_Leave);
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(15, 76);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(117, 13);
this.label4.TabIndex = 3;
this.label4.Text = "Patch definitions xml-file";
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(15, 124);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(107, 13);
this.label5.TabIndex = 6;
this.label5.Text = "Patch definition name";
//
// cmbPatchDefinitionName
//
this.cmbPatchDefinitionName.FormattingEnabled = true;
this.cmbPatchDefinitionName.Location = new System.Drawing.Point(18, 140);
this.cmbPatchDefinitionName.Name = "cmbPatchDefinitionName";
this.cmbPatchDefinitionName.Size = new System.Drawing.Size(302, 21);
this.cmbPatchDefinitionName.TabIndex = 7;
this.cmbPatchDefinitionName.SelectedValueChanged += new System.EventHandler(this.cmbPatchDefinitionName_SelectedValueChanged);
this.cmbPatchDefinitionName.Leave += new System.EventHandler(this.cmbPatchDefinitionName_Leave);
//
// cmbTargetVersion
//
this.cmbTargetVersion.FormattingEnabled = true;
this.cmbTargetVersion.Location = new System.Drawing.Point(18, 189);
this.cmbTargetVersion.Name = "cmbTargetVersion";
this.cmbTargetVersion.Size = new System.Drawing.Size(302, 21);
this.cmbTargetVersion.TabIndex = 9;
this.cmbTargetVersion.SelectedValueChanged += new System.EventHandler(this.cmbTargetVersion_SelectedValueChanged);
this.cmbTargetVersion.Leave += new System.EventHandler(this.cmbTargetVersion_Leave);
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(15, 173);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(129, 13);
this.label6.TabIndex = 8;
this.label6.Text = "Target version description";
//
// cmbTargetPath
//
this.cmbTargetPath.FormattingEnabled = true;
this.cmbTargetPath.Location = new System.Drawing.Point(18, 238);
this.cmbTargetPath.Name = "cmbTargetPath";
this.cmbTargetPath.Size = new System.Drawing.Size(302, 21);
this.cmbTargetPath.TabIndex = 11;
//
// label7
//
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(15, 222);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(269, 13);
this.label7.TabIndex = 10;
this.label7.Text = "Folder for target file relative to Patch Definition rootfolder";
//
// label8
//
this.label8.AutoSize = true;
this.label8.Location = new System.Drawing.Point(15, 497);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(365, 13);
this.label8.TabIndex = 22;
this.label8.Text = "ARM32 Patch / Shell assembly code (labels need to be followed by a colon)";
//
// txtAssemblyCode
//
this.txtAssemblyCode.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtAssemblyCode.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.txtAssemblyCode.Location = new System.Drawing.Point(18, 513);
this.txtAssemblyCode.Multiline = true;
this.txtAssemblyCode.Name = "txtAssemblyCode";
this.txtAssemblyCode.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.txtAssemblyCode.Size = new System.Drawing.Size(706, 161);
this.txtAssemblyCode.TabIndex = 23;
//
// txtCompiledOpcodes
//
this.txtCompiledOpcodes.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtCompiledOpcodes.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.txtCompiledOpcodes.Location = new System.Drawing.Point(18, 713);
this.txtCompiledOpcodes.Multiline = true;
this.txtCompiledOpcodes.Name = "txtCompiledOpcodes";
this.txtCompiledOpcodes.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.txtCompiledOpcodes.Size = new System.Drawing.Size(706, 59);
this.txtCompiledOpcodes.TabIndex = 25;
//
// label9
//
this.label9.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label9.AutoSize = true;
this.label9.Location = new System.Drawing.Point(15, 697);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(94, 13);
this.label9.TabIndex = 24;
this.label9.Text = "Compiled opcodes";
//
// txtVirtualOffset
//
this.txtVirtualOffset.Location = new System.Drawing.Point(18, 416);
this.txtVirtualOffset.Name = "txtVirtualOffset";
this.txtVirtualOffset.Size = new System.Drawing.Size(302, 20);
this.txtVirtualOffset.TabIndex = 19;
//
// label10
//
this.label10.AutoSize = true;
this.label10.Location = new System.Drawing.Point(15, 400);
this.label10.Name = "label10";
this.label10.Size = new System.Drawing.Size(309, 13);
this.label10.TabIndex = 18;
this.label10.Text = "Virtual offset (hex) (leave empty for only recalculating checksum)";
//
// cmbCodeType
//
this.cmbCodeType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cmbCodeType.FormattingEnabled = true;
this.cmbCodeType.Items.AddRange(new object[] {
"ARM",
"Thumb",
"Thumb2"});
this.cmbCodeType.Location = new System.Drawing.Point(18, 464);
this.cmbCodeType.Name = "cmbCodeType";
this.cmbCodeType.Size = new System.Drawing.Size(302, 21);
this.cmbCodeType.TabIndex = 21;
//
// label11
//
this.label11.AutoSize = true;
this.label11.Location = new System.Drawing.Point(15, 448);
this.label11.Name = "label11";
this.label11.Size = new System.Drawing.Size(55, 13);
this.label11.TabIndex = 20;
this.label11.Text = "Code type";
//
// cmdCompile
//
this.cmdCompile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.cmdCompile.Location = new System.Drawing.Point(470, 792);
this.cmdCompile.Name = "cmdCompile";
this.cmdCompile.Size = new System.Drawing.Size(120, 33);
this.cmdCompile.TabIndex = 26;
this.cmdCompile.Text = "Compile";
this.cmdCompile.UseVisualStyleBackColor = true;
this.cmdCompile.Click += new System.EventHandler(this.cmdCompile_Click);
//
// cmdPatch
//
this.cmdPatch.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.cmdPatch.Location = new System.Drawing.Point(604, 792);
this.cmdPatch.Name = "cmdPatch";
this.cmdPatch.Size = new System.Drawing.Size(120, 33);
this.cmdPatch.TabIndex = 27;
this.cmdPatch.Text = "Patch";
this.cmdPatch.UseVisualStyleBackColor = true;
this.cmdPatch.Click += new System.EventHandler(this.cmdPatch_Click);
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(742, 840);
this.Controls.Add(this.cmdPatch);
this.Controls.Add(this.cmdCompile);
this.Controls.Add(this.cmbCodeType);
this.Controls.Add(this.label11);
this.Controls.Add(this.txtVirtualOffset);
this.Controls.Add(this.label10);
this.Controls.Add(this.txtCompiledOpcodes);
this.Controls.Add(this.label9);
this.Controls.Add(this.txtAssemblyCode);
this.Controls.Add(this.label8);
this.Controls.Add(this.cmbTargetPath);
this.Controls.Add(this.label7);
this.Controls.Add(this.cmbTargetVersion);
this.Controls.Add(this.label6);
this.Controls.Add(this.cmbPatchDefinitionName);
this.Controls.Add(this.label5);
this.Controls.Add(this.cmdPatchDefinitionsFile);
this.Controls.Add(this.txtPatchDefinitionsFile);
this.Controls.Add(this.label4);
this.Controls.Add(this.cmdOutputFile);
this.Controls.Add(this.txtOutputFile);
this.Controls.Add(this.label3);
this.Controls.Add(this.cmdInputFile);
this.Controls.Add(this.txtInputFile);
this.Controls.Add(this.label2);
this.Controls.Add(this.cmdVisualStudioPath);
this.Controls.Add(this.txtVisualStudioPath);
this.Controls.Add(this.label1);
this.Name = "MainForm";
this.Text = "ARM patcher by Rene Lergner";
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.MainForm_FormClosed);
this.Load += new System.EventHandler(this.MainForm_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox txtVisualStudioPath;
private System.Windows.Forms.FolderBrowserDialog FolderBrowserDialog;
private System.Windows.Forms.OpenFileDialog OpenFileDialog;
private System.Windows.Forms.SaveFileDialog SaveFileDialog;
private System.Windows.Forms.Button cmdVisualStudioPath;
private System.Windows.Forms.Button cmdInputFile;
private System.Windows.Forms.TextBox txtInputFile;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button cmdOutputFile;
private System.Windows.Forms.TextBox txtOutputFile;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Button cmdPatchDefinitionsFile;
private System.Windows.Forms.TextBox txtPatchDefinitionsFile;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.ComboBox cmbPatchDefinitionName;
private System.Windows.Forms.ComboBox cmbTargetVersion;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.ComboBox cmbTargetPath;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.TextBox txtAssemblyCode;
private System.Windows.Forms.TextBox txtCompiledOpcodes;
private System.Windows.Forms.Label label9;
private System.Windows.Forms.TextBox txtVirtualOffset;
private System.Windows.Forms.Label label10;
private System.Windows.Forms.ComboBox cmbCodeType;
private System.Windows.Forms.Label label11;
private System.Windows.Forms.Button cmdCompile;
private System.Windows.Forms.Button cmdPatch;
}
}
+410
View File
@@ -0,0 +1,410 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using WPinternals;
namespace Patcher
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
cmbCodeType.SelectedItem = "Thumb2";
LoadPaths();
CenterToScreen();
}
private void cmdCompile_Click(object sender, EventArgs e)
{
string VirtualOffsetString = txtVirtualOffset.Text.Trim();
if (VirtualOffsetString.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
VirtualOffsetString = VirtualOffsetString[2..];
CodeType CodeType = Patcher.CodeType.Thumb2;
byte[] CompiledCode = null;
if (UInt32.TryParse(VirtualOffsetString, System.Globalization.NumberStyles.HexNumber, null, out uint VirtualOffset))
{
CodeType = (CodeType)Enum.Parse(typeof(Patcher.CodeType), cmbCodeType.SelectedItem.ToString());
CompiledCode = ArmCompiler.Compile(txtVisualStudioPath.Text, VirtualOffset, CodeType, txtAssemblyCode.Text);
}
if ((VirtualOffset != 0) && (CompiledCode == null))
txtCompiledOpcodes.Text = ArmCompiler.Output;
else if (CompiledCode != null)
txtCompiledOpcodes.Text = Converter.ConvertHexToString(CompiledCode, " ");
}
private void LoadPaths()
{
RegistryKey Key = Registry.CurrentUser.OpenSubKey(@"Software\Patcher", true) ?? Registry.CurrentUser.CreateSubKey(@"Software\Patcher");
txtVisualStudioPath.Text = (string)Key.GetValue("VisualStudioPath", "");
if (txtVisualStudioPath.Text.Length == 0)
txtVisualStudioPath.Text = FindVisualStudioPath();
txtPatchDefinitionsFile.Text = (string)Key.GetValue("PatchDefinitionsFilePath", "");
cmbPatchDefinitionName.Text = (string)Key.GetValue("PatchDefinitionName", "");
cmbTargetVersion.Text = (string)Key.GetValue("TargetVersion", "");
cmbTargetPath.Text = (string)Key.GetValue("TargetFilePath", "");
txtInputFile.Text = (string)Key.GetValue("InputFilePath", "");
txtOutputFile.Text = (string)Key.GetValue("OutputFilePath", "");
LoadPatchDefinitions();
}
public static string[] FindMSVCBinaryPaths(string s)
{
string LegacyPath = Path.Combine(s, @"VC\bin");
if (Directory.Exists(LegacyPath))
{
return new string[] { LegacyPath };
}
if (Directory.Exists(Path.Combine(s, @"VC\Tools\MSVC")))
{
IEnumerable<string> MSVCs = Directory.EnumerateDirectories(Path.Combine(s, @"VC\Tools\MSVC"));
IEnumerable<string> Bins = MSVCs.Select(s => Path.Combine(s, "bin")).Where(s => Directory.Exists(s));
return Bins.ToArray();
}
return Array.Empty<string>();
}
public static string FindArmAsmPath(string s)
{
foreach (string MSVCBin in FindMSVCBinaryPaths(s))
{
string path1 = Path.Combine(MSVCBin, "x86_arm");
string path2 = Path.Combine(MSVCBin, @"Hostx86\arm");
if (File.Exists(Path.Combine(path1, "armasm.exe")))
{
return path1;
}
if (File.Exists(Path.Combine(path2, "armasm.exe")))
{
return path2;
}
}
return "";
}
private static string FindVisualStudioPath()
{
IEnumerable<string> MainX86VSDirectories = Directory.EnumerateDirectories(@"C:\Program Files (x86)\", "Microsoft Visual Studio*");
IEnumerable<string> MainX64VSDirectories = Directory.EnumerateDirectories(@"C:\Program Files\", "Microsoft Visual Studio*");
IEnumerable<string> MainVSDirectories = MainX86VSDirectories.Union(MainX64VSDirectories);
IEnumerable<string> SubMainVSDirectories = MainVSDirectories.SelectMany(s => Directory.EnumerateDirectories(s));
IEnumerable<string> SubSubMainVSDirectories = SubMainVSDirectories.SelectMany(s => Directory.EnumerateDirectories(s));
IEnumerable<string> Directories = MainVSDirectories.Union(SubMainVSDirectories).Union(SubSubMainVSDirectories);
string attempt1 = Directories.Where(s => FindArmAsmPath(s) != "").OrderByDescending(s => File.GetCreationTime(Path.Combine(s, @"VC\bin\x86_arm\armasm.exe"))).FirstOrDefault() ?? "";
if (attempt1 != "")
return attempt1;
return Directories.Where(s => Directory.Exists(Path.Combine(s, @"VC\Tools\MSVC"))).Select(s => Path.Combine(s, @"VC\Tools\MSVC")).SelectMany(s => Directory.EnumerateDirectories(s)).Where(s => File.Exists(Path.Combine(s, @"bin\Hostx86\arm\armasm.exe"))).OrderByDescending(s => File.GetCreationTime(Path.Combine(s, @"bin\Hostx86\arm\armasm.exe"))).FirstOrDefault() ?? "";
}
private void StorePaths()
{
RegistryKey Key = Registry.CurrentUser.OpenSubKey(@"Software\Patcher", true) ?? Registry.CurrentUser.CreateSubKey(@"Software\Patcher");
string VisualStudioPath = txtVisualStudioPath.Text.Trim();
if (VisualStudioPath.Length == 0)
{
if (Key.GetValue("VisualStudioPath") != null)
Key.DeleteValue("VisualStudioPath");
}
else
{
Key.SetValue("VisualStudioPath", VisualStudioPath);
}
string PatchDefinitionsFilePath = txtPatchDefinitionsFile.Text.Trim();
if (PatchDefinitionsFilePath.Length == 0)
{
if (Key.GetValue("PatchDefinitionsFilePath") != null)
Key.DeleteValue("PatchDefinitionsFilePath");
}
else
{
Key.SetValue("PatchDefinitionsFilePath", PatchDefinitionsFilePath);
}
string PatchDefinitionName = cmbPatchDefinitionName.Text.Trim();
if (PatchDefinitionName.Length == 0)
{
if (Key.GetValue("PatchDefinitionName") != null)
Key.DeleteValue("PatchDefinitionName");
}
else
{
Key.SetValue("PatchDefinitionName", PatchDefinitionName);
}
string TargetVersion = cmbTargetVersion.Text.Trim();
if (TargetVersion.Length == 0)
{
if (Key.GetValue("TargetVersion") != null)
Key.DeleteValue("TargetVersion");
}
else
{
Key.SetValue("TargetVersion", TargetVersion);
}
string TargetFilePath = cmbTargetPath.Text.Trim();
if (TargetFilePath.Length == 0)
{
if (Key.GetValue("TargetFilePath") != null)
Key.DeleteValue("TargetFilePath");
}
else
{
Key.SetValue("TargetFilePath", TargetFilePath);
}
string InputFilePath = txtInputFile.Text.Trim();
if (InputFilePath.Length == 0)
{
if (Key.GetValue("InputFilePath") != null)
Key.DeleteValue("InputFilePath");
}
else
{
Key.SetValue("InputFilePath", InputFilePath);
}
string OutputFilePath = txtOutputFile.Text.Trim();
if (OutputFilePath.Length == 0)
{
if (Key.GetValue("OutputFilePath") != null)
Key.DeleteValue("OutputFilePath");
}
else
{
Key.SetValue("OutputFilePath", OutputFilePath);
}
}
private bool LoadingPatchDefinitions = false;
private void LoadPatchDefinitions()
{
if (LoadingPatchDefinitions)
return;
LoadingPatchDefinitions = true;
string PatchDefinitionName = cmbPatchDefinitionName.Text;
string TargetVersion = cmbTargetVersion.Text;
string TargetPath = cmbTargetPath.Text;
cmbPatchDefinitionName.SelectedIndex = -1;
cmbTargetVersion.SelectedIndex = -1;
cmbTargetPath.SelectedIndex = -1;
cmbPatchDefinitionName.Items.Clear();
cmbTargetVersion.Items.Clear();
cmbTargetPath.Items.Clear();
cmbPatchDefinitionName.Text = PatchDefinitionName;
cmbTargetVersion.Text = TargetVersion;
cmbTargetPath.Text = TargetPath;
try
{
string Definitions = File.ReadAllText(txtPatchDefinitionsFile.Text);
PatchEngine Engine = new(Definitions);
Engine.PatchDefinitions.Where(d => !string.IsNullOrEmpty(d.Name)).Select(d => d.Name).Distinct().ToList().ForEach(n => cmbPatchDefinitionName.Items.Add(n));
PatchDefinition Definition = null;
if (cmbPatchDefinitionName.Text.Trim().Length > 0)
Definition = Engine.PatchDefinitions.Find(d => string.Equals(d.Name, cmbPatchDefinitionName.Text.Trim(), StringComparison.CurrentCultureIgnoreCase));
if (Definition != null)
{
Definition.TargetVersions.Where(v => !string.IsNullOrEmpty(v.Description)).Select(v => v.Description).Distinct().ToList().ForEach(d => cmbTargetVersion.Items.Add(d));
TargetVersion Version = null;
if (cmbTargetVersion.Text.Trim().Length > 0)
Version = Definition.TargetVersions.Find(v => string.Equals(v.Description, cmbTargetVersion.Text.Trim(), StringComparison.CurrentCultureIgnoreCase));
if (Version != null)
{
Version.TargetFiles.Where(f => !string.IsNullOrEmpty(f.Path)).Select(f => Path.GetDirectoryName(f.Path)).Distinct().ToList().ForEach(f => cmbTargetPath.Items.Add(f));
}
}
}
catch { }
LoadingPatchDefinitions = false;
}
private void cmdVisualStudioPath_Click(object sender, EventArgs e)
{
FolderBrowserDialog.SelectedPath = txtVisualStudioPath.Text;
FolderBrowserDialog.Description = "Select path to Visual Studio with ARM32 SDK";
System.Windows.Forms.DialogResult Result = FolderBrowserDialog.ShowDialog();
if (Result == System.Windows.Forms.DialogResult.OK)
txtVisualStudioPath.Text = FolderBrowserDialog.SelectedPath;
}
private void cmdPatchDefinitionsFile_Click(object sender, EventArgs e)
{
OpenFileDialog.CheckFileExists = false;
OpenFileDialog.DefaultExt = "xml";
try
{
OpenFileDialog.FileName = Path.GetFileName(txtPatchDefinitionsFile.Text);
OpenFileDialog.InitialDirectory = Path.GetDirectoryName(txtPatchDefinitionsFile.Text);
}
catch { }
OpenFileDialog.Multiselect = false;
OpenFileDialog.Title = "Open patch-definitions file";
System.Windows.Forms.DialogResult Result = OpenFileDialog.ShowDialog();
if (Result == System.Windows.Forms.DialogResult.OK)
{
txtPatchDefinitionsFile.Text = OpenFileDialog.FileName;
WindowsFormsSynchronizationContext.Current.Post(s => LoadPatchDefinitions(), null);
}
}
private void txtPatchDefinitionsFile_Leave(object sender, EventArgs e)
{
WindowsFormsSynchronizationContext.Current.Post(s => LoadPatchDefinitions(), null);
}
private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
{
StorePaths();
}
private void cmbPatchDefinitionName_SelectedValueChanged(object sender, EventArgs e)
{
WindowsFormsSynchronizationContext.Current.Post(s => LoadPatchDefinitions(), null);
}
private void cmbPatchDefinitionName_Leave(object sender, EventArgs e)
{
WindowsFormsSynchronizationContext.Current.Post(s => LoadPatchDefinitions(), null);
}
private void cmbTargetVersion_SelectedValueChanged(object sender, EventArgs e)
{
WindowsFormsSynchronizationContext.Current.Post(s => LoadPatchDefinitions(), null);
}
private void cmbTargetVersion_Leave(object sender, EventArgs e)
{
WindowsFormsSynchronizationContext.Current.Post(s => LoadPatchDefinitions(), null);
}
private void cmdInputFile_Click(object sender, EventArgs e)
{
OpenFileDialog.CheckFileExists = true;
OpenFileDialog.DefaultExt = "";
try
{
OpenFileDialog.FileName = Path.GetFileName(txtInputFile.Text);
OpenFileDialog.InitialDirectory = Path.GetDirectoryName(txtInputFile.Text);
}
catch { }
OpenFileDialog.Multiselect = false;
OpenFileDialog.Title = "Open input file";
System.Windows.Forms.DialogResult Result = OpenFileDialog.ShowDialog();
if (Result == System.Windows.Forms.DialogResult.OK)
{
txtInputFile.Text = OpenFileDialog.FileName;
txtOutputFile.Text = "";
}
}
private void cmdOutputFile_Click(object sender, EventArgs e)
{
SaveFileDialog.CheckFileExists = false;
SaveFileDialog.DefaultExt = "";
try
{
SaveFileDialog.FileName = Path.GetFileName(txtInputFile.Text);
SaveFileDialog.InitialDirectory = Path.GetDirectoryName(txtOutputFile.Text);
}
catch { }
SaveFileDialog.Title = "Open input file";
System.Windows.Forms.DialogResult Result = SaveFileDialog.ShowDialog();
if (Result == System.Windows.Forms.DialogResult.OK)
txtOutputFile.Text = SaveFileDialog.FileName;
}
private void cmdPatch_Click(object sender, EventArgs e)
{
string VirtualOffsetString = txtVirtualOffset.Text.Trim();
if (VirtualOffsetString.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
VirtualOffsetString = VirtualOffsetString[2..];
CodeType CodeType = Patcher.CodeType.Thumb2;
byte[] CompiledCode = null;
if (UInt32.TryParse(VirtualOffsetString, System.Globalization.NumberStyles.HexNumber, null, out uint VirtualAddress))
{
CodeType = (CodeType)Enum.Parse(typeof(Patcher.CodeType), cmbCodeType.SelectedItem.ToString());
CompiledCode = ArmCompiler.Compile(txtVisualStudioPath.Text, VirtualAddress, CodeType, txtAssemblyCode.Text);
}
if ((VirtualAddress != 0) && (CompiledCode == null))
{
txtCompiledOpcodes.Text = ArmCompiler.Output;
}
else
{
if (CompiledCode != null)
txtCompiledOpcodes.Text = Converter.ConvertHexToString(CompiledCode, " ");
string TargetFilePath = Path.Combine(cmbTargetPath.Text, Path.GetFileName(txtInputFile.Text));
if (TargetFilePath.StartsWith(@"\"))
TargetFilePath = TargetFilePath[1..];
try
{
MainPatcher.AddPatch(txtInputFile.Text, (txtOutputFile.Text.Trim().Length > 0) ? txtOutputFile.Text : null, cmbPatchDefinitionName.Text, cmbTargetVersion.Text, TargetFilePath, txtVisualStudioPath.Text, VirtualAddress, CodeType, txtAssemblyCode.Text, txtPatchDefinitionsFile.Text);
}
catch (ArgumentOutOfRangeException)
{
txtCompiledOpcodes.Text = "BAD VIRTUAL OFFSET";
}
catch
{
txtCompiledOpcodes.Text = "UNKNOWN ERROR";
}
txtVirtualOffset.Focus();
txtVirtualOffset.SelectAll();
}
}
}
}
+129
View File
@@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="FolderBrowserDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="OpenFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>182, 17</value>
</metadata>
<metadata name="SaveFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>317, 17</value>
</metadata>
</root>
+189
View File
@@ -0,0 +1,189 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using WPinternals;
namespace Patcher
{
public static class MainPatcher
{
/// <summary>
/// TargetFilePath is relative to the root of the PatchDefinition
/// OutputFilePath can be null
/// </summary>
/// <param name="InputFilePath"></param>
/// <param name="OutputFilePath"></param>
/// <param name="PatchDefinitionName"></param>
/// <param name="TargetVersionDescription"></param>
/// <param name="TargetFilePath"></param>
/// <param name="PathToVisualStudioWithWP8SDK"></param>
/// <param name="VirtualAddress"></param>
/// <param name="CodeType"></param>
/// <param name="ArmCodeFragment"></param>
/// <param name="PatchDefinitionsXmlPath"></param>
public static void AddPatch(string InputFilePath, string OutputFilePath, string PatchDefinitionName, string TargetVersionDescription, string TargetFilePath, string PathToVisualStudioWithWP8SDK, UInt32 VirtualAddress, CodeType CodeType, string ArmCodeFragment, string PatchDefinitionsXmlPath)
{
SHA1Managed SHA = new();
// Compile ARM code
byte[] CompiledCode = null;
if (VirtualAddress != 0)
CompiledCode = ArmCompiler.Compile(PathToVisualStudioWithWP8SDK, VirtualAddress, CodeType, ArmCodeFragment);
// Read original binary
byte[] Binary = File.ReadAllBytes(InputFilePath);
// Backup original checksum
UInt32 ChecksumOffset = GetChecksumOffset(Binary);
UInt32 OriginalChecksum = ByteOperations.ReadUInt32(Binary, ChecksumOffset);
// Determine Raw Offset
PeFile PeFile = new(Binary);
UInt32 RawOffset = 0;
if (VirtualAddress != 0)
RawOffset = PeFile.ConvertVirtualAddressToRawOffset(VirtualAddress);
// Add or replace patch
string PatchDefinitionsXml = File.ReadAllText(PatchDefinitionsXmlPath);
PatchEngine PatchEngine = new(PatchDefinitionsXml);
PatchDefinition PatchDefinition = PatchEngine.PatchDefinitions.Find(d => string.Equals(d.Name, PatchDefinitionName, StringComparison.CurrentCultureIgnoreCase));
if (PatchDefinition == null)
{
PatchDefinition = new PatchDefinition
{
Name = PatchDefinitionName
};
PatchEngine.PatchDefinitions.Add(PatchDefinition);
}
TargetVersion TargetVersion = PatchDefinition.TargetVersions.Find(v => string.Equals(v.Description, TargetVersionDescription, StringComparison.CurrentCultureIgnoreCase));
if (TargetVersion == null)
{
TargetVersion = new TargetVersion
{
Description = TargetVersionDescription
};
PatchDefinition.TargetVersions.Add(TargetVersion);
}
TargetFile TargetFile = TargetVersion.TargetFiles.Find(f => (f.Path != null) && (string.Equals(f.Path.TrimStart(new char[] { '\\' }), TargetFilePath.TrimStart(new char[] { '\\' }), StringComparison.CurrentCultureIgnoreCase)));
if (TargetFile == null)
{
TargetFile = new TargetFile();
TargetVersion.TargetFiles.Add(TargetFile);
}
TargetFile.Path = TargetFilePath;
TargetFile.HashOriginal = SHA.ComputeHash(Binary);
Patch Patch;
if (VirtualAddress != 0)
{
Patch = TargetFile.Patches.Find(p => p.Address == RawOffset);
if (Patch == null)
{
Patch = new Patch
{
Address = RawOffset
};
TargetFile.Patches.Add(Patch);
}
Patch.OriginalBytes = new byte[CompiledCode.Length];
Buffer.BlockCopy(Binary, (int)RawOffset, Patch.OriginalBytes, 0, CompiledCode.Length);
Patch.PatchedBytes = CompiledCode;
}
// Apply all patches
foreach (Patch CurrentPatch in TargetFile.Patches)
{
Buffer.BlockCopy(CurrentPatch.PatchedBytes, 0, Binary, (int)CurrentPatch.Address, CurrentPatch.PatchedBytes.Length);
}
// Calculate checksum
// This also modifies the binary
// Original checksum is already backed up
UInt32 Checksum = CalculateChecksum(Binary);
// Add or replace checksum patch
Patch = TargetFile.Patches.Find(p => p.Address == ChecksumOffset);
if (Patch == null)
{
Patch = new Patch
{
Address = ChecksumOffset
};
TargetFile.Patches.Add(Patch);
}
Patch.OriginalBytes = new byte[4];
ByteOperations.WriteUInt32(Patch.OriginalBytes, 0, OriginalChecksum);
Patch.PatchedBytes = new byte[4];
ByteOperations.WriteUInt32(Patch.PatchedBytes, 0, Checksum);
// Calculate hash for patched target file
TargetFile.HashPatched = SHA.ComputeHash(Binary);
// Write patched file
if (OutputFilePath != null)
File.WriteAllBytes(OutputFilePath, Binary);
// Write PatchDefinitions
PatchEngine.WriteDefinitions(PatchDefinitionsXmlPath);
}
private static UInt32 CalculateChecksum(byte[] PEFile)
{
UInt32 Checksum = 0;
UInt32 Hi;
// Clear file checksum
ByteOperations.WriteUInt32(PEFile, GetChecksumOffset(PEFile), 0);
for (UInt32 i = 0; i < ((UInt32)PEFile.Length & 0xfffffffe); i += 2)
{
Checksum += ByteOperations.ReadUInt16(PEFile, i);
Hi = Checksum >> 16;
if (Hi != 0)
{
Checksum = Hi + (Checksum & 0xFFFF);
}
}
if ((PEFile.Length % 2) != 0)
{
Checksum += (UInt32)ByteOperations.ReadUInt8(PEFile, (UInt32)PEFile.Length - 1);
Hi = Checksum >> 16;
if (Hi != 0)
{
Checksum = Hi + (Checksum & 0xFFFF);
}
}
Checksum += (UInt32)PEFile.Length;
// Write file checksum
ByteOperations.WriteUInt32(PEFile, GetChecksumOffset(PEFile), Checksum);
return Checksum;
}
private static UInt32 GetChecksumOffset(byte[] PEFile)
{
return ByteOperations.ReadUInt32(PEFile, 0x3C) + +0x58;
}
}
}
+819
View File
@@ -0,0 +1,819 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// This code is based on Get-ObjDump from Matthew Graeber (@mattifestation)
using System;
using System.IO;
using System.Text;
using System.Linq;
namespace COFF
{
public enum Machine : ushort
{
UNKNOWN = 0,
/// <summary>
/// Intel 386.
/// </summary>
I386 = 0x014C,
/// <summary>
/// MIPS little-endian =0x160 big-endian
/// </summary>
R3000 = 0x0162,
/// <summary>
/// MIPS little-endian
/// </summary>
R4000 = 0x0166,
/// <summary>
/// MIPS little-endian
/// </summary>
R10000 = 0x0168,
/// <summary>
/// MIPS little-endian WCE v2
/// </summary>
WCEMIPSV2 = 0x0169,
/// <summary>
/// Alpha_AXP
/// </summary>
ALPHA = 0x0184,
/// <summary>
/// SH3 little-endian
/// </summary>
SH3 = 0x01A2,
SH3DSP = 0x01A3,
/// <summary>
/// SH3E little-endian
/// </summary>
SH3E = 0x01A4,
/// <summary>
/// SH4 little-endian
/// </summary>
SH4 = 0x01A6,
/// <summary>
/// SH5
/// </summary>
SH5 = 0x01A8,
/// <summary>
/// ARM Little-Endian
/// </summary>
ARM = 0x01C0,
THUMB = 0x01C2,
/// <summary>
/// ARM Thumb-2 Little-Endian
/// </summary>
ARMV7 = 0x01C4,
AM33 = 0x01D3,
/// <summary>
/// IBM PowerPC Little-Endian
/// </summary>
POWERPC = 0x01F0,
POWERPCFP = 0x01F1,
/// <summary>
/// Intel 64
/// </summary>
IA64 = 0x0200,
/// <summary>
/// MIPS
/// </summary>
MIPS16 = 0x0266,
/// <summary>
/// ALPHA64
/// </summary>
ALPHA64 = 0x0284,
/// <summary>
/// MIPS
/// </summary>
MIPSFPU = 0x0366,
/// <summary>
/// MIPS
/// </summary>
MIPSFPU16 = 0x0466,
AXP64 = ALPHA64,
/// <summary>
/// Infineon
/// </summary>
TRICORE = 0x0520,
CEF = 0x0CEF,
/// <summary>
/// EFI public byte Code
/// </summary>
EBC = 0x0EBC,
/// <summary>
/// AMD64 (K8)
/// </summary>
AMD64 = 0x8664,
/// <summary>
/// M32R little-endian
/// </summary>
M32R = 0x9041,
/// <summary>
/// ARMv8 in 64-bit mode
/// </summary>
ARM64 = 0xAA64,
CEE = 0xC0EE
}
[Flags]
public enum CoffHeaderCharacteristics : ushort
{
/// <summary>
/// Relocation info stripped from file.
/// </summary>
RELOCS_STRIPPED = 0x0001,
/// <summary>
/// File is executable (i.e. no unresolved external references).
/// </summary>
EXECUTABLE_IMAGE = 0x0002,
/// <summary>
/// Line nunbers stripped from file.
/// </summary>
LINE_NUMS_STRIPPED = 0x0004,
/// <summary>
/// Local symbols stripped from file.
/// </summary>
LOCAL_SYMS_STRIPPED = 0x0008,
/// <summary>
/// Agressively trim working set
/// </summary>
AGGRESIVE_WS_TRIM = 0x0010,
/// <summary>
/// App can handle >2gb addresses
/// </summary>
LARGE_ADDRESS_AWARE = 0x0020,
/// <summary>
/// public bytes of machine public ushort are reversed.
/// </summary>
REVERSED_LO = 0x0080,
/// <summary>
/// 32 bit public ushort machine.
/// </summary>
BIT32_MACHINE = 0x0100,
/// <summary>
/// Debugging info stripped from file in .DBG file
/// </summary>
DEBUG_STRIPPED = 0x0200,
/// <summary>
/// If Image is on removable media =copy and run from the swap file.
/// </summary>
REMOVABLE_RUN_FROM_SWAP = 0x0400,
/// <summary>
/// If Image is on Net =copy and run from the swap file.
/// </summary>
NET_RUN_FROM_SWAP = 0x0800,
/// <summary>
/// System File.
/// </summary>
SYSTEM = 0x1000,
/// <summary>
/// File is a DLL.
/// </summary>
DLL = 0x2000,
/// <summary>
/// File should only be run on a UP machine
/// </summary>
UP_SYSTEM_ONLY = 0x4000,
/// <summary>
/// public bytes of machine public ushort are reversed.
/// </summary>
REVERSED_HI = 0x8000
}
public class HEADER
{
public Machine Machine;
public ushort NumberOfSections;
public DateTime TimeDateStamp;
public uint PointerToSymbolTable;
public uint NumberOfSymbols;
public ushort SizeOfOptionalHeader;
public CoffHeaderCharacteristics Characteristics;
public HEADER(BinaryReader br)
{
this.Machine = (Machine)br.ReadUInt16();
this.NumberOfSections = br.ReadUInt16();
this.TimeDateStamp = new DateTime(1970, 1, 1, 0, 0, 0).AddSeconds(br.ReadUInt32());
this.PointerToSymbolTable = br.ReadUInt32();
this.NumberOfSymbols = br.ReadUInt32();
this.SizeOfOptionalHeader = br.ReadUInt16();
this.Characteristics = (CoffHeaderCharacteristics)br.ReadUInt16();
}
}
[Flags]
public enum SectionHeaderCharacteristics : uint
{
/// <summary>
/// Reserved.
/// </summary>
TYPE_NO_PAD = 0x00000008,
/// <summary>
/// Section contains code.
/// </summary>
CNT_CODE = 0x00000020,
/// <summary>
/// Section contains initialized data.
/// </summary>
CNT_INITIALIZED_DATA = 0x00000040,
/// <summary>
/// Section contains uninitialized data.
/// </summary>
CNT_UNINITIALIZED_DATA = 0x00000080,
/// <summary>
/// Section contains comments or some other type of information.
/// </summary>
LNK_INFO = 0x00000200,
/// <summary>
/// Section contents will not become part of image.
/// </summary>
LNK_REMOVE = 0x00000800,
/// <summary>
/// Section contents comdat.
/// </summary>
LNK_COMDAT = 0x00001000,
/// <summary>
/// Reset speculative exceptions handling bits in the TLB entries for this section.
/// </summary>
NO_DEFER_SPEC_EXC = 0x00004000,
/// <summary>
/// Section content can be accessed relative to GP
/// </summary>
GPREL = 0x00008000,
MEM_FARDATA = 0x00008000,
MEM_PURGEABLE = 0x00020000,
MEM_16BIT = 0x00020000,
MEM_LOCKED = 0x00040000,
MEM_PRELOAD = 0x00080000,
ALIGN_1BYTES = 0x00100000,
ALIGN_2BYTES = 0x00200000,
ALIGN_4BYTES = 0x00300000,
ALIGN_8BYTES = 0x00400000,
/// <summary>
/// Default alignment if no others are specified.
/// </summary>
ALIGN_16BYTES = 0x00500000,
ALIGN_32BYTES = 0x00600000,
ALIGN_64BYTES = 0x00700000,
ALIGN_128BYTES = 0x00800000,
ALIGN_256BYTES = 0x00900000,
ALIGN_512BYTES = 0x00A00000,
ALIGN_1024BYTES = 0x00B00000,
ALIGN_2048BYTES = 0x00C00000,
ALIGN_4096BYTES = 0x00D00000,
ALIGN_8192BYTES = 0x00E00000,
ALIGN_MASK = 0x00F00000,
/// <summary>
/// Section contains extended relocations.
/// </summary>
LNK_NRELOC_OVFL = 0x01000000,
/// <summary>
/// Section can be discarded.
/// </summary>
MEM_DISCARDABLE = 0x02000000,
/// <summary>
/// Section is not cachable.
/// </summary>
MEM_NOT_CACHED = 0x04000000,
/// <summary>
/// Section is not pageable.
/// </summary>
MEM_NOT_PAGED = 0x08000000,
/// <summary>
/// Section is shareable.
/// </summary>
MEM_SHARED = 0x10000000,
/// <summary>
/// Section is executable.
/// </summary>
MEM_EXECUTE = 0x20000000,
/// <summary>
/// Section is readable.
/// </summary>
MEM_READ = 0x40000000,
/// <summary>
/// Section is writeable.
/// </summary>
MEM_WRITE = 0x80000000
}
public enum AMD64RelocationType : ushort
{
ABSOLUTE,
ADDR64,
ADDR32,
ADDR32NB,
REL32,
REL32_1,
REL32_2,
REL32_3,
REL32_4,
REL32_5,
SECTION,
SECREL,
SECREL7,
TOKEN,
SREL32,
PAIR,
SSPAN32
}
public enum ARMRelocationType : ushort
{
ABSOLUTE,
ADDR32,
ADDR32NB,
BRANCH24,
BRANCH11,
TOKEN,
BLX24 = 0x08,
BLX11 = 0x09,
SECTION = 0x0E,
SECREL = 0x0F,
MOV32A = 0x10,
MOV32T = 0x11,
BRANCH20T = 0x12,
BRANCH24T = 0x14,
BLX23T = 0x15
}
public enum ARMv8RelocationType : ushort
{
ABSOLUTE,
ADDR32,
ADDR32NB,
BRANCH26,
PAGEBASE_REL21,
REL21,
PAGEOFFSET_12A,
PAGEOFFSET_12L,
SECREL,
SECREL_LOW12A,
SECREL_HIGH12A,
SECREL_LOW12L,
TOKEN,
SECTION,
ADDR64
}
public enum X86RelocationType : ushort
{
ABSOLUTE,
DIR16,
DIR32 = 0x06,
DIR32NB = 0x07,
SEG12 = 0x09,
SECTION = 0x0A,
SECREL = 0x0B,
TOKEN = 0x0C,
SECREL7 = 0x0D,
REL32 = 0x14
}
public class RelocationEntry
{
public uint VirtualAddress;
public uint SymbolTableIndex;
public Enum Type;
public string Name;
public RelocationEntry(BinaryReader br)
{
this.VirtualAddress = br.ReadUInt32();
this.SymbolTableIndex = br.ReadUInt32();
// Default to X86RelocationType. This will be changed once the processor type is determined
this.Type = (X86RelocationType)br.ReadUInt16();
}
}
public class SECTION_HEADER
{
public string Name;
public uint PhysicalAddress;
public uint VirtualSize;
public uint VirtualAddress;
public uint SizeOfRawData;
public uint PointerToRawData;
public uint PointerToRelocations;
public uint PointerToLinenumbers;
public ushort NumberOfRelocations;
public ushort NumberOfLinenumbers;
public SectionHeaderCharacteristics Characteristics;
public Byte[] RawData;
public RelocationEntry[] Relocations;
public SECTION_HEADER(BinaryReader br)
{
this.Name = Encoding.UTF8.GetString(br.ReadBytes(8)).Split((Char)0)[0];
this.PhysicalAddress = br.ReadUInt32();
this.VirtualSize = this.PhysicalAddress;
this.VirtualAddress = br.ReadUInt32();
this.SizeOfRawData = br.ReadUInt32();
this.PointerToRawData = br.ReadUInt32();
this.PointerToRelocations = br.ReadUInt32();
this.PointerToLinenumbers = br.ReadUInt32();
this.NumberOfRelocations = br.ReadUInt16();
this.NumberOfLinenumbers = br.ReadUInt16();
this.Characteristics = (SectionHeaderCharacteristics)br.ReadUInt32();
}
}
public enum SectionNumber : short
{
UNDEFINED,
ABSOLUTE = -1,
DEBUG = -2
}
[Flags]
public enum TypeClass : short
{
TYPE_NULL,
TYPE_VOID,
TYPE_CHAR,
TYPE_SHORT,
TYPE_INT,
TYPE_LONG,
TYPE_FLOAT,
TYPE_DOUBLE,
TYPE_STRUCT,
TYPE_UNION,
TYPE_ENUM,
TYPE_MOE,
TYPE_BYTE,
TYPE_WORD,
TYPE_UINT,
TYPE_DWORD,
DTYPE_POINTER = 0x100,
DTYPE_FUNCTION = 0x200,
DTYPE_ARRAY = 0x300,
/// <summary>
/// Technically, this is defined as 0 in the MSB
/// </summary>
DTYPE_NULL = 0x400
}
public enum StorageClass : byte
{
NULL,
AUTOMATIC,
EXTERNAL,
STATIC,
REGISTER,
EXTERNAL_DEF,
LABEL,
UNDEFINED_LABEL,
MEMBER_OF_STRUCT,
ARGUMENT,
STRUCT_TAG,
MEMBER_OF_UNION,
UNION_TAG,
TYPE_DEFINITION,
ENUM_TAG,
MEMBER_OF_ENUM,
REGISTER_PARAM,
BIT_FIELD,
BLOCK = 0x64,
FUNCTION = 0x65,
END_OF_STRUCT = 0x66,
FILE = 0x67,
SECTION = 0x68,
WEAK_EXTERNAL = 0x69,
CLR_TOKEN = 0x6B,
END_OF_FUNCTION = 0xFF
}
public class SYMBOL_TABLE
{
public string Name;
public uint Value;
public SectionNumber SectionNumber;
public TypeClass Type;
public StorageClass StorageClass;
public byte NumberOfAuxSymbols;
public Object AuxSymbols;
private readonly Byte[] NameArray;
public SYMBOL_TABLE(BinaryReader br)
{
this.NameArray = br.ReadBytes(8);
if (this.NameArray[0] == 0 && this.NameArray[1] == 0 && this.NameArray[2] == 0 && this.NameArray[3] == 0)
{
// Per specification, if the high DWORD is 0, then then low DWORD is an index into the string table
this.Name = "/" + BitConverter.ToInt32(NameArray, 4).ToString();
}
else
{
this.Name = Encoding.UTF8.GetString(NameArray).Trim((char)0);
}
this.Value = br.ReadUInt32();
this.SectionNumber = (SectionNumber)br.ReadInt16();
this.Type = (TypeClass)br.ReadInt16();
if ((((int)this.Type) & 0xff00) == 0) { this.Type = (TypeClass)Enum.Parse(typeof(TypeClass), ((int)this.Type | 0x400).ToString()); }
this.StorageClass = (StorageClass)br.ReadByte();
this.NumberOfAuxSymbols = br.ReadByte();
}
}
public class SECTION_DEFINITION
{
public uint Length;
public ushort NumberOfRelocations;
public ushort NumberOfLinenumbers;
public uint CheckSum;
public ushort Number;
public byte Selection;
public SECTION_DEFINITION(BinaryReader br)
{
this.Length = br.ReadUInt32();
this.NumberOfRelocations = br.ReadUInt16();
this.NumberOfLinenumbers = br.ReadUInt16();
this.CheckSum = br.ReadUInt32();
this.Number = br.ReadUInt16();
this.Selection = br.ReadByte();
br.ReadBytes(3);
}
}
public class ParsedObjectFile
{
public HEADER CoffHeader;
public SECTION_HEADER[] SectionHeaders;
public SYMBOL_TABLE[] SymbolTable;
}
public static class ObjectFileParser
{
public static ParsedObjectFile ParseObjectFile(string ObjectFilePath)
{
ParsedObjectFile Result = null;
// Fixed structure sizes
const int SizeofCOFFFileHeader = 20;
const int SizeofSectionHeader = 40;
const int SizeofSymbolTableEntry = 18;
const int SizeofRelocationEntry = 10;
// Open the object file for reading
using (FileStream FileStream = System.IO.File.OpenRead(ObjectFilePath))
{
long FileLength = FileStream.Length;
if (FileLength < SizeofCOFFFileHeader)
{
// You cannot parse the COFF header if the file is not big enough to contain a COFF header.
throw new Exception("ObjectFile is too small to store a COFF header.");
}
// Open a BinaryReader object for the object file
using BinaryReader BinaryReader = new(FileStream);
// Parse the COFF header
COFF.HEADER CoffHeader = new(BinaryReader);
if (CoffHeader.SizeOfOptionalHeader != 0)
{
// Per the PECOFF specification, an object file does not have an optional header
throw new Exception("Coff header indicates the existence of an optional header. An object file cannot have an optional header.");
}
if (CoffHeader.PointerToSymbolTable == 0)
{
throw new Exception("An object file is supposed to have a symbol table.");
}
if (FileLength < ((CoffHeader.NumberOfSections * SizeofSectionHeader) + SizeofCOFFFileHeader))
{
// The object file isn't big enough to store the number of sections present.
throw new Exception("ObjectFile is too small to store section header data.");
}
// A string collection used to store section header names. This collection is referenced while
// parsing the symbol table entries whose name is the same as the section header. In this case,
// the symbol entry will have a particular auxiliary symbol table entry.
System.Collections.Specialized.StringCollection SectionHeaderNames = new();
// Correlate the processor type to the relocation type. There are more relocation type defined
// in the PECOFF specification, but I don't expect those to be present. In that case, relocation
// entries default to X86RelocationType.
COFF.SECTION_HEADER[] SectionHeaders = new COFF.SECTION_HEADER[CoffHeader.NumberOfSections];
// Parse section headers
for (int i = 0; i < CoffHeader.NumberOfSections; i++)
{
SectionHeaders[i] = new COFF.SECTION_HEADER(BinaryReader);
// Add the section name to the string collection. This will be referenced during symbol table parsing.
SectionHeaderNames.Add(SectionHeaders[i].Name);
// Save the current filestream position. We are about to jump out of place.
long SavedFilePosition = FileStream.Position;
// Check to see if the raw data points beyond the actual file size
if ((SectionHeaders[i].PointerToRawData + SectionHeaders[i].SizeOfRawData) > FileLength)
{
throw new Exception("Section header's raw data exceeds the size of the object file.");
}
else
{
// Read the raw data into a byte array
FileStream.Seek(SectionHeaders[i].PointerToRawData, SeekOrigin.Begin);
SectionHeaders[i].RawData = BinaryReader.ReadBytes((int)SectionHeaders[i].SizeOfRawData);
}
// Check to see if the section has a relocation table
if ((SectionHeaders[i].PointerToRelocations != 0) && (SectionHeaders[i].NumberOfRelocations != 0))
{
// Check to see if the relocation entries point beyond the actual file size
if ((SectionHeaders[i].PointerToRelocations + (SizeofRelocationEntry * SectionHeaders[i].NumberOfRelocations)) > FileLength)
{
throw new Exception("(SectionHeaders[i].Name) section header's relocation entries exceeds the soze of the object file.");
}
FileStream.Seek(SectionHeaders[i].PointerToRelocations, SeekOrigin.Begin);
COFF.RelocationEntry[] Relocations = new COFF.RelocationEntry[SectionHeaders[i].NumberOfRelocations];
for (int j = 0; j < SectionHeaders[i].NumberOfRelocations; j++)
{
Relocations[j] = new COFF.RelocationEntry(BinaryReader);
// Cast the relocation as its respective type
switch (CoffHeader.Machine)
{
case Machine.I386:
Relocations[j].Type = (COFF.X86RelocationType)Relocations[j].Type;
break;
case Machine.AMD64:
Relocations[j].Type = (COFF.AMD64RelocationType)Relocations[j].Type;
break;
case Machine.ARMV7:
Relocations[j].Type = (COFF.ARMRelocationType)Relocations[j].Type;
break;
case Machine.ARM64:
Relocations[j].Type = (COFF.ARMv8RelocationType)Relocations[j].Type;
break;
}
}
// Add the relocation table entry to the section header
SectionHeaders[i].Relocations = Relocations;
}
// Restore the original filestream pointer
FileStream.Seek(SavedFilePosition, SeekOrigin.Begin);
}
// Retrieve the contents of the COFF string table
long SymTableSize = CoffHeader.NumberOfSymbols * SizeofSymbolTableEntry;
long StringTableOffset = CoffHeader.PointerToSymbolTable + SymTableSize;
if (StringTableOffset > FileLength)
{
throw new Exception("The string table points beyond the end of the file.");
}
FileStream.Seek(StringTableOffset, SeekOrigin.Begin);
UInt32 StringTableLength = BinaryReader.ReadUInt32();
if (StringTableLength > FileLength)
{
throw new Exception("The string table's length exceeds the length of the file.");
}
string StringTable = System.Text.Encoding.UTF8.GetString(BinaryReader.ReadBytes((int)StringTableLength));
COFF.SYMBOL_TABLE[] RawSymbolTable = new COFF.SYMBOL_TABLE[CoffHeader.NumberOfSymbols];
// Retrieve the symbol table
if (FileLength < StringTableOffset)
{
throw new Exception("Symbol table is larger than the file size.");
}
FileStream.Seek(CoffHeader.PointerToSymbolTable, SeekOrigin.Begin);
int NumberofRegularSymbols = 0;
/*
Go through each symbol table looking for auxiliary symbols to parse
Currently supported auxiliary symbol table entry formats:
1) .file
2) Entry names that match the name of a section header
*/
for (int i = 0; i < CoffHeader.NumberOfSymbols; i++)
{
// Parse the symbol tables regardless of whether they are normal or auxiliary symbols
RawSymbolTable[i] = new COFF.SYMBOL_TABLE(BinaryReader);
if (RawSymbolTable[i].NumberOfAuxSymbols == 0)
{
// This symbol table entry has no auxiliary symbols
NumberofRegularSymbols++;
}
else if (RawSymbolTable[i].Name == ".file")
{
long TempPosition = FileStream.Position; // Save filestream position
// Retrieve the file name
RawSymbolTable[i].AuxSymbols = System.Text.Encoding.UTF8.GetString(BinaryReader.ReadBytes(RawSymbolTable[i].NumberOfAuxSymbols * SizeofSymbolTableEntry)).TrimEnd((Char)0);
FileStream.Seek(TempPosition, SeekOrigin.Begin); // Restore filestream position
}
else if (SectionHeaderNames.Contains(RawSymbolTable[i].Name))
{
long TempPosition = FileStream.Position; // Save filestream position
RawSymbolTable[i].AuxSymbols = new COFF.SECTION_DEFINITION(BinaryReader);
FileStream.Seek(TempPosition, SeekOrigin.Begin); // Restore filestream position
}
}
// Create an array of symbol table entries without auxiliary table entries
COFF.SYMBOL_TABLE[] SymbolTable = new COFF.SYMBOL_TABLE[NumberofRegularSymbols];
int k = 0;
for (int i = 0; i < CoffHeader.NumberOfSymbols; i++)
{
SymbolTable[k] = RawSymbolTable[i]; // FYI, the first symbol table entry will never be an aux symbol
k++;
// Skip over the auxiliary symbols
if (RawSymbolTable[i].NumberOfAuxSymbols != 0)
{
i += RawSymbolTable[i].NumberOfAuxSymbols;
}
}
// Fix the section names if any of them point to the COFF string table
for (int i = 0; i < CoffHeader.NumberOfSections; i++)
{
if (SectionHeaders[i].Name?.IndexOf('/') == 0)
{
string StringTableIndexString = SectionHeaders[i].Name[1..];
if (int.TryParse(StringTableIndexString, out int StringTableIndex))
{
StringTableIndex -= 4;
if (StringTableIndex > (StringTableLength + 4))
{
throw new Exception("String table entry exceeds the bounds of the object file.");
}
int Length = StringTable.IndexOf((Char)0, StringTableIndex);
SectionHeaders[i].Name = StringTable.Substring(StringTableIndex, Length);
}
}
}
// Fix the symbol table names
for (int i = 0; i < SymbolTable.Length; i++)
{
if (SymbolTable[i].Name?.IndexOf('/') == 0)
{
string StringTableIndexString = SymbolTable[i].Name[1..];
if (int.TryParse(StringTableIndexString, out int StringTableIndex))
{
StringTableIndex -= 4;
int Length = StringTable.IndexOf((Char)0, StringTableIndex) - StringTableIndex;
SymbolTable[i].Name = StringTable.Substring(StringTableIndex, Length);
}
}
}
// Apply symbol names to the relocation entries
// SectionHeaders | Where-Object { _.Relocations } | % {
// _.Relocations | % { _.Name = RawSymbolTable[_.SymbolTableIndex].Name }
// }
SectionHeaders.Where(h => h.Relocations != null).ToList().ForEach(h => h.Relocations.ToList().ForEach(r => r.Name = RawSymbolTable[r.SymbolTableIndex].Name));
Result = new ParsedObjectFile
{
CoffHeader = CoffHeader,
SectionHeaders = SectionHeaders,
SymbolTable = SymbolTable
};
}
return Result;
}
}
}
+261
View File
@@ -0,0 +1,261 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace WPinternals
{
internal class PatchEngine
{
internal List<PatchDefinition> PatchDefinitions = new();
internal readonly List<TargetRedirection> TargetRedirections = new();
internal PatchEngine() { }
internal PatchEngine(string PatchDefinitionsXmlString)
{
XmlSerializer x = new(PatchDefinitions.GetType(), null, Array.Empty<Type>(), new XmlRootAttribute("PatchDefinitions"), "");
MemoryStream s = new(System.Text.Encoding.ASCII.GetBytes(PatchDefinitionsXmlString));
PatchDefinitions = (List<PatchDefinition>)x.Deserialize(s);
}
internal void WriteDefinitions(string FilePath)
{
XmlSerializer x = new(PatchDefinitions.GetType(), null, Array.Empty<Type>(), new XmlRootAttribute("PatchDefinitions"), "");
XmlSerializerNamespaces ns = new();
ns.Add("", "");
System.IO.StreamWriter FileWriter = new(FilePath);
XmlWriter XmlWriter = XmlWriter.Create(FileWriter, new XmlWriterSettings() { OmitXmlDeclaration = true, Indent = true, NewLineHandling = NewLineHandling.Entitize });
FileWriter.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
FileWriter.WriteLine("");
FileWriter.WriteLine("<!--");
FileWriter.WriteLine("Copyright(c) 2018, Rene Lergner - @Heathcliff74xda");
FileWriter.WriteLine("");
FileWriter.WriteLine("Permission is hereby granted, free of charge, to any person obtaining a");
FileWriter.WriteLine("copy of this software and associated documentation files(the \"Software\"),");
FileWriter.WriteLine("to deal in the Software without restriction, including without limitation");
FileWriter.WriteLine("the rights to use, copy, modify, merge, publish, distribute, sublicense,");
FileWriter.WriteLine("and / or sell copies of the Software, and to permit persons to whom the");
FileWriter.WriteLine("Software is furnished to do so, subject to the following conditions:");
FileWriter.WriteLine("");
FileWriter.WriteLine("The above copyright notice and this permission notice shall be included in");
FileWriter.WriteLine("all copies or substantial portions of the Software.");
FileWriter.WriteLine("");
FileWriter.WriteLine("THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR");
FileWriter.WriteLine("IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,");
FileWriter.WriteLine("FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE");
FileWriter.WriteLine("AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER");
FileWriter.WriteLine("LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING");
FileWriter.WriteLine("FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER");
FileWriter.WriteLine("DEALINGS IN THE SOFTWARE.");
FileWriter.WriteLine("-->");
FileWriter.WriteLine("");
x.Serialize(XmlWriter, PatchDefinitions, ns);
FileWriter.Close();
}
private string _TargetPath = null;
internal string TargetPath
{
get
{
return _TargetPath;
}
set
{
_TargetPath = value.TrimEnd(new char[] { '\\' });
}
}
}
internal class TargetRedirection
{
private string _RelativePath;
private string _TargetPath;
internal TargetRedirection(string RelativePath, string TargetPath)
{
this.RelativePath = RelativePath;
this.TargetPath = TargetPath;
}
internal string RelativePath
{
get
{
return _RelativePath;
}
set
{
_RelativePath = value.TrimStart(new char[] { '\\' }).TrimEnd(new char[] { '\\' });
}
}
internal string TargetPath
{
get
{
return _TargetPath;
}
set
{
_TargetPath = value.TrimEnd(new char[] { '\\' });
}
}
}
/// <summary>
/// Must be public to be serializable
/// </summary>
public class PatchDefinition
{
[XmlAttribute]
public string Name;
public List<TargetVersion> TargetVersions = new();
}
/// <summary>
/// Must be public to be serializable
/// </summary>
public class TargetVersion
{
[XmlAttribute]
public string Description;
public List<TargetFile> TargetFiles = new();
}
/// <summary>
/// Must be public to be serializable
/// </summary>
public class TargetFile
{
private string _Path;
[XmlAttribute]
public string Path
{
get
{
return _Path;
}
set
{
_Path = value.TrimStart(new char[] { '\\' });
}
}
[XmlIgnore]
public byte[] HashOriginal;
[XmlAttribute("HashOriginal")]
public string HashOriginalAsString
{
get
{
return Converter.ConvertHexToString(HashOriginal, "");
}
set
{
HashOriginal = Converter.ConvertStringToHex(value);
}
}
[XmlIgnore]
public byte[] HashPatched;
[XmlAttribute("HashPatched")]
public string HashPatchedAsString
{
get
{
return Converter.ConvertHexToString(HashPatched, "");
}
set
{
HashPatched = Converter.ConvertStringToHex(value);
}
}
public List<Patch> Patches = new();
public List<TargetFile> Obsolete = new();
}
/// <summary>
/// Must be public to be serializable
/// </summary>
public class Patch
{
[XmlIgnore]
public UInt32 Address;
[XmlAttribute("Address")]
public string AddressAsString
{
get
{
return "0x" + Address.ToString("X8");
}
set
{
string NewValue = value;
if (NewValue.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
NewValue = NewValue[2..];
Address = Convert.ToUInt32(NewValue, 16);
}
}
[XmlIgnore]
public byte[] OriginalBytes;
[XmlAttribute("OriginalBytes")]
public string OriginalBytesAsString
{
get
{
return Converter.ConvertHexToString(OriginalBytes, "");
}
set
{
OriginalBytes = Converter.ConvertStringToHex(value);
}
}
[XmlIgnore]
public byte[] PatchedBytes;
[XmlAttribute("PatchedBytes")]
public string PatchedBytesAsString
{
get
{
return Converter.ConvertHexToString(PatchedBytes, "");
}
set
{
PatchedBytes = Converter.ConvertStringToHex(value);
}
}
}
}
+12
View File
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<OutputType>WinExe</OutputType>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<UseWindowsForms>true</UseWindowsForms>
<Platforms>x86</Platforms>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\AutoPatcher\AutoPatcher.csproj" />
</ItemGroup>
</Project>
+9
View File
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
<ItemGroup>
<Compile Update="MainForm.cs">
<SubType>Form</SubType>
</Compile>
</ItemGroup>
</Project>
+818
View File
@@ -0,0 +1,818 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// Explanation of PE header here:
// https://msdn.microsoft.com/en-us/library/ms809762.aspx
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Linq;
using WPinternals;
namespace Patcher
{
#region Structs
[StructLayout(LayoutKind.Sequential)]
public struct IMAGE_DOS_HEADER
{
public UInt16 e_magic;
public UInt16 e_cblp;
public UInt16 e_cp;
public UInt16 e_crlc;
public UInt16 e_cparhdr;
public UInt16 e_minalloc;
public UInt16 e_maxalloc;
public UInt16 e_ss;
public UInt16 e_sp;
public UInt16 e_csum;
public UInt16 e_ip;
public UInt16 e_cs;
public UInt16 e_lfarlc;
public UInt16 e_ovno;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public UInt16[] e_res1;
public UInt16 e_oemid;
public UInt16 e_oeminfo;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public UInt16[] e_res2;
public UInt32 e_lfanew;
}
[StructLayout(LayoutKind.Sequential)]
public struct IMAGE_NT_HEADERS
{
public UInt32 Signature;
public IMAGE_FILE_HEADER FileHeader;
public IMAGE_OPTIONAL_HEADER32 OptionalHeader32;
public IMAGE_OPTIONAL_HEADER64 OptionalHeader64;
}
[StructLayout(LayoutKind.Sequential)]
public struct IMAGE_FILE_HEADER
{
public UInt16 Machine;
public UInt16 NumberOfSections;
public UInt32 TimeDateStamp;
public UInt32 PointerToSymbolTable;
public UInt32 NumberOfSymbols;
public UInt16 SizeOfOptionalHeader;
public UInt16 Characteristics;
}
[StructLayout(LayoutKind.Sequential)]
public struct IMAGE_OPTIONAL_HEADER32
{
public UInt16 Magic;
public Byte MajorLinkerVersion;
public Byte MinorLinkerVersion;
public UInt32 SizeOfCode;
public UInt32 SizeOfInitializedData;
public UInt32 SizeOfUninitializedData;
public UInt32 AddressOfEntryPoint;
public UInt32 BaseOfCode;
public UInt32 BaseOfData;
public UInt32 ImageBase;
public UInt32 SectionAlignment;
public UInt32 FileAlignment;
public UInt16 MajorOperatingSystemVersion;
public UInt16 MinorOperatingSystemVersion;
public UInt16 MajorImageVersion;
public UInt16 MinorImageVersion;
public UInt16 MajorSubsystemVersion;
public UInt16 MinorSubsystemVersion;
public UInt32 Win32VersionValue;
public UInt32 SizeOfImage;
public UInt32 SizeOfHeaders;
public UInt32 CheckSum;
public UInt16 Subsystem;
public UInt16 DllCharacteristics;
public UInt32 SizeOfStackReserve;
public UInt32 SizeOfStackCommit;
public UInt32 SizeOfHeapReserve;
public UInt32 SizeOfHeapCommit;
public UInt32 LoaderFlags;
public UInt32 NumberOfRvaAndSizes;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public IMAGE_DATA_DIRECTORY[] DataDirectory;
}
[StructLayout(LayoutKind.Sequential)]
public struct IMAGE_OPTIONAL_HEADER64
{
public UInt16 Magic;
public Byte MajorLinkerVersion;
public Byte MinorLinkerVersion;
public UInt32 SizeOfCode;
public UInt32 SizeOfInitializedData;
public UInt32 SizeOfUninitializedData;
public UInt32 AddressOfEntryPoint;
public UInt32 BaseOfCode;
public UInt64 ImageBase;
public UInt32 SectionAlignment;
public UInt32 FileAlignment;
public UInt16 MajorOperatingSystemVersion;
public UInt16 MinorOperatingSystemVersion;
public UInt16 MajorImageVersion;
public UInt16 MinorImageVersion;
public UInt16 MajorSubsystemVersion;
public UInt16 MinorSubsystemVersion;
public UInt32 Win32VersionValue;
public UInt32 SizeOfImage;
public UInt32 SizeOfHeaders;
public UInt32 CheckSum;
public UInt16 Subsystem;
public UInt16 DllCharacteristics;
public UInt64 SizeOfStackReserve;
public UInt64 SizeOfStackCommit;
public UInt64 SizeOfHeapReserve;
public UInt64 SizeOfHeapCommit;
public UInt32 LoaderFlags;
public UInt32 NumberOfRvaAndSizes;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public IMAGE_DATA_DIRECTORY[] DataDirectory;
}
[StructLayout(LayoutKind.Sequential)]
public struct IMAGE_DATA_DIRECTORY
{
public UInt32 VirtualAddress;
public UInt32 Size;
}
[StructLayout(LayoutKind.Sequential)]
public struct IMAGE_SECTION_HEADER
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
public string Name;
public Misc Misc;
public UInt32 VirtualAddress;
public UInt32 SizeOfRawData;
public UInt32 PointerToRawData;
public UInt32 PointerToRelocations;
public UInt32 PointerToLinenumbers;
public UInt16 NumberOfRelocations;
public UInt16 NumberOfLinenumbers;
public UInt32 Characteristics;
}
[StructLayout(LayoutKind.Explicit)]
public struct Misc
{
[FieldOffset(0)]
public UInt32 PhysicalAddress;
[FieldOffset(0)]
public UInt32 VirtualSize;
}
[StructLayout(LayoutKind.Sequential)]
public struct IMAGE_EXPORT_DIRECTORY
{
public UInt32 Characteristics;
public UInt32 TimeDateStamp;
public UInt16 MajorVersion;
public UInt16 MinorVersion;
public UInt32 Name;
public UInt32 Base;
public UInt32 NumberOfFunctions;
public UInt32 NumberOfNames;
/// <summary>
/// RVA from base of image
/// </summary>
public UInt32 AddressOfFunctions;
/// <summary>
/// RVA from base of image
/// </summary>
public UInt32 AddressOfNames;
/// <summary>
/// RVA from base of image
/// </summary>
public UInt32 AddressOfNameOrdinals;
}
[StructLayout(LayoutKind.Explicit)]
public struct IMAGE_IMPORT_DESCRIPTOR
{
#region union
/// <summary>
/// CSharp doesnt really support unions, but they can be emulated by a field offset 0
/// </summary>
[FieldOffset(0)]
public uint Characteristics; // 0 for terminating null import descriptor
/// <summary>
/// RVA to original unbound IAT (PIMAGE_THUNK_DATA)
/// </summary>
[FieldOffset(0)]
public uint OriginalFirstThunk;
#endregion
[FieldOffset(4)]
public uint TimeDateStamp;
[FieldOffset(8)]
public uint ForwarderChain;
[FieldOffset(12)]
public uint Name;
[FieldOffset(16)]
public uint FirstThunk;
}
public struct RUNTIME_FUNCTION_64
{
public UInt64 RVAofBeginAddress;
public UInt64 RVAofEndAddress;
public UInt64 RVAofUnwindData;
}
public struct RUNTIME_FUNCTION_32
{
public UInt32 RVAofBeginAddress;
public UInt32 RVAofUnwindData;
}
public static class Constants
{
public static class SectionFlags
{
public const UInt32 IMAGE_SCN_CNT_CODE = 0x00000020;
}
}
internal enum ResourceType
{
/// <summary>
/// Accelerator table.
/// </summary>
RT_ACCELERATOR = 9,
/// <summary>
/// Animated cursor.
/// </summary>
RT_ANICURSOR = 21,
/// <summary>
/// Animated icon.
/// </summary>
RT_ANIICON = 22,
/// <summary>
/// Bitmap resource.
/// </summary>
RT_BITMAP = 2,
/// <summary>
/// Hardware-dependent cursor resource.
/// </summary>
RT_CURSOR = 1,
/// <summary>
/// Dialog box.
/// </summary>
RT_DIALOG = 5,
/// <summary>
/// Allows
/// </summary>
RT_DLGINCLUDE = 17,
/// <summary>
/// Font resource.
/// </summary>
RT_FONT = 8,
/// <summary>
/// Font directory resource.
/// </summary>
RT_FONTDIR = 7,
/// <summary>
/// Hardware-independent cursor resource.
/// </summary>
RT_GROUP_CURSOR = RT_CURSOR + 11,
/// <summary>
/// Hardware-independent icon resource.
/// </summary>
RT_GROUP_ICON = RT_ICON + 11,
/// <summary>
/// HTML resource.
/// </summary>
RT_HTML = 23,
/// <summary>
/// Hardware-dependent icon resource.
/// </summary>
RT_ICON = 3,
/// <summary>
/// Side-by-Side Assembly Manifest.
/// </summary>
RT_MANIFEST = 24,
/// <summary>
/// Menu resource.
/// </summary>
RT_MENU = 4,
/// <summary>
/// Message-table entry.
/// </summary>
RT_MESSAGETABLE = 11,
/// <summary>
/// Plug and Play resource.
/// </summary>
RT_PLUGPLAY = 19,
/// <summary>
/// Application-defined resource (raw data).
/// </summary>
RT_RCDATA = 10,
/// <summary>
/// String-table entry.
/// </summary>
RT_STRING = 6,
/// <summary>
/// Version resource.
/// </summary>
RT_VERSION = 16,
/// <summary>
/// VXD
/// </summary>
RT_VXD = 20,
RT_DLGINIT = 240,
RT_TOOLBAR = 241
};
#endregion
public class PeFile
{
#region Fields
public readonly IMAGE_DOS_HEADER DosHeader;
public IMAGE_NT_HEADERS NtHeaders;
private readonly IList<IMAGE_SECTION_HEADER> _sectionHeaders = new List<IMAGE_SECTION_HEADER>();
public List<Section> Sections = new();
public List<FunctionDescriptor> Exports = new();
public List<FunctionDescriptor> Imports = new();
public List<FunctionDescriptor> RuntimeFunctions = new();
public byte[] Buffer;
public UInt64 ImageBase;
public UInt64 EntryPoint;
public UInt64 ExportDirectoryVirtualOffset;
public UInt64 ImportDirectoryVirtualOffset;
public UInt64 RuntimeDirectoryVirtualOffset;
public UInt32 RuntimeDirectorySize;
#endregion
public PeFile(string Path): this(File.ReadAllBytes(Path))
{
}
public PeFile(byte[] Buffer)
{
int P = 0;
this.Buffer = Buffer;
// Read MS-DOS header section
DosHeader = MarshalBytesTo<IMAGE_DOS_HEADER>(Buffer, P);
// MS-DOS magic number should read 'MZ'
if (DosHeader.e_magic != 0x5a4d)
{
throw new InvalidOperationException("File is not a portable executable.");
}
// Read NT Headers
P = (int)DosHeader.e_lfanew;
NtHeaders.Signature = MarshalBytesTo<UInt32>(Buffer, P);
// Make sure we have 'PE' in the pe signature
if (NtHeaders.Signature != 0x4550)
{
throw new InvalidOperationException("Invalid portable executable signature in NT header.");
}
P += sizeof(UInt32);
NtHeaders.FileHeader = MarshalBytesTo<IMAGE_FILE_HEADER>(Buffer, P);
// Read optional headers
P += Marshal.SizeOf(typeof(IMAGE_FILE_HEADER));
if (Is32bitAssembly())
{
Load32bitOptionalHeaders(Buffer, P);
ImageBase = NtHeaders.OptionalHeader32.ImageBase;
EntryPoint = NtHeaders.OptionalHeader32.AddressOfEntryPoint;
ExportDirectoryVirtualOffset = NtHeaders.OptionalHeader32.DataDirectory[0].VirtualAddress;
ImportDirectoryVirtualOffset = NtHeaders.OptionalHeader32.DataDirectory[1].VirtualAddress;
RuntimeDirectoryVirtualOffset = NtHeaders.OptionalHeader32.DataDirectory[3].VirtualAddress;
RuntimeDirectorySize = NtHeaders.OptionalHeader32.DataDirectory[3].Size;
}
else
{
Load64bitOptionalHeaders(Buffer, P);
ImageBase = NtHeaders.OptionalHeader64.ImageBase;
EntryPoint = NtHeaders.OptionalHeader64.AddressOfEntryPoint;
ExportDirectoryVirtualOffset = NtHeaders.OptionalHeader64.DataDirectory[0].VirtualAddress;
ImportDirectoryVirtualOffset = NtHeaders.OptionalHeader64.DataDirectory[1].VirtualAddress;
RuntimeDirectoryVirtualOffset = NtHeaders.OptionalHeader64.DataDirectory[3].VirtualAddress;
RuntimeDirectorySize = NtHeaders.OptionalHeader64.DataDirectory[3].Size;
}
// Read Sections
_sectionHeaders.ToList().ForEach(s =>
{
byte[] RawCode = new byte[s.SizeOfRawData];
System.Buffer.BlockCopy(Buffer, (int)s.PointerToRawData, RawCode, 0, (int)s.SizeOfRawData);
Sections.Add(new Section { Header = s, Buffer = RawCode, VirtualAddress = s.VirtualAddress + (UInt32)ImageBase, VirtualSize = s.Misc.VirtualSize, IsCode = (s.Characteristics & (uint)Constants.SectionFlags.IMAGE_SCN_CNT_CODE) != 0 });
});
// Read Exports
// TODO: Proper support for 64-bit files
if (ExportDirectoryVirtualOffset != 0)
{
IMAGE_EXPORT_DIRECTORY ExportDirectory = MarshalBytesTo<IMAGE_EXPORT_DIRECTORY>(Buffer, (int)ConvertVirtualOffsetToRawOffset((uint)ExportDirectoryVirtualOffset));
if (ExportDirectory.AddressOfNames != 0)
{
Section ExportsSection = GetSectionForVirtualAddress((uint)(ImageBase + ExportDirectory.AddressOfNames));
UInt32 OffsetNames = (UInt32)(ImageBase + ExportDirectory.AddressOfNames - ExportsSection.VirtualAddress);
UInt32 OffsetOrdinals = (UInt32)(ImageBase + ExportDirectory.AddressOfNameOrdinals - ExportsSection.VirtualAddress);
UInt32 OffsetFunctions = (UInt32)(ImageBase + ExportDirectory.AddressOfFunctions - ExportsSection.VirtualAddress);
string[] ExportNames = new string[ExportDirectory.NumberOfNames];
UInt16[] Ordinals = new UInt16[ExportDirectory.NumberOfNames];
UInt32[] VirtualAddresses = new UInt32[ExportDirectory.NumberOfFunctions];
for (int i = 0; i < ExportDirectory.NumberOfNames; i++)
{
UInt32 NamesRVA = ByteOperations.ReadUInt32(ExportsSection.Buffer, (UInt32)(OffsetNames + (i * sizeof(UInt32))));
UInt32 NameOffset = (UInt32)(NamesRVA + ImageBase - ExportsSection.VirtualAddress);
ExportNames[i] = ByteOperations.ReadAsciiString(ExportsSection.Buffer, NameOffset);
Ordinals[i] = ByteOperations.ReadUInt16(ExportsSection.Buffer, (UInt32)(OffsetOrdinals + (i * sizeof(UInt16))));
}
for (int i = 0; i < ExportDirectory.NumberOfFunctions; i++)
{
VirtualAddresses[i] = ByteOperations.ReadUInt32(ExportsSection.Buffer, (UInt32)(OffsetFunctions + (i * sizeof(UInt32))));
VirtualAddresses[i] -= VirtualAddresses[i] % 2; // Round down for Thumb2
}
for (int i = 0; i < ExportDirectory.NumberOfNames; i++)
{
Exports.Add(new FunctionDescriptor() { Name = ExportNames[i], VirtualAddress = (UInt32)(ImageBase + VirtualAddresses[Ordinals[i]]) });
}
}
}
// Read Imports
// TODO: Proper support for 64-bit files
if (ImportDirectoryVirtualOffset != 0)
{
Section ImportsSection = GetSectionForVirtualAddress((uint)(ImageBase + ImportDirectoryVirtualOffset));
IMAGE_IMPORT_DESCRIPTOR ImportDirectory;
do
{
ImportDirectory = MarshalBytesTo<IMAGE_IMPORT_DESCRIPTOR>(ImportsSection.Buffer, (int)(ImportDirectoryVirtualOffset - (ImportsSection.VirtualAddress - ImageBase)));
if (ImportDirectory.OriginalFirstThunk != 0)
{
// ImportDirectory.OriginalFirstThunk is the VirtualOffset to an array of VirtualOffsets. They point to a struct with a word-value, followed by a zero-terminated ascii-string, which is the name of the import.
// ImportDirectory.FirstThunk points to an array pointers which is the actual import table.
UInt32 NameArrayOffset = ImportDirectory.OriginalFirstThunk - (ImportsSection.VirtualAddress - (UInt32)ImageBase);
UInt32 NameOffset;
int i = 0;
do
{
NameOffset = ByteOperations.ReadUInt32(ImportsSection.Buffer, NameArrayOffset);
if ((NameOffset < (ImportsSection.VirtualAddress - ImageBase)) || (NameOffset >= (ImportsSection.VirtualAddress + ImportsSection.VirtualSize - ImageBase)))
NameOffset = 0; // ImportDirectory.OriginalFirstThunk seems to contain Characteristics, not an offset to an array.
NameArrayOffset += sizeof(UInt32);
if (NameOffset != 0)
{
string Name = ByteOperations.ReadAsciiString(ImportsSection.Buffer, NameOffset + 2 - (ImportsSection.VirtualAddress - (UInt32)ImageBase));
Imports.Add(new FunctionDescriptor() { Name = Name, VirtualAddress = ImportDirectory.FirstThunk + (UInt32)ImageBase + (UInt32)(i * sizeof(UInt32)) });
i++;
}
}
while (NameOffset != 0);
ImportDirectoryVirtualOffset += (UInt64)Marshal.SizeOf(typeof(IMAGE_IMPORT_DESCRIPTOR));
}
}
while (ImportDirectory.OriginalFirstThunk != 0);
}
// Read Runtime functions
// TODO: Proper support for 64-bit files
if (RuntimeDirectoryVirtualOffset != 0)
{
Section RuntimeSection = GetSectionForVirtualAddress((uint)(ImageBase + RuntimeDirectoryVirtualOffset));
RUNTIME_FUNCTION_32 RuntimeFunction;
for (int i = 0; i < (RuntimeDirectorySize / Marshal.SizeOf(typeof(RUNTIME_FUNCTION_32))); i++)
{
RuntimeFunction = MarshalBytesTo<RUNTIME_FUNCTION_32>(RuntimeSection.Buffer, (int)(RuntimeDirectoryVirtualOffset - (RuntimeSection.VirtualAddress - ImageBase)) + (i * Marshal.SizeOf(typeof(RUNTIME_FUNCTION_32))));
RuntimeFunctions.Add(new FunctionDescriptor() { Name = null, VirtualAddress = (UInt32)(RuntimeFunction.RVAofBeginAddress + ImageBase) });
}
}
}
public UInt32 GetChecksumOffset()
{
return ByteOperations.ReadUInt32(Buffer, 0x3C) + +0x58;
}
internal UInt32 CalculateChecksum()
{
UInt32 Checksum = 0;
UInt32 Hi;
// Clear file checksum
// ByteOperations.WriteUInt32(PEFile, GetChecksumOffset(), 0);
UInt32 ChecksumOffset = GetChecksumOffset();
for (UInt32 i = 0; i < ((UInt32)Buffer.Length & 0xfffffffe); i += 2)
{
if ((i < ChecksumOffset) || (i >= (ChecksumOffset + 4)))
Checksum += ByteOperations.ReadUInt16(Buffer, i);
Hi = Checksum >> 16;
if (Hi != 0)
{
Checksum = Hi + (Checksum & 0xFFFF);
}
}
if ((Buffer.Length % 2) != 0)
{
Checksum += (UInt32)ByteOperations.ReadUInt8(Buffer, (UInt32)Buffer.Length - 1);
Hi = Checksum >> 16;
if (Hi != 0)
{
Checksum = Hi + (Checksum & 0xFFFF);
}
}
Checksum += (UInt32)Buffer.Length;
// Write file checksum
// ByteOperations.WriteUInt32(Buffer, GetChecksumOffset(), Checksum);
return Checksum;
}
public IMAGE_DOS_HEADER GetDOSHeader()
{
return DosHeader;
}
public UInt32 GetPESignature()
{
return NtHeaders.Signature;
}
public IMAGE_FILE_HEADER GetFileHeader()
{
return NtHeaders.FileHeader;
}
public IMAGE_OPTIONAL_HEADER32 GetOptionalHeaders32()
{
return NtHeaders.OptionalHeader32;
}
public IMAGE_OPTIONAL_HEADER64 GetOptionalHeaders64()
{
return NtHeaders.OptionalHeader64;
}
public IList<IMAGE_SECTION_HEADER> GetSectionHeaders()
{
return _sectionHeaders;
}
public bool Is32bitAssembly()
{
return (NtHeaders.FileHeader.Characteristics & 0x0100) == 0x0100;
}
private void Load64bitOptionalHeaders(byte[] Buffer, int Offset)
{
NtHeaders.OptionalHeader64 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER64>(Buffer, Offset);
// Should have 10 data directories
if (NtHeaders.OptionalHeader64.NumberOfRvaAndSizes != 0x10)
{
throw new InvalidOperationException("Invalid number of data directories in NT header");
}
Offset += Marshal.SizeOf(typeof(IMAGE_OPTIONAL_HEADER64));
for (int i = 0; i < NtHeaders.FileHeader.NumberOfSections; i++)
{
_sectionHeaders.Add(MarshalBytesTo<IMAGE_SECTION_HEADER>(Buffer, Offset));
Offset += Marshal.SizeOf(typeof(IMAGE_SECTION_HEADER));
}
}
private void Load32bitOptionalHeaders(byte[] Buffer, int Offset)
{
NtHeaders.OptionalHeader32 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER32>(Buffer, Offset);
// Should have 10 data directories
if (NtHeaders.OptionalHeader32.NumberOfRvaAndSizes != 0x10)
{
throw new InvalidOperationException("Invalid number of data directories in NT header");
}
Offset += Marshal.SizeOf(typeof(IMAGE_OPTIONAL_HEADER32));
for (int i = 0; i < NtHeaders.FileHeader.NumberOfSections; i++)
{
_sectionHeaders.Add(MarshalBytesTo<IMAGE_SECTION_HEADER>(Buffer, Offset));
Offset += Marshal.SizeOf(typeof(IMAGE_SECTION_HEADER));
}
}
public UInt32 ConvertVirtualOffsetToRawOffset(UInt32 VirtualOffset)
{
// TODO: Add 64-bit support
if (VirtualOffset < (Sections.OrderBy(s => s.VirtualAddress).First().VirtualAddress - GetOptionalHeaders32().ImageBase))
return VirtualOffset;
IMAGE_SECTION_HEADER? SectionHeaderSelection = _sectionHeaders.FirstOrDefault(h => (h.VirtualAddress <= VirtualOffset) && ((h.VirtualAddress + h.SizeOfRawData) > VirtualOffset));
if (SectionHeaderSelection == null)
throw new ArgumentOutOfRangeException();
IMAGE_SECTION_HEADER SectionHeader = (IMAGE_SECTION_HEADER)SectionHeaderSelection;
if (string.IsNullOrEmpty(SectionHeader.Name) || (SectionHeader.SizeOfRawData == 0))
throw new ArgumentOutOfRangeException();
return SectionHeader.PointerToRawData + (VirtualOffset - SectionHeader.VirtualAddress);
}
public UInt32 ConvertVirtualAddressToRawOffset(UInt32 VirtualAddress)
{
return ConvertVirtualOffsetToRawOffset((UInt32)(VirtualAddress - ImageBase));
}
internal uint ConvertRawOffsetToVirtualAddress(uint RawOffset)
{
// TODO: Add 64-bit support
if (RawOffset < Sections.OrderBy(s => s.VirtualAddress).First().Header.PointerToRawData)
return RawOffset + GetOptionalHeaders32().ImageBase;
IMAGE_SECTION_HEADER? SectionHeaderSelection = _sectionHeaders.FirstOrDefault(h => (h.PointerToRawData <= RawOffset) && ((h.PointerToRawData + h.SizeOfRawData) > RawOffset));
if (SectionHeaderSelection == null)
throw new ArgumentOutOfRangeException();
IMAGE_SECTION_HEADER SectionHeader = (IMAGE_SECTION_HEADER)SectionHeaderSelection;
if (string.IsNullOrEmpty(SectionHeader.Name) || (SectionHeader.SizeOfRawData == 0))
throw new ArgumentOutOfRangeException();
return RawOffset - SectionHeader.PointerToRawData + SectionHeader.VirtualAddress + GetOptionalHeaders32().ImageBase;
}
public Section GetSectionForVirtualAddress(UInt32 VirtualAddress)
{
return Sections.Find(s => (VirtualAddress >= s.VirtualAddress) && (VirtualAddress < (s.VirtualAddress + s.VirtualSize)));
}
private static T MarshalBytesTo<T>(BinaryReader reader)
{
// Unmanaged data
byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T)));
// Create a pointer to the unmanaged data pinned in memory to be accessed by unmanaged code
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
// Use our previously created pointer to unmanaged data and marshal to the specified type
T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
// Deallocate pointer
handle.Free();
return theStructure;
}
private static T MarshalBytesTo<T>(byte[] Binary, int Offset)
{
// Unmanaged data
byte[] bytes = new byte[Marshal.SizeOf(typeof(T))];
System.Buffer.BlockCopy(Binary, Offset, bytes, 0, Marshal.SizeOf(typeof(T)));
// Create a pointer to the unmanaged data pinned in memory to be accessed by unmanaged code
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
// Use our previously created pointer to unmanaged data and marshal to the specified type
T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
// Deallocate pointer
handle.Free();
return theStructure;
}
internal byte[] GetResource(int[] Index)
{
UInt32 PEPointer = ByteOperations.ReadUInt32(Buffer, 0x3C);
UInt16 OptionalHeaderSize = ByteOperations.ReadUInt16(Buffer, PEPointer + 0x14);
UInt32 SectionTablePointer = PEPointer + 0x18 + OptionalHeaderSize;
UInt16 SectionCount = ByteOperations.ReadUInt16(Buffer, PEPointer + 0x06);
UInt32? ResourceSectionEntryPointer = null;
for (int i = 0; i < SectionCount; i++)
{
string SectionName = ByteOperations.ReadAsciiString(Buffer, (UInt32)(SectionTablePointer + (i * 0x28)), 8);
int e = SectionName.IndexOf('\0');
if (e >= 0)
SectionName = SectionName.Substring(0, e);
if (SectionName == ".rsrc")
{
ResourceSectionEntryPointer = (UInt32)(SectionTablePointer + (i * 0x28));
break;
}
}
if (ResourceSectionEntryPointer == null)
throw new Exception("Resource-section not found");
UInt32 ResourceRawSize = ByteOperations.ReadUInt32(Buffer, (UInt32)ResourceSectionEntryPointer + 0x10);
UInt32 ResourceRawPointer = ByteOperations.ReadUInt32(Buffer, (UInt32)ResourceSectionEntryPointer + 0x14);
UInt32 ResourceVirtualPointer = ByteOperations.ReadUInt32(Buffer, (UInt32)ResourceSectionEntryPointer + 0x0C);
UInt32 p = ResourceRawPointer;
for (int i = 0; i < Index.Length; i++)
{
UInt16 ResourceNamedEntryCount = ByteOperations.ReadUInt16(Buffer, p + 0x0c);
UInt16 ResourceIdEntryCount = ByteOperations.ReadUInt16(Buffer, p + 0x0e);
for (int j = ResourceNamedEntryCount; j < ResourceNamedEntryCount + ResourceIdEntryCount; j++)
{
UInt32 ResourceID = ByteOperations.ReadUInt32(Buffer, (UInt32)(p + 0x10 + (j * 8)));
UInt32 NextPointer = ByteOperations.ReadUInt32(Buffer, (UInt32)(p + 0x10 + (j * 8) + 4));
if (ResourceID == (UInt32)Index[i])
{
// Check high bit
if ((NextPointer & 0x80000000) == 0 != (i == (Index.Length - 1)))
throw new Exception("Bad resource path");
p = ResourceRawPointer + (NextPointer & 0x7fffffff);
break;
}
}
}
UInt32 ResourceValuePointer = ByteOperations.ReadUInt32(Buffer, p) - ResourceVirtualPointer + ResourceRawPointer;
UInt32 ResourceValueSize = ByteOperations.ReadUInt32(Buffer, p + 4);
byte[] ResourceValue = new byte[ResourceValueSize];
Array.Copy(Buffer, ResourceValuePointer, ResourceValue, 0, ResourceValueSize);
return ResourceValue;
}
internal Version GetFileVersion()
{
byte[] version = GetResource(new int[] { (int)ResourceType.RT_VERSION, 1, 1033 });
// RT_VERSION format:
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms647001(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms646997(v=vs.85).aspx
const UInt32 FixedFileInfoPointer = 0x28;
UInt16 Major = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x0A);
UInt16 Minor = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x08);
UInt16 Build = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x0E);
UInt16 Revision = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x0C);
return new Version(Major, Minor, Build, Revision);
}
internal Version GetProductVersion()
{
byte[] version = GetResource(new int[] { (int)ResourceType.RT_VERSION, 1, 1033 });
// RT_VERSION format:
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms647001(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms646997(v=vs.85).aspx
const UInt32 FixedFileInfoPointer = 0x28;
UInt16 Major = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x12);
UInt16 Minor = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x10);
UInt16 Build = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x16);
UInt16 Revision = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x14);
return new Version(Major, Minor, Build, Revision);
}
}
public class Section
{
public IMAGE_SECTION_HEADER Header;
public byte[] Buffer;
public UInt32 VirtualAddress;
public UInt32 VirtualSize;
public bool IsCode;
}
public class FunctionDescriptor
{
public string Name;
public UInt32 VirtualAddress;
}
}
+39
View File
@@ -0,0 +1,39 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Windows.Forms;
namespace Patcher
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
private static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
}
@@ -0,0 +1,35 @@
using System.Reflection;
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("ARM Patcher")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("WPinternals.net")]
[assembly: AssemblyProduct("ARM Patcher")]
[assembly: AssemblyCopyright("Copyright © 2018 by Rene Lergner")]
[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("b9aebca3-bcf8-4e4a-bf0e-5e764867be07")]
// 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.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
+71
View File
@@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Patcher.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Patcher.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}
+117
View File
@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
+30
View File
@@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Patcher.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}
@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>
+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Workaround for intermittent issue
https://developercommunity.visualstudio.com/content/problem/983843/dotnet-build-task-does-not-use-nugetorg-for-one-pr.html
-->
<configuration>
<packageSources>
<clear />
<add key="nuget" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>
+24
View File
@@ -0,0 +1,24 @@
# Windows Phone Internals
Windows Phone Internals (WPinternals or WPI for short) is a tool designed to unlock the bootloader and/or secure boot of select Lumia devices made by Nokia and Microsoft.
Thanks to specifically crafted exploits/techniques the tool is able to disable Bootloader Security/SecureBoot on select Lumia models.
After unlocking your bootloader you will be able to notably perform the following actions:
- Boot other Operating Systems
- Enable Root Access (on select OS versions)
- Flash Custom ROMs
- Backup your current Windows Phone ROM
- Access your phone internal storage over USB
## Root Access
Root Access is a set of patches/hacks disabling security inside Windows Phone at its root. Kernel Security, Permission checks, application container security, deployment capability security and much gets disabled as part of enabling root access.
## How to get started?
The tool contains all the documentation you need to know more about the tool, we invite you to read the getting started section of the tool to know more.
## Where do I download the tool?
Here: https://github.com/ReneLergner/WPinternals/releases/latest
+8
View File
@@ -0,0 +1,8 @@
<Application
x:Class="RootAccessTestUWP.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:RootAccessTestUWP"
RequestedTheme="Dark">
</Application>
+100
View File
@@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace RootAccessTestUWP
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
sealed partial class App : Application
{
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
}
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.
/// </summary>
/// <param name="e">Details about the launch request and process.</param>
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
if (e.PrelaunchActivated == false)
{
if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
rootFrame.Navigate(typeof(MainPage), e.Arguments);
}
// Ensure the current window is active
Window.Current.Activate();
}
}
/// <summary>
/// Invoked when Navigation to a certain page fails
/// </summary>
/// <param name="sender">The Frame which failed navigation</param>
/// <param name="e">Details about the navigation failure</param>
void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}
/// <summary>
/// Invoked when application execution is being suspended. Application state is saved
/// without knowing whether the application will be terminated or resumed with the contents
/// of memory still intact.
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
deferral.Complete();
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

+89
View File
@@ -0,0 +1,89 @@
using System;
using System.Runtime.InteropServices;
namespace RootAccessTestUWP
{
public static class Core
{
[DllImport("KERNELBASE.DLL", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int RegQueryValueEx(UIntPtr hKey, string lpValueName, int lpReserved, out Core.RegistryValueKind lpType, IntPtr lpData, ref int lpcbData);
[DllImport("KERNELBASE.DLL", CharSet = CharSet.Unicode)]
private static extern int RegOpenKeyEx(UIntPtr hKey, string subKey, int ulOptions, int samDesired, out UIntPtr hkResult);
[DllImport("KERNELBASE.DLL", SetLastError = true)]
private static extern int RegCloseKey(UIntPtr hKey);
internal static string RegReadStringValue(UIntPtr rootKey, string keyPath, string valueName)
{
UIntPtr hKey;
int num = Core.RegOpenKeyEx(rootKey, keyPath, 0, Core.KEY_READ, out hKey);
if (num != 0)
{
throw new COMException("Failed to open registry key", num);
}
int cb = 1024;
IntPtr intPtr = Marshal.AllocHGlobal(cb);
Core.RegistryValueKind registryValueKind;
num = Core.RegQueryValueEx(hKey, valueName, 0, out registryValueKind, intPtr, ref cb);
if (num != 0)
{
throw new COMException("Failed to read registry value", num);
}
if (registryValueKind != Core.RegistryValueKind.String)
{
throw new Exception("Wrong registry value type");
}
string result = Marshal.PtrToStringUni(intPtr);
Core.RegCloseKey(hKey);
return result;
}
internal static uint RegReadDwordValue(UIntPtr rootKey, string keyPath, string valueName)
{
UIntPtr hKey;
int num = Core.RegOpenKeyEx(rootKey, keyPath, 0, Core.KEY_READ, out hKey);
if (num != 0)
{
throw new COMException("Failed to open registry key", num);
}
int cb = 1024;
IntPtr intPtr = Marshal.AllocHGlobal(cb);
Core.RegistryValueKind registryValueKind;
num = Core.RegQueryValueEx(hKey, valueName, 0, out registryValueKind, intPtr, ref cb);
if (num != 0)
{
throw new COMException("Failed to read registry value", num);
}
if (registryValueKind != Core.RegistryValueKind.DWord)
{
throw new Exception("Wrong registry value type");
}
uint result = (uint)Marshal.ReadInt32(intPtr);
Core.RegCloseKey(hKey);
return result;
}
public static UIntPtr HKEY_CLASSES_ROOT = (UIntPtr)2147483648U;
public static UIntPtr HKEY_CURRENT_USER = (UIntPtr)2147483649U;
public static UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)2147483650U;
public static UIntPtr HKEY_USERS = (UIntPtr)2147483651U;
private static int KEY_READ = 131097;
public enum RegistryValueKind
{
Unknown,
String,
ExpandString,
Binary,
DWord,
MultiString = 7,
QWord = 11,
None = -1
}
}
}
+19
View File
@@ -0,0 +1,19 @@
<Page
x:Class="RootAccessTestUWP.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:RootAccessTestUWP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock x:Name="TextBlock"
Margin="10"
HorizontalAlignment="Stretch"
TextWrapping="Wrap"
Text=""
VerticalAlignment="Stretch"
FontFamily="Courier New" />
</Grid>
</Page>
+65
View File
@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
namespace RootAccessTestUWP
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
TextBlock.Text = "Reading: HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\PhoneProvisioner\\ColdBootDone" + Environment.NewLine + Environment.NewLine;
bool flag = false;
try
{
Core.RegReadDwordValue(Core.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\PhoneProvisioner", "ColdBootDone");
flag = true;
}
catch
{
}
if (flag)
{
TextBlock.Text = string.Concat(new string[]
{
TextBlock.Text,
"Success!",
Environment.NewLine,
Environment.NewLine,
"Root Access: Enabled"
});
}
else
{
TextBlock.Text = string.Concat(new string[]
{
TextBlock.Text,
"Failed!",
Environment.NewLine,
Environment.NewLine,
"Root Access: Disabled"
});
}
}
}
}
+49
View File
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
IgnorableNamespaces="uap mp">
<Identity
Name="66bf96f4-f5ba-41f1-8ceb-ac4e9065ac52"
Publisher="CN=Rene"
Version="1.0.0.0" />
<mp:PhoneIdentity PhoneProductId="66bf96f4-f5ba-41f1-8ceb-ac4e9065ac52" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
<Properties>
<DisplayName>RootAccessTestUWP</DisplayName>
<PublisherDisplayName>Rene</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="RootAccessTestUWP.App">
<uap:VisualElements
DisplayName="RootAccessTestUWP"
Square150x150Logo="Assets\Square150x150Logo.png"
Square44x44Logo="Assets\Square44x44Logo.png"
Description="RootAccessTestUWP"
BackgroundColor="transparent">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
</Capabilities>
</Package>
@@ -0,0 +1,29 @@
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("RootAccessTestUWP")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RootAccessTestUWP")]
[assembly: AssemblyCopyright("Copyright © 2021")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 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.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ComVisible(false)]
@@ -0,0 +1,31 @@
<!--
This file contains Runtime Directives used by .NET Native. The defaults here are suitable for most
developers. However, you can modify these parameters to modify the behavior of the .NET Native
optimizer.
Runtime Directives are documented at https://go.microsoft.com/fwlink/?LinkID=391919
To fully enable reflection for App1.MyClass and all of its public/private members
<Type Name="App1.MyClass" Dynamic="Required All"/>
To enable dynamic creation of the specific instantiation of AppClass<T> over System.Int32
<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32" Activate="Required Public" />
Using the Namespace directive to apply reflection policy to all the types in a particular namespace
<Namespace Name="DataClasses.ViewModels" Serialize="All" />
-->
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<!--
An Assembly element with Name="*Application*" applies to all assemblies in
the application package. The asterisks are not wildcards.
-->
<Assembly Name="*Application*" Dynamic="Required All" />
<!-- Add your application specific runtime directives here. -->
</Application>
</Directives>
+169
View File
@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{8B6AADBB-C750-492E-AF60-82F6323401CC}</ProjectGuid>
<OutputType>AppContainerExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>RootAccessTestUWP</RootNamespace>
<AssemblyName>RootAccessTestUWP</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.22000.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WindowsXamlEnableOverview>true</WindowsXamlEnableOverview>
<AppxPackageSigningEnabled>false</AppxPackageSigningEnabled>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM64'">
<OutputPath>bin\ARM64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>
<ItemGroup>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="Core.cs" />
<Compile Include="MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
</ItemGroup>
<ItemGroup>
<Content Include="Properties\Default.rd.xml" />
<Content Include="Assets\LockScreenLogo.scale-200.png" />
<Content Include="Assets\SplashScreen.scale-200.png" />
<Content Include="Assets\Square150x150Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
<Content Include="Assets\StoreLogo.png" />
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
<Version>6.2.13</Version>
</PackageReference>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
-966
View File
@@ -1,966 +0,0 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Data;
namespace WPinternals
{
internal class DownloadsViewModel : ContextViewModel
{
private readonly PhoneNotifierViewModel Notifier;
private readonly Timer SpeedTimer;
private bool IsSearching = false;
internal DownloadsViewModel(PhoneNotifierViewModel Notifier)
{
IsSwitchingInterface = false;
IsFlashModeOperation = false;
this.Notifier = Notifier;
Notifier.NewDeviceArrived += Notifier_NewDeviceArrived;
RegistryKey Key = Registry.CurrentUser.OpenSubKey(@"Software\WPInternals", true) ?? Registry.CurrentUser.CreateSubKey(@"Software\WPInternals");
DownloadFolder = (string)Key.GetValue("DownloadFolder", @"C:\ProgramData\WPinternals\Repository");
Key.Close();
SpeedTimer = new Timer(TimerCallback, this, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
AddFFUCommand = new DelegateCommand(() =>
{
string FFUPath = null;
OpenFileDialog dlg = new();
dlg.DefaultExt = ".ffu"; // Default file extension
dlg.Filter = "ROM images (.ffu)|*.ffu"; // Filter files by extension
bool? result = dlg.ShowDialog();
if (result == true)
{
FFUPath = dlg.FileName;
string FFUFile = Path.GetFileName(FFUPath);
try
{
App.Config.AddFfuToRepository(FFUPath);
App.Config.WriteConfig();
LastStatusText = "File \"" + FFUFile + "\" was added to the repository.";
}
catch (WPinternalsException Ex)
{
LastStatusText = "Error: " + Ex.Message + ". File \"" + FFUFile + "\" was not added.";
}
catch
{
LastStatusText = "Error: File \"" + FFUFile + "\" was not added.";
}
}
else
{
LastStatusText = null;
}
});
}
private string _LastStatusText = null;
public string LastStatusText
{
get
{
return _LastStatusText;
}
set
{
_LastStatusText = value;
OnPropertyChanged(nameof(LastStatusText));
}
}
internal static void TimerCallback(object State)
{
foreach (DownloadEntry Entry in App.DownloadManager.DownloadList)
{
if (Entry.SpeedIndex >= 0)
{
int ArrayIndex = (int)(Entry.SpeedIndex % 10);
Entry.Speeds[ArrayIndex] = Entry.BytesReceived - Entry.LastBytesReceived;
int Count = (int)((Entry.SpeedIndex + 1) > 10 ? 10 : (Entry.SpeedIndex + 1));
long Sum = 0;
for (int i = 0; i < Count; i++)
{
Sum += Entry.Speeds[i];
}
Entry.Speed = Sum / Count;
Entry.TimeLeft = Entry.Speed < 1000 ? Timeout.InfiniteTimeSpan : TimeSpan.FromSeconds((Entry.Size - Entry.BytesReceived) / Entry.Speed);
}
Entry.LastBytesReceived = Entry.BytesReceived;
Entry.SpeedIndex++;
}
}
private void Notifier_NewDeviceArrived(ArrivalEventArgs Args)
{
EvaluateViewState();
}
internal static long GetFileLengthFromURL(string URL)
{
long Length = 0;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(URL);
req.Method = "HEAD";
req.ServicePoint.ConnectionLimit = 10;
using (WebResponse resp = req.GetResponse())
{
long.TryParse(resp.Headers.Get("Content-Length"), out Length);
}
return Length;
}
internal static string GetFileNameFromURL(string URL)
{
string FileName = Path.GetFileName(URL);
int End = FileName.IndexOf('?');
if (End >= 0)
{
FileName = FileName.Substring(0, End);
}
return FileName;
}
private void Search()
{
if (IsSearching)
{
return;
}
IsSearching = true;
SynchronizationContext UIContext = SynchronizationContext.Current;
SearchResultList.Clear();
new Thread(() =>
{
string FFUURL = null;
string[] EmergencyURLs = null;
try
{
string TempProductType = ProductType.ToUpper();
if ((TempProductType?.StartsWith("RM") == true) && !TempProductType.StartsWith("RM-"))
{
TempProductType = "RM-" + TempProductType[2..];
}
ProductType = TempProductType;
FFUURL = LumiaDownloadModel.SearchFFU(ProductType, ProductCode, OperatorCode, out TempProductType);
if (TempProductType != null)
{
ProductType = TempProductType;
}
if (ProductType != null)
{
EmergencyURLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
}
}
catch { }
UIContext.Post(s =>
{
if (FFUURL != null)
{
SearchResultList.Add(new SearchResult(FFUURL, ProductType, FFUDownloaded, null));
}
if (EmergencyURLs != null)
{
SearchResultList.Add(new SearchResult(ProductType + " emergency-files", EmergencyURLs, ProductType, EmergencyDownloaded, ProductType));
}
}, null);
IsSearching = false;
}).Start();
}
internal void Download(string URL, string Category, Action<string[], object> Callback, object State = null)
{
string Folder = Category == null ? DownloadFolder : Path.Combine(DownloadFolder, Category);
DownloadList.Add(new DownloadEntry(URL, Folder, null, Callback, State));
}
internal void Download(string[] URLs, string Category, Action<string[], object> Callback, object State = null)
{
string Folder = Category == null ? DownloadFolder : Path.Combine(DownloadFolder, Category);
foreach (string URL in URLs)
{
DownloadList.Add(new DownloadEntry(URL, Folder, URLs, Callback, State));
}
}
private void DownloadAll()
{
SynchronizationContext UIContext = SynchronizationContext.Current;
new Thread(() =>
{
string FFUURL = null;
string[] EmergencyURLs = null;
try
{
string TempProductType = ProductType.ToUpper();
if ((TempProductType?.StartsWith("RM") == true) && !TempProductType.StartsWith("RM-"))
{
TempProductType = "RM-" + TempProductType[2..];
}
ProductType = TempProductType;
FFUURL = LumiaDownloadModel.SearchFFU(ProductType, ProductCode, OperatorCode, out TempProductType);
if (TempProductType != null)
{
ProductType = TempProductType;
}
if (ProductType != null)
{
EmergencyURLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
}
}
catch { }
UIContext.Post(s =>
{
if (FFUURL != null)
{
Download(FFUURL, ProductType, FFUDownloadedAndCheckSupported, null);
}
if (EmergencyURLs != null)
{
Download(EmergencyURLs, ProductType, EmergencyDownloaded, ProductType);
}
}, null);
}).Start();
}
private void DownloadSelected()
{
IEnumerable<SearchResult> Selection = SearchResultList.Where(r => r.IsSelected);
foreach (SearchResult Result in Selection)
{
App.DownloadManager.Download(Result.URLs, Result.Category, Result.Callback, Result.State);
}
}
private void FFUDownloaded(string[] Files, object State)
{
App.Config.AddFfuToRepository(Files[0]);
}
private void FFUDownloadedAndCheckSupported(string[] Files, object State)
{
App.Config.AddFfuToRepository(Files[0]);
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
{
const string ProductType2 = "RM-1085";
string URL = LumiaDownloadModel.SearchFFU(ProductType2, null, null);
Download(URL, ProductType2, FFUDownloaded, null);
}
}
private void EmergencyDownloaded(string[] Files, object State)
{
string Type = (string)State;
string ProgrammerPath = null;
string PayloadPath = null;
for (int i = 0; i < Files.Length; i++)
{
if (Files[i].EndsWith(".ede", StringComparison.OrdinalIgnoreCase))
{
ProgrammerPath = Files[i];
}
if (Files[i].EndsWith(".edp", StringComparison.OrdinalIgnoreCase))
{
PayloadPath = Files[i];
}
}
if ((Type != null) && (ProgrammerPath != null) && (PayloadPath != null))
{
App.Config.AddEmergencyToRepository(Type, ProgrammerPath, PayloadPath);
}
}
public ObservableCollection<DownloadEntry> DownloadList { get; } = new();
public ObservableCollection<SearchResult> SearchResultList { get; } = new();
private DelegateCommand _DownloadSelectedCommand = null;
public DelegateCommand DownloadSelectedCommand
{
get
{
return _DownloadSelectedCommand ??= new DelegateCommand(() => DownloadSelected());
}
}
private DelegateCommand _SearchCommand = null;
public DelegateCommand SearchCommand
{
get
{
return _SearchCommand ??= new DelegateCommand(() => Search());
}
}
private DelegateCommand _DownloadAllCommand = null;
public DelegateCommand DownloadAllCommand
{
get
{
return _DownloadAllCommand ??= new DelegateCommand(() => DownloadAll());
}
}
private string _DownloadFolder = null;
public string DownloadFolder
{
get
{
return _DownloadFolder;
}
set
{
if (_DownloadFolder != value)
{
_DownloadFolder = value;
try
{
Directory.CreateDirectory(_DownloadFolder);
}
catch { }
if (!Directory.Exists(_DownloadFolder))
{
_DownloadFolder = @"C:\ProgramData\WPinternals\Repository";
Directory.CreateDirectory(_DownloadFolder);
}
RegistryKey Key = Registry.CurrentUser.OpenSubKey(@"Software\WPInternals", true);
if (_DownloadFolder == null)
{
if (Key.GetValue("DownloadFolder") != null)
{
Key.DeleteValue("DownloadFolder");
}
}
else
{
Key.SetValue("DownloadFolder", _DownloadFolder);
}
Key.Close();
OnPropertyChanged(nameof(DownloadFolder));
}
}
}
private string _ProductCode = null;
public string ProductCode
{
get
{
return _ProductCode;
}
set
{
if (_ProductCode != value)
{
_ProductCode = value;
OnPropertyChanged(nameof(ProductCode));
}
}
}
private string _ProductType = null;
public string ProductType
{
get
{
return _ProductType;
}
set
{
if (_ProductType != value)
{
_ProductType = value;
OnPropertyChanged(nameof(ProductType));
}
}
}
private string _OperatorCode = null;
public string OperatorCode
{
get
{
return _OperatorCode;
}
set
{
if (_OperatorCode != value)
{
_OperatorCode = value;
OnPropertyChanged(nameof(OperatorCode));
}
}
}
internal override void EvaluateViewState()
{
if (!IsActive)
{
return;
}
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash)
{
NokiaFlashModel LumiaFlashModel = (NokiaFlashModel)Notifier.CurrentModel;
PhoneInfo Info = LumiaFlashModel.ReadPhoneInfo();
ProductType = Info.Type;
OperatorCode = "";
ProductCode = Info.ProductCode;
}
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
{
NokiaPhoneModel LumiaNormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
OperatorCode = LumiaNormalModel.ExecuteJsonMethodAsString("ReadOperatorName", "OperatorName"); // Example: 000-NL
string TempProductType = LumiaNormalModel.ExecuteJsonMethodAsString("ReadManufacturerModelName", "ManufacturerModelName"); // RM-821_eu_denmark_251
if (TempProductType.Contains('_'))
{
TempProductType = TempProductType.Substring(0, TempProductType.IndexOf('_'));
}
ProductType = TempProductType;
ProductCode = LumiaNormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode"); // 059Q9D7
}
}
public DelegateCommand AddFFUCommand { get; } = null;
}
internal enum DownloadStatus
{
Downloading,
Ready,
Failed
};
internal class DownloadEntry : INotifyPropertyChanged
{
private readonly SynchronizationContext UIContext;
public event PropertyChangedEventHandler PropertyChanged = delegate { };
internal Action<string[], object> Callback;
internal object State;
internal string URL;
internal string[] URLCollection;
internal string Folder;
internal HttpClient Client;
internal long SpeedIndex = -1;
internal long[] Speeds = new long[10];
internal long LastBytesReceived;
internal long BytesReceived;
internal DownloadEntry(string URL, string Folder, string[] URLCollection, Action<string[], object> Callback, object State)
{
UIContext = SynchronizationContext.Current;
this.URL = URL;
this.Callback = Callback;
this.State = State;
this.URLCollection = URLCollection;
this.Folder = Folder;
Directory.CreateDirectory(Folder);
Name = DownloadsViewModel.GetFileNameFromURL(URL);
Uri Uri = new(URL);
Status = DownloadStatus.Downloading;
new Thread(() =>
{
Size = DownloadsViewModel.GetFileLengthFromURL(URL);
Client = new HttpClient();
_ = Client.DownloadFileAsync(Uri, Path.Combine(Folder, DownloadsViewModel.GetFileNameFromURL(Uri.LocalPath)), Client_DownloadProgressChanged, Client_DownloadFileCompleted);
}).Start();
}
private void Client_DownloadFileCompleted(bool Error)
{
void Finish()
{
Status = Error ? DownloadStatus.Failed : DownloadStatus.Ready;
App.DownloadManager.DownloadList.Remove(this);
if (Status == DownloadStatus.Ready)
{
if (URLCollection?.Any(c => App.DownloadManager.DownloadList.Any(d => d.URL == c)) != true) // if there are no files left to download from this collection, then call the callback-function.
{
string[] Files;
if (URLCollection == null)
{
Files = new string[1];
Files[0] = Path.Combine(Folder, DownloadsViewModel.GetFileNameFromURL(URL));
}
else
{
Files = new string[URLCollection.Length];
for (int i = 0; i < URLCollection.Length; i++)
{
Files[i] = Path.Combine(Folder, DownloadsViewModel.GetFileNameFromURL(URLCollection[i]));
}
}
Callback(Files, State);
}
}
}
UIContext?.Post(d => Finish(), null);
}
private void Client_DownloadProgressChanged(HttpClientDownloadProgress e)
{
BytesReceived = e.BytesReceived;
Progress = e.ProgressPercentage;
}
protected void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
if (SynchronizationContext.Current == UIContext)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
else
{
UIContext.Post((s) => PropertyChanged(this, new PropertyChangedEventArgs(propertyName)), null);
}
}
}
private DownloadStatus _Status;
public DownloadStatus Status
{
get
{
return _Status;
}
set
{
if (_Status != value)
{
_Status = value;
OnPropertyChanged(nameof(Status));
}
}
}
private string _Name;
public string Name
{
get
{
return _Name;
}
set
{
if (_Name != value)
{
_Name = value;
OnPropertyChanged(nameof(Name));
}
}
}
private long _Size;
public long Size
{
get
{
return _Size;
}
set
{
if (_Size != value)
{
_Size = value;
OnPropertyChanged(nameof(Size));
}
}
}
private TimeSpan _TimeLeft;
public TimeSpan TimeLeft
{
get
{
return _TimeLeft;
}
set
{
if (_TimeLeft != value)
{
_TimeLeft = value;
OnPropertyChanged(nameof(TimeLeft));
}
}
}
private double _Speed;
public double Speed
{
get
{
return _Speed;
}
set
{
if (_Speed != value)
{
_Speed = value;
OnPropertyChanged(nameof(Speed));
}
}
}
private int _Progress;
public int Progress
{
get
{
return _Progress;
}
set
{
if (_Progress != value)
{
_Progress = value;
OnPropertyChanged(nameof(Progress));
}
}
}
}
internal class SearchResult : INotifyPropertyChanged
{
private readonly SynchronizationContext UIContext;
public event PropertyChangedEventHandler PropertyChanged;
internal string[] URLs;
internal Action<string[], object> Callback;
internal object State;
internal string Category;
internal SearchResult(string URL, string Category, Action<string[], object> Callback, object State)
{
UIContext = SynchronizationContext.Current;
URLs = new string[1];
URLs[0] = URL;
Name = DownloadsViewModel.GetFileNameFromURL(URL);
this.Callback = Callback;
this.State = State;
this.Category = Category;
GetSize();
}
internal SearchResult(string Name, string[] URLs, string Category, Action<string[], object> Callback, object State)
{
UIContext = SynchronizationContext.Current;
this.URLs = URLs;
this.Name = Name;
this.Callback = Callback;
this.State = State;
this.Category = Category;
GetSize();
}
private void GetSize()
{
new Thread(() =>
{
long CalcSize = 0;
foreach (string URL in URLs)
{
CalcSize += DownloadsViewModel.GetFileLengthFromURL(URL);
}
Size = CalcSize;
}).Start();
}
protected void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
if (SynchronizationContext.Current == UIContext)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
else
{
UIContext.Post((s) => PropertyChanged(this, new PropertyChangedEventArgs(propertyName)), null);
}
}
}
private string _Name;
public string Name
{
get
{
return _Name;
}
set
{
if (_Name != value)
{
_Name = value;
OnPropertyChanged(nameof(Name));
}
}
}
private long _Size;
public long Size
{
get
{
return _Size;
}
set
{
if (_Size != value)
{
_Size = value;
OnPropertyChanged(nameof(Size));
}
}
}
private bool _IsSelected;
public bool IsSelected
{
get
{
return _IsSelected;
}
set
{
if (_IsSelected != value)
{
_IsSelected = value;
OnPropertyChanged(nameof(IsSelected));
}
}
}
}
public class HttpClientDownloadProgress
{
//
// Summary:
// Gets the asynchronous task progress percentage.
//
// Returns:
// A percentage value indicating the asynchronous task progress.
public int ProgressPercentage { get; }
//
// Summary:
// Gets the number of bytes received.
//
// Returns:
// An System.Int64 value that indicates the number of bytes received.
public long BytesReceived { get; }
//
// Summary:
// Gets the total number of bytes in a System.Net.WebClient data download operation.
//
// Returns:
// An System.Int64 value that indicates the number of bytes that will be received.
public long TotalBytesToReceive { get; }
internal HttpClientDownloadProgress(long BytesReceived, long TotalBytesToReceive)
{
this.TotalBytesToReceive = TotalBytesToReceive;
this.BytesReceived = BytesReceived;
ProgressPercentage = (int)Math.Round((float)BytesReceived / TotalBytesToReceive * 100f);
}
}
public static class HttpClientProgressExtensions
{
public static async Task DownloadFileAsync(this HttpClient client, Uri address, string fileName, Action<HttpClientDownloadProgress> progress = null, Action<bool> completed = null, CancellationToken cancellationToken = default(CancellationToken))
{
try
{
using FileStream destination = File.Create(fileName);
using HttpResponseMessage response = await client.GetAsync(address, HttpCompletionOption.ResponseHeadersRead);
long? contentLength = response.Content.Headers.ContentLength;
using Stream download = await response.Content.ReadAsStreamAsync();
if (progress is null || !contentLength.HasValue)
{
await download.CopyToAsync(destination);
if (completed != null)
completed(true);
return;
}
Progress<long> progressWrapper = new Progress<long>(totalBytes => progress(new HttpClientDownloadProgress(totalBytes, contentLength.Value)));
await download.CopyToAsync(destination, 81920, progressWrapper, cancellationToken);
if (completed != null)
completed(true);
}
catch
{
if (completed != null)
completed(false);
}
}
private static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress<long> progress = null, CancellationToken cancellationToken = default(CancellationToken))
{
if (bufferSize < 0)
throw new ArgumentOutOfRangeException(nameof(bufferSize));
if (source is null)
throw new ArgumentNullException(nameof(source));
if (!source.CanRead)
throw new InvalidOperationException($"'{nameof(source)}' is not readable.");
if (destination == null)
throw new ArgumentNullException(nameof(destination));
if (!destination.CanWrite)
throw new InvalidOperationException($"'{nameof(destination)}' is not writable.");
byte[] buffer = new byte[bufferSize];
long totalBytesRead = 0;
int bytesRead;
while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
{
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
totalBytesRead += bytesRead;
progress?.Report(totalBytesRead);
}
}
}
public class DownloaderNameConvertor : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
return Path.GetFileNameWithoutExtension((string)value);
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
return Binding.DoNothing;
}
}
public class DownloaderSizeConvertor : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
long? Size = value as long?;
if (Size < 1024)
{
return Size + " B";
}
if (Size < (1024 * 1024))
{
return Math.Round((double)Size / 1024, 0) + " KB";
}
return Math.Round((double)Size / 1024 / 1024, 0) + " MB";
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
return Binding.DoNothing;
}
}
public class DownloaderSpeedConvertor : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
return ((int)((double)value / 1024)).ToString() + " KB/s";
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
return Binding.DoNothing;
}
}
public class DownloaderTimeRemainingConvertor : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
TimeSpan TimeLeft = (TimeSpan)value;
if (TimeLeft == Timeout.InfiniteTimeSpan)
{
return "";
}
return TimeLeft.ToString(@"h\:mm\:ss");
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
return Binding.DoNothing;
}
}
}
-918
View File
@@ -1,918 +0,0 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace WPinternals
{
internal delegate void ModeSwitchProgressHandler(string Message, string SubMessage);
internal delegate void ModeSwitchErrorHandler(string Message);
internal delegate void ModeSwitchSuccessHandler(IDisposable NewModel, PhoneInterfaces NewInterface);
internal class SwitchModeViewModel : ContextViewModel
{
protected PhoneNotifierViewModel PhoneNotifier;
protected IDisposable CurrentModel;
protected PhoneInterfaces? CurrentMode;
protected PhoneInterfaces? TargetMode;
protected bool IsSwitching = false;
internal event ModeSwitchProgressHandler ModeSwitchProgress = delegate { };
internal event ModeSwitchErrorHandler ModeSwitchError = delegate { };
internal event ModeSwitchSuccessHandler ModeSwitchSuccess = delegate { };
internal new SetWorkingStatus SetWorkingStatus = (m, s, v, a, st) => { };
internal new UpdateWorkingStatus UpdateWorkingStatus = (m, s, v, st) => { };
private string MassStorageWarning = null;
internal SwitchModeViewModel(PhoneNotifierViewModel PhoneNotifier, PhoneInterfaces? TargetMode)
: base()
{
if ((PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Flash) && (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader) && (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Label) && (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Normal))
{
throw new ArgumentException();
}
this.PhoneNotifier = PhoneNotifier;
this.CurrentModel = (NokiaPhoneModel)PhoneNotifier.CurrentModel;
this.CurrentMode = PhoneNotifier.CurrentInterface;
this.TargetMode = TargetMode;
if (this.CurrentMode == null)
{
LogFile.Log("Waiting for phone to connect...", LogType.FileAndConsole);
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
}
else
{
// Make sure this ViewModel has its View loaded before we continue,
// or else loading of Views can get mixed up.
if (SynchronizationContext.Current == null)
{
StartSwitch();
}
else
{
SynchronizationContext.Current.Post((s) => ((SwitchModeViewModel)s).StartSwitch(), this);
}
}
}
internal SwitchModeViewModel(PhoneNotifierViewModel PhoneNotifier, PhoneInterfaces? TargetMode, ModeSwitchProgressHandler ModeSwitchProgress, ModeSwitchErrorHandler ModeSwitchError, ModeSwitchSuccessHandler ModeSwitchSuccess, SetWorkingStatus SetWorkingStatus = null, UpdateWorkingStatus UpdateWorkingStatus = null)
: base()
{
if ((PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) && (TargetMode == PhoneInterfaces.Lumia_Flash))
{
PhoneInfo Info = ((NokiaFlashModel)PhoneNotifier.CurrentModel).ReadPhoneInfo(false);
if (Info.BootManagerProtocolVersionMajor >= 2)
{
try
{
// The implementation of SwitchToFlashAppContext() is improved
// SwitchToFlashAppContext() should only be used with BootMgr v2
// For switching from BootMgr to FlashApp, it will use NOKS
// That will switch to a charging state, whereas a normal context switch will not start charging
// The implementation of NOKS in BootMgr mode has changed in BootMgr v2
// It does not disconnect / reconnect anymore and the apptype is changed immediately
// NOKS still doesnt return a status
// BootMgr v1 uses normal NOKS and waits for arrival of FlashApp
((NokiaFlashModel)PhoneNotifier.CurrentModel).SwitchToFlashAppContext();
// But this was called as a real switch, so we will raise an arrival event.
PhoneNotifier.CurrentInterface = PhoneInterfaces.Lumia_Flash;
PhoneNotifier.NotifyArrival();
}
catch { }
}
}
if (PhoneNotifier.CurrentInterface == TargetMode)
{
ModeSwitchSuccess(PhoneNotifier.CurrentModel, (PhoneInterfaces)PhoneNotifier.CurrentInterface);
}
else
{
this.PhoneNotifier = PhoneNotifier;
this.CurrentModel = (NokiaPhoneModel)PhoneNotifier.CurrentModel;
this.CurrentMode = PhoneNotifier.CurrentInterface;
this.TargetMode = TargetMode;
if (ModeSwitchProgress != null)
{
this.ModeSwitchProgress += ModeSwitchProgress;
}
if (ModeSwitchError != null)
{
this.ModeSwitchError += ModeSwitchError;
}
if (ModeSwitchSuccess != null)
{
this.ModeSwitchSuccess += ModeSwitchSuccess;
}
if (SetWorkingStatus != null)
{
this.SetWorkingStatus = SetWorkingStatus;
}
if (UpdateWorkingStatus != null)
{
this.UpdateWorkingStatus = UpdateWorkingStatus;
}
if (this.CurrentMode == null)
{
LogFile.Log("Waiting for phone to connect...", LogType.FileAndConsole);
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
}
else
{
// Make sure this ViewModel has its View loaded before we continue,
// or else loading of Views can get mixed up.
if (SynchronizationContext.Current == null)
{
StartSwitch();
}
else
{
SynchronizationContext.Current.Post((s) => ((SwitchModeViewModel)s).StartSwitch(), this);
}
}
}
}
private void ModeSwitchProgressWrapper(string Message, string SubMessage)
{
if ((UIContext == null) || (SynchronizationContext.Current == UIContext))
{
ModeSwitchProgress(Message, SubMessage);
SetWorkingStatus(Message, SubMessage);
}
else
{
UIContext.Post(s =>
{
ModeSwitchProgress(Message, SubMessage);
SetWorkingStatus(Message, SubMessage);
}, null);
}
}
private void ModeSwitchErrorWrapper(string Message)
{
IsSwitching = false;
if ((UIContext == null) || (SynchronizationContext.Current == UIContext))
{
ModeSwitchError(Message);
}
else
{
UIContext.Post(s => ModeSwitchError(Message), null);
}
}
private void ModeSwitchSuccessWrapper()
{
IsSwitching = false;
if ((UIContext == null) || (SynchronizationContext.Current == UIContext))
{
if (PhoneNotifier.CurrentInterface == null)
{
ModeSwitchErrorWrapper("Phone disconnected");
}
else
{
ModeSwitchSuccess(PhoneNotifier.CurrentModel, (PhoneInterfaces)PhoneNotifier.CurrentInterface);
}
}
else
{
if (PhoneNotifier.CurrentInterface == null)
{
UIContext.Post(s => ModeSwitchErrorWrapper("Phone disconnected"), null);
}
else
{
UIContext.Post(s => ModeSwitchSuccess(PhoneNotifier.CurrentModel, (PhoneInterfaces)PhoneNotifier.CurrentInterface), null);
}
}
}
~SwitchModeViewModel()
{
if (PhoneNotifier != null)
{
PhoneNotifier.NewDeviceArrived -= NewDeviceArrived;
}
}
internal void StartSwitch()
{
IsSwitching = true;
// Make switch and set message or navigate to error
switch (CurrentMode)
{
case PhoneInterfaces.Lumia_Normal:
case PhoneInterfaces.Lumia_Label:
string DeviceMode;
switch (TargetMode)
{
case PhoneInterfaces.Lumia_Normal:
DeviceMode = "Normal";
IsSwitchingInterface = true;
ModeSwitchProgressWrapper("Rebooting phone to Normal mode...", null);
LogFile.Log("Rebooting phone to Normal mode", LogType.FileAndConsole);
break;
case PhoneInterfaces.Lumia_Bootloader:
DeviceMode = "Normal";
IsSwitchingInterface = true;
ModeSwitchProgressWrapper("Rebooting phone to Bootloader mode...", null);
LogFile.Log("Rebooting phone to Bootloader mode", LogType.FileAndConsole);
break;
case PhoneInterfaces.Lumia_Flash:
DeviceMode = "Flash";
IsSwitchingInterface = true;
ModeSwitchProgressWrapper("Rebooting phone to Flash mode...", null);
LogFile.Log("Rebooting phone to Flash mode", LogType.FileAndConsole);
break;
case PhoneInterfaces.Lumia_Label:
DeviceMode = "Flash";
IsSwitchingInterface = true;
ModeSwitchProgressWrapper("First rebooting phone to Flash mode...", null);
LogFile.Log("First rebooting phone to Flash mode (then attempt Label mode)", LogType.FileAndConsole);
break;
case PhoneInterfaces.Lumia_MassStorage:
DeviceMode = "Flash";
IsSwitchingInterface = true;
ModeSwitchProgressWrapper("First rebooting phone to Flash mode...", null);
LogFile.Log("First rebooting phone to Flash mode (then attempt Mass Storage mode)", LogType.FileAndConsole);
break;
case PhoneInterfaces.Qualcomm_Download: // Only available in new Lumia's
DeviceMode = "Flash";
IsSwitchingInterface = true;
ModeSwitchProgressWrapper("First rebooting phone to Flash mode...", null);
LogFile.Log("First rebooting phone to Flash mode (then attempt Qualcomm Download mode", LogType.FileAndConsole);
break;
default:
return;
}
Dictionary<string, object> Params = new();
Params.Add("DeviceMode", DeviceMode);
Params.Add("ResetMethod", "HwReset");
try
{
((NokiaPhoneModel)CurrentModel).ExecuteJsonMethodAsync("SetDeviceMode", Params);
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
}
catch (Exception Ex)
{
LogFile.LogException(Ex);
ModeSwitchErrorWrapper("Failed to switch to Qualcomm Download mode");
IsSwitchingInterface = false;
}
break;
case PhoneInterfaces.Lumia_Flash:
case PhoneInterfaces.Lumia_Bootloader:
byte[] BootModeFlagCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x58, 0x46, 0x57, 0x00, 0x55, 0x42, 0x46, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 }; // NOKFW UBF
byte[] RebootCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x52 }; // NOKR
byte[] RebootCommandResult;
IsSwitchingInterface = true;
switch (TargetMode)
{
case null:
((NokiaFlashModel)CurrentModel).Shutdown();
ModeSwitchProgressWrapper("Please disconnect your device. Waiting...", null);
LogFile.Log("Please disconnect your device. Waiting...", LogType.FileAndConsole);
new Thread(() =>
{
PhoneNotifier.WaitForRemoval().Wait();
ModeSwitchSuccessWrapper();
}).Start();
break;
case PhoneInterfaces.Lumia_Normal:
((NokiaPhoneModel)CurrentModel).ExecuteRawVoidMethod(RebootCommand);
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
ModeSwitchProgressWrapper("Rebooting phone to Normal mode...", null);
LogFile.Log("Rebooting phone to Normal mode", LogType.FileAndConsole);
break;
case PhoneInterfaces.Lumia_Bootloader:
((NokiaPhoneModel)CurrentModel).ExecuteRawVoidMethod(RebootCommand);
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
ModeSwitchProgressWrapper("Rebooting phone to Bootloader mode...", null);
LogFile.Log("Rebooting phone to Bootloader mode", LogType.FileAndConsole);
break;
case PhoneInterfaces.Lumia_Label:
SwitchFromFlashToLabelMode();
break;
case PhoneInterfaces.Lumia_Flash: // attempt to boot from limited flash to full flash
byte[] RebootToFlashCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x53 }; // NOKS
((NokiaPhoneModel)CurrentModel).ExecuteRawVoidMethod(RebootToFlashCommand);
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
ModeSwitchProgressWrapper("Rebooting phone to Flash mode...", null);
LogFile.Log("Rebooting phone to Flash mode", LogType.FileAndConsole);
break;
case PhoneInterfaces.Lumia_MassStorage:
SwitchFromFlashToMassStorageMode();
break;
case PhoneInterfaces.Qualcomm_Download:
byte[] RebootToQualcommDownloadCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x58, 0x43, 0x42, 0x45 }; // NOKXCBE
RebootCommandResult = ((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(RebootToQualcommDownloadCommand);
if (RebootCommandResult?.Length == 4) // This means fail: NOKU (unknow command)
{
IsSwitchingInterface = false;
ModeSwitchErrorWrapper("Failed to switch to Qualcomm Download mode");
}
else
{
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
ModeSwitchProgressWrapper("Rebooting phone to Qualcomm Download mode...", null);
LogFile.Log("Rebooting phone to Qualcomm Download mode", LogType.FileAndConsole);
}
break;
default:
return;
}
break;
case PhoneInterfaces.Lumia_MassStorage:
IsSwitchingInterface = true;
switch (TargetMode)
{
case PhoneInterfaces.Lumia_Normal:
((MassStorage)CurrentModel).Reboot();
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
ModeSwitchProgressWrapper("Rebooting phone to Normal mode...", null);
LogFile.Log("Rebooting phone to Normal mode", LogType.FileAndConsole);
break;
case PhoneInterfaces.Lumia_Label:
((MassStorage)CurrentModel).Reboot();
PhoneNotifier.NewDeviceArrived += NewDeviceArrivedFromMassStorageMode;
ModeSwitchProgressWrapper("Rebooting phone to Label mode...", null);
LogFile.Log("Rebooting phone to Label mode...", LogType.FileAndConsole);
break;
case PhoneInterfaces.Lumia_Flash:
((MassStorage)CurrentModel).Reboot();
PhoneNotifier.NewDeviceArrived += NewDeviceArrivedFromMassStorageMode;
ModeSwitchProgressWrapper("Rebooting phone to Flash mode...", null);
LogFile.Log("Rebooting phone to Flash mode...", LogType.FileAndConsole);
break;
case null:
((MassStorage)CurrentModel).Reboot();
PhoneNotifier.NewDeviceArrived += NewDeviceArrivedFromMassStorageMode;
ModeSwitchProgressWrapper("First rebooting phone to Flash mode...", null);
LogFile.Log("First rebooting phone to Bootloader mode...", LogType.FileAndConsole);
break;
default:
return;
}
break;
case PhoneInterfaces.Qualcomm_Download:
// TODO: don't know how to switch from Qualcomm Download mode to other mode
break;
}
}
private void NewDeviceArrivedFromMassStorageMode(ArrivalEventArgs Args)
{
PhoneNotifier.NewDeviceArrived -= NewDeviceArrivedFromMassStorageMode;
CurrentModel = Args.NewModel;
CurrentMode = Args.NewInterface;
// After the mass storage mode reboot command, the phone must be in Bootloader mode.
// If it isn't, something unexpected happened and the phone can't be switched.
//
if (CurrentMode == PhoneInterfaces.Lumia_Bootloader)
{
Task.Run(async () =>
{
try
{
await SwitchToWithStatus(PhoneNotifier, TargetMode, SetWorkingStatus, UpdateWorkingStatus);
ModeSwitchSuccessWrapper();
}
catch
{
switch (TargetMode)
{
case PhoneInterfaces.Lumia_Flash:
ModeSwitchErrorWrapper("Failed to switch to Flash mode");
break;
case PhoneInterfaces.Lumia_Label:
ModeSwitchErrorWrapper("Failed to switch to Label mode");
break;
case PhoneInterfaces.Lumia_Normal:
ModeSwitchErrorWrapper("Failed to switch to Normal mode");
break;
case null:
ModeSwitchSuccessWrapper();
break;
}
}
});
}
else
{
switch (TargetMode)
{
case PhoneInterfaces.Lumia_Flash:
ModeSwitchErrorWrapper("Failed to switch to Flash mode");
break;
case PhoneInterfaces.Lumia_Label:
ModeSwitchErrorWrapper("Failed to switch to Label mode");
break;
case PhoneInterfaces.Lumia_Normal:
ModeSwitchErrorWrapper("Failed to switch to Normal mode");
break;
case null:
ModeSwitchErrorWrapper("Failed to shutdown");
break;
}
}
}
private void NewDeviceArrived(ArrivalEventArgs Args)
{
PhoneNotifier.NewDeviceArrived -= NewDeviceArrived;
CurrentModel = Args.NewModel;
CurrentMode = Args.NewInterface;
if ((CurrentMode == PhoneInterfaces.Lumia_Bootloader) && (TargetMode == PhoneInterfaces.Lumia_Flash))
{
try
{
// Going from BootMgr to FlashApp
// SwitchToFlashAppContext() will only switch context. Phone will not charge.
// ResetPhoneToFlashMode() reboots to real flash app. Phone will charge. Works when in BootMgrApp, not when already in FlashApp.
((NokiaFlashModel)CurrentModel).ResetPhoneToFlashMode();
CurrentMode = PhoneInterfaces.Lumia_Flash;
PhoneNotifier.NotifyArrival();
}
catch { }
}
if (CurrentMode == TargetMode)
{
if (TargetMode == PhoneInterfaces.Lumia_Bootloader)
{
((NokiaFlashModel)CurrentModel).DisableRebootTimeOut();
}
ModeSwitchSuccessWrapper();
}
else if (!IsSwitching)
{
StartSwitch();
}
else if ((CurrentMode == PhoneInterfaces.Lumia_Bootloader) && (TargetMode == PhoneInterfaces.Lumia_Normal))
{
// Do nothing, because booting to Normal shortly goes into Flash mode too.
// Just wait to arrive in Normal mode;
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
}
else if ((CurrentMode == PhoneInterfaces.Lumia_Flash) && (TargetMode == PhoneInterfaces.Lumia_MassStorage))
{
SwitchFromFlashToMassStorageMode(Continuation: true);
}
else if ((CurrentMode == PhoneInterfaces.Lumia_Flash) && (TargetMode == PhoneInterfaces.Lumia_Label))
{
SwitchFromFlashToLabelMode(Continuation: true);
}
else if ((CurrentMode == PhoneInterfaces.Lumia_Flash) && (TargetMode == PhoneInterfaces.Qualcomm_Download))
{
byte[] RebootCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x52 };
byte[] RebootToQualcommDownloadCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x58, 0x43, 0x42, 0x45 }; // NOKXCBE
IsSwitchingInterface = true;
LogFile.Log("Sending command for rebooting to Emergency Download mode");
byte[] RebootCommandResult = ((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(RebootToQualcommDownloadCommand);
if (RebootCommandResult?.Length >= 8)
{
int ResultCode = (RebootCommandResult[6] << 8) + RebootCommandResult[7];
LogFile.Log("Resultcode: 0x" + ResultCode.ToString("X4"));
}
if (RebootCommandResult?.Length == 4) // This means fail: NOKU (unknow command)
{
ModeSwitchErrorWrapper("Failed to switch to Qualcomm Download mode");
IsSwitchingInterface = false;
}
else
{
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
ModeSwitchProgressWrapper("And now rebooting phone to Qualcomm Download mode...", null);
LogFile.Log("Rebooting phone to Qualcomm Download mode");
}
}
else
{
switch (TargetMode)
{
case PhoneInterfaces.Lumia_Normal:
ModeSwitchErrorWrapper("Failed to switch to Normal mode");
break;
case PhoneInterfaces.Lumia_Flash:
ModeSwitchErrorWrapper("Failed to switch to Flash mode");
break;
case PhoneInterfaces.Lumia_Label:
ModeSwitchErrorWrapper("Failed to switch to Label mode");
break;
case PhoneInterfaces.Lumia_MassStorage:
ModeSwitchErrorWrapper("Failed to switch to Mass Storage mode");
break;
}
}
}
private void SwitchFromFlashToLabelMode(bool Continuation = false)
{
string ProgressText = Continuation ? "And now preparing to boot the phone to Label mode..." : "Preparing to boot the phone to Label mode...";
NokiaFlashModel FlashModel = (NokiaFlashModel)CurrentModel;
if (CurrentMode == PhoneInterfaces.Lumia_Bootloader)
{
try
{
FlashModel.SwitchToFlashAppContext();
}
catch { }
}
PhoneInfo Info = FlashModel.ReadPhoneInfo(ExtendedInfo: true);
if (Info.MmosOverUsbSupported)
{
new Thread(() =>
{
LogFile.BeginAction("SwitchToLabelMode");
try
{
ModeSwitchProgressWrapper(ProgressText, null);
string TempFolder = Environment.GetEnvironmentVariable("TEMP") + @"\WPInternals";
if (Info.Type == "RM-1152")
{
Info.Type = "RM-1151";
}
string ENOSWPackage = LumiaDownloadModel.SearchENOSW(Info.Type, Info.Firmware);
SetWorkingStatus("Downloading " + Info.Type + " Test Mode package...", MaxProgressValue: 100);
DownloadEntry downloadEntry = new(ENOSWPackage, TempFolder, null, null, null);
downloadEntry.PropertyChanged += (object sender, System.ComponentModel.PropertyChangedEventArgs e) =>
{
if (e.PropertyName == "Progress")
{
int progress = (sender as DownloadEntry)?.Progress ?? 0;
ulong.TryParse(progress.ToString(), out ulong progressret);
UpdateWorkingStatus(null, CurrentProgressValue: progressret);
if (progress == 100)
{
ModeSwitchProgressWrapper("Initializing Flash...", null);
string MMOSPath = TempFolder + "\\" + (sender as DownloadEntry)?.Name;
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
FileInfo info = new(MMOSPath);
uint length = uint.Parse(info.Length.ToString());
const int maximumbuffersize = 0x00240000;
uint totalcounts = (uint)Math.Truncate((decimal)length / maximumbuffersize);
SetWorkingStatus("Flashing Test Mode package...", MaxProgressValue: 100);
ProgressUpdater progressUpdater = new(totalcounts + 1, (int i, TimeSpan? time) => UpdateWorkingStatus(null, CurrentProgressValue: (ulong)i));
FlashModel.FlashMMOS(MMOSPath, progressUpdater);
SetWorkingStatus("And now booting phone to MMOS...", "If the phone stays on the lightning cog screen for a while, you may need to unplug and replug the phone to continue the boot process.");
}
}
};
}
catch (Exception Ex)
{
LogFile.LogException(Ex);
ModeSwitchErrorWrapper(Ex.Message);
}
LogFile.EndAction("SwitchToLabelMode");
}).Start();
}
else
{
byte[] BootModeFlagCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x58, 0x46, 0x57, 0x00, 0x55, 0x42, 0x46, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 }; // NOKFW UBF
byte[] RebootCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x52 }; // NOKR
BootModeFlagCommand[0x0F] = 0x59;
((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(BootModeFlagCommand);
((NokiaPhoneModel)CurrentModel).ExecuteRawVoidMethod(RebootCommand);
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
ModeSwitchProgressWrapper("Rebooting phone to Label mode", null);
LogFile.Log("Rebooting phone to Label mode", LogType.FileAndConsole);
}
}
private void SwitchFromFlashToMassStorageMode(bool Continuation = false)
{
string ProgressText = Continuation ? "And now rebooting phone to Mass Storage mode..." : "Rebooting phone to Mass Storage mode...";
NokiaFlashModel FlashModel = (NokiaFlashModel)CurrentModel;
if (CurrentMode == PhoneInterfaces.Lumia_Bootloader)
{
try
{
FlashModel.SwitchToFlashAppContext();
}
catch { }
}
PhoneInfo Info = FlashModel.ReadPhoneInfo(ExtendedInfo: false);
MassStorageWarning = null;
if (Info.FlashAppProtocolVersionMajor < 2)
{
MassStorageWarning = "Switching to Mass Storage mode should take about 10 seconds. The phone should be unlocked using an Engineering SBL3 to enable Mass Storage mode. When you unlocked the bootloader, but you did not use an Engineering SBL3, an attempt to boot to Mass Storage mode may result in an unresponsive state. Installing drivers for this interface may also cause to hang the PC. So when this switch is taking too long, you should reboot both the PC and the phone. To reboot the phone, you have to perform a soft-reset. Press and hold the volume-down-button and the power-button at the same time for at least 10 seconds. This will trigger a power-cycle and the phone will reboot. Once fully booted, the phone may show strange behavior, like complaining about mail-accounts, showing old text-messages, inability to load https-websites, etc. This is expected behavior, because the time-settings of the phone are incorrect. Just wait a few seconds for the phone to get a data-connection and have the date/time synced. After that the strange behavior will stop automatically and normal operation is resumed.";
}
else
{
MassStorageWarning = "When the screen of the phone is black for a while, it could be that the phone is already in Mass Storage Mode, but there is no drive-letter assigned. To resolve this issue, open Device Manager and manually assign a drive-letter to the MainOS partition of your phone, or open a command-prompt and type: diskpart automount enable.";
if (App.IsPnPEventLogMissing)
{
MassStorageWarning += " It is also possible that the phone is in Mass Storage mode, but the Mass Storage driver on this PC failed. Your PC does not have an eventlog to detect this misbehaviour. But in this case you will see a device with an exclamation mark in Device Manager and then you need to manually reset the phone by pressing and holding the power-button for at least 10 seconds until it vibrates and reboots. After that Windows Phone Internals will revert the changes. After the phone has rebooted to the OS, you can retry to unlock the bootloader.";
}
}
bool IsOldLumia = Info.FlashAppProtocolVersionMajor < 2;
bool IsNewLumia = Info.FlashAppProtocolVersionMajor >= 2;
bool IsUnlockedNew = false;
if (IsNewLumia)
{
GPT GPT = FlashModel.ReadGPT();
IsUnlockedNew = (GPT.GetPartition("IS_UNLOCKED") != null) || (GPT.GetPartition("BACKUP_EFIESP") != null) || (GPT.GetPartition("BACKUP_BS_NV") != null);
}
bool IsOriginalEngineeringLumia = !Info.IsBootloaderSecure && !IsUnlockedNew;
if (IsOldLumia || IsOriginalEngineeringLumia)
{
byte[] BootModeFlagCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x58, 0x46, 0x57, 0x00, 0x55, 0x42, 0x46, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 }; // NOKFW UBF
byte[] RebootCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x52 };
byte[] RebootToMassStorageCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x4D }; // NOKM
IsSwitchingInterface = true;
byte[] RebootCommandResult = ((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(RebootToMassStorageCommand);
if (RebootCommandResult?.Length == 4) // This means fail: NOKU (unknown command)
{
BootModeFlagCommand[0x0F] = 0x4D;
byte[] BootFlagResult = ((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(BootModeFlagCommand);
UInt16 ResultCode = BitConverter.ToUInt16(BootFlagResult, 6);
if (ResultCode == 0)
{
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
((NokiaPhoneModel)CurrentModel).ExecuteRawVoidMethod(RebootCommand);
ModeSwitchProgressWrapper(ProgressText, MassStorageWarning);
LogFile.Log("Rebooting phone to Mass Storage mode");
}
else
{
ModeSwitchErrorWrapper("Failed to switch to Mass Storage mode");
IsSwitchingInterface = false;
}
}
else
{
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
ModeSwitchProgressWrapper(ProgressText, MassStorageWarning);
LogFile.Log("Rebooting phone to Mass Storage mode");
}
}
else if (IsUnlockedNew)
{
new Thread(async () =>
{
LogFile.BeginAction("SwitchToMassStorageMode");
try
{
// Implementation of writing a partition with SecureBoot variable to the phone
ModeSwitchProgressWrapper(ProgressText, MassStorageWarning);
LogFile.Log("Preparing phone for Mass Storage Mode", LogType.FileAndConsole);
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
// Magic!
// The SBMSM resource is a compressed version of a raw NV-variable-partition.
// In this partition the SecureBoot variable is disabled and an extra variable is added which triggers Mass Storage Mode on next reboot.
// It overwrites the variable in a different NV-partition than where this variable is stored usually.
// This normally leads to endless-loops when the NV-variables are enumerated.
// But the partition contains an extra hack to break out the endless loops.
using (var stream = assembly.GetManifestResourceStream("WPinternals.SBMSM"))
{
using DecompressedStream dec = new(stream);
using MemoryStream SB = new(); // Must be a seekable stream!
dec.CopyTo(SB);
// We don't need to check for the BACKUP_BS_NV partition here,
// because the SecureBoot flag is disabled here.
// So either the NV was already backupped or already overwritten.
GPT GPT = FlashModel.ReadGPT();
Partition Target = GPT.GetPartition("UEFI_BS_NV");
// We've been reading the GPT, so we let the phone reset once more to be sure that memory maps are the same
WPinternalsStatus LastStatus = WPinternalsStatus.Undefined;
List<FlashPart> Parts = new();
FlashPart Part = new();
Part.StartSector = (uint)Target.FirstSector;
Part.Stream = SB;
Parts.Add(Part);
await LumiaV2UnlockBootViewModel.LumiaV2CustomFlash(PhoneNotifier, null, false, false, Parts, DoResetFirst: true, ClearFlashingStatusAtEnd: false, ShowProgress: false,
SetWorkingStatus: (m, s, v, a, st) =>
{
if (SetWorkingStatus != null)
{
if ((st == WPinternalsStatus.Scanning) || (st == WPinternalsStatus.WaitingForManualReset))
{
SetWorkingStatus(m, s, v, a, st);
}
else if ((LastStatus == WPinternalsStatus.Scanning) || (LastStatus == WPinternalsStatus.WaitingForManualReset))
{
SetWorkingStatus(ProgressText, MassStorageWarning);
}
LastStatus = st;
}
},
UpdateWorkingStatus: (m, s, v, st) =>
{
if (UpdateWorkingStatus != null)
{
if ((st == WPinternalsStatus.Scanning) || (st == WPinternalsStatus.WaitingForManualReset))
{
UpdateWorkingStatus(m, s, v, st);
}
else if ((LastStatus == WPinternalsStatus.Scanning) || (LastStatus == WPinternalsStatus.WaitingForManualReset))
{
SetWorkingStatus(ProgressText, MassStorageWarning);
}
LastStatus = st;
}
});
}
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_BadMassStorage)
{
throw new WPinternalsException("Phone is in Mass Storage mode, but the driver on PC failed to start");
}
// Wait for bootloader
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_MassStorage)
{
LogFile.Log("Waiting for Mass Storage Mode (1)...", LogType.FileOnly);
await PhoneNotifier.WaitForArrival();
}
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_BadMassStorage)
{
throw new WPinternalsException("Phone is in Mass Storage mode, but the driver on PC failed to start");
}
// Wait for mass storage mode
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_MassStorage)
{
LogFile.Log("Waiting for Mass Storage Mode (2)...", LogType.FileOnly);
await PhoneNotifier.WaitForArrival();
}
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_BadMassStorage)
{
throw new WPinternalsException("Phone is in Mass Storage mode, but the driver on PC failed to start");
}
MassStorage Storage = null;
if (PhoneNotifier.CurrentModel is MassStorage)
{
Storage = (MassStorage)PhoneNotifier.CurrentModel;
}
if (Storage == null)
{
ModeSwitchErrorWrapper("Failed to switch to Mass Storage Mode");
}
else
{
ModeSwitchSuccessWrapper();
}
}
catch (Exception Ex)
{
LogFile.LogException(Ex);
ModeSwitchErrorWrapper(Ex.Message);
}
LogFile.EndAction("SwitchToMassStorageMode");
}).Start();
}
else
{
ModeSwitchErrorWrapper("Bootloader was not unlocked. First unlock bootloader before you try to switch to Mass Storage Mode.");
}
}
internal async static Task<IDisposable> SwitchTo(PhoneNotifierViewModel Notifier, PhoneInterfaces? TargetMode, string RequestedVolumeForMassStorage = "MainOS")
{
return await SwitchToWithProgress(Notifier, TargetMode, null, RequestedVolumeForMassStorage);
}
internal async static Task<IDisposable> SwitchToWithProgress(PhoneNotifierViewModel Notifier, PhoneInterfaces? TargetMode, ModeSwitchProgressHandler ModeSwitchProgress, string RequestedVolumeForMassStorage = "MainOS")
{
if (Notifier.CurrentInterface == TargetMode)
{
return Notifier.CurrentModel;
}
IDisposable Result = null;
string LocalErrorMessage = null;
AsyncAutoResetEvent Event = new(false);
SwitchModeViewModel Switch = new(
Notifier,
TargetMode,
ModeSwitchProgress,
(string ErrorMessage) =>
{
LocalErrorMessage = ErrorMessage;
Event.Set();
},
(IDisposable NewModel, PhoneInterfaces NewInterface) =>
{
Result = NewModel;
Event.Set();
}
);
await Event.WaitAsync(Timeout.InfiniteTimeSpan);
if (LocalErrorMessage != null)
{
throw new WPinternalsException(LocalErrorMessage);
}
return Result;
}
internal async static Task<IDisposable> SwitchToWithStatus(PhoneNotifierViewModel Notifier, PhoneInterfaces? TargetMode, SetWorkingStatus SetWorkingStatus = null, UpdateWorkingStatus UpdateWorkingStatus = null, string RequestedVolumeForMassStorage = "MainOS")
{
if (Notifier.CurrentInterface == TargetMode)
{
return Notifier.CurrentModel;
}
IDisposable Result = null;
string LocalErrorMessage = null;
AsyncAutoResetEvent Event = new(false);
SwitchModeViewModel Switch = new(
Notifier,
TargetMode,
null,
(string ErrorMessage) =>
{
LocalErrorMessage = ErrorMessage;
Event.Set();
},
(IDisposable NewModel, PhoneInterfaces NewInterface) =>
{
Result = NewModel;
Event.Set();
}, SetWorkingStatus, UpdateWorkingStatus
);
await Event.WaitAsync(Timeout.InfiniteTimeSpan);
if (LocalErrorMessage != null)
{
throw new WPinternalsException(LocalErrorMessage);
}
return Result;
}
}
}
-240
View File
@@ -1,240 +0,0 @@
<!--
Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
-->
<UserControl x:Class="WPinternals.LumiaDownloadView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPinternals"
mc:Ignorable="d"
d:DesignWidth="700">
<UserControl.Resources>
<local:ObjectToVisibilityConverter x:Key="ObjectToVisibilityConverter" />
<local:DownloaderNameConvertor x:Key="DownloaderNameConvertor" />
<local:DownloaderSizeConvertor x:Key="DownloaderSizeConvertor" />
<local:DownloaderSpeedConvertor x:Key="DownloaderSpeedConvertor" />
<local:DownloaderTimeRemainingConvertor x:Key="DownloaderTimeRemainingConvertor" />
<Style x:Key="HeaderLeftAligned" TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="HorizontalContentAlignment" Value="Left"></Setter>
<Setter Property="Padding" Value="6,0,0,0"></Setter>
</Style>
<Style x:Key="HeaderRightAligned" TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="HorizontalContentAlignment" Value="Right"></Setter>
<Setter Property="Padding" Value="0,0,6,0"></Setter>
</Style>
<Style x:Key="ContentRightAligned" TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Right" />
<Setter Property="Padding" Value="0,0,6,0" />
</Style>
</UserControl.Resources>
<StackPanel VerticalAlignment="Center">
<Border BorderThickness="1" BorderBrush="#FFD4D4D4" HorizontalAlignment="Stretch" VerticalAlignment="Center" Margin="0,0,0,20">
<StackPanel>
<local:FlowDocumentScrollViewerNoMouseWheel Grid.Column="1" Margin="20,0,20,0" VerticalScrollBarVisibility="Auto" >
<FlowDocument FontFamily="Segoe UI" FontSize="12" Loaded="Document_Loaded" TextAlignment="Left">
<FlowDocument.Resources>
<!-- This style is used to set the margins for all paragraphs in the FlowDocument to 0. -->
<Style TargetType="{x:Type Paragraph}">
<Setter Property="Margin" Value="0"/>
</Style>
<Style TargetType="{x:Type Section}">
<Setter Property="Margin" Value="0"/>
</Style>
</FlowDocument.Resources>
<local:Paragraph>
<Run Text="Download" FontSize="18" FontWeight="Bold" Foreground="#FF3753A6" />
<LineBreak />
<LineBreak />
<local:FolderPicker Caption="Download folder: " SelectionText="Select the destination location for the downloaded files..." Path="{Binding DownloadFolder, Mode=TwoWay}" AllowNull="False" HorizontalAlignment="Stretch" />
</local:Paragraph>
</FlowDocument>
</local:FlowDocumentScrollViewerNoMouseWheel>
<TextBlock Margin="36,0,36,6">Currently downloading:</TextBlock>
<ListView Grid.Row="1" ItemsSource="{Binding DownloadList}" Margin="36,0,36,24" MinHeight="66" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Visible" local:GridViewColumnResize.Enabled="True" >
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridViewColumn local:GridViewColumnResize.Width="*" Header="Name" DisplayMemberBinding="{Binding Name}" HeaderContainerStyle="{StaticResource HeaderLeftAligned}" />
<GridViewColumn Width="80" Header="Size" HeaderContainerStyle="{StaticResource HeaderRightAligned}" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Style="{x:Null}" Text="{Binding Size, Converter={StaticResource DownloaderSizeConvertor}}" TextAlignment="Right" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="75" Header="Time Left" HeaderContainerStyle="{StaticResource HeaderRightAligned}" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Style="{x:Null}" Text="{Binding TimeLeft,Mode=OneWay,Converter={StaticResource DownloaderTimeRemainingConvertor}}" TextAlignment="Right" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="75" Header="Speed" HeaderContainerStyle="{StaticResource HeaderRightAligned}" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Style="{x:Null}" Text="{Binding Speed, Mode=OneWay,Converter={StaticResource DownloaderSpeedConvertor}}" TextAlignment="Right" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="123" Header="Progress">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ProgressBar Value="{Binding Progress, Mode=OneWay}" Width="120" Height="16" Maximum="100"></ProgressBar>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</StackPanel>
</Border>
<Border BorderThickness="1" BorderBrush="#FFD4D4D4" HorizontalAlignment="Stretch" VerticalAlignment="Center" Margin="0,0,0,20">
<StackPanel>
<local:FlowDocumentScrollViewerNoMouseWheel Grid.Column="1" Margin="20,0,20,0" VerticalScrollBarVisibility="Auto" >
<FlowDocument FontFamily="Segoe UI" FontSize="12" Loaded="Document_Loaded" TextAlignment="Left">
<FlowDocument.Resources>
<!-- This style is used to set the margins for all paragraphs in the FlowDocument to 0. -->
<Style TargetType="{x:Type Paragraph}">
<Setter Property="Margin" Value="0"/>
</Style>
<Style TargetType="{x:Type Section}">
<Setter Property="Margin" Value="0"/>
</Style>
</FlowDocument.Resources>
<local:Paragraph>
<Run Text="Model" FontSize="18" FontWeight="Bold" Foreground="#FF3753A6" />
<LineBreak/>
<LineBreak/>
<Run Text="When you choose &quot;Download all&quot;, Windows Phone Internals will download an FFU-file and emergency-files for your phone. When the FFU-file is downloaded, it will be analyzed. And if the OS-version is not a supported version, then Windows Phone Internals will start to download another FFU-file, which should have a supported OS-version. It will be for a different model, but Windows Phone Internals needs it extract some files from it." />
<LineBreak/>
<LineBreak/>
<Run Text="When you connect your phone, the search criteria will be detected automatically. For some older Lumia models this may not work when the phone is in Flash mode. To get the exact search criteria, you need to switch the phone to Normal mode first." />
<LineBreak/>
<LineBreak/>
<Run Text="In some cases the emergency files cannot be found and you will need to download the emergency files yourself. This " />
<Hyperlink NavigateUri="https://www.google.com/search?q=%22Lumia 650 emergency files%22">google search</Hyperlink>
<Run Text=" may yield some relevant results." />
<LineBreak/>
<LineBreak/>
<Run Text="For some older Lumia models the operatorcode search criterion doesn't work. Your search may not yield any results when use the Operatorcode search criterion. You should use the Productcode to find the files for your exact model." />
<LineBreak/>
</local:Paragraph>
</FlowDocument>
</local:FlowDocumentScrollViewerNoMouseWheel>
<Grid Margin="36,-6,36,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="120" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0">Producttype</TextBlock>
<TextBlock Grid.Column="0" Grid.Row="1">Productcode</TextBlock>
<TextBlock Grid.Column="0" Grid.Row="2">Operatorcode</TextBlock>
<TextBox Grid.Column="1" Grid.Row="0" Width="Auto" Margin="0,0,0,8" Text="{Binding ProductType, Mode=TwoWay}"/>
<TextBox Grid.Column="1" Grid.Row="1" Width="Auto" Margin="0,0,0,8" Text="{Binding ProductCode, Mode=TwoWay}"/>
<TextBox Grid.Column="1" Grid.Row="2" Width="Auto" Text="{Binding OperatorCode, Mode=TwoWay}"/>
</Grid>
<StackPanel Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Bottom" Orientation="Horizontal">
<Button Content="Search" Padding="0,5" Width="120" Margin="0,0,20,0" Command="{Binding Path=SearchCommand, Mode=OneWay}" IsDefault="True"/>
<Button Content="Download all" Padding="0,5" Width="120" Command="{Binding Path=DownloadAllCommand, Mode=OneWay}" />
</StackPanel>
</Grid>
<TextBlock Margin="36,30,36,6">Search results:</TextBlock>
<ListView Grid.Row="1" Name="SearchResultsListView" ItemsSource="{Binding SearchResultList}" Margin="36,0,36,0" MinHeight="66" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Visible" local:GridViewColumnResize.Enabled="True">
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridViewColumn local:GridViewColumnResize.Width="*" Header="Name" DisplayMemberBinding="{Binding Name}" HeaderContainerStyle="{StaticResource HeaderLeftAligned}" />
<GridViewColumn Width="80" Header="Size" HeaderContainerStyle="{StaticResource HeaderRightAligned}" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Style="{x:Null}" Text="{Binding Size, Converter={StaticResource DownloaderSizeConvertor}}" TextAlignment="Right" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<StackPanel Orientation="Horizontal" Width="Auto" Height="Auto" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,16,36,25">
<Button Command="{Binding Path=DownloadSelectedCommand, Mode=OneWay}" Content="Download selected" Width="Auto" Height="Auto" Padding="20,5" />
</StackPanel>
</StackPanel>
</Border>
<Border BorderThickness="1" BorderBrush="#FFD4D4D4" HorizontalAlignment="Stretch" VerticalAlignment="Center">
<StackPanel>
<local:FlowDocumentScrollViewerNoMouseWheel Grid.Column="1" Margin="20,0,20,0" VerticalScrollBarVisibility="Auto">
<FlowDocument FontFamily="Segoe UI" FontSize="12" Loaded="Document_Loaded" TextAlignment="Left">
<FlowDocument.Resources>
<!-- This style is used to set the margins for all paragraphs in the FlowDocument to 0. -->
<Style TargetType="{x:Type Paragraph}">
<Setter Property="Margin" Value="0"/>
</Style>
<Style TargetType="{x:Type Section}">
<Setter Property="Margin" Value="0"/>
</Style>
</FlowDocument.Resources>
<local:Paragraph>
<Run Text="Repository" FontSize="18" FontWeight="Bold" Foreground="#FF3753A6" />
</local:Paragraph>
</FlowDocument>
</local:FlowDocumentScrollViewerNoMouseWheel>
<local:FlowDocumentScrollViewerNoMouseWheel Grid.Column="1" Margin="20,-15,20,0" VerticalScrollBarVisibility="Auto" Visibility="{Binding Path=LastStatusText, Converter={StaticResource ObjectToVisibilityConverter}}">
<FlowDocument FontFamily="Segoe UI" FontSize="12" Loaded="Document_Loaded" TextAlignment="Left">
<FlowDocument.Resources>
<!-- This style is used to set the margins for all paragraphs in the FlowDocument to 0. -->
<Style TargetType="{x:Type Paragraph}">
<Setter Property="Margin" Value="0"/>
</Style>
<Style TargetType="{x:Type Section}">
<Setter Property="Margin" Value="0"/>
</Style>
</FlowDocument.Resources>
<local:Paragraph>
<Run Text="{Binding Path=LastStatusText}" />
</local:Paragraph>
</FlowDocument>
</local:FlowDocumentScrollViewerNoMouseWheel>
<Button Height="30" Width="Auto" Content="Add existing FFU-file..." Padding="20,5,20,5" HorizontalAlignment="Right" Margin="0,0,36,20" Command="{Binding Path=AddFFUCommand}"/>
</StackPanel>
</Border>
</StackPanel>
</UserControl>
+3604 -5
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,5 +1,5 @@
<!--
Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
+5 -4
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
@@ -20,9 +20,10 @@
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;
using WPinternals.HelperClasses;
using WPinternals.Config;
namespace WPinternals
{
@@ -76,14 +77,14 @@ namespace WPinternals
Registration.CheckExpiration();
string PatchDefintionsXml;
string PatchDefintionsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PatchDefintions.xml");
string PatchDefintionsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Assets", "PatchDefintions.xml");
if (File.Exists(PatchDefintionsPath))
{
PatchDefintionsXml = File.ReadAllText(PatchDefintionsPath);
}
else
{
using Stream stream = System.Reflection.Assembly.GetEntryAssembly().GetManifestResourceStream("WPinternals.PatchDefinitions.xml");
using Stream stream = System.Reflection.Assembly.GetEntryAssembly().GetManifestResourceStream("WPinternals.Assets.PatchDefinitions.xml");
using StreamReader sr = new(stream);
PatchDefintionsXml = sr.ReadToEnd();
}

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright(c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
Copyright(c) 2018, Rene Lergner - @Heathcliff74xda
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files(the "Software"),

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View File
View File
View File

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

+95 -729
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
@@ -26,6 +26,11 @@ using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using WPinternals.Config;
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia.NCSd;
using WPinternals.Models.UEFIApps.BootMgr;
using WPinternals.Models.UEFIApps.Flash;
namespace WPinternals
{
@@ -83,18 +88,16 @@ namespace WPinternals
{
FFU FFU = null;
PhoneNotifierViewModel Notifier;
NokiaFlashModel FlashModel;
NokiaPhoneModel NormalModel;
PhoneInfo Info;
LumiaFlashAppModel FlashModel;
LumiaBootManagerAppModel BootMgrModel;
NokiaCareSuiteModel NormalModel;
LumiaFlashAppPhoneInfo FlashInfo;
LumiaBootManagerPhoneInfo BootManagerInfo;
string ProductType;
string ProductCode;
string OperatorCode;
string DownloadFolder;
string FFUFilePath;
string URL;
string[] URLs;
Uri URI;
string FFUFileName;
string EmergencyFileName;
string EmergencyFilePath;
string ProgrammerPath = "";
@@ -114,7 +117,7 @@ namespace WPinternals
return;
}
switch (args[1].ToLower().TrimStart(new char[] { '-', '/' }))
switch (args[1].ToLower().TrimStart(['-', '/']))
{
#if DEBUG
case "test":
@@ -152,8 +155,12 @@ namespace WPinternals
? Convert.ToUInt64(args[2][2..], 16)
: Convert.ToUInt64(args[2], 10);
}
catch
catch (Exception ex)
{
LogFile.Log("An unexpected error happened", LogType.FileAndConsole);
LogFile.Log(ex.GetType().ToString(), LogType.FileAndConsole);
LogFile.Log(ex.Message, LogType.FileAndConsole);
LogFile.Log(ex.StackTrace, LogType.FileAndConsole);
LogFile.Log("Bad start sector", LogType.ConsoleOnly);
break;
}
@@ -181,24 +188,13 @@ namespace WPinternals
{
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader); // This also works for Bootloader Spec A
GPT GPT = FlashModel.ReadGPT(); // May throw NotSupportedException
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader);
GPT GPT = await LumiaUnlockBootloaderViewModel.ReadGPTFromFlashOrBootMgr(Notifier);
foreach (Partition Partition in GPT.Partitions)
{
LogFile.Log(Partition.Name.PadRight(20) + "0x" + Partition.FirstSector.ToString("X8") + " - 0x" + Partition.LastSector.ToString("X8") + " " + Partition.Volume, LogType.ConsoleOnly);
}
if (FlashModel.ReadPhoneInfo(false).FlashAppProtocolVersionMajor >= 2)
{
FlashModel.SwitchToFlashAppContext();
}
else
{
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
}
Notifier.Stop();
}
catch (Exception Ex)
@@ -221,11 +217,14 @@ namespace WPinternals
{
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
GPT GPT = FlashModel.ReadGPT(); // May throw NotSupportedException
Directory.CreateDirectory(Path.GetDirectoryName(args[2]));
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader);
GPT GPT = await LumiaUnlockBootloaderViewModel.ReadGPTFromFlashOrBootMgr(Notifier);
string DirPath = Path.GetDirectoryName(args[2]);
if (!string.IsNullOrEmpty(DirPath) && !Directory.Exists(DirPath))
{
Directory.CreateDirectory(DirPath);
}
GPT.WritePartitions(args[2]);
FlashModel.SwitchToFlashAppContext();
Notifier.Stop();
}
catch (Exception Ex)
@@ -237,6 +236,35 @@ namespace WPinternals
LogFile.EndAction("BackupGPT");
}
break;
case "convertgpt":
if (args.Length < 4)
{
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -ConvertGPT <Path to GPT-file> <Path to xml-file>");
}
LogFile.BeginAction("ConvertGPT");
try
{
using FileStream stream = File.OpenRead(args[2]);
byte[] GPTBuffer = new byte[34 * 0x200];
stream.Read(GPTBuffer, 0, 34 * 0x200);
GPT GPT = new(GPTBuffer);// May throw NotSupportedException
string DirPath = Path.GetDirectoryName(args[3]);
if (!string.IsNullOrEmpty(DirPath) && !Directory.Exists(DirPath))
{
Directory.CreateDirectory(DirPath);
}
GPT.WritePartitions(args[3]);
}
catch (Exception Ex)
{
LogFile.LogException(Ex);
}
finally
{
LogFile.EndAction("ConvertGPT");
}
break;
case "restoregpt":
if (args.Length < 3)
{
@@ -248,14 +276,12 @@ namespace WPinternals
{
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
byte[] GptChunk = LumiaUnlockBootloaderViewModel.GetGptChunk(FlashModel, 0x20000);
byte[] GptChunk = await LumiaUnlockBootloaderViewModel.GetGptChunkFromFlashOrBootMgr(Notifier, 0x20000);
GPT GPT = new(GptChunk);
string Xml = File.ReadAllText(args[2]);
GPT.MergePartitions(Xml, false);
GPT.Rebuild();
await LumiaV2UnlockBootViewModel.LumiaV2CustomFlash(Notifier, null, false, false, 0, GptChunk, true, true);
FlashModel.SwitchToFlashAppContext();
Notifier.Stop();
}
catch (Exception Ex)
@@ -285,7 +311,10 @@ namespace WPinternals
s = new FileStream(args[3], FileMode.Open, FileAccess.Read);
Archive = new ZipArchive(s);
}
catch { }
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
if (Archive == null)
{
@@ -393,7 +422,11 @@ namespace WPinternals
};
}
string EfiPath = Path.Combine(args[3], Name);
Directory.CreateDirectory(Path.GetDirectoryName(EfiPath));
string DirPath = Path.GetDirectoryName(EfiPath);
if (!string.IsNullOrEmpty(DirPath) && !Directory.Exists(DirPath))
{
Directory.CreateDirectory(DirPath);
}
File.WriteAllBytes(EfiPath, EfiBinary);
}
break;
@@ -512,9 +545,9 @@ namespace WPinternals
try
{
UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
Info = FlashModel.ReadPhoneInfo();
Info.Log(LogType.ConsoleOnly);
FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
FlashInfo = FlashModel.ReadPhoneInfo();
FlashInfo.Log(LogType.ConsoleOnly);
FFU ProfileFFU = null;
FFU CurrentFFU;
@@ -527,7 +560,7 @@ namespace WPinternals
string PlatformID = CurrentFFU.PlatformID;
// Check if the current FFU matches the connected phone, so that the FFU can be used for profiling.
if (Info.PlatformID.StartsWith(PlatformID, StringComparison.OrdinalIgnoreCase))
if (FlashInfo.PlatformID.StartsWith(PlatformID, StringComparison.OrdinalIgnoreCase))
{
ProfileFFU = CurrentFFU;
}
@@ -536,7 +569,7 @@ namespace WPinternals
if (ProfileFFU == null)
{
List<FFUEntry> FFUs = App.Config.FFURepository.Where(e => Info.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
List<FFUEntry> FFUs = App.Config.FFURepository.Where(e => FlashInfo.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
ProfileFFU = FFUs.Count > 0
? new FFU(FFUs[0].Path)
: throw new WPinternalsException("Profile FFU missing", "No profile FFU has been found in the repository for your device. You can add a profile FFU within the download section of the tool or by using the command line.");
@@ -661,9 +694,9 @@ namespace WPinternals
LogFile.Log("Command: Show phone info", LogType.FileAndConsole);
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
Info = FlashModel.ReadPhoneInfo();
Info.Log(LogType.ConsoleOnly);
FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
FlashInfo = FlashModel.ReadPhoneInfo();
FlashInfo.Log(LogType.ConsoleOnly);
Notifier.Stop();
break;
case "unlockbootloader":
@@ -673,9 +706,9 @@ namespace WPinternals
LogFile.Log("Command: Unlock Bootloader", LogType.FileAndConsole);
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
Info = FlashModel.ReadPhoneInfo();
Info.Log(LogType.ConsoleOnly);
FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
FlashInfo = FlashModel.ReadPhoneInfo();
FlashInfo.Log(LogType.ConsoleOnly);
FFU ProfileFFU = null;
FFU SupportedFFU = null;
@@ -689,7 +722,7 @@ namespace WPinternals
string PlatformID = CurrentFFU.PlatformID;
// Check if the current FFU matches the connected phone, so that the FFU can be used for profiling.
if (Info.PlatformID.StartsWith(PlatformID, StringComparison.OrdinalIgnoreCase))
if (FlashInfo.PlatformID.StartsWith(PlatformID, StringComparison.OrdinalIgnoreCase))
{
ProfileFFU = CurrentFFU;
}
@@ -704,7 +737,7 @@ namespace WPinternals
if (ProfileFFU == null)
{
List<FFUEntry> FFUs = App.Config.FFURepository.Where(e => Info.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
List<FFUEntry> FFUs = App.Config.FFURepository.Where(e => FlashInfo.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
ProfileFFU = FFUs.Count > 0
? new FFU(FFUs[0].Path)
: throw new WPinternalsException("Profile FFU missing", "No profile FFU has been found in the repository for your device. You can add a profile FFU within the download section of the tool or by using the command line.");
@@ -746,9 +779,9 @@ namespace WPinternals
LogFile.Log("Custom ROM: " + CustomRomPath, LogType.FileAndConsole);
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
Info = FlashModel.ReadPhoneInfo();
Info.Log(LogType.ConsoleOnly);
FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
FlashInfo = FlashModel.ReadPhoneInfo();
FlashInfo.Log(LogType.ConsoleOnly);
LogFile.Log("Preparing to flash Custom ROM", LogType.FileAndConsole);
await LumiaV2UnlockBootViewModel.LumiaV2FlashArchive(Notifier, CustomRomPath);
LogFile.Log("Custom ROM flashed successfully", LogType.FileAndConsole);
@@ -777,11 +810,11 @@ namespace WPinternals
LogFile.Log("FFU file: " + FFUPath, LogType.FileAndConsole);
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
Info = FlashModel.ReadPhoneInfo();
Info.Log(LogType.ConsoleOnly);
FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
FlashInfo = FlashModel.ReadPhoneInfo();
FlashInfo.Log(LogType.ConsoleOnly);
LogFile.Log("Flashing FFU...", LogType.FileAndConsole);
await Task.Run(() => FlashModel.FlashFFU(new FFU(FFUPath), true, (byte)(!Info.IsBootloaderSecure ? FlashOptions.SkipSignatureCheck : 0)));
await Task.Run(() => FlashModel.FlashFFU(new FFU(FFUPath), true, (byte)(!FlashInfo.IsBootloaderSecure ? FlashOptions.SkipSignatureCheck : 0)));
LogFile.Log("FFU flashed successfully", LogType.FileAndConsole);
Notifier.Stop();
}
@@ -1234,680 +1267,6 @@ namespace WPinternals
LogFile.Log("Root access enabled on image", LogType.FileAndConsole);
break;
case "downloadffu":
LogFile.Log("Command: Download FFU", LogType.FileAndConsole);
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
{
NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
}
else if ((Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) || (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash))
{
FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
Info = FlashModel.ReadPhoneInfo();
ProductCode = Info.ProductCode;
}
else
{
NormalModel = (NokiaPhoneModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
}
URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
DownloadFolder = args.Length >= 3
? args[4]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
Notifier.Stop();
break;
case "downloadffubyoperatorcode":
LogFile.Log("Command: Download FFU by Operator Code", LogType.FileAndConsole);
if (args.Length < 4)
{
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadFFUbyOperatorCode <Product type> <Operator code> <Optional: Download folder>");
}
ProductType = args[2];
LogFile.Log("Product type: " + ProductType, LogType.FileAndConsole);
OperatorCode = args[3];
LogFile.Log("Operator code: " + OperatorCode, LogType.FileAndConsole);
DownloadFolder = args.Length >= 5
? args[4]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
URL = LumiaDownloadModel.SearchFFU(ProductType, null, OperatorCode);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
break;
case "downloadffubyproductcode":
LogFile.Log("Command: Download FFU by Product Code", LogType.FileAndConsole);
if (args.Length < 3)
{
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadFFUbyProductCode <Product code> <Optional: Download folder>");
}
ProductCode = args[2];
LogFile.Log("Product code: " + ProductCode, LogType.FileAndConsole);
URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
DownloadFolder = args.Length >= 4
? args[3]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
break;
case "downloadffubyproducttype":
LogFile.Log("Command: Download FFU by Product Type", LogType.FileAndConsole);
if (args.Length < 3)
{
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadFFUbyProductType <Product type> <Optional: Download folder>");
}
ProductType = args[2];
LogFile.Log("Product type: " + ProductType, LogType.FileAndConsole);
DownloadFolder = args.Length >= 4
? args[3]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
break;
case "searchffubyproducttype":
LogFile.Log("Command: Search FFU by Product Type", LogType.FileAndConsole);
if (args.Length < 3)
{
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -SearchFFUbyProductType <Lumia model>");
}
ProductType = args[2];
LogFile.Log("Lumia model: " + ProductType, LogType.FileAndConsole);
URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
break;
case "downloademergency":
LogFile.Log("Command: Download Emergency files", LogType.FileAndConsole);
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
{
NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
ProductType = NormalModel.ExecuteJsonMethodAsString("ReadManufacturerModelName", "ManufacturerModelName");
if (ProductType.Contains('_'))
{
ProductType = ProductType.Substring(0, ProductType.IndexOf('_'));
}
}
else if ((Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) || (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash))
{
FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
Info = FlashModel.ReadPhoneInfo();
ProductType = Info.Type;
}
else
{
NormalModel = (NokiaPhoneModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
ProductType = NormalModel.ExecuteJsonMethodAsString("ReadManufacturerModelName", "ManufacturerModelName");
if (ProductType.Contains('_'))
{
ProductType = ProductType.Substring(0, ProductType.IndexOf('_'));
}
}
URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
if (URLs != null)
{
DownloadFolder = args.Length >= 3
? args[2]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
for (int i = 0; i < URLs.Length; i++)
{
LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
URI = new Uri(URLs[i]);
EmergencyFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
if (i == 0)
{
ProgrammerPath = EmergencyFilePath;
}
else
{
PayloadPath = EmergencyFilePath;
}
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
}
App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
}
Notifier.Stop();
break;
case "downloademergencybyproducttype":
LogFile.Log("Command: Download Emergency files", LogType.FileAndConsole);
if (args.Length < 3)
{
throw new WPinternalsException("Wrong number of arguments. Usage: WPinternals.exe -DownloadEmergencyByProductType <Product type> <Optional: Download folder>");
}
ProductType = args[2];
URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
if (URLs != null)
{
DownloadFolder = args.Length >= 4
? args[3]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
for (int i = 0; i < URLs.Length; i++)
{
LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
URI = new Uri(URLs[i]);
EmergencyFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
if (i == 0)
{
ProgrammerPath = EmergencyFilePath;
}
else
{
PayloadPath = EmergencyFilePath;
}
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
}
App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
}
break;
case "downloadall":
LogFile.Log("Command: Download all", LogType.FileAndConsole);
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
{
NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
}
else if ((Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) || (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash))
{
FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
Info = FlashModel.ReadPhoneInfo();
ProductCode = Info.ProductCode;
}
else
{
NormalModel = (NokiaPhoneModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
}
URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
DownloadFolder = args.Length >= 3
? args[2]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
if (URLs != null)
{
for (int i = 0; i < URLs.Length; i++)
{
LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
URI = new Uri(URLs[i]);
EmergencyFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
if (i == 0)
{
ProgrammerPath = EmergencyFilePath;
}
else
{
PayloadPath = EmergencyFilePath;
}
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
}
App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
}
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
{
ProductType = "RM-1085";
URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
DownloadFolder = args.Length >= 3
? args[2]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
{
throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
}
}
Notifier.Stop();
break;
case "downloadallbyproducttype":
LogFile.Log("Command: Download all by Product Type", LogType.FileAndConsole);
if (args.Length < 3)
{
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadAllByProductType <Product type> <Optional: Download folder>");
}
ProductType = args[2];
LogFile.Log("Product type: " + ProductType, LogType.FileAndConsole);
DownloadFolder = args.Length >= 4
? args[3]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
if (URLs != null)
{
for (int i = 0; i < URLs.Length; i++)
{
LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
URI = new Uri(URLs[i]);
EmergencyFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
if (i == 0)
{
ProgrammerPath = EmergencyFilePath;
}
else
{
PayloadPath = EmergencyFilePath;
}
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
}
App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
}
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
{
ProductType = "RM-1085";
URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
DownloadFolder = args.Length >= 4
? args[3]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
{
throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
}
}
break;
case "downloadallbyproductcode":
LogFile.Log("Command: Download all by Product Code", LogType.FileAndConsole);
if (args.Length < 3)
{
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadAllByProductCode <Product code> <Optional: Download folder>");
}
ProductCode = args[2];
LogFile.Log("Product code: " + ProductCode, LogType.FileAndConsole);
URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
DownloadFolder = args.Length >= 4
? args[3]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
if (URLs != null)
{
for (int i = 0; i < URLs.Length; i++)
{
LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
URI = new Uri(URLs[i]);
EmergencyFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
if (i == 0)
{
ProgrammerPath = EmergencyFilePath;
}
else
{
PayloadPath = EmergencyFilePath;
}
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
}
App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
}
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
{
ProductType = "RM-1085";
URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
DownloadFolder = args.Length >= 4
? args[3]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
{
throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
}
}
break;
case "downloadallbyoperatorcode":
LogFile.Log("Command: Download FFU by Operator Code", LogType.FileAndConsole);
if (args.Length < 4)
{
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadFFUbyOperatorCode <Product type> <Operator code> <Optional: Download folder>");
}
ProductType = args[2];
LogFile.Log("Product type: " + ProductType, LogType.FileAndConsole);
OperatorCode = args[3];
LogFile.Log("Operator code: " + OperatorCode, LogType.FileAndConsole);
DownloadFolder = args.Length >= 5
? args[4]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
URL = LumiaDownloadModel.SearchFFU(ProductType, null, OperatorCode);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
if (URLs != null)
{
for (int i = 0; i < URLs.Length; i++)
{
LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
URI = new Uri(URLs[i]);
EmergencyFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
if (i == 0)
{
ProgrammerPath = EmergencyFilePath;
}
else
{
PayloadPath = EmergencyFilePath;
}
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
}
App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
}
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
{
ProductType = "RM-1085";
URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
DownloadFolder = args.Length >= 5
? args[4]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
if (!Directory.Exists(DownloadFolder))
{
Directory.CreateDirectory(DownloadFolder);
}
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
URI = new Uri(URL);
FFUFileName = Path.GetFileName(URI.LocalPath);
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
LogFile.Log("Downloading...", LogType.FileAndConsole);
using (System.Net.WebClient myWebClient = new())
{
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
}
LogFile.Log("Download finished", LogType.FileAndConsole);
App.Config.AddFfuToRepository(FFUFilePath);
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
{
throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
}
}
break;
case "rewritepartitionsfrommassstorage":
if (args.Length < 2)
{
@@ -1968,6 +1327,7 @@ namespace WPinternals
LogFile.Log("WPinternals -ClearNV", LogType.ConsoleOnly);
LogFile.Log("WPinternals -ReadGPT", LogType.ConsoleOnly);
LogFile.Log("WPinternals -BackupGPT <Path to xml-file>", LogType.ConsoleOnly);
LogFile.Log("WPinternals -ConvertGPT <Path to GPT-file> <Path to xml-file>", LogType.ConsoleOnly);
LogFile.Log("WPinternals -RestoreGPT <Path to xml-file>", LogType.ConsoleOnly);
LogFile.Log("WPinternals -MergeGPT <Path to input-xml-file> <Path to input-xml-file>", LogType.ConsoleOnly);
LogFile.Log(" <Optional: Path to output-xml-file>", LogType.ConsoleOnly);
@@ -2055,12 +1415,18 @@ namespace WPinternals
Microsoft.Win32.SafeHandles.SafeFileHandle safeFileHandle = new(stdHandle, true);
FileStream fileStream = new(safeFileHandle, FileAccess.Write);
Encoding encoding = Encoding.GetEncoding(MY_CODE_PAGE);
StreamWriter standardOutput = new(fileStream, encoding);
standardOutput.AutoFlush = true;
StreamWriter standardOutput = new(fileStream, encoding)
{
AutoFlush = true
};
Console.SetOut(standardOutput);
}
catch
catch (Exception ex)
{
LogFile.Log("An unexpected error happened", LogType.FileAndConsole);
LogFile.Log(ex.GetType().ToString(), LogType.FileAndConsole);
LogFile.Log(ex.Message, LogType.FileAndConsole);
LogFile.Log(ex.StackTrace, LogType.FileAndConsole);
}
}
+59
View File
@@ -0,0 +1,59 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.IO;
using System.Xml.Serialization;
using WPinternals.HelperClasses;
namespace WPinternals.Config
{
public class EmergencyFileEntry
{
public string Type;
[XmlIgnore]
public byte[] RKH;
[XmlElement(ElementName = "RKH")]
public string RKHAsString
{
get
{
return RKH == null ? null : Converter.ConvertHexToString(RKH, "");
}
set
{
RKH = value == null ? null : Converter.ConvertStringToHex(value);
}
}
public string ProgrammerPath;
public string PayloadPath;
internal bool ProgrammerExists()
{
return File.Exists(ProgrammerPath);
}
internal bool PayloadExists()
{
return File.Exists(PayloadPath);
}
}
}
+37
View File
@@ -0,0 +1,37 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.IO;
namespace WPinternals.Config
{
public class FFUEntry
{
public string PlatformID;
public string FirmwareVersion;
public string OSVersion;
public string Path;
internal bool Exists()
{
return File.Exists(Path);
}
}
}
+75
View File
@@ -0,0 +1,75 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Xml.Serialization;
namespace WPinternals.Config
{
public class FlashProfile
{
public string Type;
public string PlatformID;
public string ProductCode;
public string PhoneFirmware;
public string FfuFirmware;
[XmlIgnore]
internal uint FillSize;
[XmlIgnore]
internal uint HeaderSize;
[XmlIgnore]
internal bool AssumeImageHeaderFallsInGap;
[XmlIgnore]
internal bool AllocateAsyncBuffersOnPhone;
[XmlElement(ElementName = "Profile")]
public string ProfileAsString
{
get
{
byte[] ValueBuffer = new byte[10];
ValueBuffer[0] = 1; // Profile version
ByteOperations.WriteUInt32(ValueBuffer, 1, FillSize);
ByteOperations.WriteUInt32(ValueBuffer, 5, HeaderSize);
if (AssumeImageHeaderFallsInGap)
{
ValueBuffer[9] |= 1;
}
if (AllocateAsyncBuffersOnPhone)
{
ValueBuffer[9] |= 2;
}
return Convert.ToBase64String(ValueBuffer);
}
set
{
byte[] ValueBuffer = Convert.FromBase64String(value);
byte Version = ValueBuffer[0];
FillSize = ByteOperations.ReadUInt32(ValueBuffer, 1);
HeaderSize = ByteOperations.ReadUInt32(ValueBuffer, 5);
AssumeImageHeaderFallsInGap = (ValueBuffer[9] & 1) != 0;
AllocateAsyncBuffersOnPhone = (ValueBuffer[9] & 2) != 0;
}
}
}
}
+84
View File
@@ -0,0 +1,84 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Windows;
namespace WPinternals.Config
{
internal static class Registration
{
#if PREVIEW
internal const bool IsPrerelease = true;
#else
internal const bool IsPrerelease = false;
#endif
internal static readonly DateTime ExpirationDate = new(2027, 4, 1);
internal static void CheckExpiration()
{
#if PREVIEW
//if (IsPrerelease && (DateTime.Now >= ExpirationDate))
if (DateTime.Now >= ExpirationDate)
{
if (Environment.GetCommandLineArgs().Count() > 1)
{
Console.WriteLine("This prerelease version is expired!");
CommandLine.CloseConsole();
}
else
MessageBox.Show("This prerelease version is expired!", "Windows Phone Internals", MessageBoxButton.OK, MessageBoxImage.Exclamation);
Environment.Exit(0);
}
#endif
}
internal static bool IsRegistered()
{
bool Result = false;
if (App.Config.RegistrationName != null)
{
Result = CalcRegKey() == App.Config.RegistrationKey;
}
return Result;
}
internal static string CalcRegKey()
{
string KeyBase = App.Config.RegistrationName;
if (Environment.MachineName == null)
{
KeyBase += "-Unknown";
}
else
{
KeyBase += "-" + Environment.MachineName;
}
byte[] KeyBytes = System.Text.Encoding.UTF8.GetBytes(KeyBase);
SHA1Managed sha = new();
byte[] Key = sha.ComputeHash(KeyBytes);
return Convert.ToBase64String(Key);
}
}
}
+35
View File
@@ -0,0 +1,35 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.IO;
namespace WPinternals.Config
{
public class SecWimEntry
{
public string FirmwareVersion;
public string Path;
internal bool Exists()
{
return File.Exists(Path);
}
}
}
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
@@ -22,67 +22,11 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Xml.Serialization;
using WPinternals.HelperClasses;
namespace WPinternals
namespace WPinternals.Config
{
internal static class Registration
{
#if PREVIEW
internal const bool IsPrerelease = true;
#else
internal const bool IsPrerelease = false;
#endif
internal static readonly DateTime ExpirationDate = new(2019, 01, 06);
internal static void CheckExpiration()
{
#if PREVIEW
//if (IsPrerelease && (DateTime.Now >= ExpirationDate))
if (DateTime.Now >= ExpirationDate)
{
if (Environment.GetCommandLineArgs().Count() > 1)
{
Console.WriteLine("This prerelease version is expired!");
CommandLine.CloseConsole();
}
else
MessageBox.Show("This prerelease version is expired!", "Windows Phone Internals", MessageBoxButton.OK, MessageBoxImage.Exclamation);
Environment.Exit(0);
}
#endif
}
internal static bool IsRegistered()
{
bool Result = false;
if (App.Config.RegistrationName != null)
{
Result = CalcRegKey() == App.Config.RegistrationKey;
}
return Result;
}
internal static string CalcRegKey()
{
string KeyBase = App.Config.RegistrationName;
if (Environment.MachineName == null)
{
KeyBase += "-Unknown";
}
else
{
KeyBase += "-" + Environment.MachineName;
}
byte[] KeyBytes = System.Text.Encoding.UTF8.GetBytes(KeyBase);
SHA1Managed sha = new();
byte[] Key = sha.ComputeHash(KeyBytes);
return Convert.ToBase64String(Key);
}
}
public class WPinternalsConfig
{
@@ -121,7 +65,7 @@ namespace WPinternals
FileWriter.Close();
}
internal void SetProfile(string Type, string PlatformID, string ProductCode, string PhoneFirmware, string FfuFirmware, UInt32 FillSize, UInt32 HeaderSize, bool AssumeImageHeaderFallsInGap, bool AllocateAsyncBuffersOnPhone)
internal void SetProfile(string Type, string PlatformID, string ProductCode, string PhoneFirmware, string FfuFirmware, uint FillSize, uint HeaderSize, bool AssumeImageHeaderFallsInGap, bool AllocateAsyncBuffersOnPhone)
{
FlashProfile Profile = GetProfile(PlatformID, PhoneFirmware, FfuFirmware);
if (Profile == null)
@@ -147,10 +91,10 @@ namespace WPinternals
internal FlashProfile GetProfile(string PlatformID, string PhoneFirmware, string FfuFirmware = null)
{
return FlashProfiles.Find(p => string.Equals(p.PlatformID, PlatformID, StringComparison.CurrentCultureIgnoreCase) && string.Equals(p.PhoneFirmware, PhoneFirmware, StringComparison.CurrentCultureIgnoreCase) && ((FfuFirmware == null) || string.Equals(p.FfuFirmware, FfuFirmware, StringComparison.CurrentCultureIgnoreCase)));
return FlashProfiles.Find(p => string.Equals(p.PlatformID, PlatformID, StringComparison.CurrentCultureIgnoreCase) && string.Equals(p.PhoneFirmware, PhoneFirmware, StringComparison.CurrentCultureIgnoreCase) && (FfuFirmware == null || string.Equals(p.FfuFirmware, FfuFirmware, StringComparison.CurrentCultureIgnoreCase)));
}
public List<FlashProfile> FlashProfiles = new();
public List<FlashProfile> FlashProfiles = [];
internal void AddFfuToRepository(string FFUPath)
{
@@ -167,7 +111,7 @@ namespace WPinternals
internal void AddFfuToRepository(string FFUPath, string PlatformID, string FirmwareVersion, string OSVersion)
{
FFUEntry Entry = FFURepository.Find(e => (e.PlatformID == PlatformID) && (e.FirmwareVersion == FirmwareVersion) && string.Equals(e.Path, FFUPath, StringComparison.CurrentCultureIgnoreCase));
FFUEntry Entry = FFURepository.Find(e => e.PlatformID == PlatformID && e.FirmwareVersion == FirmwareVersion && string.Equals(e.Path, FFUPath, StringComparison.CurrentCultureIgnoreCase));
if (Entry == null)
{
LogFile.Log("Adding FFU to repository: " + FFUPath, LogType.FileAndConsole);
@@ -217,14 +161,60 @@ namespace WPinternals
}
}
public List<FFUEntry> FFURepository = new();
public List<FFUEntry> FFURepository = [];
public List<EmergencyFileEntry> EmergencyRepository = new();
internal void AddSecWimToRepository(string SecWimPath, string FirmwareVersion)
{
SecWimEntry Entry = SecWimRepository.Find(e => e.FirmwareVersion == FirmwareVersion && string.Equals(e.Path, SecWimPath, StringComparison.CurrentCultureIgnoreCase));
if (Entry == null)
{
LogFile.Log("Adding Secure WIM to repository: " + SecWimPath, LogType.FileAndConsole);
if (FirmwareVersion != null)
{
LogFile.Log("Firmware version: " + FirmwareVersion, LogType.FileAndConsole);
}
Entry = new SecWimEntry
{
Path = SecWimPath,
FirmwareVersion = FirmwareVersion
};
SecWimRepository.Add(Entry);
WriteConfig();
}
else
{
LogFile.Log("Secure WIM not added, because it was already present in the repository.", LogType.FileAndConsole);
}
}
internal void RemoveSecWimFromRepository(string SecWimPath)
{
int Count = 0;
SecWimRepository.Where(e => string.Equals(e.Path, SecWimPath, StringComparison.CurrentCultureIgnoreCase)).ToList().ForEach(e =>
{
Count++;
SecWimRepository.Remove(e);
});
if (Count == 0)
{
LogFile.Log("Secure WIM was not removed from repository because it was not present.", LogType.FileAndConsole);
}
else
{
LogFile.Log("Removed Secure WIM from repository: " + SecWimPath, LogType.FileAndConsole);
WriteConfig();
}
}
public List<SecWimEntry> SecWimRepository = [];
public List<EmergencyFileEntry> EmergencyRepository = [];
internal void AddEmergencyToRepository(string Type, string ProgrammerPath, string PayloadPath)
{
EmergencyFileEntry Entry = EmergencyRepository.Find(e => (e.Type == Type) && string.Equals(e.ProgrammerPath, ProgrammerPath, StringComparison.CurrentCultureIgnoreCase));
if ((Entry != null) && (PayloadPath != null) && (!string.Equals(Entry.PayloadPath, PayloadPath, StringComparison.CurrentCultureIgnoreCase)))
EmergencyFileEntry Entry = EmergencyRepository.Find(e => e.Type == Type && string.Equals(e.ProgrammerPath, ProgrammerPath, StringComparison.CurrentCultureIgnoreCase));
if (Entry != null && PayloadPath != null && !string.Equals(Entry.PayloadPath, PayloadPath, StringComparison.CurrentCultureIgnoreCase))
{
LogFile.Log("Updating emergency payload path in repository: " + PayloadPath, LogType.FileAndConsole);
Entry.PayloadPath = PayloadPath;
@@ -279,100 +269,4 @@ namespace WPinternals
public string RegistrationTelegramID;
public string RegistrationKey;
}
public class FlashProfile
{
public string Type;
public string PlatformID;
public string ProductCode;
public string PhoneFirmware;
public string FfuFirmware;
[XmlIgnore]
internal UInt32 FillSize;
[XmlIgnore]
internal UInt32 HeaderSize;
[XmlIgnore]
internal bool AssumeImageHeaderFallsInGap;
[XmlIgnore]
internal bool AllocateAsyncBuffersOnPhone;
[XmlElement(ElementName = "Profile")]
public string ProfileAsString
{
get
{
byte[] ValueBuffer = new byte[10];
ValueBuffer[0] = 1; // Profile version
ByteOperations.WriteUInt32(ValueBuffer, 1, FillSize);
ByteOperations.WriteUInt32(ValueBuffer, 5, HeaderSize);
if (AssumeImageHeaderFallsInGap)
{
ValueBuffer[9] |= 1;
}
if (AllocateAsyncBuffersOnPhone)
{
ValueBuffer[9] |= 2;
}
return Convert.ToBase64String(ValueBuffer);
}
set
{
byte[] ValueBuffer = Convert.FromBase64String(value);
byte Version = ValueBuffer[0];
FillSize = ByteOperations.ReadUInt32(ValueBuffer, 1);
HeaderSize = ByteOperations.ReadUInt32(ValueBuffer, 5);
AssumeImageHeaderFallsInGap = (ValueBuffer[9] & 1) != 0;
AllocateAsyncBuffersOnPhone = (ValueBuffer[9] & 2) != 0;
}
}
}
public class FFUEntry
{
public string PlatformID;
public string FirmwareVersion;
public string OSVersion;
public string Path;
internal bool Exists()
{
return File.Exists(Path);
}
}
public class EmergencyFileEntry
{
public string Type;
[XmlIgnore]
public byte[] RKH;
[XmlElement(ElementName = "RKH")]
public string RKHAsString
{
get
{
return RKH == null ? null : Converter.ConvertHexToString(RKH, "");
}
set
{
RKH = value == null ? null : Converter.ConvertStringToHex(value);
}
}
public string ProgrammerPath;
public string PayloadPath;
internal bool ProgrammerExists()
{
return File.Exists(ProgrammerPath);
}
internal bool PayloadExists()
{
return File.Exists(PayloadPath);
}
}
}
@@ -1,5 +1,5 @@
<!--
Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -1,4 +1,4 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
@@ -24,6 +24,7 @@ using System.Globalization;
using System.Threading;
using System.Windows;
using System.Windows.Media;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -149,7 +150,7 @@ namespace WPinternals
protected override Size MeasureOverride(Size availableSize)
{
var resultSize = new Size(availableSize.Width, 0);
Size resultSize = new Size(availableSize.Width, 0);
#if NETCORE
FormattedText formatted = new FormattedText(
@@ -316,13 +317,19 @@ namespace WPinternals
{
filename = System.IO.Path.GetFileName(Text);
}
catch { }
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
string directory = "";
try
{
directory = System.IO.Path.GetDirectoryName(Text);
}
catch { }
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
FormattedText formatted;
bool widthOK = false;
bool changedWidth = false;
@@ -423,9 +430,10 @@ namespace WPinternals
if (SaveDialog)
{
Microsoft.Win32.SaveFileDialog savedlg = new();
savedlg.FileName = Path ?? DefaultFileName;
Microsoft.Win32.SaveFileDialog savedlg = new()
{
FileName = Path ?? DefaultFileName
};
// Show open file dialog box
result = savedlg.ShowDialog();
@@ -440,9 +448,10 @@ namespace WPinternals
else
{
// Select file
Microsoft.Win32.OpenFileDialog dlg = new();
dlg.FileName = Path ?? DefaultFileName;
Microsoft.Win32.OpenFileDialog dlg = new()
{
FileName = Path ?? DefaultFileName
};
// Show open file dialog box
result = dlg.ShowDialog();
+120
View File
@@ -0,0 +1,120 @@
// This class was found online.
// Original author is probably: Swizzy
// https://github.com/ttgxdinger/Random/blob/master/CPUKey%20Checker/CPUKey%20Checker/FolderSelectDialog.cs
using System;
using System.Windows.Forms;
namespace WPinternals
{
/// <summary>
/// Wraps System.Windows.Forms.OpenFileDialog to make it present
/// a vista-style dialog.
/// </summary>
public class FolderSelectDialog
{
// Wrapped dialog
private readonly OpenFileDialog ofd = null;
/// <summary>
/// Default constructor
/// </summary>
public FolderSelectDialog()
{
ofd = new OpenFileDialog
{
Filter = "Folders|\n",
AddExtension = false,
CheckFileExists = false,
DereferenceLinks = true,
Multiselect = false
};
}
#region Properties
/// <summary>
/// Gets/Sets the initial folder to be selected. A null value selects the current directory.
/// </summary>
public string InitialDirectory
{
get { return ofd.InitialDirectory; }
set { ofd.InitialDirectory = string.IsNullOrEmpty(value) ? Environment.CurrentDirectory : value; }
}
/// <summary>
/// Gets/Sets the title to show in the dialog
/// </summary>
public string Title
{
get { return ofd.Title; }
set { ofd.Title = value ?? "Select a folder"; }
}
/// <summary>
/// Gets the selected folder
/// </summary>
public string FileName
{
get { return ofd.FileName; }
}
#endregion
#region Methods
/// <summary>
/// Shows the dialog
/// </summary>
/// <returns>True if the user presses OK else false</returns>
public bool ShowDialog()
{
return ShowDialog(IntPtr.Zero);
}
/// <summary>
/// Shows the dialog
/// </summary>
/// <param name="hWndOwner">Handle of the control to be parent</param>
/// <returns>True if the user presses OK else false</returns>
public bool ShowDialog(IntPtr hWndOwner)
{
FolderBrowserDialog fbd = new FolderBrowserDialog
{
Description = this.Title,
SelectedPath = this.InitialDirectory,
ShowNewFolderButton = false
};
if (fbd.ShowDialog(new WindowWrapper(hWndOwner)) != DialogResult.OK)
{
return false;
}
ofd.FileName = fbd.SelectedPath;
return true;
}
#endregion
}
/// <summary>
/// Creates IWin32Window around an IntPtr
/// </summary>
public class WindowWrapper : IWin32Window
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="handle">Handle to wrap</param>
public WindowWrapper(IntPtr handle)
{
Handle = handle;
}
/// <summary>
/// Original ptr
/// </summary>
public IntPtr Handle { get; }
}
}
@@ -0,0 +1,40 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
namespace WPinternals.HelperClasses
{
internal class ArrivalEventArgs : EventArgs
{
public PhoneInterfaces NewInterface;
public IDisposable NewModel;
public ArrivalEventArgs(PhoneInterfaces NewInterface, IDisposable NewModel)
: base()
{
this.NewInterface = NewInterface;
this.NewModel = NewModel;
}
}
}

Some files were not shown because too many files have changed in this diff Show More