Author SHA1 Message Date
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
229 changed files with 19977 additions and 6357 deletions
+2 -2
View File
@@ -15,7 +15,7 @@ jobs:
platform: [win]
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Install .NET SDK
uses: actions/setup-dotnet@v1
@@ -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 }}
+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
+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)
{
var 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; }
}
}
+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;
}
}
}
}
@@ -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>
+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>
+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 -1
View File
@@ -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
{
+96 -511
View File
@@ -26,6 +26,12 @@ using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using WPinternals.Config;
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia.MSR;
using WPinternals.Models.Lumia.NCSd;
using WPinternals.Models.UEFIApps.BootMgr;
using WPinternals.Models.UEFIApps.Flash;
namespace WPinternals
{
@@ -83,18 +89,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 = "";
@@ -152,8 +156,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 +189,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,15 +218,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
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)
@@ -250,7 +246,7 @@ namespace WPinternals
LogFile.BeginAction("ConvertGPT");
try
{
using var stream = File.OpenRead(args[2]);
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
@@ -281,14 +277,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)
@@ -318,7 +312,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)
{
@@ -549,9 +546,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;
@@ -564,7 +561,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;
}
@@ -573,7 +570,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.");
@@ -698,9 +695,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":
@@ -710,9 +707,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;
@@ -726,7 +723,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;
}
@@ -741,7 +738,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.");
@@ -783,9 +780,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);
@@ -814,11 +811,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();
}
@@ -1271,189 +1268,36 @@ 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;
NormalModel = (NokiaCareSuiteModel)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))
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
{
FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
Info = FlashModel.ReadPhoneInfo();
ProductType = Info.Type;
BootMgrModel = (LumiaBootManagerAppModel)Notifier.CurrentModel;
BootManagerInfo = BootMgrModel.ReadPhoneInfo();
//ProductType = BootManagerInfo.Type; // TODO: FIXME
ProductType = "";
}
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash)
{
FlashModel = (LumiaFlashAppModel)Notifier.CurrentModel;
FlashInfo = FlashModel.ReadPhoneInfo();
//ProductType = FlashInfo.Type; // TODO: FIXME
ProductType = "";
}
else
{
NormalModel = (NokiaPhoneModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
NormalModel = (NokiaCareSuiteModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
ProductType = NormalModel.ExecuteJsonMethodAsString("ReadManufacturerModelName", "ManufacturerModelName");
if (ProductType.Contains('_'))
{
@@ -1553,21 +1397,37 @@ namespace WPinternals
UIContext.Send(s => Notifier.Start(), null);
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
{
NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
NormalModel = (NokiaCareSuiteModel)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))
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
{
FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
Info = FlashModel.ReadPhoneInfo();
ProductCode = Info.ProductCode;
BootMgrModel = (LumiaBootManagerAppModel)Notifier.CurrentModel;
BootManagerInfo = BootMgrModel.ReadPhoneInfo();
//ProductType = BootManagerInfo.Type; // TODO: FIXME
ProductType = "";
}
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash)
{
FlashModel = (LumiaFlashAppModel)Notifier.CurrentModel;
FlashInfo = FlashModel.ReadPhoneInfo();
//ProductType = FlashInfo.Type; // TODO: FIXME
ProductType = "";
}
else
{
NormalModel = (NokiaPhoneModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
NormalModel = (NokiaCareSuiteModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
ProductType = NormalModel.ExecuteJsonMethodAsString("ReadManufacturerModelName", "ManufacturerModelName");
if (ProductType.Contains('_'))
{
ProductType = ProductType.Substring(0, ProductType.IndexOf('_'));
}
}
URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
DownloadFolder = args.Length >= 3
? args[2]
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
@@ -1577,20 +1437,6 @@ namespace WPinternals
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)
{
@@ -1622,36 +1468,7 @@ namespace WPinternals
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.");
}
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;
@@ -1673,21 +1490,6 @@ namespace WPinternals
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)
{
@@ -1719,230 +1521,7 @@ namespace WPinternals
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.");
}
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":
@@ -2093,12 +1672,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(2025, 06, 21);
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);
}
}
}
@@ -22,68 +22,11 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Windows;
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(2023, 12, 21);
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
{
@@ -122,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)
@@ -148,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)
{
@@ -168,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);
@@ -218,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;
@@ -280,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);
}
}
}
@@ -61,7 +61,7 @@ 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)
{
@@ -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)
{
@@ -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)
{
@@ -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)
{
@@ -1273,7 +1273,7 @@ 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];
}
@@ -1309,7 +1309,7 @@ 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];
}
+18 -9
View File
@@ -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();
+1 -1
View File
@@ -79,7 +79,7 @@ namespace WPinternals
/// <returns>True if the user presses OK else false</returns>
public bool ShowDialog(IntPtr hWndOwner)
{
var fbd = new FolderBrowserDialog
FolderBrowserDialog fbd = new FolderBrowserDialog
{
Description = this.Title,
SelectedPath = this.InitialDirectory,
File diff suppressed because it is too large Load Diff
@@ -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;
}
}
}
@@ -0,0 +1,111 @@
// 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;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace WPinternals.HelperClasses
{
internal class AsyncAutoResetEvent
{
private readonly LinkedList<TaskCompletionSource<bool>> waiters =
new();
private bool isSignaled;
public AsyncAutoResetEvent(bool signaled)
{
isSignaled = signaled;
}
public Task<bool> WaitAsync(TimeSpan timeout)
{
return WaitAsync(timeout, CancellationToken.None);
}
public async Task<bool> WaitAsync(TimeSpan timeout, CancellationToken cancellationToken)
{
TaskCompletionSource<bool> tcs;
lock (waiters)
{
if (isSignaled)
{
isSignaled = false;
return true;
}
else if (timeout == TimeSpan.Zero)
{
return isSignaled;
}
else
{
tcs = new TaskCompletionSource<bool>();
waiters.AddLast(tcs);
}
}
Task winner = await Task.WhenAny(tcs.Task, Task.Delay(timeout, cancellationToken));
if (winner == tcs.Task)
{
// The task was signaled.
return true;
}
else
{
// We timed-out; remove our reference to the task.
// This is an O(n) operation since waiters is a LinkedList<T>.
lock (waiters)
{
bool removed = waiters.Remove(tcs);
System.Diagnostics.Debug.Assert(removed);
return false;
}
}
}
public void Set()
{
TaskCompletionSource<bool> toRelease = null;
lock (waiters)
{
if (waiters.Count > 0)
{
// Signal the first task in the waiters list.
toRelease = waiters.First.Value;
waiters.RemoveFirst();
}
else if (!isSignaled)
{
// No tasks are pending
isSignaled = true;
}
}
toRelease?.SetResult(true);
}
}
}
+162
View File
@@ -0,0 +1,162 @@
// 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;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace WPinternals.HelperClasses
{
// This class was found online.
// Original author is probably: John Melville
// https://social.msdn.microsoft.com/Forums/en-US/163ef755-ff7b-4ea5-b226-bbe8ef5f4796/is-there-a-pattern-for-calling-an-async-method-synchronously?forum=async
public static class AsyncHelpers
{
/// <summary>
/// Execute's an async Task<T> method which has a void return value synchronously
/// </summary>
/// <param name="task">Task<T> method to execute</param>
public static void RunSync(Func<Task> task)
{
SynchronizationContext oldContext = SynchronizationContext.Current;
ExclusiveSynchronizationContext synch = new ExclusiveSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(synch);
synch.Post(async _ =>
{
try
{
await task();
}
catch (Exception e)
{
synch.InnerException = e;
throw;
}
finally
{
synch.EndMessageLoop();
}
}, null);
synch.BeginMessageLoop();
SynchronizationContext.SetSynchronizationContext(oldContext);
}
/// <summary>
/// Execute's an async Task<T> method which has a T return type synchronously
/// </summary>
/// <typeparam name="T">Return Type</typeparam>
/// <param name="task">Task<T> method to execute</param>
/// <returns></returns>
public static T RunSync<T>(Func<Task<T>> task)
{
SynchronizationContext oldContext = SynchronizationContext.Current;
ExclusiveSynchronizationContext synch = new ExclusiveSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(synch);
T ret = default;
synch.Post(async _ =>
{
try
{
ret = await task();
}
catch (Exception e)
{
synch.InnerException = e;
throw;
}
finally
{
synch.EndMessageLoop();
}
}, null);
synch.BeginMessageLoop();
SynchronizationContext.SetSynchronizationContext(oldContext);
return ret;
}
private class ExclusiveSynchronizationContext : SynchronizationContext
{
private bool done;
public Exception InnerException
{
get; set;
}
private readonly AutoResetEvent workItemsWaiting = new(false);
private readonly Queue<Tuple<SendOrPostCallback, object>> items =
new();
public override void Send(SendOrPostCallback d, object state)
{
throw new NotSupportedException("We cannot send to our same thread");
}
public override void Post(SendOrPostCallback d, object state)
{
lock (items)
{
items.Enqueue(Tuple.Create(d, state));
}
workItemsWaiting.Set();
}
public void EndMessageLoop()
{
Post(_ => done = true, null);
}
public void BeginMessageLoop()
{
while (!done)
{
Tuple<SendOrPostCallback, object> task = null;
lock (items)
{
if (items.Count > 0)
{
task = items.Dequeue();
}
}
if (task != null)
{
task.Item1(task.Item2);
if (InnerException != null) // the method threw an exeption
{
throw new AggregateException("AsyncHelpers.Run method threw an exception.", InnerException);
}
}
else
{
workItemsWaiting.WaitOne();
}
}
}
public override SynchronizationContext CreateCopy()
{
return this;
}
}
}
}
+125
View File
@@ -0,0 +1,125 @@
// 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 static class BigEndian
{
public static byte[] GetBytes(object Value)
{
byte[] Bytes;
if (Value is short)
{
Bytes = BitConverter.GetBytes((short)Value);
}
else if (Value is ushort)
{
Bytes = BitConverter.GetBytes((ushort)Value);
}
else if (Value is int)
{
Bytes = BitConverter.GetBytes((int)Value);
}
else
{
Bytes = Value is uint ? BitConverter.GetBytes((uint)Value) : throw new NotSupportedException();
}
byte[] Result = new byte[Bytes.Length];
for (int i = 0; i < Bytes.Length; i++)
{
Result[i] = Bytes[Bytes.Length - 1 - i];
}
return Result;
}
public static byte[] GetBytes(object Value, int Width)
{
byte[] Result;
byte[] BigEndianBytes = GetBytes(Value);
if (BigEndianBytes.Length == Width)
{
return BigEndianBytes;
}
else if (BigEndianBytes.Length > Width)
{
Result = new byte[Width];
Buffer.BlockCopy(BigEndianBytes, BigEndianBytes.Length - Width, Result, 0, Width);
return Result;
}
else
{
Result = new byte[Width];
Buffer.BlockCopy(BigEndianBytes, 0, Result, Width - BigEndianBytes.Length, BigEndianBytes.Length);
return Result;
}
}
public static ushort ToUInt16(byte[] Buffer, int Offset)
{
byte[] Bytes = new byte[2];
for (int i = 0; i < 2; i++)
{
Bytes[i] = Buffer[Offset + 1 - i];
}
return BitConverter.ToUInt16(Bytes, 0);
}
public static short ToInt16(byte[] Buffer, int Offset)
{
byte[] Bytes = new byte[2];
for (int i = 0; i < 2; i++)
{
Bytes[i] = Buffer[Offset + 1 - i];
}
return BitConverter.ToInt16(Bytes, 0);
}
public static uint ToUInt32(byte[] Buffer, int Offset)
{
byte[] Bytes = new byte[4];
for (int i = 0; i < 4; i++)
{
Bytes[i] = Buffer[Offset + 3 - i];
}
return BitConverter.ToUInt32(Bytes, 0);
}
public static int ToInt32(byte[] Buffer, int Offset)
{
byte[] Bytes = new byte[4];
for (int i = 0; i < 4; i++)
{
Bytes[i] = Buffer[Offset + 3 - i];
}
return BitConverter.ToInt32(Bytes, 0);
}
}
}
@@ -0,0 +1,138 @@
// 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;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace WPinternals.HelperClasses
{
public class BooleanConverter : DependencyObject, IValueConverter
{
public static readonly DependencyProperty OnTrueProperty =
DependencyProperty.Register("OnTrue", typeof(object), typeof(BooleanConverter),
new PropertyMetadata(default(object)));
public static readonly DependencyProperty OnFalseProperty =
DependencyProperty.Register("OnFalse", typeof(object), typeof(BooleanConverter),
new PropertyMetadata(default(object)));
public static readonly DependencyProperty OnNullProperty =
DependencyProperty.Register("OnNull", typeof(object), typeof(BooleanConverter),
new PropertyMetadata(default(object)));
public object OnTrue
{
get
{
return GetValue(OnTrueProperty);
}
set
{
SetValue(OnTrueProperty, value);
}
}
public object OnFalse
{
get
{
return GetValue(OnFalseProperty);
}
set
{
SetValue(OnFalseProperty, value);
}
}
public object OnNull
{
get
{
return GetValue(OnNullProperty);
}
set
{
SetValue(OnNullProperty, value);
}
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null
? OnNull ?? Default(targetType)
: string.Equals(value.ToString(), false.ToString(), StringComparison.CurrentCultureIgnoreCase)
? OnFalse
: OnTrue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == OnNull)
{
return Default(targetType);
}
if (value == OnFalse)
{
return false;
}
if (value == OnTrue)
{
return true;
}
if (value == null)
{
return null;
}
if (OnNull != null &&
string.Equals(value.ToString(), OnNull.ToString(), StringComparison.CurrentCultureIgnoreCase))
{
return Default(targetType);
}
if (OnFalse != null &&
string.Equals(value.ToString(), OnFalse.ToString(), StringComparison.CurrentCultureIgnoreCase))
{
return false;
}
if (OnTrue != null &&
string.Equals(value.ToString(), OnTrue.ToString(), StringComparison.CurrentCultureIgnoreCase))
{
return true;
}
return null;
}
public static object Default(Type type)
{
return type.IsValueType ? Activator.CreateInstance(type) : null;
}
}
}
@@ -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.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Windows;
using System.Windows.Documents;
namespace WPinternals.HelperClasses
{
internal class CollapsibleRun : Run
{
private string CollapsibleText;
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
CollapsibleText = Text;
}
public bool IsVisible
{
get
{
return (bool)GetValue(IsVisibleProperty);
}
set
{
SetValue(IsVisibleProperty, value);
}
}
public static readonly DependencyProperty IsVisibleProperty = DependencyProperty.Register(
"IsVisible", typeof(bool), typeof(CollapsibleRun), new PropertyMetadata(true, IsVisibleChanged));
public static void IsVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((CollapsibleRun)d).Text = (bool)e.NewValue ? ((CollapsibleRun)d).CollapsibleText : string.Empty;
}
}
}
@@ -0,0 +1,79 @@
// 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;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Documents;
namespace WPinternals.HelperClasses
{
internal class CollapsibleSection : Section
{
public CollapsibleSection()
{
CollapsibleBlocks = [];
}
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
foreach (Block Block in Blocks)
{
CollapsibleBlocks.Add(Block);
}
Blocks.Clear();
}
public List<Block> CollapsibleBlocks
{
get;
}
public bool IsCollapsed
{
get
{
return (bool)GetValue(IsCollapsedProperty);
}
set
{
SetValue(IsCollapsedProperty, value);
Blocks.Clear();
if (IsInitialized && !value)
{
foreach (Block Block in CollapsibleBlocks)
{
Blocks.Add(Block);
}
}
}
}
public static readonly DependencyProperty IsCollapsedProperty = DependencyProperty.Register(
"IsCollapsed", typeof(bool), typeof(CollapsibleSection), new PropertyMetadata(false));
}
}
@@ -0,0 +1,136 @@
// 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;
using System.IO;
using System.IO.Compression;
using System.Text;
namespace WPinternals.HelperClasses
{
// For writing a compressed stream
internal class CompressedStream : Stream
{
private readonly uint HeaderSize;
private ulong WritePosition;
private readonly GZipStream UnderlyingStream;
internal CompressedStream(Stream OutputStream, ulong TotalDecompressedStreamLength)
{
// Write header
HeaderSize = (uint)(0x12 + "CompressedPartition".Length);
OutputStream.WriteByte(0xFF);
OutputStream.Write(Encoding.ASCII.GetBytes("CompressedPartition"), 0, "CompressedPartition".Length);
OutputStream.WriteByte(0x00);
OutputStream.Write(BitConverter.GetBytes((uint)1), 0, 4); // Format version = 1
OutputStream.Write(BitConverter.GetBytes(HeaderSize), 0, 4); // Headersize
OutputStream.Write(BitConverter.GetBytes(TotalDecompressedStreamLength), 0, 8);
UnderlyingStream = new GZipStream(OutputStream, CompressionLevel.Optimal, false);
WritePosition = 0;
}
public override bool CanRead
{
get
{
return false;
}
}
public override bool CanSeek
{
get
{
return false;
}
}
public override int Read(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override long Position
{
get
{
return (long)WritePosition;
}
set
{
throw new NotSupportedException();
}
}
public override bool CanTimeout
{
get
{
return UnderlyingStream.CanTimeout;
}
}
public override bool CanWrite
{
get
{
return true;
}
}
public override long Length
{
get
{
return (long)WritePosition;
}
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
WritePosition += (ulong)count;
UnderlyingStream.Write(buffer, offset, count);
}
public override void Flush()
{
UnderlyingStream.Flush();
}
public override void Close()
{
UnderlyingStream.Close();
}
public new void Dispose()
{
UnderlyingStream.Dispose();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
UnderlyingStream.Dispose();
}
}
}
}
+60
View File
@@ -0,0 +1,60 @@
// 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.Collections;
using System.IO;
using System.IO.Compression;
namespace WPinternals.HelperClasses
{
internal static class Compression
{
internal static Stream GetDecompressedStreamWithSeek(Stream InputStream)
{
long P = InputStream.Position;
byte[] GZipHeader = new byte[3];
InputStream.Read(GZipHeader, 0, 3);
InputStream.Position = P;
if (StructuralComparisons.StructuralEqualityComparer.Equals(GZipHeader, new byte[] { 0x1F, 0x8B, 0x08 }))
{
return new GZipStream(InputStream, CompressionMode.Decompress, false);
}
else
{
return InputStream;
}
}
internal static bool IsCompressedStream(Stream InputStream)
{
byte[] GZipHeader = new byte[3];
InputStream.Read(GZipHeader, 0, 3);
return StructuralComparisons.StructuralEqualityComparer.Equals(GZipHeader, new byte[] { 0x1F, 0x8B, 0x08 });
}
internal static GZipStream GetDecompressedStream(Stream InputStream)
{
return new GZipStream(InputStream, CompressionMode.Decompress, false);
}
}
}
+74
View File
@@ -0,0 +1,74 @@
// 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;
using System.Text;
namespace WPinternals.HelperClasses
{
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 = 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);
}
}
}
@@ -0,0 +1,181 @@
// 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;
using System.Collections;
using System.IO;
using System.IO.Compression;
using System.Text;
namespace WPinternals.HelperClasses
{
// For reading a compressed stream or normal stream
internal class DecompressedStream : Stream
{
private readonly Stream UnderlyingStream;
private readonly bool IsSourceCompressed;
private readonly ulong DecompressedLength;
private long ReadPosition = 0;
// For reading a compressed stream
internal DecompressedStream(Stream InputStream)
{
UnderlyingStream = new ReadSeekableStream(InputStream, 0x100);
byte[] Signature = new byte["CompressedPartition".Length + 2];
Signature[0x00] = 0xFF;
Buffer.BlockCopy(Encoding.ASCII.GetBytes("CompressedPartition"), 0, Signature, 0x01, "CompressedPartition".Length);
Signature["CompressedPartition".Length + 1] = 0x00;
int PrimaryHeaderSize = 0x0A + "CompressedPartition".Length;
byte[] SignatureRead = new byte[Signature.Length];
UnderlyingStream.Read(SignatureRead, 0, Signature.Length);
IsSourceCompressed = StructuralComparisons.StructuralEqualityComparer.Equals(Signature, SignatureRead);
if (IsSourceCompressed)
{
byte[] FormatVersionBytes = new byte[4];
UnderlyingStream.Read(FormatVersionBytes, 0, 4);
if (BitConverter.ToUInt32(FormatVersionBytes, 0) > 1) // Max supported format version = 1
{
throw new InvalidDataException();
}
byte[] HeaderSizeBytes = new byte[4];
UnderlyingStream.Read(HeaderSizeBytes, 0, 4);
uint HeaderSize = BitConverter.ToUInt32(HeaderSizeBytes, 0);
if (HeaderSize >= Signature.Length + 0x10)
{
byte[] DecompressedLengthBytes = new byte[8];
UnderlyingStream.Read(DecompressedLengthBytes, 0, 8);
DecompressedLength = BitConverter.ToUInt64(DecompressedLengthBytes, 0);
}
else
{
throw new InvalidDataException();
}
uint HeaderBytesRemaining = (uint)(HeaderSize - Signature.Length - 0x10);
if (HeaderBytesRemaining > 0)
{
byte[] HeaderBytes = new byte[HeaderBytesRemaining];
UnderlyingStream.Read(HeaderBytes, 0, (int)HeaderBytesRemaining);
}
UnderlyingStream = new GZipStream(UnderlyingStream, CompressionMode.Decompress, false);
}
else
{
UnderlyingStream.Position = 0;
}
}
public override bool CanRead
{
get
{
return true;
}
}
public override bool CanSeek
{
get
{
return false;
}
}
public override int Read(byte[] buffer, int offset, int count)
{
int RealCount = UnderlyingStream.Read(buffer, offset, count);
ReadPosition += RealCount;
return RealCount;
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override long Position
{
get
{
return ReadPosition;
}
set
{
throw new NotSupportedException();
}
}
public override bool CanTimeout
{
get
{
return UnderlyingStream.CanTimeout;
}
}
public override bool CanWrite
{
get
{
return true;
}
}
public override long Length
{
get
{
if (IsSourceCompressed)
{
return (long)DecompressedLength;
}
else
{
return UnderlyingStream.Length;
}
}
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
public override void Flush()
{
UnderlyingStream.Flush();
}
public override void Close()
{
UnderlyingStream.Close();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
UnderlyingStream.Dispose();
}
}
}
}
@@ -0,0 +1,51 @@
// 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
{
// This class is taken from the Prism library by Microsoft Patterns & Practices
// License: http://compositewpf.codeplex.com/license
public class DelegateCommand : DelegateCommandBase
{
public DelegateCommand(Action executeMethod)
: this(executeMethod, () => true)
{
}
public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod) : base(o => executeMethod(), f => canExecuteMethod())
{
}
public bool CanExecute()
{
return CanExecute(null);
}
public void Execute()
{
Execute(null);
}
}
}
@@ -0,0 +1,118 @@
// 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;
using System.Collections.Generic;
using System.Windows.Input;
namespace WPinternals.HelperClasses
{
// This class is taken from the Prism library by Microsoft Patterns & Practices
// License: http://compositewpf.codeplex.com/license
public abstract class DelegateCommandBase : ICommand, IActiveAware
{
private List<WeakReference> _canExecuteChangedHandlers;
private bool _isActive;
private readonly Func<object, bool> canExecuteMethod;
private readonly Action<object> executeMethod;
public event EventHandler CanExecuteChanged
{
add
{
WeakEventHandlerManager.AddWeakReferenceHandler(ref _canExecuteChangedHandlers, value, 2);
}
remove
{
WeakEventHandlerManager.RemoveWeakReferenceHandler(_canExecuteChangedHandlers, value);
}
}
public event EventHandler IsActiveChanged;
protected DelegateCommandBase(Action<object> executeMethod, Func<object, bool> canExecuteMethod)
{
if (executeMethod == null || canExecuteMethod == null)
{
throw new ArgumentNullException(nameof(executeMethod), "Delegate Command Delegates Cannot Be Null");
}
this.executeMethod = executeMethod;
this.canExecuteMethod = canExecuteMethod;
}
protected bool CanExecute(object parameter)
{
if (canExecuteMethod != null)
{
return canExecuteMethod(parameter);
}
return true;
}
protected void Execute(object parameter)
{
executeMethod(parameter);
}
protected virtual void OnCanExecuteChanged()
{
WeakEventHandlerManager.CallWeakReferenceHandlers(this, _canExecuteChangedHandlers);
}
protected virtual void OnIsActiveChanged()
{
IsActiveChanged?.Invoke(this, EventArgs.Empty);
}
public void RaiseCanExecuteChanged()
{
OnCanExecuteChanged();
}
bool ICommand.CanExecute(object parameter)
{
return CanExecute(parameter);
}
void ICommand.Execute(object parameter)
{
Execute(parameter);
}
public bool IsActive
{
get
{
return _isActive;
}
set
{
if (_isActive != value)
{
_isActive = value;
OnIsActiveChanged();
}
}
}
}
}
@@ -0,0 +1,49 @@
// 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;
using System.Threading;
using System.Threading.Tasks;
namespace WPinternals.HelperClasses
{
internal static class ExtensionMethods
{
// This method was written by: Lawrence Johnston
// https://stackoverflow.com/a/22078975
public static async Task<TResult> TimeoutAfter<TResult>(this Task<TResult> task, TimeSpan timeout)
{
using CancellationTokenSource timeoutCancellationTokenSource = new CancellationTokenSource();
Task completedTask = await Task.WhenAny(task, Task.Delay(timeout, timeoutCancellationTokenSource.Token));
if (completedTask == task)
{
timeoutCancellationTokenSource.Cancel();
return await task; // Very important in order to propagate exceptions
}
else
{
throw new TimeoutException("The operation has timed out.");
}
}
}
}
@@ -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.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System.Windows.Controls;
using System.Windows.Input;
namespace WPinternals.HelperClasses
{
internal class FlowDocumentScrollViewerNoMouseWheel : FlowDocumentScrollViewer
{
protected override void OnMouseWheel(MouseWheelEventArgs e)
{
}
}
}
+150
View File
@@ -0,0 +1,150 @@
// 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;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
namespace WPinternals.HelperClasses
{
// This class was found online.
// Original author is probably: mdm20
// https://stackoverflow.com/questions/5566330/get-gif-to-play-in-wpf-with-gifimage-class/5568703#5568703
internal class GifImage : Image
{
private bool _isInitialized;
private GifBitmapDecoder _gifDecoder;
private Int32Animation _animation;
public int FrameIndex
{
get
{
return (int)GetValue(FrameIndexProperty);
}
set
{
SetValue(FrameIndexProperty, value);
}
}
private void Initialize()
{
_gifDecoder = new GifBitmapDecoder(new Uri("pack://application:,,," + GifSource), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
_animation = new Int32Animation(0, _gifDecoder.Frames.Count - 1, new Duration(new TimeSpan(0, 0, 0, _gifDecoder.Frames.Count / 10, (int)((_gifDecoder.Frames.Count / 10.0 - _gifDecoder.Frames.Count / 10) * 1000))))
{
RepeatBehavior = RepeatBehavior.Forever
};
Source = _gifDecoder.Frames[0];
_isInitialized = true;
}
static GifImage()
{
VisibilityProperty.OverrideMetadata(typeof(GifImage),
new FrameworkPropertyMetadata(VisibilityPropertyChanged));
}
private static void VisibilityPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
if ((Visibility)e.NewValue == Visibility.Visible)
{
((GifImage)sender).StartAnimation();
}
else
{
((GifImage)sender).StopAnimation();
}
}
public static readonly DependencyProperty FrameIndexProperty =
DependencyProperty.Register("FrameIndex", typeof(int), typeof(GifImage), new UIPropertyMetadata(0, new PropertyChangedCallback(ChangingFrameIndex)));
private static void ChangingFrameIndex(DependencyObject obj, DependencyPropertyChangedEventArgs ev)
{
GifImage gifImage = obj as GifImage;
gifImage.Source = gifImage._gifDecoder.Frames[(int)ev.NewValue];
}
public bool AutoStart
{
get
{
return (bool)GetValue(AutoStartProperty);
}
set
{
SetValue(AutoStartProperty, value);
}
}
public static readonly DependencyProperty AutoStartProperty =
DependencyProperty.Register("AutoStart", typeof(bool), typeof(GifImage), new UIPropertyMetadata(false, AutoStartPropertyChanged));
private static void AutoStartPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue)
{
(sender as GifImage)?.StartAnimation();
}
}
public string GifSource
{
get
{
return (string)GetValue(GifSourceProperty);
}
set
{
SetValue(GifSourceProperty, value);
}
}
public static readonly DependencyProperty GifSourceProperty =
DependencyProperty.Register("GifSource", typeof(string), typeof(GifImage), new UIPropertyMetadata(string.Empty, GifSourcePropertyChanged));
private static void GifSourcePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
(sender as GifImage)?.Initialize();
}
public void StartAnimation()
{
if (!_isInitialized)
{
Initialize();
}
BeginAnimation(FrameIndexProperty, _animation);
}
public void StopAnimation()
{
BeginAnimation(FrameIndexProperty, null);
}
}
}
@@ -0,0 +1,321 @@
// 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;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
namespace WPinternals.HelperClasses
{
// This class was written by: Rolf Wessels
// https://github.com/rolfwessels/lazycowprojects/tree/master/Wpf
/// <summary>
/// Static class used to attach to wpf control
/// </summary>
public static class GridViewColumnResize
{
#region DependencyProperties
public static readonly DependencyProperty WidthProperty =
DependencyProperty.RegisterAttached("Width", typeof(string), typeof(GridViewColumnResize),
new PropertyMetadata(OnSetWidthCallback));
public static readonly DependencyProperty GridViewColumnResizeBehaviorProperty =
DependencyProperty.RegisterAttached("GridViewColumnResizeBehavior",
typeof(GridViewColumnResizeBehavior), typeof(GridViewColumnResize),
null);
public static readonly DependencyProperty EnabledProperty =
DependencyProperty.RegisterAttached("Enabled", typeof(bool), typeof(GridViewColumnResize),
new PropertyMetadata(OnSetEnabledCallback));
public static readonly DependencyProperty ListViewResizeBehaviorProperty =
DependencyProperty.RegisterAttached("ListViewResizeBehaviorProperty",
typeof(ListViewResizeBehavior), typeof(GridViewColumnResize), null);
#endregion
public static string GetWidth(DependencyObject obj)
{
return (string)obj.GetValue(WidthProperty);
}
public static void SetWidth(DependencyObject obj, string value)
{
obj.SetValue(WidthProperty, value);
}
public static bool GetEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(EnabledProperty);
}
public static void SetEnabled(DependencyObject obj, bool value)
{
obj.SetValue(EnabledProperty, value);
}
#region CallBack
private static void OnSetWidthCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
if (dependencyObject is GridViewColumn element)
{
GridViewColumnResizeBehavior behavior = GetOrCreateBehavior(element);
behavior.Width = e.NewValue as string;
}
else
{
Console.Error.WriteLine("Error: Expected type GridViewColumn but found " +
dependencyObject.GetType().Name);
}
}
private static void OnSetEnabledCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
if (dependencyObject is ListView element)
{
ListViewResizeBehavior behavior = GetOrCreateBehavior(element);
behavior.Enabled = (bool)e.NewValue;
}
else
{
Console.Error.WriteLine("Error: Expected type ListView but found " + dependencyObject.GetType().Name);
}
}
private static ListViewResizeBehavior GetOrCreateBehavior(ListView element)
{
if (element.GetValue(GridViewColumnResizeBehaviorProperty) is not ListViewResizeBehavior behavior)
{
behavior = new ListViewResizeBehavior(element);
element.SetValue(ListViewResizeBehaviorProperty, behavior);
}
return behavior;
}
private static GridViewColumnResizeBehavior GetOrCreateBehavior(GridViewColumn element)
{
if (element.GetValue(GridViewColumnResizeBehaviorProperty) is not GridViewColumnResizeBehavior behavior)
{
behavior = new GridViewColumnResizeBehavior(element);
element.SetValue(GridViewColumnResizeBehaviorProperty, behavior);
}
return behavior;
}
#endregion
#region Nested type: GridViewColumnResizeBehavior
// This class was written by: Rolf Wessels
// https://github.com/rolfwessels/lazycowprojects/tree/master/Wpf
/// <summary>
/// GridViewColumn class that gets attached to the GridViewColumn control
/// </summary>
public class GridViewColumnResizeBehavior
{
private readonly GridViewColumn _element;
public GridViewColumnResizeBehavior(GridViewColumn element)
{
_element = element;
}
public string Width
{
get; set;
}
public bool IsStatic
{
get
{
return StaticWidth >= 0;
}
}
public double StaticWidth
{
get
{
return double.TryParse(Width, out double result) ? result : -1;
}
}
public double Percentage
{
get
{
if (!IsStatic)
{
return Mulitplier * 100;
}
return 0;
}
}
public double Mulitplier
{
get
{
if (Width == "*" || Width == "1*")
{
return 1;
}
if (Width.EndsWith("*") && double.TryParse(Width[0..^1], out double perc))
{
return perc;
}
return 1;
}
}
public void SetWidth(double allowedSpace, double totalPercentage)
{
if (IsStatic)
{
_element.Width = StaticWidth;
}
else
{
_element.Width = (double)Math.Max(allowedSpace * (Percentage / totalPercentage), 0);
}
}
}
#endregion
#region Nested type: ListViewResizeBehavior
// This class was written by: Rolf Wessels
// https://github.com/rolfwessels/lazycowprojects/tree/master/Wpf
/// <summary>
/// ListViewResizeBehavior class that gets attached to the ListView control
/// </summary>
public class ListViewResizeBehavior
{
private const int Margin = 25;
private const long RefreshTime = Timeout.Infinite;
private const long Delay = 500;
private readonly ListView _element;
private readonly Timer _timer;
public ListViewResizeBehavior(ListView element)
{
_element = element ?? throw new ArgumentNullException(nameof(element));
element.Loaded += OnLoaded;
// Action for resizing and re-enable the size lookup
// This stops the columns from constantly resizing to improve performance
Action resizeAndEnableSize = () =>
{
Resize();
_element.SizeChanged += OnSizeChanged;
};
_timer = new Timer(x => Application.Current.Dispatcher.BeginInvoke(resizeAndEnableSize), null, Delay,
RefreshTime);
}
public bool Enabled
{
get; set;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
_element.SizeChanged += OnSizeChanged;
}
private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
if (e.WidthChanged)
{
_element.SizeChanged -= OnSizeChanged;
_timer.Change(Delay, RefreshTime);
}
}
private void Resize()
{
if (Enabled)
{
double totalWidth = _element.ActualWidth;
if (_element.View is GridView gv)
{
double allowedSpace = totalWidth - GetAllocatedSpace(gv);
allowedSpace -= Margin;
double totalPercentage = GridViewColumnResizeBehaviors(gv).Sum(x => x.Percentage);
foreach (GridViewColumnResizeBehavior behavior in GridViewColumnResizeBehaviors(gv))
{
behavior.SetWidth(allowedSpace, totalPercentage);
}
}
}
}
private static IEnumerable<GridViewColumnResizeBehavior> GridViewColumnResizeBehaviors(GridView gv)
{
foreach (GridViewColumn t in gv.Columns)
{
if (t.GetValue(GridViewColumnResizeBehaviorProperty) is GridViewColumnResizeBehavior gridViewColumnResizeBehavior)
{
yield return gridViewColumnResizeBehavior;
}
}
}
private static double GetAllocatedSpace(GridView gv)
{
double totalWidth = 0;
foreach (GridViewColumn t in gv.Columns)
{
if (t.GetValue(GridViewColumnResizeBehaviorProperty) is GridViewColumnResizeBehavior gridViewColumnResizeBehavior)
{
if (gridViewColumnResizeBehavior.IsStatic)
{
totalWidth += gridViewColumnResizeBehavior.StaticWidth;
}
}
else
{
totalWidth += t.ActualWidth;
}
}
return totalWidth;
}
}
#endregion
}
}
@@ -0,0 +1,30 @@
// 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.
namespace WPinternals.HelperClasses
{
internal delegate void SetWorkingStatus(string Message, string SubMessage = null, ulong? MaxProgressValue = null, bool ShowAnimation = true, WPinternalsStatus Status = WPinternalsStatus.Undefined);
internal delegate void UpdateWorkingStatus(string Message, string SubMessage = null, ulong? CurrentProgressValue = null, WPinternalsStatus Status = WPinternalsStatus.Undefined);
internal delegate void ExitSuccess(string Message, string SubMessage = null);
internal delegate void ExitFailure(string Message, string SubMessage = null);
}
+82
View File
@@ -0,0 +1,82 @@
// 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;
using System.Globalization;
using System.Text;
using System.Windows;
using System.Windows.Data;
namespace WPinternals.HelperClasses
{
public class HexConverter : DependencyObject, IValueConverter
{
public static readonly DependencyProperty SeparatorProperty =
DependencyProperty.Register("OnTrue", typeof(object), typeof(HexConverter),
new PropertyMetadata(" "));
public object Separator
{
get
{
return GetValue(SeparatorProperty);
}
set
{
SetValue(SeparatorProperty, value);
}
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is byte[] bytes)
{
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();
}
else
{
return "";
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public static object Default(Type type)
{
return type.IsValueType ? Activator.CreateInstance(type) : null;
}
}
}
+46
View File
@@ -0,0 +1,46 @@
// 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
{
// This interface is taken from the Prism library by Microsoft Patterns & Practices
// License: http://compositewpf.codeplex.com/license
public interface IActiveAware
{
/// <summary>
/// Gets or sets a value indicating whether the object is active.
/// </summary>
/// <value><see langword="true" /> if the object is active; otherwise <see langword="false" />.</value>
bool IsActive
{
get; set;
}
/// <summary>
/// Notifies that the value for <see cref="IsActive"/> property has changed.
/// </summary>
event EventHandler IsActiveChanged;
}
}
@@ -0,0 +1,55 @@
// 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;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace WPinternals.HelperClasses
{
public class InverseObjectToVisibilityConverter : DependencyObject, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
{
return "Visible";
}
else
{
return "Collapsed";
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public static object Default(Type type)
{
return type.IsValueType ? Activator.CreateInstance(type) : null;
}
}
}
+202
View File
@@ -0,0 +1,202 @@
// 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;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text;
namespace WPinternals.HelperClasses
{
internal static class LogFile
{
private static readonly StreamWriter w = null;
private static readonly object lockobject = new();
#if PREVIEW
private static string LogAction = null;
private static StringBuilder LogBuilder;
#endif
static LogFile()
{
try
{
if (!Directory.Exists(Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals")))
{
Directory.CreateDirectory(Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals"));
}
w = File.AppendText(Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\WPInternals.log"));
}
catch { }
}
public static void Log(string logMessage, LogType Type = LogType.FileOnly)
{
if (w == null)
{
return;
}
lock (lockobject)
{
if (Type == LogType.FileOnly || Type == LogType.FileAndConsole)
{
DateTime Now = DateTime.Now;
string Text = Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + ": " + logMessage;
w.WriteLine(Text);
w.Flush();
#if PREVIEW
if (LogAction != null)
LogBuilder.AppendLine(Text);
#endif
}
if (CommandLine.IsConsoleVisible && (Type == LogType.ConsoleOnly || Type == LogType.FileAndConsole))
{
Console.WriteLine(logMessage);
}
}
}
public static void LogException(Exception Ex, LogType Type = LogType.FileAndConsole, string AdditionalInfo = null)
{
string Indent = "";
Exception CurrentEx = Ex;
while (CurrentEx != null)
{
Log(Indent + "Error: " + RemoveBadChars(CurrentEx.Message).Replace("of type '.' ", "") + (AdditionalInfo == null ? "" : " - " + AdditionalInfo), Type);
AdditionalInfo = null;
if (CurrentEx is WPinternalsException)
{
Log(Indent + ((WPinternalsException)CurrentEx).SubMessage, Type);
}
#if DEBUG
if (CurrentEx.StackTrace != null)
{
Log(Indent + CurrentEx.StackTrace, LogType.FileOnly);
}
#endif
Indent += " ";
CurrentEx = CurrentEx.InnerException;
}
}
private static string RemoveBadChars(string Text)
{
return System.Text.RegularExpressions.Regex.Replace(Text, @"[^\u0020-\u007E]+", string.Empty);
}
public static void DumpLog(StreamReader r)
{
string line;
while ((line = r.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
public static void LogApplicationVersion()
{
Log("Windows Phone Internals version " +
Assembly.GetExecutingAssembly().GetName().Version.Major.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Minor.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Build.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Revision.ToString(), LogType.FileAndConsole);
Log("Copyright Heathcliff74", LogType.FileAndConsole);
}
internal static void BeginAction(string Action)
{
#if PREVIEW
if (LogAction == null)
{
LogAction = Action;
LogBuilder = new StringBuilder();
LogBuilder.AppendLine("Windows Phone Internals version " +
Assembly.GetExecutingAssembly().GetName().Version.Major.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Minor.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Build.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Revision.ToString());
LogBuilder.AppendLine("Copyright Heathcliff74");
LogBuilder.AppendLine("Action: " + Action);
if (App.Config.RegistrationName != null)
LogBuilder.AppendLine("Name: " + App.Config.RegistrationName);
if (App.Config.RegistrationEmail != null)
LogBuilder.AppendLine("Mail: " + App.Config.RegistrationEmail);
if (App.Config.RegistrationSkypeID != null)
LogBuilder.AppendLine("Skype: " + App.Config.RegistrationSkypeID);
if (App.Config.RegistrationTelegramID != null)
LogBuilder.AppendLine("Telegram: " + App.Config.RegistrationTelegramID);
if (Environment.MachineName != null)
LogBuilder.AppendLine("Machine: " + Environment.MachineName);
}
#endif
}
internal static void EndAction()
{
EndAction(null);
}
internal static void EndAction(string Action)
{
#if PREVIEW
if (LogAction != null && (Action == null || LogAction == Action))
{
Action = LogAction;
LogAction = null;
string FileName = "";
if (App.Config.RegistrationName != null)
FileName += App.Config.RegistrationName + " - ";
FileName += DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture) + " - " + Action + " - " +
Assembly.GetExecutingAssembly().GetName().Version.Major.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Minor.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Build.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Revision.ToString() + ".log";
// Normalize filename
try
{
FileName = Encoding.ASCII.GetString(Encoding.GetEncoding("ISO-8859-8").GetBytes(FileName));
}
catch { }
FileName = FileName.Replace("?", "");
if (Action.ToLower() == "registration")
Uploader.Upload(FileName, LogBuilder.ToString());
else
{
try
{
Uploader.Upload(FileName, LogBuilder.ToString());
}
catch { }
}
}
#endif
}
}
}
+32
View File
@@ -0,0 +1,32 @@
// 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.
namespace WPinternals.HelperClasses
{
internal enum LogType
{
FileOnly,
FileAndConsole,
ConsoleOnly
};
}
@@ -0,0 +1,55 @@
// 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;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace WPinternals.HelperClasses
{
public class ObjectToVisibilityConverter : DependencyObject, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
{
return "Collapsed";
}
else
{
return "Visible";
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public static object Default(Type type)
{
return type.IsValueType ? Activator.CreateInstance(type) : null;
}
}
}
+128
View File
@@ -0,0 +1,128 @@
// 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 static class PE
{
internal static byte[] GetResource(byte[] PEfile, int[] Index)
{
// Explanation of PE header here:
// https://msdn.microsoft.com/en-us/library/ms809762.aspx?f=255&MSPPError=-2147217396
uint PEPointer = ByteOperations.ReadUInt32(PEfile, 0x3C);
ushort OptionalHeaderSize = ByteOperations.ReadUInt16(PEfile, PEPointer + 0x14);
uint SectionTablePointer = PEPointer + 0x18 + OptionalHeaderSize;
ushort SectionCount = ByteOperations.ReadUInt16(PEfile, PEPointer + 0x06);
uint? ResourceSectionEntryPointer = null;
for (int i = 0; i < SectionCount; i++)
{
string SectionName = ByteOperations.ReadAsciiString(PEfile, (uint)(SectionTablePointer + i * 0x28), 8);
int e = SectionName.IndexOf('\0');
if (e >= 0)
{
SectionName = SectionName.Substring(0, e);
}
if (SectionName == ".rsrc")
{
ResourceSectionEntryPointer = (uint)(SectionTablePointer + i * 0x28);
break;
}
}
if (ResourceSectionEntryPointer == null)
{
throw new WPinternalsException("Resource-section not found");
}
uint ResourceRawSize = ByteOperations.ReadUInt32(PEfile, (uint)ResourceSectionEntryPointer + 0x10);
uint ResourceRawPointer = ByteOperations.ReadUInt32(PEfile, (uint)ResourceSectionEntryPointer + 0x14);
uint ResourceVirtualPointer = ByteOperations.ReadUInt32(PEfile, (uint)ResourceSectionEntryPointer + 0x0C);
uint p = ResourceRawPointer;
for (int i = 0; i < Index.Length; i++)
{
ushort ResourceNamedEntryCount = ByteOperations.ReadUInt16(PEfile, p + 0x0c);
ushort ResourceIdEntryCount = ByteOperations.ReadUInt16(PEfile, p + 0x0e);
for (int j = ResourceNamedEntryCount; j < ResourceNamedEntryCount + ResourceIdEntryCount; j++)
{
uint ResourceID = ByteOperations.ReadUInt32(PEfile, (uint)(p + 0x10 + j * 8));
uint NextPointer = ByteOperations.ReadUInt32(PEfile, (uint)(p + 0x10 + j * 8 + 4));
if (ResourceID == (uint)Index[i])
{
// Check high bit
if ((NextPointer & 0x80000000) == 0 != (i == Index.Length - 1))
{
throw new WPinternalsException("Bad resource path");
}
p = ResourceRawPointer + (NextPointer & 0x7fffffff);
break;
}
}
}
uint ResourceValuePointer = ByteOperations.ReadUInt32(PEfile, p) - ResourceVirtualPointer + ResourceRawPointer;
uint ResourceValueSize = ByteOperations.ReadUInt32(PEfile, p + 4);
byte[] ResourceValue = new byte[ResourceValueSize];
Array.Copy(PEfile, ResourceValuePointer, ResourceValue, 0, ResourceValueSize);
return ResourceValue;
}
internal static Version GetFileVersion(byte[] PEfile)
{
byte[] version = GetResource(PEfile, [(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 uint FixedFileInfoPointer = 0x28;
ushort Major = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x0A);
ushort Minor = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x08);
ushort Build = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x0E);
ushort Revision = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x0C);
return new Version(Major, Minor, Build, Revision);
}
internal static Version GetProductVersion(byte[] PEfile)
{
byte[] version = GetResource(PEfile, [(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 uint FixedFileInfoPointer = 0x28;
ushort Major = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x12);
ushort Minor = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x10);
ushort Build = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x16);
ushort Revision = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x14);
return new Version(Major, Minor, Build, Revision);
}
}
}
+52
View File
@@ -0,0 +1,52 @@
// 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;
using System.Linq;
using System.Windows.Documents;
namespace WPinternals.HelperClasses
{
// Overloaded Paragraph class to remove empty Run-elements, caused by auto-formatting new-lines in the XAML
// Use helpers:Paragraph in a FlowDocument
// This correction only works at run-time
public class Paragraph : System.Windows.Documents.Paragraph
{
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
int inlinesCount = Inlines.Count;
for (int i = 0; i < inlinesCount; i++)
{
Inline inline = Inlines.ElementAt(i);
if (inline is Run run)
{
if (run.Text == Convert.ToChar(32).ToString()) //ACSII 32 is the white space
{
run.Text = string.Empty;
}
}
}
}
}
}
@@ -0,0 +1,88 @@
// 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 ProgressUpdater
{
private readonly DateTime InitTime;
private DateTime LastUpdateTime;
private readonly ulong MaxValue;
private readonly Action<int, TimeSpan?> ProgressUpdateCallback;
internal int ProgressPercentage;
internal ProgressUpdater(ulong MaxValue, Action<int, TimeSpan?> ProgressUpdateCallback)
{
InitTime = DateTime.Now;
LastUpdateTime = DateTime.Now;
this.MaxValue = MaxValue;
this.ProgressUpdateCallback = ProgressUpdateCallback;
SetProgress(0);
}
private ulong _Progress;
internal ulong Progress
{
get
{
return _Progress;
}
}
internal void SetProgress(ulong NewValue)
{
if (_Progress != NewValue)
{
int PreviousProgressPercentage = (int)((double)_Progress / MaxValue * 100);
ProgressPercentage = (int)((double)NewValue / MaxValue * 100);
_Progress = NewValue;
if (DateTime.Now - LastUpdateTime > TimeSpan.FromSeconds(0.5) || ProgressPercentage == 100)
{
#if DEBUG
Console.WriteLine("Init time: " + InitTime.ToShortTimeString() + " / Now: " + DateTime.Now.ToString() + " / NewValue: " + NewValue.ToString() + " / MaxValue: " + MaxValue.ToString() + " ->> Percentage: " + ProgressPercentage.ToString() + " / Remaining: " + TimeSpan.FromTicks((long)((DateTime.Now - InitTime).Ticks / ((double)NewValue / MaxValue) * (1 - (double)NewValue / MaxValue))).ToString());
#endif
if (DateTime.Now - InitTime < TimeSpan.FromSeconds(30) && ProgressPercentage < 15)
{
ProgressUpdateCallback(ProgressPercentage, null);
}
else
{
ProgressUpdateCallback(ProgressPercentage, TimeSpan.FromTicks((long)((DateTime.Now - InitTime).Ticks / ((double)NewValue / MaxValue) * (1 - (double)NewValue / MaxValue))));
}
LastUpdateTime = DateTime.Now;
}
}
}
internal void IncreaseProgress(ulong Progress)
{
SetProgress(_Progress + Progress);
}
}
}
@@ -0,0 +1,342 @@
// 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;
using System.IO;
namespace WPinternals.HelperClasses
{
// This class is written by: Eugene Beresovsky
// https://stackoverflow.com/questions/13035925/stream-wrapper-to-make-stream-seekable/28036366#28036366
internal class ReadSeekableStream : Stream
{
private long _underlyingPosition;
private readonly byte[] _seekBackBuffer;
private int _seekBackBufferCount;
private int _seekBackBufferIndex;
private readonly Stream _underlyingStream;
public ReadSeekableStream(Stream underlyingStream, int seekBackBufferSize)
{
if (!underlyingStream.CanRead)
{
throw new Exception("Provided stream " + underlyingStream + " is not readable");
}
_underlyingStream = underlyingStream;
_seekBackBuffer = new byte[seekBackBufferSize];
}
public override bool CanRead
{
get
{
return true;
}
}
public override bool CanSeek
{
get
{
return true;
}
}
public override int Read(byte[] buffer, int offset, int count)
{
int copiedFromBackBufferCount = 0;
if (_seekBackBufferIndex < _seekBackBufferCount)
{
copiedFromBackBufferCount = Math.Min(count, _seekBackBufferCount - _seekBackBufferIndex);
Buffer.BlockCopy(_seekBackBuffer, _seekBackBufferIndex, buffer, offset, copiedFromBackBufferCount);
offset += copiedFromBackBufferCount;
count -= copiedFromBackBufferCount;
_seekBackBufferIndex += copiedFromBackBufferCount;
}
int bytesReadFromUnderlying = 0;
if (count > 0)
{
bytesReadFromUnderlying = _underlyingStream.Read(buffer, offset, count);
if (bytesReadFromUnderlying > 0)
{
_underlyingPosition += bytesReadFromUnderlying;
int copyToBufferCount = Math.Min(bytesReadFromUnderlying, _seekBackBuffer.Length);
int copyToBufferOffset = Math.Min(_seekBackBufferCount, _seekBackBuffer.Length - copyToBufferCount);
int bufferBytesToMove = Math.Min(_seekBackBufferCount - 1, copyToBufferOffset);
if (bufferBytesToMove > 0)
{
Buffer.BlockCopy(_seekBackBuffer, _seekBackBufferCount - bufferBytesToMove, _seekBackBuffer, 0, bufferBytesToMove);
}
Buffer.BlockCopy(buffer, offset, _seekBackBuffer, copyToBufferOffset, copyToBufferCount);
_seekBackBufferCount = Math.Min(_seekBackBuffer.Length, _seekBackBufferCount + copyToBufferCount);
_seekBackBufferIndex = _seekBackBufferCount;
}
}
return copiedFromBackBufferCount + bytesReadFromUnderlying;
}
public override long Seek(long offset, SeekOrigin origin)
{
if (origin == SeekOrigin.End)
{
return SeekFromEnd((int)Math.Max(0, -offset));
}
long relativeOffset = origin == SeekOrigin.Current
? offset
: offset - Position;
if (relativeOffset == 0)
{
return Position;
}
else if (relativeOffset > 0)
{
return SeekForward(relativeOffset);
}
else
{
return SeekBackwards(-relativeOffset);
}
}
private long SeekForward(long origOffset)
{
long offset = origOffset;
int seekBackBufferLength = _seekBackBuffer.Length;
int backwardSoughtBytes = _seekBackBufferCount - _seekBackBufferIndex;
int seekForwardInBackBuffer = (int)Math.Min(offset, backwardSoughtBytes);
offset -= seekForwardInBackBuffer;
_seekBackBufferIndex += seekForwardInBackBuffer;
if (offset > 0)
{
// first completely fill seekBackBuffer to remove special cases from while loop below
if (_seekBackBufferCount < seekBackBufferLength)
{
int maxRead = seekBackBufferLength - _seekBackBufferCount;
if (offset < maxRead)
{
maxRead = (int)offset;
}
int bytesRead = _underlyingStream.Read(_seekBackBuffer, _seekBackBufferCount, maxRead);
_underlyingPosition += bytesRead;
_seekBackBufferCount += bytesRead;
_seekBackBufferIndex = _seekBackBufferCount;
if (bytesRead < maxRead)
{
if (_seekBackBufferCount < offset)
{
throw new NotSupportedException("Reached end of stream seeking forward " + origOffset + " bytes");
}
return Position;
}
offset -= bytesRead;
}
// now alternate between filling tempBuffer and seekBackBuffer
bool fillTempBuffer = true;
byte[] tempBuffer = new byte[seekBackBufferLength];
while (offset > 0)
{
int maxRead = offset < seekBackBufferLength ? (int)offset : seekBackBufferLength;
int bytesRead = _underlyingStream.Read(fillTempBuffer ? tempBuffer : _seekBackBuffer, 0, maxRead);
_underlyingPosition += bytesRead;
int bytesReadDiff = maxRead - bytesRead;
offset -= bytesRead;
if (bytesReadDiff > 0 /* reached end-of-stream */ || offset == 0)
{
if (fillTempBuffer)
{
if (bytesRead > 0)
{
Buffer.BlockCopy(_seekBackBuffer, bytesRead, _seekBackBuffer, 0, bytesReadDiff);
Buffer.BlockCopy(tempBuffer, 0, _seekBackBuffer, bytesReadDiff, bytesRead);
}
}
else
{
if (bytesRead > 0)
{
Buffer.BlockCopy(_seekBackBuffer, 0, _seekBackBuffer, bytesReadDiff, bytesRead);
}
Buffer.BlockCopy(tempBuffer, bytesRead, _seekBackBuffer, 0, bytesReadDiff);
}
if (offset > 0)
{
throw new NotSupportedException("Reached end of stream seeking forward " + origOffset + " bytes");
}
}
fillTempBuffer = !fillTempBuffer;
}
}
return Position;
}
private long SeekBackwards(long offset)
{
int intOffset = (int)offset;
if (offset > int.MaxValue || intOffset > _seekBackBufferIndex)
{
throw new NotSupportedException("Cannot currently seek backwards more than " + _seekBackBufferIndex + " bytes");
}
_seekBackBufferIndex -= intOffset;
return Position;
}
private long SeekFromEnd(long offset)
{
int intOffset = (int)offset;
int seekBackBufferLength = _seekBackBuffer.Length;
if (offset > int.MaxValue || intOffset > seekBackBufferLength)
{
throw new NotSupportedException("Cannot seek backwards from end more than " + seekBackBufferLength + " bytes");
}
// first completely fill seekBackBuffer to remove special cases from while loop below
if (_seekBackBufferCount < seekBackBufferLength)
{
int maxRead = seekBackBufferLength - _seekBackBufferCount;
int bytesRead = _underlyingStream.Read(_seekBackBuffer, _seekBackBufferCount, maxRead);
_underlyingPosition += bytesRead;
_seekBackBufferCount += bytesRead;
_seekBackBufferIndex = Math.Max(0, _seekBackBufferCount - intOffset);
if (bytesRead < maxRead)
{
if (_seekBackBufferCount < intOffset)
{
throw new NotSupportedException("Could not seek backwards from end " + intOffset + " bytes");
}
return Position;
}
}
else
{
_seekBackBufferIndex = _seekBackBufferCount;
}
// now alternate between filling tempBuffer and seekBackBuffer
bool fillTempBuffer = true;
byte[] tempBuffer = new byte[seekBackBufferLength];
while (true)
{
int bytesRead = _underlyingStream.Read(fillTempBuffer ? tempBuffer : _seekBackBuffer, 0, seekBackBufferLength);
_underlyingPosition += bytesRead;
int bytesReadDiff = seekBackBufferLength - bytesRead;
if (bytesReadDiff > 0) // reached end-of-stream
{
if (fillTempBuffer)
{
if (bytesRead > 0)
{
Buffer.BlockCopy(_seekBackBuffer, bytesRead, _seekBackBuffer, 0, bytesReadDiff);
Buffer.BlockCopy(tempBuffer, 0, _seekBackBuffer, bytesReadDiff, bytesRead);
}
}
else
{
if (bytesRead > 0)
{
Buffer.BlockCopy(_seekBackBuffer, 0, _seekBackBuffer, bytesReadDiff, bytesRead);
}
Buffer.BlockCopy(tempBuffer, bytesRead, _seekBackBuffer, 0, bytesReadDiff);
}
_seekBackBufferIndex -= intOffset;
return Position;
}
fillTempBuffer = !fillTempBuffer;
}
}
public override long Position
{
get
{
return _underlyingPosition - (_seekBackBufferCount - _seekBackBufferIndex);
}
set
{
Seek(value, SeekOrigin.Begin);
}
}
public override bool CanTimeout
{
get
{
return _underlyingStream.CanTimeout;
}
}
public override bool CanWrite
{
get
{
return _underlyingStream.CanWrite;
}
}
public override long Length
{
get
{
return _underlyingStream.Length;
}
}
public override void SetLength(long value)
{
_underlyingStream.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
_underlyingStream.Write(buffer, offset, count);
}
public override void Flush()
{
_underlyingStream.Flush();
}
public override void Close()
{
_underlyingStream.Close();
}
public new void Dispose()
{
_underlyingStream.Dispose();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_underlyingStream.Dispose();
}
}
}
}
+52
View File
@@ -0,0 +1,52 @@
// 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.
namespace WPinternals.HelperClasses
{
internal enum ResourceType
{
RT_CURSOR = 1,
RT_BITMAP = 2,
RT_ICON = 3,
RT_MENU = 4,
RT_DIALOG = 5,
RT_STRING = 6,
RT_FONTDIR = 7,
RT_FONT = 8,
RT_ACCELERATOR = 9,
RT_RCDATA = 10,
RT_MESSAGETABLE = 11,
RT_GROUP_CURSOR = RT_CURSOR + 11,
RT_GROUP_ICON = RT_ICON + 11,
RT_VERSION = 16,
RT_DLGINCLUDE = 17,
RT_PLUGPLAY = 19,
RT_VXD = 20,
RT_ANICURSOR = 21,
RT_ANIICON = 22,
RT_HTML = 23,
RT_MANIFEST = 24,
RT_DLGINIT = 240,
RT_TOOLBAR = 241
};
}
+188
View File
@@ -0,0 +1,188 @@
// 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;
using System.IO;
namespace WPinternals.HelperClasses
{
internal class SeekableStream : Stream
{
private Stream UnderlyingStream;
private long ReadPosition = 0;
private readonly Func<Stream> StreamInitializer;
private readonly long UnderlyingStreamLength;
// For reading a compressed stream
internal SeekableStream(Func<Stream> StreamInitializer, long? Length = null)
{
this.StreamInitializer = StreamInitializer;
UnderlyingStream = StreamInitializer();
if (Length != null)
{
UnderlyingStreamLength = (long)Length;
}
else
{
try
{
UnderlyingStreamLength = UnderlyingStream.Length;
}
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);
throw new ArgumentException("Unknown stream length");
}
}
}
public override bool CanRead
{
get
{
return true;
}
}
public override bool CanSeek
{
get
{
return true;
}
}
public override int Read(byte[] buffer, int offset, int count)
{
int RealCount = UnderlyingStream.Read(buffer, offset, count);
ReadPosition += RealCount;
return RealCount;
}
public override long Seek(long offset, SeekOrigin origin)
{
if (UnderlyingStream.CanSeek)
{
ReadPosition = UnderlyingStream.Seek(offset, origin);
return ReadPosition;
}
else
{
long NewPosition = 0;
switch (origin)
{
case SeekOrigin.Begin:
NewPosition = offset;
break;
case SeekOrigin.Current:
NewPosition = ReadPosition + offset;
break;
case SeekOrigin.End:
NewPosition = UnderlyingStreamLength - offset;
break;
}
if (NewPosition < 0 || NewPosition > UnderlyingStreamLength)
{
throw new ArgumentOutOfRangeException(nameof(offset));
}
if (NewPosition < ReadPosition)
{
UnderlyingStream.Close();
UnderlyingStream = StreamInitializer();
ReadPosition = 0;
}
ulong Remaining;
byte[] Buffer = new byte[16384];
while (ReadPosition < NewPosition)
{
Remaining = (ulong)(NewPosition - ReadPosition);
if (Remaining > (ulong)Buffer.Length)
{
Remaining = (ulong)Buffer.Length;
}
UnderlyingStream.Read(Buffer, 0, (int)Remaining);
ReadPosition += (long)Remaining;
}
return ReadPosition;
}
}
public override long Position
{
get
{
return ReadPosition;
}
set
{
Seek(value, SeekOrigin.Begin);
}
}
public override bool CanTimeout
{
get
{
return UnderlyingStream.CanTimeout;
}
}
public override bool CanWrite
{
get
{
return false;
}
}
public override long Length
{
get
{
return UnderlyingStreamLength;
}
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
public override void Flush()
{
throw new NotSupportedException();
}
public override void Close()
{
UnderlyingStream.Close();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
UnderlyingStream.Dispose();
}
}
}
}
+81
View File
@@ -0,0 +1,81 @@
// 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;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace WPinternals.HelperClasses
{
#if PREVIEW
internal static class Uploader
{
internal static List<Task> Uploads = [];
internal static void Upload(string FileName, string Text)
{
byte[] byteArray = Encoding.UTF8.GetBytes(Text);
MemoryStream FileStream = new(byteArray);
Upload(FileName, FileStream);
}
internal static void Upload(string FileName, byte[] Data)
{
Upload(FileName, new MemoryStream(Data));
}
internal static void Upload(string FileName, Stream FileStream)
{
//TODO: Fix
//Upload(new Uri(@"https://www.wpinternals.net/upload.php", UriKind.Absolute), "uploadedfile", FileName, FileStream);
}
private static void Upload(Uri Address, string InputName, string FileName, Stream FileStream)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
System.Net.Http.HttpClient httpClient = new();
System.Net.Http.MultipartFormDataContent form = [];
System.Net.Http.StreamContent Content = new(FileStream);
Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("text/plain");
form.Add(Content, InputName, FileName);
Task<System.Net.Http.HttpResponseMessage> UploadTask = httpClient.PostAsync(Address, form);
Uploads.Add(
UploadTask.ContinueWith((t) =>
{
Uploads.Remove(t);
httpClient.Dispose();
})
);
}
internal static void WaitForUploads()
{
Task.WaitAll([.. Uploads]);
}
}
#endif
}
@@ -0,0 +1,43 @@
// 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 WPinternalsException : Exception
{
// Message and SubMessaage are always printable
internal string SubMessage = null;
internal WPinternalsException() : base() { }
internal WPinternalsException(string Message) : base(Message) { }
internal WPinternalsException(string Message, Exception InnerException) : base(Message, InnerException) { }
internal WPinternalsException(string Message, string SubMessage) : base(Message) { this.SubMessage = SubMessage; }
internal WPinternalsException(string Message, string SubMessage, Exception InnerException) : base(Message, InnerException) { this.SubMessage = SubMessage; }
}
}
@@ -0,0 +1,36 @@
// 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.
namespace WPinternals.HelperClasses
{
internal enum WPinternalsStatus
{
Undefined,
Scanning,
Flashing,
Patching,
WaitingForManualReset,
SwitchingMode,
Initializing
};
}
@@ -0,0 +1,132 @@
// 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;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Threading;
namespace WPinternals.HelperClasses
{
// This class is taken from the Prism library by Microsoft Patterns & Practices
// License: http://compositewpf.codeplex.com/license
internal static class WeakEventHandlerManager
{
public static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler, int defaultListSize)
{
(handlers ??= defaultListSize > 0 ? new List<WeakReference>(defaultListSize) : []).Add(new WeakReference(handler));
}
private static void CallHandler(object sender, EventHandler eventHandler)
{
DispatcherProxy proxy = DispatcherProxy.CreateDispatcher();
if (eventHandler != null)
{
if (proxy?.CheckAccess() == false)
{
proxy.BeginInvoke(new Action<object, EventHandler>(CallHandler), [sender, eventHandler]);
}
else
{
eventHandler(sender, EventArgs.Empty);
}
}
}
public static void CallWeakReferenceHandlers(object sender, List<WeakReference> handlers)
{
if (handlers != null)
{
EventHandler[] callees = new EventHandler[handlers.Count];
int count = 0;
count = CleanupOldHandlers(handlers, callees, count);
for (int i = 0; i < count; i++)
{
CallHandler(sender, callees[i]);
}
}
}
private static int CleanupOldHandlers(List<WeakReference> handlers, EventHandler[] callees, int count)
{
for (int i = handlers.Count - 1; i >= 0; i--)
{
WeakReference reference = handlers[i];
if (reference.Target is not EventHandler target)
{
handlers.RemoveAt(i);
}
else
{
callees[count] = target;
count++;
}
}
return count;
}
public static void RemoveWeakReferenceHandler(List<WeakReference> handlers, EventHandler handler)
{
if (handlers != null)
{
for (int i = handlers.Count - 1; i >= 0; i--)
{
WeakReference reference = handlers[i];
if (reference.Target is not EventHandler target || target == handler)
{
handlers.RemoveAt(i);
}
}
}
}
private class DispatcherProxy
{
private readonly Dispatcher innerDispatcher;
private DispatcherProxy(Dispatcher dispatcher)
{
innerDispatcher = dispatcher;
}
public DispatcherOperation BeginInvoke(Delegate method, params object[] args)
{
return innerDispatcher.BeginInvoke(method, DispatcherPriority.Normal, args);
}
public bool CheckAccess()
{
return innerDispatcher.CheckAccess();
}
public static DispatcherProxy CreateDispatcher()
{
if (Application.Current == null)
{
return null;
}
return new DispatcherProxy(Application.Current.Dispatcher);
}
}
}
}
+1 -1
View File
@@ -388,7 +388,7 @@ namespace WPinternals
unchecked
{
uint crc = (uint)(((uint)0) ^ (-1));
for (var i = Offset; i < (Offset + Length); i++)
for (uint i = Offset; i < (Offset + Length); i++)
{
crc = (crc >> 8) ^ CRC32Table[(crc ^ Input[i]) & 0xFF];
}
+3 -3
View File
@@ -20,7 +20,7 @@
using System;
using System.IO;
using System.Linq;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -289,7 +289,7 @@ namespace WPinternals
Partition Target = GPT.Partitions.Find(p => string.Equals(p.Name, Name, StringComparison.CurrentCultureIgnoreCase));
if (Target == null)
{
throw new ArgumentOutOfRangeException();
throw new ArgumentOutOfRangeException(nameof(Name));
}
return GetSectors((int)Target.FirstSector, (int)(Target.LastSector - Target.FirstSector + 1));
@@ -315,7 +315,7 @@ namespace WPinternals
Partition Target = GPT.Partitions.Find(p => string.Equals(p.Name, Name, StringComparison.CurrentCultureIgnoreCase));
if (Target == null)
{
throw new ArgumentOutOfRangeException();
throw new ArgumentOutOfRangeException(nameof(Name));
}
int FirstChunk = GetChunkIndexFromSectorIndex((int)Target.FirstSector);
+24 -12
View File
@@ -24,6 +24,7 @@ using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Xml.Serialization;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -42,7 +43,7 @@ namespace WPinternals
internal bool HasChanged = false;
[XmlElement("Partition")]
public List<Partition> Partitions = new();
public List<Partition> Partitions = [];
public GPT() // Only for serialization
{
@@ -80,13 +81,15 @@ namespace WPinternals
break;
}
Partition CurrentPartition = new();
CurrentPartition.Name = Name;
CurrentPartition.FirstSector = ByteOperations.ReadUInt64(GPTBuffer, PartitionOffset + 0x20);
CurrentPartition.LastSector = ByteOperations.ReadUInt64(GPTBuffer, PartitionOffset + 0x28);
CurrentPartition.PartitionTypeGuid = ByteOperations.ReadGuid(GPTBuffer, PartitionOffset + 0x00);
CurrentPartition.PartitionGuid = ByteOperations.ReadGuid(GPTBuffer, PartitionOffset + 0x10);
CurrentPartition.Attributes = ByteOperations.ReadUInt64(GPTBuffer, PartitionOffset + 0x30);
Partition CurrentPartition = new()
{
Name = Name,
FirstSector = ByteOperations.ReadUInt64(GPTBuffer, PartitionOffset + 0x20),
LastSector = ByteOperations.ReadUInt64(GPTBuffer, PartitionOffset + 0x28),
PartitionTypeGuid = ByteOperations.ReadGuid(GPTBuffer, PartitionOffset + 0x00),
PartitionGuid = ByteOperations.ReadGuid(GPTBuffer, PartitionOffset + 0x10),
Attributes = ByteOperations.ReadUInt64(GPTBuffer, PartitionOffset + 0x30)
};
Partitions.Add(CurrentPartition);
PartitionOffset += PartitionEntrySize;
}
@@ -275,7 +278,10 @@ namespace WPinternals
{
StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200;
}
catch { }
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
}
if (NewPartition.LastSector == 0)
@@ -331,7 +337,7 @@ namespace WPinternals
}
}
List<Partition> DynamicPartitions = new();
List<Partition> DynamicPartitions = [];
if (Archive != null)
{
// Partitions which are present in the archive, and which have no start-sector in the new GPT data (dynamic relocation),
@@ -471,7 +477,10 @@ namespace WPinternals
{
StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200;
}
catch { }
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
DecompressedStream.Close();
UInt64 MaxPartitionSizeInSectors = OldPartition.SizeInSectors;
@@ -521,7 +530,10 @@ namespace WPinternals
{
StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200;
}
catch { }
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
DecompressedStream.Close();
if (NewPartition.SizeInSectors != StreamLengthInSectors)
{
@@ -0,0 +1,113 @@
// 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.Net;
using System.Xml;
using WPinternals.HelperClasses;
namespace WPinternals.Models.Lumia.MSR
{
internal static class LumiaDownloadModel
{
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 = [];
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 (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("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];
}
}
}
@@ -18,29 +18,21 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using MadWizard.WinUSBNet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using WPinternals.HelperClasses;
namespace WPinternals
namespace WPinternals.Models.Lumia.NCSd
{
internal class NokiaPhoneModel : IDisposable
internal class NokiaCareSuiteModel : NokiaPhoneModel
{
protected bool Disposed = false;
private readonly USBDevice Device = null;
private int MessageId = 0;
private readonly object UsbLock = new();
public NokiaPhoneModel(string DevicePath)
public NokiaCareSuiteModel(string DevicePath) : base(DevicePath)
{
// Mass Storage device is not WinUSB
try
{
Device = new USBDevice(DevicePath);
}
catch { }
}
private JsonElement? ExecuteJsonMethodAsJsonToken(string JsonMethod, Dictionary<string, object> Params, string ResultElement)
@@ -53,7 +45,7 @@ namespace WPinternals
const string jsonrpc = "2.0";
int id = MessageId++;
string method = JsonMethod;
Dictionary<string, object> @params = new();
Dictionary<string, object> @params = [];
if (Params != null)
{
foreach (KeyValuePair<string, object> Param in Params)
@@ -69,27 +61,39 @@ namespace WPinternals
}
}
@params.Add("MessageVersion", 0);
string Request = JsonSerializer.Serialize(new { jsonrpc, id, method, @params });
string Request = JsonSerializer.Serialize(new
{
jsonrpc,
id,
method,
@params
});
Device.OutputPipe.Write(System.Text.Encoding.ASCII.GetBytes(Request));
Buffer = new byte[0x10000];
Length = Device.InputPipe.Read(Buffer);
}
JsonDocument ResultMessage = JsonDocument.Parse(System.Text.Encoding.ASCII.GetString(Buffer, 0, Length));
string ResultString = System.Text.Encoding.ASCII.GetString(Buffer, 0, Length);
JsonDocument ResultMessage = JsonDocument.Parse(ResultString);
try
{
JsonElement? ResultToken = ResultMessage.RootElement.GetProperty("result");
if ((ResultToken == null) || (ResultElement == null))
bool result = ResultMessage.RootElement.TryGetProperty("result", out JsonElement ResultToken);
if (!result || ResultElement == null)
{
return null;
}
return ResultToken.Value.GetProperty(ResultElement);
return ResultToken.GetProperty(ResultElement);
}
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);
return null;
}
}
@@ -173,6 +177,11 @@ namespace WPinternals
return null;
}
if (Token.Value.ValueKind == JsonValueKind.String)
{
return Token.Value.GetString().Equals("true", StringComparison.InvariantCultureIgnoreCase);
}
return Token.Value.GetBoolean();
}
@@ -183,7 +192,7 @@ namespace WPinternals
const string jsonrpc = "2.0";
int id = MessageId++;
string method = JsonMethod;
Dictionary<string, object> @params = new();
Dictionary<string, object> @params = [];
if (Params != null)
{
foreach (KeyValuePair<string, object> Param in Params)
@@ -199,7 +208,13 @@ namespace WPinternals
}
}
@params.Add("MessageVersion", 0);
string Request = JsonSerializer.Serialize(new { jsonrpc, id, method, @params });
string Request = JsonSerializer.Serialize(new
{
jsonrpc,
id,
method,
@params
});
byte[] OutBuffer = System.Text.Encoding.ASCII.GetBytes(Request);
Device.OutputPipe.BeginWrite(OutBuffer, 0, OutBuffer.Length, (AsyncResultWrite) => Device.OutputPipe.EndWrite(AsyncResultWrite), null);
@@ -271,7 +286,7 @@ namespace WPinternals
const string jsonrpc = "2.0";
int id = MessageId++;
string method = JsonMethod;
Dictionary<string, object> @params = new();
Dictionary<string, object> @params = [];
if (Params != null)
{
foreach (KeyValuePair<string, object> Param in Params)
@@ -287,28 +302,34 @@ namespace WPinternals
}
}
@params.Add("MessageVersion", 0);
string Request = JsonSerializer.Serialize(new { jsonrpc, id, method, @params });
string Request = JsonSerializer.Serialize(new
{
jsonrpc,
id,
method,
@params
});
byte[] OutBuffer = System.Text.Encoding.ASCII.GetBytes(Request);
Device.OutputPipe.BeginWrite(OutBuffer, 0, OutBuffer.Length, (AsyncResultWrite) =>
{
Device.OutputPipe.EndWrite(AsyncResultWrite);
Buffer = new byte[0x10000];
Device.InputPipe.BeginRead(Buffer, 0, 0x10000, (AsyncResultRead) =>
{
Device.OutputPipe.EndWrite(AsyncResultWrite);
Buffer = new byte[0x10000];
Device.InputPipe.BeginRead(Buffer, 0, 0x10000, (AsyncResultRead) =>
{
Length = Device.InputPipe.EndRead(AsyncResultRead);
Length = Device.InputPipe.EndRead(AsyncResultRead);
JsonDocument ResultMessage = JsonDocument.Parse(System.Text.Encoding.ASCII.GetString(Buffer, 0, Length));
JsonDocument ResultMessage = JsonDocument.Parse(System.Text.Encoding.ASCII.GetString(Buffer, 0, Length));
JsonElement? ResultToken = ResultMessage.RootElement.GetProperty("result");
if ((ResultToken == null) || (ResultElement == null))
{
Callback(AsyncResultRead.AsyncState, null);
}
JsonElement? ResultToken = ResultMessage.RootElement.GetProperty("result");
if (ResultToken == null || ResultElement == null)
{
Callback(AsyncResultRead.AsyncState, null);
}
Callback(AsyncResultRead.AsyncState, ResultToken.Value.GetProperty(ResultElement));
}, AsyncResultWrite.AsyncState);
}, State);
Callback(AsyncResultRead.AsyncState, ResultToken.Value.GetProperty(ResultElement));
}, AsyncResultWrite.AsyncState);
}, State);
}
}
@@ -316,97 +337,5 @@ namespace WPinternals
{
ExecuteJsonMethodAsTokenAsync(JsonMethod, null, ResultElement, State, Callback);
}
public byte[] ExecuteRawMethod(byte[] RawMethod)
{
return ExecuteRawMethod(RawMethod, RawMethod.Length);
}
public byte[] ExecuteRawMethod(byte[] RawMethod, int Length)
{
byte[] Buffer = new byte[0x8000]; // Should be at least 0x4408 for receiving the GPT packet.
byte[] Result = null;
lock (UsbLock)
{
Device.OutputPipe.Write(RawMethod, 0, Length);
try
{
int OutputLength = Device.InputPipe.Read(Buffer);
Result = new byte[OutputLength];
System.Buffer.BlockCopy(Buffer, 0, Result, 0, OutputLength);
}
catch { } // Reboot command looses connection
}
return Result;
}
public void ExecuteRawVoidMethod(byte[] RawMethod)
{
ExecuteRawVoidMethod(RawMethod, RawMethod.Length);
}
public void ExecuteRawVoidMethod(byte[] RawMethod, int Length)
{
lock (UsbLock)
{
Device.OutputPipe.Write(RawMethod, 0, Length);
}
}
public void ResetDevice()
{
try
{
foreach (var pipe in Device.Pipes)
{
pipe.Abort();
pipe.Reset();
}
}
catch { }
}
/// <summary>
/// Disposes the UsbDevice including all unmanaged WinUSB handles. This function
/// should be called when the UsbDevice object is no longer in use, otherwise
/// unmanaged handles will remain open until the garbage collector finalizes the
/// object.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Finalizer for the UsbDevice. Disposes all unmanaged handles.
/// </summary>
~NokiaPhoneModel()
{
Dispose(false);
}
/// <summary>
/// Disposes the object
/// </summary>
/// <param name="disposing">Indicates wether Dispose was called manually (true) or by
/// the garbage collector (false) via the destructor.</param>
protected virtual void Dispose(bool disposing)
{
if (Disposed)
{
return;
}
if (disposing)
{
Device?.Dispose();
}
// Clean unmanaged resources here.
// (none currently)
Disposed = true;
}
}
}
+105
View File
@@ -0,0 +1,105 @@
// 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 MadWizard.WinUSBNet;
using System;
using WPinternals.HelperClasses;
namespace WPinternals.Models.Lumia
{
internal class NokiaPhoneModel : IDisposable
{
protected bool Disposed = false;
internal readonly USBDevice Device = null;
internal readonly object UsbLock = new();
public NokiaPhoneModel(string DevicePath)
{
// Mass Storage device is not WinUSB
try
{
Device = new USBDevice(DevicePath);
}
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
}
public void ResetDevice()
{
try
{
foreach (USBPipe pipe in Device.Pipes)
{
pipe.Abort();
pipe.Reset();
}
}
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
}
/// <summary>
/// Disposes the UsbDevice including all unmanaged WinUSB handles. This function
/// should be called when the UsbDevice object is no longer in use, otherwise
/// unmanaged handles will remain open until the garbage collector finalizes the
/// object.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Finalizer for the UsbDevice. Disposes all unmanaged handles.
/// </summary>
~NokiaPhoneModel()
{
Dispose(false);
}
/// <summary>
/// Disposes the object
/// </summary>
/// <param name="disposing">Indicates wether Dispose was called manually (true) or by
/// the garbage collector (false) via the destructor.</param>
protected virtual void Dispose(bool disposing)
{
if (Disposed)
{
return;
}
if (disposing)
{
Device?.Dispose();
}
// Clean unmanaged resources here.
// (none currently)
Disposed = true;
}
}
}
@@ -0,0 +1,405 @@
// 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 WPinternals.HelperClasses;
using WPinternals.Models.Lumia.UEFI;
namespace WPinternals.Models.UEFIApps.BootMgr
{
internal class LumiaBootManagerAppModel : NokiaUEFIModel
{
internal readonly LumiaBootManagerPhoneInfo BootManagerInfo = new();
internal enum SecureBootKeyType : byte
{
Retail = 0,
Engineering = 1
}
//
// Not valid commands
//
/* NOK */
private const string Signature = "NOK";
/* NOKX */
private const string ExtendedMessageSignature = $"{Signature}X";
/* NOKXB */
private const string LumiaBootManagerExtendedMessageSignature = $"{ExtendedMessageSignature}B";
//
// Normal commands
//
/* NOKA */
private const string ContinueBootSignature = $"{Signature}A";
/* NOKB */
private const string RPMBSignature = $"{Signature}B";
/* NOKC */
private const string BatteryStatusSignature = $"{Signature}C";
/* NOKD */
private const string DisableTimeoutsSignature = $"{Signature}D";
/* NOKI */
private const string HelloSignature = $"{Signature}I";
/* NOKM */
private const string RebootToMassStorageSignature = $"{Signature}M";
/* NOKP */
private const string RebootToPhoneInfoAppSignature = $"{Signature}P";
/* NOKR */
private const string RebootSignature = $"{Signature}R";
/* NOKS */
private const string RebootToFlashAppSignature = $"{Signature}S";
/* NOKT */
private const string GetGPTSignature = $"{Signature}T";
/* NOKV */
private const string InfoQuerySignature = $"{Signature}V";
/* NOKW */
private const string WriteBootFlagFileSignature = $"{Signature}W";
/* NOKY */
private const string MMOSStartCommandSignature = $"{Signature}Y";
/* NOKZ */
private const string ShutdownSignature = $"{Signature}Z";
//
// Lumia Boot Manager extended commands
//
/* NOKXBD */
private const string PlatformSecureBootEnableSignature = $"{LumiaBootManagerExtendedMessageSignature}D";
/* NOKXBH */
private const string WriteRootCertificateHashSignature = $"{LumiaBootManagerExtendedMessageSignature}H";
/* NOKXBK */
private const string UEFIKeysProvisionSignature = $"{LumiaBootManagerExtendedMessageSignature}K";
/* NOKXBR */
private const string ReadManufacturingStateSignature = $"{LumiaBootManagerExtendedMessageSignature}R";
/* NOKXBU */
private const string FlushVariablesSignature = $"{LumiaBootManagerExtendedMessageSignature}U";
/* NOKXBW */
private const string WriteManufacturingStateSignature = $"{LumiaBootManagerExtendedMessageSignature}W";
public LumiaBootManagerAppModel(string DevicePath) : base(DevicePath)
{
}
internal void ResetToMassStorageMode()
{
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, RebootToMassStorageSignature);
byte[] Response = ExecuteRawMethod(Request);
if (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU")
{
throw new NotSupportedException();
}
UInt16 Error = (UInt16)((Response[6] << 8) + Response[7]);
if (Error > 0)
{
throw new NotSupportedException("SendCommonExtendedSwitchToCommand: Error 0x" + Error.ToString("X4"));
}
}
internal void ContinueBoot()
{
LogFile.Log("Continue boot...");
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, ContinueBootSignature);
ExecuteRawVoidMethod(Request);
}
internal LumiaBootManagerPhoneInfo ReadPhoneInfo(bool ExtendedInfo = true)
{
// NOKH = Get Phone Info (IMEI and info from Product.dat) - Not available on some phones, like Lumia 640.
// NOKV = Info Query
bool PhoneInfoLogged = BootManagerInfo.State != PhoneInfoState.Empty;
ReadPhoneInfoBootManager();
LumiaBootManagerPhoneInfo Result = BootManagerInfo;
if (!PhoneInfoLogged)
{
Result.Log(LogType.FileOnly);
}
return Result;
}
internal LumiaBootManagerPhoneInfo ReadPhoneInfoBootManager()
{
// NOKH = Get Phone Info (IMEI and info from Product.dat) - Not available on some phones, like Lumia 640.
// NOKV = Info Query
LumiaBootManagerPhoneInfo Result = BootManagerInfo;
if (Result.State == PhoneInfoState.Empty)
{
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, InfoQuerySignature);
byte[] Response = ExecuteRawMethod(Request);
if (Response != null && ByteOperations.ReadAsciiString(Response, 0, 4) != "NOKU")
{
Result.App = (FlashAppType)Response[5];
switch (Result.App)
{
case FlashAppType.BootManager:
Result.BootManagerProtocolVersionMajor = Response[6];
Result.BootManagerProtocolVersionMinor = Response[7];
Result.BootManagerVersionMajor = Response[8];
Result.BootManagerVersionMinor = Response[9];
break;
}
byte SubblockCount = Response[10];
int SubblockOffset = 11;
for (int i = 0; i < SubblockCount; i++)
{
byte SubblockID = Response[SubblockOffset + 0x00];
LogFile.Log($"{Result.App} SubblockID: 0x{SubblockID:X}");
ushort SubblockLength = BigEndian.ToUInt16(Response, SubblockOffset + 0x01);
int SubblockPayloadOffset = SubblockOffset + 3;
switch (SubblockID)
{
case 0x01:
Result.TransferSize = BigEndian.ToUInt32(Response, SubblockPayloadOffset);
break;
case 0x04:
Result.FlashAppProtocolVersionMajor = Response[SubblockPayloadOffset + 0x00];
Result.FlashAppProtocolVersionMinor = Response[SubblockPayloadOffset + 0x01];
Result.FlashAppVersionMajor = Response[SubblockPayloadOffset + 0x02];
Result.FlashAppVersionMinor = Response[SubblockPayloadOffset + 0x03];
break;
case 0x1F:
Result.MmosOverUsbSupported = Response[SubblockPayloadOffset] == 1;
break;
case 0x20:
// CRC header info
break;
}
SubblockOffset += SubblockLength + 3;
}
}
Result.State = PhoneInfoState.Basic;
}
return Result;
}
internal GPT ReadGPT()
{
// If this function is used with a locked BootMgr v1,
// then the mode-switching should be done outside this function,
// because the context-switches that are used here are not supported on BootMgr v1.
// Only works in BootLoader-mode or on unlocked bootloaders in Flash-mode!!
byte[] Request = new byte[0x04];
const string Header = GetGPTSignature;
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
byte[] Buffer = ExecuteRawMethod(Request);
if (Buffer == null || Buffer.Length < 0x4408)
{
throw new InvalidOperationException("Unable to read GPT!");
}
ushort Error = (ushort)((Buffer[6] << 8) + Buffer[7]);
if (Error > 0)
{
throw new NotSupportedException("ReadGPT: Error 0x" + Error.ToString("X4"));
}
byte[] GPTBuffer = new byte[Buffer.Length - 0x208];
System.Buffer.BlockCopy(Buffer, 0x208, GPTBuffer, 0, 0x4200);
return new GPT(GPTBuffer); // NOKT message header and MBR are ignored
}
internal byte[] GetGptChunk(uint Size) // TODO!
{
// This function is also used to generate a dummy chunk to flash for testing.
// The dummy chunk will contain the GPT, so it can be flashed to the first sectors for testing.
byte[] GPTChunk = new byte[Size];
byte[] Request = new byte[0x04];
const string Header = "NOKT";
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
byte[] Buffer = ExecuteRawMethod(Request);
if (Buffer == null || Buffer.Length < 0x4408)
{
throw new InvalidOperationException("Unable to read GPT!");
}
ushort Error = (ushort)((Buffer[6] << 8) + Buffer[7]);
if (Error > 0)
{
throw new NotSupportedException("ReadGPT: Error 0x" + Error.ToString("X4"));
}
System.Buffer.BlockCopy(Buffer, 8, GPTChunk, 0, 0x4400);
return GPTChunk;
}
internal void ProvisionSecureBootKeys(SecureBootKeyType KeyType) // Only for Flashmode, not BootManager mode.
{
byte[] Request = new byte[8];
ByteOperations.WriteAsciiString(Request, 0, UEFIKeysProvisionSignature);
Request[6] = 0; // Options
Request[7] = (byte)KeyType;
byte[] Response = ExecuteRawMethod(Request);
uint Status = ByteOperations.ReadUInt32(Response, 6);
if (Status != 0)
{
ThrowFlashError((int)Status);
}
}
private void ThrowFlashError(int ErrorCode)
{
string SubMessage = ErrorCode switch
{
0x0008 => "Unsupported protocol / Invalid options",
0x000F => "Invalid sub block count",
0x0010 => "Invalid sub block length",
0x0012 => "Authentication required",
0x000E => "Invalid sub block type",
0x0013 => "Failed async message",
0x1000 => "Invalid header type",
0x1001 => "FFU header contain unknown extra data",
0x0001 => "Couldn't allocate memory",
0x1106 => "Security header validation failed",
0x1105 => "Invalid hash table size",
0x1104 => "Invalid catalog size",
0x1103 => "Invalid chunk size",
0x1102 => "Unsupported algorithm",
0x1101 => "Invalid struct size",
0x1100 => "Invalid signature",
0x1202 => "Invalid struct size",
0x1203 => "Unsupported algorithm",
0x1204 => "Invalid chunk size",
0x1005 => "Data not aligned correctly",
0x0009 => "Locate protocol failed",
0x1003 => "Hash mismatch",
0x1006 => "Couldn't find hash from security header for index",
0x1004 => "Security header import missing / All FFU headers have not been imported",
0x1304 => "Invalid platform ID",
0x1307 => "Invalid write descriptor info",
0x1306 => "Invalid write descriptor info",
0x1305 => "Invalid block size",
0x1303 => "Unsupported FFU version",
0x1302 => "Unsupported struct version",
0x1301 => "Invalid update type",
0x100B => "Too much payload data, all data has already been written",
0x1008 => "Internal error",
0x1007 => "Payload data does not contain all data",
0x0004 => "Flash write failed",
0x000D => "Flash verify failed",
0x0002 => "Flash read failed",
_ => "Unknown error",
};
WPinternalsException Ex = new("Flash failed!")
{
SubMessage = "Error 0x" + ErrorCode.ToString("X4") + ": " + SubMessage
};
throw Ex;
}
public void Shutdown()
{
byte[] Request = new byte[4];
const string Header = ShutdownSignature;
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
ExecuteRawMethod(Request);
}
internal void ResetPhone()
{
LogFile.Log("Rebooting phone", LogType.FileAndConsole);
try
{
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, RebootSignature);
ExecuteRawVoidMethod(Request);
}
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("Sending reset-request failed", LogType.FileOnly);
LogFile.Log("Assuming automatic reset already in progress", LogType.FileOnly);
}
}
internal void ResetPhoneToFlashMode()
{
LumiaBootManagerPhoneInfo info = ReadPhoneInfoBootManager();
bool ModernFlashApp = info.BootManagerVersionMajor >= 2;
// This only works when the phone is in BootMgr mode. If it is already in FlashApp, it will not reboot. It only makes the phone unresponsive.
LogFile.Log("Rebooting phone to Flash mode...");
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, RebootToFlashAppSignature);
ExecuteRawVoidMethod(Request);
if (ModernFlashApp)
{
//DisableRebootTimeOut();
info.App = FlashAppType.FlashApp;
RaiseInterfaceChanged(PhoneInterfaces.Lumia_Flash);
}
}
internal void SwitchToPhoneInfoAppContextLegacy()
{
LumiaBootManagerPhoneInfo info = ReadPhoneInfoBootManager();
bool ModernFlashApp = info.BootManagerVersionMajor >= 2;
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, RebootToPhoneInfoAppSignature);
ExecuteRawVoidMethod(Request);
if (ModernFlashApp)
{
DisableRebootTimeOut();
info.App = FlashAppType.PhoneInfoApp;
RaiseInterfaceChanged(PhoneInterfaces.Lumia_PhoneInfo);
}
}
}
}
@@ -0,0 +1,60 @@
// 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 WPinternals.HelperClasses;
using WPinternals.Models.Lumia.UEFI;
namespace WPinternals.Models.UEFIApps.BootMgr
{
internal class LumiaBootManagerPhoneInfo
{
public PhoneInfoState State = PhoneInfoState.Empty;
public FlashAppType App;
public byte FlashAppVersionMajor;
public byte FlashAppVersionMinor;
public byte FlashAppProtocolVersionMajor;
public byte FlashAppProtocolVersionMinor;
public byte BootManagerVersionMajor;
public byte BootManagerVersionMinor;
public byte BootManagerProtocolVersionMajor;
public byte BootManagerProtocolVersionMinor;
public uint TransferSize;
public bool MmosOverUsbSupported;
internal void Log(LogType Type)
{
switch (App)
{
case FlashAppType.BootManager:
LogFile.Log($"Bootmanager: {BootManagerVersionMajor}.{BootManagerVersionMinor}", Type);
LogFile.Log($"Bootmanager protocol: {BootManagerProtocolVersionMajor}.{BootManagerProtocolVersionMinor}", Type);
LogFile.Log($"Flash app: {FlashAppVersionMajor}.{FlashAppVersionMinor}", Type);
LogFile.Log($"Flash protocol: {FlashAppProtocolVersionMajor}.{FlashAppProtocolVersionMinor}", Type);
LogFile.Log($"Flash app: {FlashAppVersionMajor}.{FlashAppVersionMinor}", Type);
LogFile.Log($"Flash protocol: {FlashAppProtocolVersionMajor}.{FlashAppProtocolVersionMinor}", Type);
break;
}
}
}
}
@@ -0,0 +1,63 @@
// 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.
// 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 WPinternals.HelperClasses;
namespace WPinternals.Models.Lumia.UEFI
{
internal class CommonPhoneInfo
{
public PhoneInfoState State = PhoneInfoState.Empty;
public FlashAppType App;
public byte VersionMajor;
public byte VersionMinor;
public byte ProtocolVersionMajor;
public byte ProtocolVersionMinor;
internal void Log(LogType Type)
{
LogFile.Log($"App: {VersionMajor}.{VersionMinor}", Type);
LogFile.Log($"Protocol: {ProtocolVersionMajor}.{ProtocolVersionMinor}", Type);
}
}
}

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