Author SHA1 Message Date
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
186 changed files with 6833 additions and 5808 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 }}
+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
{
+48 -519
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
{
@@ -85,20 +91,14 @@ namespace WPinternals
PhoneNotifierViewModel Notifier;
LumiaFlashAppModel FlashModel;
LumiaBootManagerAppModel BootMgrModel;
LumiaPhoneInfoAppModel PhoneInfoModel;
NokiaPhoneModel NormalModel;
NokiaCareSuiteModel NormalModel;
LumiaFlashAppPhoneInfo FlashInfo;
LumiaPhoneInfoAppPhoneInfo PhoneInfo;
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 = "";
@@ -156,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;
}
@@ -185,10 +189,8 @@ namespace WPinternals
{
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
BootMgrModel = (LumiaBootManagerAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader); // This also works for Bootloader Spec A
GPT GPT = BootMgrModel.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);
@@ -216,8 +218,8 @@ namespace WPinternals
{
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
BootMgrModel = (LumiaBootManagerAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader);
GPT GPT = BootMgrModel.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))
{
@@ -244,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
@@ -275,8 +277,7 @@ namespace WPinternals
{
Notifier = new PhoneNotifierViewModel();
UIContext.Send(s => Notifier.Start(), null);
BootMgrModel = (LumiaBootManagerAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader);
byte[] GptChunk = BootMgrModel.GetGptChunk(0x20000);
byte[] GptChunk = await LumiaUnlockBootloaderViewModel.GetGptChunkFromFlashOrBootMgr(Notifier, 0x20000);
GPT GPT = new(GptChunk);
string Xml = File.ReadAllText(args[2]);
GPT.MergePartitions(Xml, false);
@@ -1267,218 +1268,13 @@ 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.CurrentModel as LumiaBootManagerAppModel).SwitchToPhoneInfoAppContext();
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
{
await Notifier.WaitForArrival();
}
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
{
throw new WPinternalsException("Unexpected Mode");
}
PhoneInfoModel = (LumiaPhoneInfoAppModel)Notifier.CurrentModel;
PhoneInfo = PhoneInfoModel.ReadPhoneInfo();
ProductCode = PhoneInfo.ProductCode;
}
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_PhoneInfo)
{
PhoneInfoModel = (LumiaPhoneInfoAppModel)Notifier.CurrentModel;
PhoneInfo = PhoneInfoModel.ReadPhoneInfo();
ProductCode = PhoneInfo.ProductCode;
}
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash)
{
bool ModernFlashApp = ((LumiaFlashAppModel)Notifier.CurrentModel).ReadPhoneInfo().FlashAppProtocolVersionMajor >= 2;
if (ModernFlashApp)
{
((LumiaFlashAppModel)Notifier.CurrentModel).SwitchToPhoneInfoAppContext();
}
else
{
((LumiaFlashAppModel)Notifier.CurrentModel).SwitchToPhoneInfoAppContextLegacy();
}
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
{
await Notifier.WaitForArrival();
}
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
{
throw new WPinternalsException("Unexpected Mode");
}
PhoneInfoModel = (LumiaPhoneInfoAppModel)Notifier.CurrentModel;
PhoneInfo = PhoneInfoModel.ReadPhoneInfo();
ProductCode = PhoneInfo.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('_'))
{
@@ -1501,7 +1297,7 @@ namespace WPinternals
}
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('_'))
{
@@ -1601,29 +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)
{
BootMgrModel = (LumiaBootManagerAppModel)Notifier.CurrentModel;
BootManagerInfo = BootMgrModel.ReadPhoneInfo();
//ProductCode = BootManagerInfo.ProductCode; // TODO: FIXME
ProductCode = "";
//ProductType = BootManagerInfo.Type; // TODO: FIXME
ProductType = "";
}
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash)
{
FlashModel = (LumiaFlashAppModel)Notifier.CurrentModel;
FlashInfo = FlashModel.ReadPhoneInfo();
//ProductCode = FlashInfo.ProductCode; // TODO: FIXME
ProductCode = "";
//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());
@@ -1633,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)
{
@@ -1678,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;
@@ -1729,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)
{
@@ -1775,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":
@@ -2149,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(2024, 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);
}
}
}
+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(2024, 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,11 +161,11 @@ namespace WPinternals
}
}
public List<FFUEntry> FFURepository = new();
public List<FFUEntry> FFURepository = [];
internal void AddSecWimToRepository(string SecWimPath, string FirmwareVersion)
{
SecWimEntry Entry = SecWimRepository.Find(e => (e.FirmwareVersion == FirmwareVersion) && string.Equals(e.Path, SecWimPath, StringComparison.CurrentCultureIgnoreCase));
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);
@@ -264,14 +207,14 @@ namespace WPinternals
}
}
public List<SecWimEntry> SecWimRepository = new();
public List<SecWimEntry> SecWimRepository = [];
public List<EmergencyFileEntry> EmergencyRepository = new();
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;
@@ -326,111 +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 SecWimEntry
{
public string FirmwareVersion;
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];
}
+10 -7
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(
@@ -429,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();
@@ -446,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
@@ -17,26 +17,24 @@
// 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
namespace WPinternals.HelperClasses
{
internal class CommonPhoneInfo
internal class ArrivalEventArgs : EventArgs
{
public PhoneInfoState State = PhoneInfoState.Empty;
public PhoneInterfaces NewInterface;
public IDisposable NewModel;
public FlashAppType App;
public byte VersionMajor;
public byte VersionMinor;
public byte ProtocolVersionMajor;
public byte ProtocolVersionMinor;
internal void Log(LogType Type)
public ArrivalEventArgs(PhoneInterfaces NewInterface, IDisposable NewModel)
: base()
{
LogFile.Log($"App: {VersionMajor}.{VersionMinor}", Type);
LogFile.Log($"Protocol: {ProtocolVersionMajor}.{ProtocolVersionMinor}", Type);
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);
+12 -9
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;
}
@@ -334,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),
@@ -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,32 +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 (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
}
private JsonElement? ExecuteJsonMethodAsJsonToken(string JsonMethod, Dictionary<string, object> Params, string ResultElement)
@@ -56,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)
@@ -72,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;
}
}
@@ -191,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)
@@ -207,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);
@@ -279,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)
@@ -295,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);
}
}
@@ -324,103 +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 (Exception ex) // Reboot command looses connection
{
LogFile.LogException(ex, LogType.FileOnly);
}
}
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 (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;
}
}
}
+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;
}
}
}
@@ -19,12 +19,12 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.IO;
using System.Linq;
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia.UEFI;
namespace WPinternals
namespace WPinternals.Models.UEFIApps.BootMgr
{
internal class LumiaBootManagerAppModel : NokiaFlashModel
internal class LumiaBootManagerAppModel : NokiaUEFIModel
{
internal readonly LumiaBootManagerPhoneInfo BootManagerInfo = new();
@@ -96,6 +96,26 @@ namespace WPinternals
{
}
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...");
@@ -134,7 +154,7 @@ namespace WPinternals
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, InfoQuerySignature);
byte[] Response = ExecuteRawMethod(Request);
if ((Response != null) && (ByteOperations.ReadAsciiString(Response, 0, 4) != "NOKU"))
if (Response != null && ByteOperations.ReadAsciiString(Response, 0, 4) != "NOKU")
{
Result.App = (FlashAppType)Response[5];
@@ -157,9 +177,8 @@ namespace WPinternals
LogFile.Log($"{Result.App} SubblockID: 0x{SubblockID:X}");
UInt16 SubblockLength = BigEndian.ToUInt16(Response, SubblockOffset + 0x01);
ushort SubblockLength = BigEndian.ToUInt16(Response, SubblockOffset + 0x01);
int SubblockPayloadOffset = SubblockOffset + 3;
byte SubblockVersion;
switch (SubblockID)
{
case 0x01:
@@ -202,12 +221,12 @@ namespace WPinternals
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
byte[] Buffer = ExecuteRawMethod(Request);
if ((Buffer == null) || (Buffer.Length < 0x4408))
if (Buffer == null || Buffer.Length < 0x4408)
{
throw new InvalidOperationException("Unable to read GPT!");
}
UInt16 Error = (UInt16)((Buffer[6] << 8) + Buffer[7]);
ushort Error = (ushort)((Buffer[6] << 8) + Buffer[7]);
if (Error > 0)
{
throw new NotSupportedException("ReadGPT: Error 0x" + Error.ToString("X4"));
@@ -219,7 +238,7 @@ namespace WPinternals
return new GPT(GPTBuffer); // NOKT message header and MBR are ignored
}
internal byte[] GetGptChunk(UInt32 Size) // TODO!
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.
@@ -231,12 +250,12 @@ namespace WPinternals
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
byte[] Buffer = ExecuteRawMethod(Request);
if ((Buffer == null) || (Buffer.Length < 0x4408))
if (Buffer == null || Buffer.Length < 0x4408)
{
throw new InvalidOperationException("Unable to read GPT!");
}
UInt16 Error = (UInt16)((Buffer[6] << 8) + Buffer[7]);
ushort Error = (ushort)((Buffer[6] << 8) + Buffer[7]);
if (Error > 0)
{
throw new NotSupportedException("ReadGPT: Error 0x" + Error.ToString("X4"));
@@ -254,7 +273,7 @@ namespace WPinternals
Request[6] = 0; // Options
Request[7] = (byte)KeyType;
byte[] Response = ExecuteRawMethod(Request);
UInt32 Status = ByteOperations.ReadUInt32(Response, 6);
uint Status = ByteOperations.ReadUInt32(Response, 6);
if (Status != 0)
{
ThrowFlashError((int)Status);
@@ -304,8 +323,10 @@ namespace WPinternals
0x0002 => "Flash read failed",
_ => "Unknown error",
};
WPinternalsException Ex = new("Flash failed!");
Ex.SubMessage = "Error 0x" + ErrorCode.ToString("X4") + ": " + SubMessage;
WPinternalsException Ex = new("Flash failed!")
{
SubMessage = "Error 0x" + ErrorCode.ToString("X4") + ": " + SubMessage
};
throw Ex;
}
@@ -327,8 +348,13 @@ namespace WPinternals
ByteOperations.WriteAsciiString(Request, 0, RebootSignature);
ExecuteRawVoidMethod(Request);
}
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("Sending reset-request failed", LogType.FileOnly);
LogFile.Log("Assuming automatic reset already in progress", LogType.FileOnly);
}
@@ -348,7 +374,7 @@ namespace WPinternals
if (ModernFlashApp)
{
DisableRebootTimeOut();
//DisableRebootTimeOut();
info.App = FlashAppType.FlashApp;
@@ -375,25 +401,5 @@ namespace WPinternals
RaiseInterfaceChanged(PhoneInterfaces.Lumia_PhoneInfo);
}
}
internal void RebootToFlashApp()
{
LumiaBootManagerPhoneInfo info = ReadPhoneInfoBootManager();
bool ModernFlashApp = info.BootManagerVersionMajor >= 2;
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, RebootToFlashAppSignature); // This will let the phone charge
ExecuteRawVoidMethod(Request); // On phone with bootloader Spec A this triggers a reboot, so DisableRebootTimeOut() cannot be called immediately.
if (ModernFlashApp)
{
DisableRebootTimeOut();
info.App = FlashAppType.FlashApp;
RaiseInterfaceChanged(PhoneInterfaces.Lumia_Flash);
}
}
}
}
@@ -18,9 +18,10 @@
// 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
namespace WPinternals.Models.UEFIApps.BootMgr
{
internal class LumiaBootManagerPhoneInfo
{
@@ -38,7 +39,7 @@ namespace WPinternals
public byte BootManagerProtocolVersionMajor;
public byte BootManagerProtocolVersionMinor;
public UInt32 TransferSize;
public uint TransferSize;
public bool MmosOverUsbSupported;
internal void Log(LogType Type)
@@ -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);
}
}
}
@@ -0,0 +1,31 @@
// 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.
namespace WPinternals.Models.UEFIApps.Flash
{
internal enum FfuProtocol
{
ProtocolSyncV1 = 1,
ProtocolAsyncV1 = 2,
ProtocolSyncV2 = 4,
ProtocolAsyncV2 = 8,
ProtocolAsyncV3 = 16
}
}
@@ -0,0 +1,33 @@
// 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;
namespace WPinternals.Models.UEFIApps.Flash
{
[Flags]
internal enum FlashOptions : byte
{
SkipWrite = 1,
SkipHashCheck = 2,
SkipIdCheck = 4,
SkipSignatureCheck = 8
}
}
@@ -18,7 +18,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
namespace WPinternals
namespace WPinternals.Models.Lumia.UEFI.Flash
{
internal class FlashVersion
{
@@ -0,0 +1,44 @@
// 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;
namespace WPinternals.Models.UEFIApps.Flash
{
[Flags]
internal enum Fuse
{
SecureBoot = 1,
FfuVerify = 2,
Jtag = 4,
Shk = 8,
Simlock = 16,
ProductionDone = 32,
Rkh = 64,
PublicId = 128,
Dak = 256,
SecGen = 512,
OemId = 1024,
FastBoot = 2048,
SpdmSecMode = 4096,
RpmWdog = 8192,
Ssm = 16384
}
}
@@ -21,54 +21,15 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia.UEFI;
using WPinternals.Models.Lumia.UEFI.Flash;
using WPinternals.Terminal;
namespace WPinternals
namespace WPinternals.Models.UEFIApps.Flash
{
internal enum SecureBootKeyType : byte
{
Retail = 0,
Engineering = 1
}
[Flags]
internal enum Fuse
{
SecureBoot = 1,
FfuVerify = 2,
Jtag = 4,
Shk = 8,
Simlock = 16,
ProductionDone = 32,
Rkh = 64,
PublicId = 128,
Dak = 256,
SecGen = 512,
OemId = 1024,
FastBoot = 2048,
SpdmSecMode = 4096,
RpmWdog = 8192,
Ssm = 16384
}
internal enum FfuProtocol
{
ProtocolSyncV1 = 1,
ProtocolAsyncV1 = 2,
ProtocolSyncV2 = 4,
ProtocolAsyncV2 = 8,
ProtocolAsyncV3 = 16
}
[Flags]
internal enum FlashOptions : byte
{
SkipWrite = 1,
SkipHashCheck = 2,
SkipIdCheck = 4,
SkipSignatureCheck = 8
}
internal class LumiaFlashAppModel : NokiaFlashModel
internal class LumiaFlashAppModel : NokiaUEFIModel
{
internal readonly LumiaFlashAppPhoneInfo FlashAppInfo = new();
private UefiSecurityStatusResponse _SecurityStatus = null;
@@ -157,6 +118,68 @@ namespace WPinternals
{
}
public void WriteParam(string Param, byte[] Value)
{
// Command: NOKXFW
// Padding (one byte)
// Parameter (4 bytes)
// Length (4 bytes)
// Data
if (Param.Length > 4)
{
throw new ArgumentOutOfRangeException(nameof(Param));
}
byte[] Request = new byte[15 + Param.Length];
const string Header = WriteParamSignature;
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Param), 0, Request, 7, Param.Length);
Buffer.BlockCopy(BigEndian.GetBytes(Value.Length, 4), 0, Request, 11, 4);
Buffer.BlockCopy(Value, 0, Request, 15, Value.Length);
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("WriteParam: Error 0x" + Error.ToString("X4"));
}
}
internal void ResetToMassStorageMode()
{
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, RebootToMassStorageSignature);
byte[] Response = ExecuteRawMethod(Request);
if (Response == null)
{
// Succeeded
return;
}
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 LumiaFlashAppPhoneInfo ReadPhoneInfo(bool ExtendedInfo = true)
{
// NOKH = Get Phone Info (IMEI and info from Product.dat) - Not available on some phones, like Lumia 640.
@@ -167,13 +190,10 @@ namespace WPinternals
LumiaFlashAppPhoneInfo Result = FlashAppInfo;
if (ExtendedInfo && (Result.State == PhoneInfoState.Basic))
if (ExtendedInfo && Result.State == PhoneInfoState.Basic)
{
if (Result.App == FlashAppType.FlashApp)
{
Result.Firmware = ReadStringParam("FVER");
Result.RKH = ReadParam("RRKH");
}
Result.Firmware = ReadStringParam("FVER");
Result.RKH = ReadParam("RRKH");
Result.State = PhoneInfoState.Extended;
}
@@ -198,7 +218,7 @@ namespace WPinternals
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, InfoQuerySignature);
byte[] Response = ExecuteRawMethod(Request);
if ((Response != null) && (ByteOperations.ReadAsciiString(Response, 0, 4) != "NOKU"))
if (Response != null && ByteOperations.ReadAsciiString(Response, 0, 4) != "NOKU")
{
Result.App = (FlashAppType)Response[5];
@@ -221,7 +241,7 @@ namespace WPinternals
LogFile.Log($"{Result.App} SubblockID: 0x{SubblockID:X}");
UInt16 SubblockLength = BigEndian.ToUInt16(Response, SubblockOffset + 0x01);
ushort SubblockLength = BigEndian.ToUInt16(Response, SubblockOffset + 0x01);
int SubblockPayloadOffset = SubblockOffset + 3;
byte SubblockVersion;
switch (SubblockID)
@@ -250,7 +270,7 @@ namespace WPinternals
Result.SecureFfuEnabled = Response[SubblockPayloadOffset + 0x02] == 0x01;
Result.JtagDisabled = Response[SubblockPayloadOffset + 0x03] == 0x01;
Result.RdcPresent = Response[SubblockPayloadOffset + 0x04] == 0x01;
Result.Authenticated = (Response[SubblockPayloadOffset + 0x05] == 0x01) || (Response[SubblockPayloadOffset + 0x05] == 0x02);
Result.Authenticated = Response[SubblockPayloadOffset + 0x05] == 0x01 || Response[SubblockPayloadOffset + 0x05] == 0x02;
Result.UefiSecureBootEnabled = Response[SubblockPayloadOffset + 0x06] == 0x01;
Result.SecondaryHardwareKeyPresent = Response[SubblockPayloadOffset + 0x07] == 0x01;
break;
@@ -277,6 +297,13 @@ namespace WPinternals
return Result;
}
internal bool CanReadGPT()
{
LumiaFlashAppPhoneInfo Info = ReadPhoneInfo(ExtendedInfo: false);
FlashAppType OriginalAppType = Info.App;
return Info.IsBootloaderSecure;
}
internal GPT ReadGPT()
{
// If this function is used with a locked BootMgr v1,
@@ -285,10 +312,7 @@ namespace WPinternals
// Only works in BootLoader-mode or on unlocked bootloaders in Flash-mode!!
LumiaFlashAppPhoneInfo Info = ReadPhoneInfo(ExtendedInfo: false);
FlashAppType OriginalAppType = Info.App;
bool Switch = Info.IsBootloaderSecure;
if (Switch)
if (CanReadGPT())
{
throw new InvalidOperationException("Bootloader is not unlocked!");
}
@@ -299,15 +323,16 @@ namespace WPinternals
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
byte[] Buffer = ExecuteRawMethod(Request);
if ((Buffer == null) || (Buffer.Length < 0x4408))
if (Buffer == null || Buffer.Length < 0x4408)
{
throw new InvalidOperationException("Unable to read GPT!");
}
UInt16 Error = (UInt16)((Buffer[6] << 8) + Buffer[7]);
ushort Error = (ushort)((Buffer[6] << 8) + Buffer[7]);
if (Error > 0)
{
throw new NotSupportedException("ReadGPT: Error 0x" + Error.ToString("X4"));
ThrowFlashError(Error);
//throw new NotSupportedException("ReadGPT: Error 0x" + Error.ToString("X4"));
}
byte[] GPTBuffer = new byte[Buffer.Length - 0x208];
@@ -316,32 +341,35 @@ namespace WPinternals
return new GPT(GPTBuffer); // NOKT message header and MBR are ignored
}
internal byte[] GetGptChunk(UInt32 Size) // TODO!
internal byte[] GetGptChunk(uint Size)
{
// 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];
// 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.
LumiaFlashAppPhoneInfo Info = ReadPhoneInfo(ExtendedInfo: false);
FlashAppType OriginalAppType = Info.App;
bool Switch = Info.IsBootloaderSecure;
if (Switch)
// Only works in BootLoader-mode or on unlocked bootloaders in Flash-mode!!
if (CanReadGPT())
{
throw new InvalidOperationException("Bootloader is not unlocked!");
}
// 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))
if (Buffer == null || Buffer.Length < 0x4408)
{
throw new InvalidOperationException("Unable to read GPT!");
}
UInt16 Error = (UInt16)((Buffer[6] << 8) + Buffer[7]);
ushort Error = (ushort)((Buffer[6] << 8) + Buffer[7]);
if (Error > 0)
{
ThrowFlashError(Error);
@@ -362,7 +390,7 @@ namespace WPinternals
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Param), 0, Request, 7, Param.Length);
byte[] Response = ExecuteRawMethod(Request);
if ((Response == null) || (Response.Length < 0x10))
if (Response == null || Response.Length < 0x10)
{
return null;
}
@@ -386,37 +414,37 @@ namespace WPinternals
public uint? ReadSecurityFlags()
{
byte[] Response = ReadParam("FCS");
if ((Response == null) || (Response.Length != 4))
if (Response == null || Response.Length != 4)
{
return null;
}
// This value is in big endian
return (UInt32)((Response[0] << 24) | (Response[1] << 16) | (Response[2] << 8) | Response[3]);
return (uint)(Response[0] << 24 | Response[1] << 16 | Response[2] << 8 | Response[3]);
}
public uint? ReadCurrentChargeLevel()
{
byte[] Response = ReadParam("CS");
if ((Response == null) || (Response.Length != 8))
if (Response == null || Response.Length != 8)
{
return null;
}
// This value is in big endian
return (UInt32)((Response[0] << 24) | (Response[1] << 16) | (Response[2] << 8) | Response[3]) + 1;
return (uint)(Response[0] << 24 | Response[1] << 16 | Response[2] << 8 | Response[3]) + 1;
}
public int? ReadCurrentChargeCurrent()
{
byte[] Response = ReadParam("CS");
if ((Response == null) || (Response.Length != 8))
if (Response == null || Response.Length != 8)
{
return null;
}
// This value is in big endian and needs to be XOR'd with 0xFFFFFFFF
return (Int32)(((Response[4] << 24) | (Response[5] << 16) | (Response[6] << 8) | Response[7]) ^ 0xFFFFFFFF) + 1;
return (int)((Response[4] << 24 | Response[5] << 16 | Response[6] << 8 | Response[7]) ^ 0xFFFFFFFF) + 1;
}
public UefiSecurityStatusResponse ReadSecurityStatus()
@@ -432,16 +460,17 @@ namespace WPinternals
return null;
}
UefiSecurityStatusResponse Result = new();
Result.IsTestDevice = Response[0];
Result.PlatformSecureBootStatus = Convert.ToBoolean(Response[1]);
Result.SecureFfuEfuseStatus = Convert.ToBoolean(Response[2]);
Result.DebugStatus = Convert.ToBoolean(Response[3]);
Result.RdcStatus = Convert.ToBoolean(Response[4]);
Result.AuthenticationStatus = Convert.ToBoolean(Response[5]);
Result.UefiSecureBootStatus = Convert.ToBoolean(Response[6]);
Result.CryptoHardwareKey = Convert.ToBoolean(Response[7]);
UefiSecurityStatusResponse Result = new()
{
IsTestDevice = Response[0],
PlatformSecureBootStatus = Convert.ToBoolean(Response[1]),
SecureFfuEfuseStatus = Convert.ToBoolean(Response[2]),
DebugStatus = Convert.ToBoolean(Response[3]),
RdcStatus = Convert.ToBoolean(Response[4]),
AuthenticationStatus = Convert.ToBoolean(Response[5]),
UefiSecureBootStatus = Convert.ToBoolean(Response[6]),
CryptoHardwareKey = Convert.ToBoolean(Response[7])
};
_SecurityStatus = Result;
@@ -451,22 +480,23 @@ namespace WPinternals
public FlashVersion GetFlashVersion()
{
byte[] Response = ReadParam("FAI");
if ((Response == null) || (Response.Length < 6))
if (Response == null || Response.Length < 6)
{
return null;
}
FlashVersion Result = new();
Result.ProtocolMajor = Response[1];
Result.ProtocolMinor = Response[2];
Result.ApplicationMajor = Response[3];
Result.ApplicationMinor = Response[4];
FlashVersion Result = new()
{
ProtocolMajor = Response[1],
ProtocolMinor = Response[2],
ApplicationMajor = Response[3],
ApplicationMinor = Response[4]
};
return Result;
}
internal UInt16 ReadSecureFfuSupportedProtocolMask()
internal ushort ReadSecureFfuSupportedProtocolMask()
{
return BigEndian.ToUInt16(ReadParam("SFPI"), 0);
}
@@ -483,10 +513,10 @@ namespace WPinternals
Buffer.BlockCopy(BigEndian.GetBytes(0x00, 4), 0, Request, 0x10, 4); // AsicIndex = 0x00
Buffer.BlockCopy(AsskMask, 0, Request, 0x14, 0x10);
byte[] TerminalResponse = ExecuteRawMethod(Request);
if ((TerminalResponse?.Length > 0x20) && (BigEndian.ToUInt32(TerminalResponse, 0x14) == (TerminalResponse.Length - 0x18)) && (BitConverter.ToUInt32(TerminalResponse, 0x1C) == (TerminalResponse.Length - 0x20)))
if (TerminalResponse?.Length > 0x20 && BigEndian.ToUInt32(TerminalResponse, 0x14) == TerminalResponse.Length - 0x18 && BitConverter.ToUInt32(TerminalResponse, 0x1C) == TerminalResponse.Length - 0x20)
{
// Parse Terminal Response from offset 0x18
return Terminal.Parse(TerminalResponse, 0x18);
return Terminal.Terminal.Parse(TerminalResponse, 0x18);
}
else
{
@@ -524,7 +554,7 @@ namespace WPinternals
}
}
public void SendFfuHeaderV2(UInt32 TotalHeaderLength, UInt32 OffsetForThisPart, byte[] FfuHeader, byte Options = 0)
public void SendFfuHeaderV2(uint TotalHeaderLength, uint OffsetForThisPart, byte[] FfuHeader, byte Options = 0)
{
byte[] Request = new byte[FfuHeader.Length + 0x3C];
@@ -627,7 +657,7 @@ namespace WPinternals
}
}
public void SendFfuPayloadV3(byte[] FfuChunk, UInt32 WriteDescriptorIndex, UInt32 CRC, int Progress = 0, byte Options = 0)
public void SendFfuPayloadV3(byte[] FfuChunk, uint WriteDescriptorIndex, uint CRC, int Progress = 0, byte Options = 0)
{
byte[] Request = new byte[FfuChunk.Length + 0x20];
@@ -691,7 +721,7 @@ namespace WPinternals
}
}
public void LoadMmosBinary(UInt32 TotalLength, UInt32 Offset, bool SkipMmosSupportCheck, byte[] MmosPart)
public void LoadMmosBinary(uint TotalLength, uint Offset, bool SkipMmosSupportCheck, byte[] MmosPart)
{
byte[] Request = new byte[MmosPart.Length + 0x20];
const string Header = LoadSignature;
@@ -763,7 +793,7 @@ namespace WPinternals
Request[6] = 0; // Options
Request[7] = (byte)KeyType;
byte[] Response = ExecuteRawMethod(Request);
UInt32 Status = ByteOperations.ReadUInt32(Response, 6);
uint Status = ByteOperations.ReadUInt32(Response, 6);
if (Status != 0)
{
ThrowFlashError((int)Status);
@@ -813,8 +843,10 @@ namespace WPinternals
0x0002 => "Flash read failed",
_ => "Unknown error",
};
WPinternalsException Ex = new("Flash failed!");
Ex.SubMessage = "Error 0x" + ErrorCode.ToString("X4") + ": " + SubMessage;
WPinternalsException Ex = new("Flash failed!")
{
SubMessage = "Error 0x" + ErrorCode.ToString("X4") + ": " + SubMessage
};
throw Ex;
}
@@ -827,7 +859,7 @@ namespace WPinternals
return null;
}
var finalconfig = (Fuse)flags.Value;
Fuse finalconfig = (Fuse)flags.Value;
return finalconfig.HasFlag(fuse);
}
@@ -842,7 +874,7 @@ namespace WPinternals
return null;
}
public void FlashSectors(UInt32 StartSector, byte[] Data, int Progress = 0)
public void FlashSectors(uint StartSector, byte[] Data, int Progress = 0)
{
// Start sector is in UInt32, so max size of eMMC is 2 TB.
@@ -879,8 +911,13 @@ namespace WPinternals
ByteOperations.WriteAsciiString(Request, 0, RebootSignature);
ExecuteRawVoidMethod(Request);
}
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("Sending reset-request failed", LogType.FileOnly);
LogFile.Log("Assuming automatic reset already in progress", LogType.FileOnly);
}
@@ -903,7 +940,7 @@ namespace WPinternals
byte[] Buffer = NewGPT.Rebuild();
UInt32? HeaderOffset = ByteOperations.FindAscii(Buffer, "EFI PART");
uint? HeaderOffset = ByteOperations.FindAscii(Buffer, "EFI PART");
if (HeaderOffset != 0)
{
throw new BadImageFormatException();
@@ -984,14 +1021,14 @@ namespace WPinternals
throw new WPinternalsException("Flash failed!", "Protocols not supported. The device reports that both Protocol Sync v1 and Protocol Sync v2 are not supported for FFU flashing. Is this an old device?");
}
UInt64 CombinedFFUHeaderSize = FFU.HeaderSize;
ulong CombinedFFUHeaderSize = FFU.HeaderSize;
byte[] FfuHeader = new byte[CombinedFFUHeaderSize];
using (FileStream FfuFile = new(FFU.Path, FileMode.Open, FileAccess.Read))
{
FfuFile.Read(FfuHeader, 0, (int)CombinedFFUHeaderSize);
SendFfuHeaderV1(FfuHeader, Options);
UInt64 Position = CombinedFFUHeaderSize;
ulong Position = CombinedFFUHeaderSize;
byte[] Payload;
int ChunkCount = 0;
@@ -1000,7 +1037,7 @@ namespace WPinternals
// Protocol v1
Payload = new byte[FFU.ChunkSize];
while (Position < (UInt64)FfuFile.Length)
while (Position < (ulong)FfuFile.Length)
{
FfuFile.Read(Payload, 0, Payload.Length);
ChunkCount++;
@@ -1015,12 +1052,12 @@ namespace WPinternals
// Protocol v2
Payload = new byte[Info.WriteBufferSize];
while (Position < (UInt64)FfuFile.Length)
while (Position < (ulong)FfuFile.Length)
{
UInt32 PayloadSize = Info.WriteBufferSize;
if (((UInt64)FfuFile.Length - Position) < PayloadSize)
uint PayloadSize = Info.WriteBufferSize;
if ((ulong)FfuFile.Length - Position < PayloadSize)
{
PayloadSize = (UInt32)((UInt64)FfuFile.Length - Position);
PayloadSize = (uint)((ulong)FfuFile.Length - Position);
Payload = new byte[PayloadSize];
}
@@ -1095,7 +1132,7 @@ namespace WPinternals
private void FlashRawPartition(string Path, Stream Stream, string PartitionName, Action<int, TimeSpan?> ProgressUpdateCallback, ProgressUpdater UpdaterPerSector)
{
GPT GPT = ReadGPT();
FlashRawPartition(Path, Stream, PartitionName, ProgressUpdateCallback, UpdaterPerSector);
FlashRawPartition(GPT, Path, Stream, PartitionName, ProgressUpdateCallback, UpdaterPerSector);
}
private void FlashRawPartition(GPT GPT, string Path, Stream Stream, string PartitionName, Action<int, TimeSpan?> ProgressUpdateCallback, ProgressUpdater UpdaterPerSector)
@@ -1124,25 +1161,25 @@ namespace WPinternals
{
using (InputStream)
{
UInt64? InputStreamLength = null;
ulong? InputStreamLength = null;
try
{
InputStreamLength = (UInt64)InputStream.Length;
InputStreamLength = (ulong)InputStream.Length;
}
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
if ((InputStreamLength != null) && ((UInt64)InputStream.Length > PartitionSize))
if (InputStreamLength != null && (ulong)InputStream.Length > PartitionSize)
{
throw new InvalidOperationException("Partition can not be flashed, because its size is too big!");
}
ProgressUpdater Progress = UpdaterPerSector;
if ((Progress == null) && (ProgressUpdateCallback != null) && (InputStreamLength != null))
if (Progress == null && ProgressUpdateCallback != null && InputStreamLength != null)
{
Progress = new ProgressUpdater((UInt64)(InputStreamLength / 0x200), ProgressUpdateCallback);
Progress = new ProgressUpdater((ulong)(InputStreamLength / 0x200), ProgressUpdateCallback);
}
int ProgressPercentage = 0;
@@ -1150,7 +1187,7 @@ namespace WPinternals
const int FlashBufferSize = 0x200000; // Flash 8 GB phone -> buffersize 0x200000 = 11:45 min, buffersize 0x20000 = 12:30 min
byte[] FlashBuffer = new byte[FlashBufferSize];
int BytesRead;
UInt64 i = 0;
ulong i = 0;
do
{
BytesRead = InputStream.Read(FlashBuffer, 0, FlashBufferSize);
@@ -1168,12 +1205,12 @@ namespace WPinternals
Buffer.BlockCopy(FlashBuffer, 0, FlashBufferFinalSize, 0, BytesRead);
}
FlashSectors((UInt32)(Partition.FirstSector + (i / 0x200)), FlashBufferFinalSize, ProgressPercentage);
FlashSectors((uint)(Partition.FirstSector + i / 0x200), FlashBufferFinalSize, ProgressPercentage);
}
if (Progress != null)
{
Progress.IncreaseProgress((UInt64)FlashBuffer.Length / 0x200);
Progress.IncreaseProgress((ulong)FlashBuffer.Length / 0x200);
ProgressPercentage = Progress.ProgressPercentage;
}
@@ -18,9 +18,10 @@
// 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
namespace WPinternals.Models.UEFIApps.Flash
{
internal class LumiaFlashAppPhoneInfo
{
@@ -36,13 +37,13 @@ namespace WPinternals
public byte FlashAppProtocolVersionMajor;
public byte FlashAppProtocolVersionMinor;
public UInt32 TransferSize;
public uint TransferSize;
public bool MmosOverUsbSupported;
public UInt32 SdCardSizeInSectors;
public UInt32 WriteBufferSize;
public UInt32 EmmcSizeInSectors;
public uint SdCardSizeInSectors;
public uint WriteBufferSize;
public uint EmmcSizeInSectors;
public string PlatformID;
public UInt16 SecureFfuSupportedProtocolMask;
public ushort SecureFfuSupportedProtocolMask;
public bool AsyncSupport;
public bool PlatformSecureBootEnabled;
@@ -78,14 +79,14 @@ namespace WPinternals
break;
}
LogFile.Log($"SecureBoot: {((!PlatformSecureBootEnabled || !UefiSecureBootEnabled) ? "Disabled" : "Enabled")} (Platform Secure Boot: {(PlatformSecureBootEnabled ? "Enabled" : "Disabled")}, UEFI Secure Boot: {(UefiSecureBootEnabled ? "Enabled" : "Disabled")})", Type);
LogFile.Log($"SecureBoot: {(!PlatformSecureBootEnabled || !UefiSecureBootEnabled ? "Disabled" : "Enabled")} (Platform Secure Boot: {(PlatformSecureBootEnabled ? "Enabled" : "Disabled")}, UEFI Secure Boot: {(UefiSecureBootEnabled ? "Enabled" : "Disabled")})", Type);
if ((Type == LogType.ConsoleOnly) || (Type == LogType.FileAndConsole))
if (Type == LogType.ConsoleOnly || Type == LogType.FileAndConsole)
{
LogFile.Log($"Flash app security: {(!IsBootloaderSecure ? "Disabled" : "Enabled")}", LogType.ConsoleOnly);
}
if ((Type == LogType.FileOnly) || (Type == LogType.FileAndConsole))
if (Type == LogType.FileOnly || Type == LogType.FileAndConsole)
{
LogFile.Log($"Flash app security: {(!IsBootloaderSecure ? "Disabled" : "Enabled")} (FFU security: {(SecureFfuEnabled ? "Enabled" : "Disabled")}, RDC: {(RdcPresent ? "Present" : "Not found")}, Authenticated: {(Authenticated ? "True" : "False")})", LogType.FileOnly);
}
@@ -0,0 +1,28 @@
// 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.
namespace WPinternals.Models.UEFIApps.Flash
{
internal enum SecureBootKeyType : byte
{
Retail = 0,
Engineering = 1
}
}
@@ -18,7 +18,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
namespace WPinternals
namespace WPinternals.Models.Lumia.UEFI.Flash
{
internal class UefiSecurityStatusResponse
{
@@ -18,7 +18,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
namespace WPinternals
namespace WPinternals.Models.Lumia.UEFI
{
internal enum FlashAppType
{
@@ -0,0 +1,122 @@
// 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;
namespace WPinternals.Models.Lumia.UEFI
{
internal partial class NokiaUEFIModel : NokiaPhoneModel
{
internal void SwitchToFlashAppContext()
{
CommonPhoneInfo info = ReadPhoneInfoCommon();
bool ModernFlashApp = info.VersionMajor >= 2;
SendCommonExtendedSwitchToCommand('F');
if (ModernFlashApp)
{
DisableRebootTimeOut();
InterfaceChanged(PhoneInterfaces.Lumia_Flash, _devicePath);
}
}
internal void SwitchToPhoneInfoAppContext()
{
CommonPhoneInfo info = ReadPhoneInfoCommon();
bool ModernFlashApp = info.VersionMajor >= 2;
SendCommonExtendedSwitchToCommand('P');
if (ModernFlashApp)
{
DisableRebootTimeOut();
CommonInfo.App = FlashAppType.PhoneInfoApp;
InterfaceChanged(PhoneInterfaces.Lumia_PhoneInfo, _devicePath);
}
}
internal void SwitchToBootManagerContext(bool DisableTimeOut = true)
{
CommonPhoneInfo info = ReadPhoneInfoCommon();
bool ModernFlashApp = info.VersionMajor >= 2;
SendCommonExtendedSwitchToCommand('B');
if (ModernFlashApp)
{
DisableRebootTimeOut();
InterfaceChanged(PhoneInterfaces.Lumia_Bootloader, _devicePath);
}
}
internal void SwitchToMmosContext()
{
SendCommonExtendedSwitchToCommand('A');
}
internal void SwitchToNormalModeContext()
{
SendCommonExtendedSwitchToCommand('W');
}
internal void SwitchToMassStorageModeContext()
{
SendCommonExtendedSwitchToCommand('M');
}
internal void SwitchToResetContext()
{
SendCommonExtendedSwitchToCommand('R');
}
internal void SwitchToEmergencyMode()
{
SendCommonExtendedSwitchToCommand('E');
}
internal void SendCommonExtendedSwitchToCommand(char Mode)
{
byte[] Request = new byte[7];
ByteOperations.WriteAsciiString(Request, 0, $"{SwitchModeSignature}{Mode}");
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"));
}
}
}
}
@@ -19,12 +19,13 @@
// DEALINGS IN THE SOFTWARE.
using System;
using WPinternals.HelperClasses;
namespace WPinternals
namespace WPinternals.Models.Lumia.UEFI
{
internal delegate void InterfaceChangedHandler(PhoneInterfaces NewInterface, string DevicePath);
internal class NokiaFlashModel : NokiaPhoneModel
internal partial class NokiaUEFIModel : NokiaPhoneModel
{
private string _devicePath;
@@ -50,115 +51,11 @@ namespace WPinternals
/* NOKXCE */
private const string EchoSignature = $"{CommonExtendedMessageSignature}E";
public NokiaFlashModel(string DevicePath) : base(DevicePath)
public NokiaUEFIModel(string DevicePath) : base(DevicePath)
{
_devicePath = DevicePath;
}
internal void SwitchToBootManagerContext(bool DisableTimeOut = true)
{
CommonPhoneInfo info = ReadPhoneInfoCommon();
bool ModernFlashApp = info.VersionMajor >= 2;
byte[] Request = new byte[7];
ByteOperations.WriteAsciiString(Request, 0, $"{SwitchModeSignature}B");
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("SwitchToBootManagerContext: Error 0x" + Error.ToString("X4"));
}
if (ModernFlashApp)
{
DisableRebootTimeOut();
InterfaceChanged(PhoneInterfaces.Lumia_Bootloader, _devicePath);
}
}
internal void SwitchToPhoneInfoAppContext()
{
CommonPhoneInfo info = ReadPhoneInfoCommon();
bool ModernFlashApp = info.VersionMajor >= 2;
byte[] Request = new byte[7];
ByteOperations.WriteAsciiString(Request, 0, SwitchModeSignature + "P");
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("SwitchToPhoneInfoAppContext: Error 0x" + Error.ToString("X4"));
}
if (ModernFlashApp)
{
DisableRebootTimeOut();
CommonInfo.App = FlashAppType.PhoneInfoApp;
InterfaceChanged(PhoneInterfaces.Lumia_PhoneInfo, _devicePath);
}
}
internal void SwitchToMmosContext()
{
byte[] Request = new byte[7];
ByteOperations.WriteAsciiString(Request, 0, $"{SwitchModeSignature}A");
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("SwitchToPhoneInfoAppContext: Error 0x" + Error.ToString("X4"));
}
}
internal void SwitchToFlashAppContext()
{
CommonPhoneInfo info = ReadPhoneInfoCommon();
bool ModernFlashApp = info.VersionMajor >= 2;
byte[] Request = new byte[7];
ByteOperations.WriteAsciiString(Request, 0, $"{SwitchModeSignature}F"); // This will stop charging the phone
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("SwitchToFlashAppContext: Error 0x" + Error.ToString("X4"));
}
if (ModernFlashApp)
{
DisableRebootTimeOut();
InterfaceChanged(PhoneInterfaces.Lumia_Flash, _devicePath);
}
}
//
// Normal commands
//
@@ -237,5 +134,46 @@ namespace WPinternals
{
InterfaceChanged(NewInterface, _devicePath);
}
// Raw USB Interfaces
protected byte[] ExecuteRawMethod(byte[] RawMethod)
{
return ExecuteRawMethod(RawMethod, RawMethod.Length);
}
protected 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 (Exception ex) // Reboot command looses connection
{
LogFile.LogException(ex, LogType.FileOnly);
}
}
return Result;
}
protected void ExecuteRawVoidMethod(byte[] RawMethod)
{
ExecuteRawVoidMethod(RawMethod, RawMethod.Length);
}
protected void ExecuteRawVoidMethod(byte[] RawMethod, int Length)
{
lock (UsbLock)
{
Device.OutputPipe.Write(RawMethod, 0, Length);
}
}
}
}
@@ -20,12 +20,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia.UEFI;
namespace WPinternals
namespace WPinternals.Models.UEFIApps.PhoneInfo
{
internal class LumiaPhoneInfoAppModel : NokiaFlashModel
internal class LumiaPhoneInfoAppModel : NokiaUEFIModel
{
internal readonly LumiaPhoneInfoAppPhoneInfo PhoneInfoAppInfo = new();
@@ -84,12 +84,12 @@ namespace WPinternals
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, GetPhoneInfoSignature);
byte[] Response = ExecuteRawMethod(Request);
if ((Response == null) || (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU"))
if (Response == null || ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU")
{
throw new NotSupportedException();
}
UInt16 Length = BigEndian.ToUInt16(Response, 0x04);
ushort Length = BigEndian.ToUInt16(Response, 0x04);
string PhoneInfoData = ByteOperations.ReadAsciiString(Response, 0x8, Length);
@@ -106,7 +106,7 @@ namespace WPinternals
LumiaPhoneInfoAppPhoneInfo Result = PhoneInfoAppInfo;
if (ExtendedInfo && (Result.State == PhoneInfoState.Basic))
if (ExtendedInfo && Result.State == PhoneInfoState.Basic)
{
try
{
@@ -177,7 +177,7 @@ namespace WPinternals
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, InfoQuerySignature);
byte[] Response = ExecuteRawMethod(Request);
if ((Response != null) && (ByteOperations.ReadAsciiString(Response, 0, 4) != "NOKU"))
if (Response != null && ByteOperations.ReadAsciiString(Response, 0, 4) != "NOKU")
{
Result.App = (FlashAppType)Response[5];
@@ -200,9 +200,8 @@ namespace WPinternals
LogFile.Log($"{Result.App} SubblockID: 0x{SubblockID:X}");
UInt16 SubblockLength = BigEndian.ToUInt16(Response, SubblockOffset + 0x01);
ushort SubblockLength = BigEndian.ToUInt16(Response, SubblockOffset + 0x01);
int SubblockPayloadOffset = SubblockOffset + 3;
byte SubblockVersion;
switch (SubblockID)
{
case 0x20:
@@ -226,7 +225,7 @@ namespace WPinternals
byte[] Request = new byte[16];
ByteOperations.WriteAsciiString(Request, 0, GetVariableSignature + VariableName + "\0"); // BTR or CTR, CTR is public ProductCode
byte[] Response = ExecuteRawMethod(Request);
UInt16 Length = BigEndian.ToUInt16(Response, 6);
ushort Length = BigEndian.ToUInt16(Response, 6);
return ByteOperations.ReadAsciiString(Response, 8, Length).Trim([' ', '\0']);
}
@@ -18,9 +18,31 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace WPinternals
// 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.PhoneInfo
{
internal class LumiaPhoneInfoAppPhoneInfo
{
@@ -51,7 +73,7 @@ namespace WPinternals
LogFile.Log($"Product code: {ProductCode}", Type);
}
if (Type != LogType.ConsoleOnly && (Imei != null))
if (Type != LogType.ConsoleOnly && Imei != null)
{
LogFile.Log($"IMEI: {Imei}", LogType.FileOnly);
}
@@ -18,7 +18,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
namespace WPinternals
namespace WPinternals.Models.Lumia.UEFI
{
internal enum PhoneInfoState
{
-859
View File
@@ -1,859 +0,0 @@
// 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.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
namespace WPinternals
{
internal static class LumiaDownloadModel
{
internal static string SearchFFU(string ProductType, string ProductCode, string OperatorCode)
{
return SearchFFU(ProductType, ProductCode, OperatorCode, out string FoundProductType);
}
internal static string SearchFFU(string ProductType, string ProductCode, string OperatorCode, out string FoundProductType)
{
if (ProductType?.Length == 0)
{
ProductType = null;
}
if (ProductCode?.Length == 0)
{
ProductCode = null;
}
if (OperatorCode?.Length == 0)
{
OperatorCode = null;
}
if (ProductCode != null)
{
ProductCode = ProductCode.ToUpper();
ProductType = null;
OperatorCode = null;
}
if (ProductType != null)
{
ProductType = ProductType.ToUpper();
if (ProductType.StartsWith("RM") && !ProductType.StartsWith("RM-"))
{
ProductType = "RM-" + ProductType[2..];
}
}
if (OperatorCode != null)
{
OperatorCode = OperatorCode.ToUpper();
}
DiscoveryQueryParameters DiscoveryQueryParams = new()
{
manufacturerName = "Microsoft",
manufacturerProductLine = "Lumia",
packageType = "Firmware",
packageClass = "Public",
manufacturerHardwareModel = ProductType,
manufacturerHardwareVariant = ProductCode,
operatorName = OperatorCode
};
DiscoveryParameters DiscoveryParams = new()
{
query = DiscoveryQueryParams
};
DataContractJsonSerializer Serializer1 = new(typeof(DiscoveryParameters));
MemoryStream JsonStream1 = new();
Serializer1.WriteObject(JsonStream1, DiscoveryParams);
JsonStream1.Seek(0L, SeekOrigin.Begin);
string JsonContent = new StreamReader(JsonStream1).ReadToEnd();
Uri RequestUri = new("https://api.swrepository.com/rest-api/discovery/1/package");
HttpClient HttpClient = new();
HttpClient.DefaultRequestHeaders.UserAgent.TryParseAdd("SoftwareRepository");
HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Task<HttpResponseMessage> HttpPostTask = HttpClient.PostAsync(RequestUri, new StringContent(JsonContent, Encoding.UTF8, "application/json"));
HttpPostTask.Wait();
HttpResponseMessage Response = HttpPostTask.Result;
string JsonResultString = "";
if (Response.StatusCode == HttpStatusCode.OK)
{
Task<string> ReadResponseTask = Response.Content.ReadAsStringAsync();
ReadResponseTask.Wait();
JsonResultString = ReadResponseTask.Result;
}
SoftwarePackage Package = null;
using (MemoryStream JsonStream2 = new(Encoding.UTF8.GetBytes(JsonResultString)))
{
DataContractJsonSerializer Serializer2 = new(typeof(SoftwarePackages));
SoftwarePackages SoftwarePackages = (SoftwarePackages)Serializer2.ReadObject(JsonStream2);
if (SoftwarePackages != null)
{
Package = SoftwarePackages.softwarePackages.FirstOrDefault();
}
}
if (Package == null)
{
throw new WPinternalsException("FFU not found", "No FFU has been found in the remote software repository for the requested model.");
}
FoundProductType = Package.manufacturerHardwareModel[0];
SoftwareFile FileInfo = Package.files.First(f => f.fileName.EndsWith(".ffu", StringComparison.OrdinalIgnoreCase));
Uri FileInfoUri = new("https://api.swrepository.com/rest-api/discovery/fileurl/1/" + Package.id + "/" + FileInfo.fileName);
Task<string> GetFileInfoTask = HttpClient.GetStringAsync(FileInfoUri);
GetFileInfoTask.Wait();
string FileInfoString = GetFileInfoTask.Result;
string FfuUrl = "";
FileUrlResult FileUrl = null;
using (MemoryStream JsonStream3 = new(Encoding.UTF8.GetBytes(FileInfoString)))
{
DataContractJsonSerializer Serializer3 = new(typeof(FileUrlResult));
FileUrl = (FileUrlResult)Serializer3.ReadObject(JsonStream3);
if (FileUrl != null)
{
FfuUrl = FileUrl.url.Replace("sr.azureedge.net", "softwarerepo.blob.core.windows.net");
}
}
HttpClient.Dispose();
return FfuUrl;
}
internal static (string SecureWIMUrl, string DPLUrl) SearchENOSW(string ProductType, string PhoneFirmwareRevision)
{
if (ProductType?.Length == 0)
{
ProductType = null;
}
if (ProductType != null)
{
ProductType = ProductType.ToUpper();
if (ProductType.StartsWith("RM") && !ProductType.StartsWith("RM-"))
{
ProductType = $"RM-{ProductType[2..]}";
}
}
DiscoveryQueryParameters DiscoveryQueryParams = new()
{
manufacturerName = "Microsoft",
manufacturerProductLine = "Lumia",
packageType = "Test Mode",
packageClass = "Public",
manufacturerHardwareModel = ProductType
};
DiscoveryParameters DiscoveryParams = new()
{
query = DiscoveryQueryParams
};
DataContractJsonSerializer Serializer1 = new(typeof(DiscoveryParameters));
MemoryStream JsonStream1 = new();
Serializer1.WriteObject(JsonStream1, DiscoveryParams);
JsonStream1.Seek(0L, SeekOrigin.Begin);
string JsonContent = new StreamReader(JsonStream1).ReadToEnd();
Uri RequestUri = new("https://api.swrepository.com/rest-api/discovery/1/package");
HttpClient HttpClient = new();
HttpClient.DefaultRequestHeaders.UserAgent.TryParseAdd("SoftwareRepository");
HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Task<HttpResponseMessage> HttpPostTask = HttpClient.PostAsync(RequestUri, new StringContent(JsonContent, Encoding.UTF8, "application/json"));
HttpPostTask.Wait();
HttpResponseMessage Response = HttpPostTask.Result;
string JsonResultString = "";
if (Response.StatusCode == HttpStatusCode.OK)
{
Task<string> ReadResponseTask = Response.Content.ReadAsStringAsync();
ReadResponseTask.Wait();
JsonResultString = ReadResponseTask.Result;
}
SoftwarePackage Package = null;
using MemoryStream JsonResultStream = new(Encoding.UTF8.GetBytes(JsonResultString));
DataContractJsonSerializer SoftwarePackagesJsonSerializer = new(typeof(SoftwarePackages));
SoftwarePackages SoftwarePackages = (SoftwarePackages)SoftwarePackagesJsonSerializer.ReadObject(JsonResultStream);
if (SoftwarePackages != null)
{
foreach (SoftwarePackage pkg in SoftwarePackages.softwarePackages)
{
Package = SoftwarePackages.softwarePackages.FirstOrDefault();
}
}
if (Package == null)
{
throw new WPinternalsException("ENOSW package not found", "No ENOSW package has been found in the remote software repository for the requested model.");
}
SoftwareFile SecureWimSoftwareFile = Package.files.First(f => f.fileName.EndsWith(".secwim", StringComparison.OrdinalIgnoreCase));
SoftwareFile DPLSoftwareFile = Package.files.First(f => f.fileName.EndsWith(".dpl", StringComparison.OrdinalIgnoreCase));
Uri DPLFileUrlUri = new($"https://api.swrepository.com/rest-api/discovery/fileurl/1/{Package.id}/{DPLSoftwareFile.fileName}");
Task<string> GetDPLTask = HttpClient.GetStringAsync(DPLFileUrlUri);
GetDPLTask.Wait();
string DPLFileUrlResultContent = GetDPLTask.Result;
FileUrlResult DPLFileUrlResult = null;
using MemoryStream DPLFileUrlResultStream = new(Encoding.UTF8.GetBytes(DPLFileUrlResultContent));
DataContractJsonSerializer DPLFileUrlResultSerializer = new(typeof(FileUrlResult));
DPLFileUrlResult = (FileUrlResult)DPLFileUrlResultSerializer.ReadObject(DPLFileUrlResultStream);
string DPLFileUrl = "";
if (DPLFileUrlResult != null)
{
DPLFileUrl = DPLFileUrlResult.url.Replace("sr.azureedge.net", "softwarerepo.blob.core.windows.net");
}
if (DPLFileUrl?.Length == 0)
{
throw new WPinternalsException("DPL not found", "No DPL has been found in the remote software repository for the requested model.");
}
Task<string> GetDPLStrTask = HttpClient.GetStringAsync(DPLFileUrl);
GetDPLStrTask.Wait();
string DPLStrString = GetDPLStrTask.Result;
DPL.Package dpl;
XmlSerializer serializer = new(typeof(DPL.Package));
using StringReader reader = new(DPLStrString.Replace("ft:", "").Replace("dpl:", "").Replace("typedes:", ""));
dpl = (DPL.Package)serializer.Deserialize(reader);
foreach (DPL.File file in dpl.Content.Files.File)
{
string name = file.Name;
DPL.Range range = file.Extensions.MmosWimFile.UseCaseCompatibilities.Compatibility.FirstOrDefault().Range;
if (IsFirmwareBetween(PhoneFirmwareRevision, range.From, range.To))
{
SecureWimSoftwareFile = Package.files.First(f => f.fileName.EndsWith(name, StringComparison.OrdinalIgnoreCase));
}
}
Uri FileInfoUri = new("https://api.swrepository.com/rest-api/discovery/fileurl/1/" + Package.id + "/" + SecureWimSoftwareFile.fileName);
Task<string> GetFileInfoTask = HttpClient.GetStringAsync(FileInfoUri);
GetFileInfoTask.Wait();
string FileInfoString = GetFileInfoTask.Result;
string ENOSWFileUrl = "";
FileUrlResult FileUrl = null;
using MemoryStream JsonStream4 = new(Encoding.UTF8.GetBytes(FileInfoString));
DataContractJsonSerializer Serializer4 = new(typeof(FileUrlResult));
FileUrl = (FileUrlResult)Serializer4.ReadObject(JsonStream4);
if (FileUrl != null)
{
ENOSWFileUrl = FileUrl.url.Replace("sr.azureedge.net", "softwarerepo.blob.core.windows.net");
}
HttpClient.Dispose();
return (ENOSWFileUrl, DPLFileUrl);
}
private static bool IsFirmwareBetween(string PhoneFirmwareRevision, string Limit1, string Limit2)
{
var version = new Version(PhoneFirmwareRevision);
var version1 = new Version(Limit1);
var version2 = new Version(Limit2);
var result = version.CompareTo(version1);
var result2 = version.CompareTo(version2);
return result >= 0 && result2 <= 0;
}
internal static string[] SearchEmergencyFiles(string ProductType)
{
ProductType = ProductType.ToUpper();
if (ProductType.StartsWith("RM") && !ProductType.StartsWith("RM-"))
{
ProductType = "RM-" + ProductType[2..];
}
LogFile.Log("Getting Emergency files for: " + ProductType, LogType.FileAndConsole);
if ((ProductType == "RM-1072") || (ProductType == "RM-1073"))
{
LogFile.Log("Due to mix-up in online-repository, redirecting to emergency files of RM-1113", LogType.FileAndConsole);
ProductType = "RM-1113";
}
List<string> Result = new();
WebClient Client = new();
string Src;
string FileName;
string Config = null;
try
{
Config = Client.DownloadString("https://repairavoidance.blob.core.windows.net/packages/EmergencyFlash/" + ProductType + "/emergency_flash_config.xml");
}
catch
{
LogFile.Log("Emergency files for " + ProductType + " not found", LogType.FileAndConsole);
return null;
}
Client.Dispose();
XmlDocument Doc = new();
Doc.LoadXml(Config);
// Hex
XmlNode Node = Doc.SelectSingleNode("//emergency_flash_config/hex_flasher");
if (Node != null)
{
FileName = Node.Attributes["image_path"].InnerText;
Src = "https://repairavoidance.blob.core.windows.net/packages/EmergencyFlash/" + ProductType + "/" + FileName;
LogFile.Log("Hex-file: " + Src);
Result.Add(Src);
}
// Mbn
Node = Doc.SelectSingleNode("//emergency_flash_config/mbn_image");
if (Node != null)
{
FileName = Node.Attributes["image_path"].InnerText;
Src = "https://repairavoidance.blob.core.windows.net/packages/EmergencyFlash/" + ProductType + "/" + FileName;
LogFile.Log("Mbn-file: " + Src);
Result.Add(Src);
}
// Ede
foreach (XmlNode SubNode in Doc.SelectNodes("//emergency_flash_config/first_boot_images/first_boot_image"))
{
FileName = SubNode.Attributes["image_path"].InnerText;
Src = "https://repairavoidance.blob.core.windows.net/packages/EmergencyFlash/" + ProductType + "/" + FileName;
LogFile.Log("Firehose-programmer-file: " + Src);
Result.Add(Src);
}
// Edp
foreach (XmlNode SubNode in Doc.SelectNodes("//emergency_flash_config/second_boot_firehose_single_image/firehose_image"))
{
FileName = SubNode.Attributes["image_path"].InnerText;
Src = "https://repairavoidance.blob.core.windows.net/packages/EmergencyFlash/" + ProductType + "/" + FileName;
LogFile.Log("Firehose-payload-file: " + Src);
Result.Add(Src);
}
return [.. Result];
}
}
#pragma warning disable 0649
[DataContract]
internal class FileUrlResult
{
[DataMember]
internal string url;
[DataMember]
internal List<string> alternateUrl;
[DataMember]
internal long fileSize;
[DataMember]
internal List<SoftwareFileChecksum> checksum;
}
#pragma warning restore 0649
[DataContract]
public class DiscoveryQueryParameters
{
[DataMember(EmitDefaultValue = false)]
public string customerName;
[DataMember(EmitDefaultValue = false)]
public ExtendedAttributes extendedAttributes;
[DataMember(EmitDefaultValue = false)]
public string manufacturerHardwareModel;
[DataMember(EmitDefaultValue = false)]
public string manufacturerHardwareVariant;
[DataMember(EmitDefaultValue = false)]
public string manufacturerModelName;
[DataMember]
public string manufacturerName;
[DataMember(EmitDefaultValue = false)]
public string manufacturerPackageId;
[DataMember(EmitDefaultValue = false)]
public string manufacturerPlatformId;
[DataMember]
public string manufacturerProductLine;
[DataMember(EmitDefaultValue = false)]
public string manufacturerVariantName;
[DataMember(EmitDefaultValue = false)]
public string operatorName;
[DataMember]
public string packageClass;
[DataMember(EmitDefaultValue = false)]
public string packageRevision;
[DataMember(EmitDefaultValue = false)]
public string packageState;
[DataMember(EmitDefaultValue = false)]
public string packageSubRevision;
[DataMember(EmitDefaultValue = false)]
public string packageSubtitle;
[DataMember(EmitDefaultValue = false)]
public string packageTitle;
[DataMember]
public string packageType;
}
[DataContract]
public class DiscoveryParameters
{
[DataMember(Name = "api-version")]
public string apiVersion;
[DataMember]
public DiscoveryQueryParameters query;
[DataMember]
public List<string> condition;
[DataMember]
public List<string> response;
public DiscoveryParameters() : this(DiscoveryCondition.Default)
{
}
public DiscoveryParameters(DiscoveryCondition Condition)
{
this.apiVersion = "1";
this.query = new DiscoveryQueryParameters();
this.condition = new List<string>();
if (Condition == DiscoveryCondition.All)
{
this.condition.Add("all");
return;
}
if (Condition == DiscoveryCondition.Latest)
{
this.condition.Add("latest");
return;
}
this.condition.Add("default");
}
}
public enum DiscoveryCondition
{
Default,
All,
Latest
}
[Serializable]
public class ExtendedAttributes : ISerializable
{
public Dictionary<string, string> Dictionary;
public ExtendedAttributes()
{
this.Dictionary = new Dictionary<string, string>();
}
protected ExtendedAttributes(SerializationInfo info, StreamingContext context)
{
if (info != null)
{
this.Dictionary = new Dictionary<string, string>();
SerializationInfoEnumerator Enumerator = info.GetEnumerator();
while (Enumerator.MoveNext())
{
this.Dictionary.Add(Enumerator.Current.Name, (string)Enumerator.Current.Value);
}
}
}
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info != null)
{
foreach (string Current in this.Dictionary.Keys)
{
info.AddValue(Current, this.Dictionary[Current]);
}
}
}
}
[DataContract]
public class SoftwareFileChecksum
{
[DataMember]
public string type;
[DataMember]
public string value;
}
[DataContract]
public class SoftwarePackages
{
[DataMember]
public List<SoftwarePackage> softwarePackages;
}
[DataContract]
public class SoftwarePackage
{
[DataMember]
public List<string> customerName;
[DataMember]
public ExtendedAttributes extendedAttributes;
[DataMember]
public List<SoftwareFile> files;
[DataMember]
public string id;
[DataMember]
public List<string> manufacturerHardwareModel;
[DataMember]
public List<string> manufacturerHardwareVariant;
[DataMember]
public List<string> manufacturerModelName;
[DataMember]
public string manufacturerName;
[DataMember]
public string manufacturerPackageId;
[DataMember]
public List<string> manufacturerPlatformId;
[DataMember]
public string manufacturerProductLine;
[DataMember]
public List<string> manufacturerVariantName;
[DataMember]
public List<string> operatorName;
[DataMember]
public List<string> packageClass;
[DataMember]
public string packageDescription;
[DataMember]
public string packageRevision;
[DataMember]
public string packageState;
[DataMember]
public string packageSubRevision;
[DataMember]
public string packageSubtitle;
[DataMember]
public string packageTitle;
[DataMember]
public string packageType;
}
[DataContract]
public class SoftwareFile
{
[DataMember]
public List<SoftwareFileChecksum> checksum;
[DataMember]
public string fileName;
[DataMember]
public long fileSize;
[DataMember]
public string fileType;
}
public static class DPL
{
[XmlRoot(ElementName = "BasicProductCodes")]
public class BasicProductCodes
{
[XmlElement(ElementName = "BasicProductCode")]
public List<string> BasicProductCode { get; set; }
}
[XmlRoot(ElementName = "Identification")]
public class Identification
{
[XmlElement(ElementName = "TypeDesignator")]
public string TypeDesignator { get; set; }
[XmlElement(ElementName = "BasicProductCodes")]
public BasicProductCodes BasicProductCodes { get; set; }
[XmlElement(ElementName = "Purpose")]
public string Purpose { get; set; }
}
[XmlRoot(ElementName = "Extensions")]
public class Extensions
{
[XmlElement(ElementName = "PackageType")]
public string PackageType { get; set; }
[XmlElement(ElementName = "Identification")]
public Identification Identification { get; set; }
[XmlElement(ElementName = "FileType")]
public string FileType { get; set; }
[XmlElement(ElementName = "MmosWimFile")]
public MmosWimFile MmosWimFile { get; set; }
}
[XmlRoot(ElementName = "PackageDescription")]
public class PackageDescription
{
[XmlElement(ElementName = "Identifier")]
public string Identifier { get; set; }
[XmlElement(ElementName = "Revision")]
public string Revision { get; set; }
[XmlElement(ElementName = "Extensions")]
public Extensions Extensions { get; set; }
}
[XmlRoot(ElementName = "Digest")]
public class Digest
{
[XmlAttribute(AttributeName = "method")]
public string Method { get; set; }
[XmlAttribute(AttributeName = "encoding")]
public string Encoding { get; set; }
[XmlText]
public string Text { get; set; }
}
[XmlRoot(ElementName = "Digests")]
public class Digests
{
[XmlElement(ElementName = "Digest")]
public List<Digest> Digest { get; set; }
}
[XmlRoot(ElementName = "Range")]
public class Range
{
[XmlAttribute(AttributeName = "from")]
public string From { get; set; }
[XmlAttribute(AttributeName = "to")]
public string To { get; set; }
}
[XmlRoot(ElementName = "Compatibility")]
public class Compatibility
{
[XmlElement(ElementName = "Range")]
public Range Range { get; set; }
[XmlAttribute(AttributeName = "useCase")]
public string UseCase { get; set; }
}
[XmlRoot(ElementName = "UseCaseCompatibilities")]
public class UseCaseCompatibilities
{
[XmlElement(ElementName = "Compatibility")]
public List<Compatibility> Compatibility { get; set; }
}
[XmlRoot(ElementName = "MmosWimFile")]
public class MmosWimFile
{
[XmlElement(ElementName = "UseCaseCompatibilities")]
public UseCaseCompatibilities UseCaseCompatibilities { get; set; }
}
[XmlRoot(ElementName = "File")]
public class File
{
[XmlElement(ElementName = "Name")]
public string Name { get; set; }
[XmlElement(ElementName = "Digests")]
public Digests Digests { get; set; }
[XmlElement(ElementName = "Revision")]
public string Revision { get; set; }
[XmlElement(ElementName = "Extensions")]
public Extensions Extensions { get; set; }
}
[XmlRoot(ElementName = "Files")]
public class Files
{
[XmlElement(ElementName = "File")]
public List<File> File { get; set; }
}
[XmlRoot(ElementName = "Content")]
public class Content
{
[XmlElement(ElementName = "PackageDescription")]
public PackageDescription PackageDescription { get; set; }
[XmlElement(ElementName = "Files")]
public Files Files { get; set; }
}
[XmlRoot(ElementName = "CanonicalizationMethod", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public class CanonicalizationMethod
{
[XmlAttribute(AttributeName = "Algorithm")]
public string Algorithm { get; set; }
}
[XmlRoot(ElementName = "SignatureMethod", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public class SignatureMethod
{
[XmlAttribute(AttributeName = "Algorithm")]
public string Algorithm { get; set; }
}
[XmlRoot(ElementName = "Transform", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public class Transform
{
[XmlAttribute(AttributeName = "Algorithm")]
public string Algorithm { get; set; }
}
[XmlRoot(ElementName = "Transforms", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public class Transforms
{
[XmlElement(ElementName = "Transform", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public Transform Transform { get; set; }
}
[XmlRoot(ElementName = "DigestMethod", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public class DigestMethod
{
[XmlAttribute(AttributeName = "Algorithm")]
public string Algorithm { get; set; }
}
[XmlRoot(ElementName = "Reference", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public class Reference
{
[XmlElement(ElementName = "Transforms", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public Transforms Transforms { get; set; }
[XmlElement(ElementName = "DigestMethod", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public DigestMethod DigestMethod { get; set; }
[XmlElement(ElementName = "DigestValue", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public string DigestValue { get; set; }
[XmlAttribute(AttributeName = "URI")]
public string URI { get; set; }
}
[XmlRoot(ElementName = "SignedInfo", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public class SignedInfo
{
[XmlElement(ElementName = "CanonicalizationMethod", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public CanonicalizationMethod CanonicalizationMethod { get; set; }
[XmlElement(ElementName = "SignatureMethod", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public SignatureMethod SignatureMethod { get; set; }
[XmlElement(ElementName = "Reference", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public Reference Reference { get; set; }
}
[XmlRoot(ElementName = "KeyInfo", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public class KeyInfo
{
[XmlElement(ElementName = "KeyName", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public string KeyName { get; set; }
}
[XmlRoot(ElementName = "Signature", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public class Signature
{
[XmlElement(ElementName = "SignedInfo", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public SignedInfo SignedInfo { get; set; }
[XmlElement(ElementName = "SignatureValue", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public string SignatureValue { get; set; }
[XmlElement(ElementName = "KeyInfo", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public KeyInfo KeyInfo { get; set; }
[XmlAttribute(AttributeName = "xmlns")]
public string Xmlns { get; set; }
}
[XmlRoot(ElementName = "Package")]
public class Package
{
[XmlElement(ElementName = "Content")]
public Content Content { get; set; }
[XmlElement(ElementName = "Signature", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public Signature Signature { get; set; }
}
}
}
+9 -6
View File
@@ -23,6 +23,8 @@ using System.IO;
using System.Linq;
using System.Management;
using System.Runtime.InteropServices;
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia;
namespace WPinternals
{
@@ -41,14 +43,14 @@ namespace WPinternals
{
try
{
foreach (ManagementObject logical in new ManagementObjectSearcher("select * from Win32_LogicalDisk").Get())
foreach (ManagementObject logical in new ManagementObjectSearcher("select * from Win32_LogicalDisk").Get().Cast<ManagementObject>())
{
System.Diagnostics.Debug.Print(logical["Name"].ToString());
string Label = "";
foreach (ManagementObject partition in logical.GetRelated("Win32_DiskPartition"))
foreach (ManagementObject partition in logical.GetRelated("Win32_DiskPartition").Cast<ManagementObject>())
{
foreach (ManagementObject drive in partition.GetRelated("Win32_DiskDrive"))
foreach (ManagementObject drive in partition.GetRelated("Win32_DiskDrive").Cast<ManagementObject>())
{
if (drive["PNPDeviceID"].ToString().Contains("VEN_QUALCOMM&PROD_MMC_STORAGE", StringComparison.CurrentCulture) ||
drive["PNPDeviceID"].ToString().Contains("VEN_MSFT&PROD_PHONE_MMC_STOR", StringComparison.CurrentCulture))
@@ -109,9 +111,10 @@ namespace WPinternals
try
{
QualcommSerial SerialDevice = new(Serial);
SerialDevice.EncodeCommands = false;
QualcommSerial SerialDevice = new(Serial)
{
EncodeCommands = false
};
// This will succeed on new models
SerialDevice.SendData([0x7, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0]);
-1
View File
@@ -20,7 +20,6 @@
using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
+9 -8
View File
@@ -28,13 +28,14 @@ using System.Security.Cryptography;
using System.Security.Principal;
using System.Xml;
using System.Xml.Serialization;
using WPinternals.HelperClasses;
namespace WPinternals
{
internal class PatchEngine
{
internal List<PatchDefinition> PatchDefinitions = new();
internal readonly List<TargetRedirection> TargetRedirections = new();
internal List<PatchDefinition> PatchDefinitions = [];
internal readonly List<TargetRedirection> TargetRedirections = [];
internal PatchEngine() { }
@@ -115,7 +116,7 @@ namespace WPinternals
internal bool Patch(string PatchDefinition)
{
bool Result = false;
List<FilePatcher> LoadedFiles = new();
List<FilePatcher> LoadedFiles = [];
LogFile.Log("Attempt patch: " + PatchDefinition);
@@ -237,7 +238,7 @@ namespace WPinternals
internal void Restore(string PatchDefinition)
{
List<FilePatcher> LoadedFiles = new();
List<FilePatcher> LoadedFiles = [];
try
{
@@ -492,7 +493,7 @@ namespace WPinternals
[XmlAttribute]
public string Name;
public List<TargetVersion> TargetVersions = new();
public List<TargetVersion> TargetVersions = [];
}
public class TargetVersion // Must be public to be serializable
@@ -500,7 +501,7 @@ namespace WPinternals
[XmlAttribute]
public string Description;
public List<TargetFile> TargetFiles = new();
public List<TargetFile> TargetFiles = [];
}
public class TargetFile // Must be public to be serializable
@@ -549,8 +550,8 @@ namespace WPinternals
}
}
public List<Patch> Patches = new();
public List<TargetFile> Obsolete = new();
public List<Patch> Patches = [];
public List<TargetFile> Obsolete = [];
}
public class Patch // Must be public to be serializable
+17 -7
View File
@@ -22,6 +22,7 @@ using System;
using System.Collections.Specialized;
using System.Runtime.InteropServices;
using System.Threading;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -35,8 +36,8 @@ namespace WPinternals
{
#region Private static members
private static readonly LocalDataStoreSlot tlsSlot = Thread.AllocateDataSlot();
private static readonly HybridDictionary privileges = new();
private static readonly HybridDictionary luids = new();
private static readonly HybridDictionary privileges = [];
private static readonly HybridDictionary luids = [];
private static readonly ReaderWriterLock privilegeLock = new();
#endregion
@@ -415,8 +416,10 @@ namespace WPinternals
(this.tlsContents.ReferenceCountValue > 1 ||
!this.tlsContents.IsImpersonating))
{
NativeMethods.TOKEN_PRIVILEGE newState = new();
newState.PrivilegeCount = 1;
NativeMethods.TOKEN_PRIVILEGE newState = new()
{
PrivilegeCount = 1
};
newState.Privilege.Luid = this.luid;
newState.Privilege.Attributes = this.initialState ? NativeMethods.SE_PRIVILEGE_ENABLED : NativeMethods.SE_PRIVILEGE_DISABLED;
@@ -486,8 +489,13 @@ namespace WPinternals
callback(state);
}
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);
p.Revert();
throw;
}
@@ -544,8 +552,10 @@ namespace WPinternals
this.tlsContents.IncrementReferenceCount();
}
NativeMethods.TOKEN_PRIVILEGE newState = new();
newState.PrivilegeCount = 1;
NativeMethods.TOKEN_PRIVILEGE newState = new()
{
PrivilegeCount = 1
};
newState.Privilege.Luid = this.luid;
newState.Privilege.Attributes = enable ? NativeMethods.SE_PRIVILEGE_ENABLED : NativeMethods.SE_PRIVILEGE_DISABLED;
+7 -1
View File
@@ -21,6 +21,7 @@
using System;
using System.IO;
using System.Linq;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -40,8 +41,13 @@ namespace WPinternals
Serial.SendCommand([0x06], [0x02]);
return true;
}
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 false;
}
}
+7 -1
View File
@@ -25,6 +25,7 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -66,8 +67,13 @@ namespace WPinternals
Serial.SendData(PacketFromPcToProgrammer);
LogFile.Log("Hello packet accepted", LogType.FileOnly);
}
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("Hello packet not accepted", LogType.FileOnly);
}
+1
View File
@@ -20,6 +20,7 @@
using System;
using System.IO;
using WPinternals.HelperClasses;
namespace WPinternals
{
+3 -2
View File
@@ -22,6 +22,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -29,7 +30,7 @@ namespace WPinternals
{
internal static List<QualcommPartition> GetPossibleLoadersForRootKeyHash(string Path, byte[] RootKeyHash)
{
List<QualcommPartition> Result = new();
List<QualcommPartition> Result = [];
try
{
@@ -52,7 +53,7 @@ namespace WPinternals
// Make sure the RootKeyHash is not blank
// If the RootKeyHash is blank, this is an engineering device, and it will accept any RKH
// We expect the user to know what he is doing in such case and we will ignore checks
if (!StructuralComparisons.StructuralEqualityComparer.Equals(RootKeyHash, new byte[RootKeyHash.Length]))
if (RootKeyHash != null && !StructuralComparisons.StructuralEqualityComparer.Equals(RootKeyHash, new byte[RootKeyHash.Length]))
{
if (StructuralComparisons.StructuralEqualityComparer.Equals(Loader.RootKeyHash, RootKeyHash)
&& (ByteOperations.FindUnicode(Loader.Binary, "QHSUSB_ARMPRG") != null)) // To detect that this is a loader, and not SBL1 or something. V1 loaders are QHSUSB_ARMPRG. V2 loaders are QHSUSB__BULK. Only V1 supported for now, because V2 only accepts signed payload.
+1
View File
@@ -22,6 +22,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using WPinternals.HelperClasses;
namespace WPinternals
{
+8 -2
View File
@@ -22,6 +22,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -117,7 +118,7 @@ namespace WPinternals
byte[] Response = Serial.GetResponse(null, Length: (int)RKHLength);
List<byte[]> RootKeyHashes = new();
List<byte[]> RootKeyHashes = [];
for (int i = 0; i < RKHLength / 0x20; i++)
{
RootKeyHashes.Add(Response[(i * 0x20)..((i + 1) * 0x20)]);
@@ -284,8 +285,13 @@ namespace WPinternals
byte[] Ready = Serial.SendCommand(HelloResponse, [0x03, 0x00, 0x00, 0x00]);
}
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);
Result = false;
}
+1
View File
@@ -21,6 +21,7 @@
using MadWizard.WinUSBNet;
using System;
using System.IO.Ports;
using WPinternals.HelperClasses;
namespace WPinternals
{
+1
View File
@@ -20,6 +20,7 @@
using System;
using System.IO;
using WPinternals.HelperClasses;
namespace WPinternals
{
+2 -3
View File
@@ -20,7 +20,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace WPinternals
{
@@ -39,7 +38,7 @@ namespace WPinternals
{
internal byte[] Binary;
private byte[] DecompressedImage;
internal List<EFI> EFIs = new();
internal List<EFI> EFIs = [];
private readonly byte PaddingByteValue = 0xFF;
private readonly UInt32 DecompressedVolumeSectionHeaderOffset;
private readonly UInt32 DecompressedVolumeHeaderOffset;
@@ -317,7 +316,7 @@ namespace WPinternals
EFI File = EFIs.Find(f => string.Equals(Name, f.Name, StringComparison.CurrentCultureIgnoreCase) || string.Equals(Name, f.Guid.ToString(), StringComparison.CurrentCultureIgnoreCase));
if (File == null)
{
throw new ArgumentOutOfRangeException();
throw new ArgumentOutOfRangeException(nameof(Name));
}
UInt32 OldBinarySize = File.Size;
@@ -19,9 +19,8 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace WPinternals
namespace WPinternals.Terminal
{
internal static class Terminal
{
@@ -30,13 +29,13 @@ namespace WPinternals
TerminalResponse Response = new();
// Get root node
if (Buffer.Length >= (Offset + 8))
if (Buffer.Length >= Offset + 8)
{
int NodeNumber = BitConverter.ToInt32(Buffer, Offset);
int NodeSize = BitConverter.ToInt32(Buffer, Offset + 4);
int End = NodeSize + Offset + 8;
int Index = Offset + 8;
if ((NodeNumber == 0x10000) && (End <= Buffer.Length))
if (NodeNumber == 0x10000 && End <= Buffer.Length)
{
// Get subnodes
while (Index < End)
@@ -58,11 +57,4 @@ namespace WPinternals
return Response;
}
}
internal class TerminalResponse
{
public Dictionary<int, byte[]> RawEntries = new();
public byte[] PublicId = null;
public byte[] RootKeyHash = null;
}
}
+31
View File
@@ -0,0 +1,31 @@
// 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.Collections.Generic;
namespace WPinternals.Terminal
{
internal class TerminalResponse
{
public Dictionary<int, byte[]> RawEntries = [];
public byte[] PublicId = null;
public byte[] RootKeyHash = null;
}
}
+13 -6
View File
@@ -23,6 +23,8 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using WPinternals.HelperClasses;
using WPinternals.Models.UEFIApps.Flash;
namespace WPinternals
{
@@ -50,8 +52,7 @@ namespace WPinternals
byte[] RootKeyHash = null;
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Qualcomm_Download)
{
QualcommDownload Download2 = new((QualcommSerial)PhoneNotifier.CurrentModel);
RootKeyHash = Download2.GetRKH();
RootKeyHash = new QualcommDownload((QualcommSerial)PhoneNotifier.CurrentModel).GetRKH();
}
List<QualcommPartition> PossibleLoaders = null;
@@ -74,6 +75,7 @@ namespace WPinternals
QualcommSerial Serial = (QualcommSerial)PhoneNotifier.CurrentModel;
QualcommDownload Download = new(Serial);
if (Download.IsAlive())
{
int Attempt = 1;
@@ -181,9 +183,9 @@ namespace WPinternals
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage);
MassStorage MassStorage = (MassStorage)Notifier.CurrentModel;
foreach (var part in Directory.EnumerateFiles(PartPath))
foreach (string part in Directory.EnumerateFiles(PartPath))
{
var partname = part.Split('\\').Last().Replace(".img", "");
string partname = part.Split('\\').Last().Replace(".img", "");
try
{
LogFile.Log($"Writing {partname} to the device.", LogType.ConsoleOnly);
@@ -193,8 +195,13 @@ namespace WPinternals
MassStorage.RestorePartition(part, partname, (v, t) => LogFile.Log("Progress: " + v + "%", LogType.ConsoleOnly));
LogFile.Log("", LogType.ConsoleOnly);
}
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("", LogType.ConsoleOnly);
LogFile.Log($"Failed writing {partname} to the device.", LogType.ConsoleOnly);
}
@@ -203,7 +210,7 @@ namespace WPinternals
internal static void PatchImg(string dump)
{
using var fil = File.Open(dump, FileMode.Open);
using FileStream fil = File.Open(dump, FileMode.Open);
byte[] gptbuffer = new byte[0x4200];
fil.Seek(0x200, SeekOrigin.Begin);
@@ -20,6 +20,7 @@
using System;
using System.Threading;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -23,6 +23,7 @@ using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Threading;
using WPinternals.HelperClasses;
namespace WPinternals
{
+1
View File
@@ -20,6 +20,7 @@
using System;
using System.Threading;
using WPinternals.HelperClasses;
namespace WPinternals
{
+7 -1
View File
@@ -21,6 +21,7 @@
using System;
using System.ComponentModel;
using System.Threading;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -28,7 +29,12 @@ namespace WPinternals
{
protected SynchronizationContext UIContext;
public bool IsSwitchingInterface = false;
private bool _IsSwitchingInterface = false;
public bool IsSwitchingInterface
{
get => _IsSwitchingInterface;
set => _IsSwitchingInterface = value;
}
public bool IsFlashModeOperation = false;
public event PropertyChangedEventHandler PropertyChanged = delegate { };
@@ -21,6 +21,7 @@
using Microsoft.Win32;
using System;
using System.Windows;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -21,6 +21,7 @@
using Microsoft.Win32;
using System;
using System.Windows;
using WPinternals.HelperClasses;
namespace WPinternals
{
+100 -98
View File
@@ -30,13 +30,17 @@ using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Data;
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia.MSR;
using WPinternals.Models.Lumia.NCSd;
using WPinternals.Models.UEFIApps.Flash;
using WPinternals.Models.UEFIApps.PhoneInfo;
namespace WPinternals
{
internal class DownloadsViewModel : ContextViewModel
{
private readonly PhoneNotifierViewModel Notifier;
private readonly Timer SpeedTimer;
private bool IsSearching = false;
internal DownloadsViewModel(PhoneNotifierViewModel Notifier)
@@ -51,15 +55,15 @@ namespace WPinternals
DownloadFolder = (string)Key.GetValue("DownloadFolder", @"C:\ProgramData\WPinternals\Repository");
Key.Close();
SpeedTimer = new Timer(TimerCallback, this, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
AddFFUCommand = new DelegateCommand(() =>
{
string FFUPath = null;
OpenFileDialog dlg = new();
dlg.DefaultExt = ".ffu"; // Default file extension
dlg.Filter = "ROM images (.ffu)|*.ffu"; // Filter files by extension
OpenFileDialog dlg = new()
{
DefaultExt = ".ffu", // Default file extension
Filter = "ROM images (.ffu)|*.ffu" // Filter files by extension
};
bool? result = dlg.ShowDialog();
@@ -72,35 +76,97 @@ namespace WPinternals
{
App.Config.AddFfuToRepository(FFUPath);
App.Config.WriteConfig();
LastStatusText = $"File \"{FFUFile}\" was added to the repository.";
LastFFUStatusText = $"File \"{FFUFile}\" was added to the repository.";
}
catch (WPinternalsException Ex)
{
LastStatusText = $"Error: {Ex.Message}. File \"{FFUFile}\" was not added.";
LastFFUStatusText = $"Error: {Ex.Message}. File \"{FFUFile}\" was not added.";
}
catch
catch (Exception ex)
{
LastStatusText = $"Error: File \"{FFUFile}\" was not added.";
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);
LastFFUStatusText = $"Error: File \"{FFUFile}\" was not added.";
}
}
else
{
LastStatusText = null;
LastFFUStatusText = null;
}
});
AddSecWIMCommand = new DelegateCommand(() =>
{
string SecWIMPath = null;
OpenFileDialog dlg = new()
{
DefaultExt = ".secwim", // Default file extension
Filter = "Secure WIM images (.secwim)|*.secwim" // Filter files by extension
};
bool? result = dlg.ShowDialog();
if (result == true)
{
SecWIMPath = dlg.FileName;
string SecWIMFile = Path.GetFileName(SecWIMPath);
try
{
App.Config.AddSecWimToRepository(SecWIMPath, FirmwareVersion);
App.Config.WriteConfig();
LastSecWIMStatusText = $"File \"{SecWIMFile}\" was added to the repository.";
}
catch (WPinternalsException Ex)
{
LastSecWIMStatusText = $"Error: {Ex.Message}. File \"{SecWIMFile}\" was not added.";
}
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);
LastSecWIMStatusText = $"Error: File \"{SecWIMFile}\" was not added.";
}
}
else
{
LastSecWIMStatusText = null;
}
});
}
private string _LastStatusText = null;
public string LastStatusText
private string _LastFFUStatusText = null;
public string LastFFUStatusText
{
get
{
return _LastStatusText;
return _LastFFUStatusText;
}
set
{
_LastStatusText = value;
OnPropertyChanged(nameof(LastStatusText));
_LastFFUStatusText = value;
OnPropertyChanged(nameof(LastFFUStatusText));
}
}
private string _LastSecWIMStatusText = null;
public string LastSecWIMStatusText
{
get
{
return _LastSecWIMStatusText;
}
set
{
_LastSecWIMStatusText = value;
OnPropertyChanged(nameof(LastSecWIMStatusText));
}
}
@@ -187,9 +253,7 @@ namespace WPinternals
new Thread(() =>
{
string FFUURL = null;
string[] EmergencyURLs = null;
string SecureWIMURL = null;
try
{
@@ -201,16 +265,6 @@ namespace WPinternals
ProductType = TempProductType;
try
{
FFUURL = LumiaDownloadModel.SearchFFU(ProductType, ProductCode, OperatorCode, out TempProductType);
}
catch (WPinternalsException ex)
{
LogFile.LogException(ex, LogType.FileOnly);
FFUURL = LumiaDownloadModel.SearchFFU(ProductType, null, OperatorCode, out TempProductType);
}
if (TempProductType != null)
{
ProductType = TempProductType;
@@ -220,11 +274,6 @@ namespace WPinternals
{
EmergencyURLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
}
if (ProductType != null && FirmwareVersion != null)
{
(SecureWIMURL, string _) = LumiaDownloadModel.SearchENOSW(ProductType, FirmwareVersion);
}
}
catch (Exception ex)
{
@@ -233,20 +282,10 @@ namespace WPinternals
UIContext.Post(s =>
{
if (FFUURL != null)
{
SearchResultList.Add(new SearchResult(FFUURL, ProductType, FFUDownloaded, null));
}
if (EmergencyURLs != null)
{
SearchResultList.Add(new SearchResult($"{ProductType} emergency-files", EmergencyURLs, ProductType, EmergencyDownloaded, ProductType));
}
if (SecureWIMURL != null)
{
SearchResultList.Add(new SearchResult($"{ProductType} ENOSW-files", SecureWIMURL, ProductType, ENOSWDownloaded, FirmwareVersion));
}
}, null);
IsSearching = false;
@@ -274,9 +313,7 @@ namespace WPinternals
new Thread(() =>
{
string FFUURL = null;
string[] EmergencyURLs = null;
string SecureWIMURL = null;
try
{
string TempProductType = ProductType.ToUpper();
@@ -286,7 +323,6 @@ namespace WPinternals
}
ProductType = TempProductType;
FFUURL = LumiaDownloadModel.SearchFFU(ProductType, ProductCode, OperatorCode, out TempProductType);
if (TempProductType != null)
{
ProductType = TempProductType;
@@ -296,11 +332,6 @@ namespace WPinternals
{
EmergencyURLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
}
if (ProductType != null && FirmwareVersion != null)
{
(SecureWIMURL, string _) = LumiaDownloadModel.SearchENOSW(ProductType, FirmwareVersion);
}
}
catch (Exception ex)
{
@@ -309,20 +340,10 @@ namespace WPinternals
UIContext.Post(s =>
{
if (FFUURL != null)
{
Download(FFUURL, ProductType, FFUDownloadedAndCheckSupported, null);
}
if (EmergencyURLs != null)
{
Download(EmergencyURLs, ProductType, EmergencyDownloaded, ProductType);
}
if (SecureWIMURL != null)
{
Download(SecureWIMURL, ProductType, ENOSWDownloaded, FirmwareVersion);
}
}, null);
}).Start();
}
@@ -335,23 +356,6 @@ namespace WPinternals
}
}
private void FFUDownloaded(string[] Files, object State)
{
App.Config.AddFfuToRepository(Files[0]);
}
private void FFUDownloadedAndCheckSupported(string[] Files, object State)
{
App.Config.AddFfuToRepository(Files[0]);
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
{
const string ProductType2 = "RM-1085";
string URL = LumiaDownloadModel.SearchFFU(ProductType2, null, null);
Download(URL, ProductType2, FFUDownloaded, null);
}
}
private void EmergencyDownloaded(string[] Files, object State)
{
string Type = (string)State;
@@ -377,13 +381,8 @@ namespace WPinternals
}
}
private void ENOSWDownloaded(string[] Files, object State)
{
App.Config.AddSecWimToRepository(Files[0], (string)State);
}
public ObservableCollection<DownloadEntry> DownloadList { get; } = new();
public ObservableCollection<SearchResult> SearchResultList { get; } = new();
public ObservableCollection<DownloadEntry> DownloadList { get; } = [];
public ObservableCollection<SearchResult> SearchResultList { get; } = [];
private DelegateCommand _DownloadSelectedCommand = null;
public DelegateCommand DownloadSelectedCommand
@@ -663,7 +662,7 @@ namespace WPinternals
}
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
{
NokiaPhoneModel LumiaNormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
NokiaCareSuiteModel LumiaNormalModel = (NokiaCareSuiteModel)Notifier.CurrentModel;
OperatorCode = LumiaNormalModel.ExecuteJsonMethodAsString("ReadOperatorName", "OperatorName"); // Example: 000-NL
string TempProductType = LumiaNormalModel.ExecuteJsonMethodAsString("ReadManufacturerModelName", "ManufacturerModelName"); // RM-821_eu_denmark_251
if (TempProductType.Contains('_'))
@@ -678,6 +677,7 @@ namespace WPinternals
}
}
public DelegateCommand AddFFUCommand { get; } = null;
public DelegateCommand AddSecWIMCommand { get; } = null;
}
internal enum DownloadStatus
@@ -1082,7 +1082,7 @@ namespace WPinternals
public static class HttpClientProgressExtensions
{
public static async Task DownloadFileAsync(this HttpClient client, Uri address, string fileName, Action<HttpClientDownloadProgress> progress = null, Action<bool> completed = null, CancellationToken cancellationToken = default(CancellationToken))
public static async Task DownloadFileAsync(this HttpClient client, Uri address, string fileName, Action<HttpClientDownloadProgress> progress = null, Action<bool> completed = null, CancellationToken cancellationToken = default)
{
try
{
@@ -1094,25 +1094,27 @@ namespace WPinternals
if (progress is null || !contentLength.HasValue)
{
await download.CopyToAsync(destination);
if (completed != null)
completed(true);
completed?.Invoke(true);
return;
}
Progress<long> progressWrapper = new Progress<long>(totalBytes => progress(new HttpClientDownloadProgress(totalBytes, contentLength.Value)));
Progress<long> progressWrapper = new(totalBytes => progress(new HttpClientDownloadProgress(totalBytes, contentLength.Value)));
await download.CopyToAsync(destination, 81920, progressWrapper, cancellationToken);
if (completed != null)
completed(true);
completed?.Invoke(true);
}
catch
catch (Exception ex)
{
if (completed != null)
completed(false);
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);
completed?.Invoke(false);
}
}
private static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress<long> progress = null, CancellationToken cancellationToken = default(CancellationToken))
private static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress<long> progress = null, CancellationToken cancellationToken = default)
{
if (bufferSize < 0)
throw new ArgumentOutOfRangeException(nameof(bufferSize));
@@ -1128,9 +1130,9 @@ namespace WPinternals
byte[] buffer = new byte[bufferSize];
long totalBytesRead = 0;
int bytesRead;
while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
while ((bytesRead = await source.ReadAsync(buffer, cancellationToken).ConfigureAwait(false)) != 0)
{
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
await destination.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken).ConfigureAwait(false);
totalBytesRead += bytesRead;
progress?.Report(totalBytesRead);
}
@@ -20,6 +20,7 @@
using System;
using System.Threading;
using WPinternals.HelperClasses;
namespace WPinternals
{

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