mirror of
https://github.com/ReneLergner/WPinternals.git
synced 2026-08-09 17:41:13 +10:00
Compare commits
13
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6be24faee0 | ||
|
|
e078bb10ed | ||
|
|
605b19aede | ||
|
|
d9da49915e | ||
|
|
7c18a168fa | ||
|
|
303c2d4b5a | ||
|
|
d700ae5911 | ||
|
|
14bf607111 | ||
|
|
57c9595d86 | ||
|
|
7fc332e912 | ||
|
|
bcec0a72e6 | ||
|
|
00407d6f24 | ||
|
|
2d5b0fd3db |
@@ -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 }}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
+46
-517
@@ -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)
|
||||
{
|
||||
@@ -1676,39 +1466,10 @@ namespace WPinternals
|
||||
App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
|
||||
}
|
||||
|
||||
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
|
||||
{
|
||||
ProductType = "RM-1085";
|
||||
|
||||
URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
|
||||
DownloadFolder = args.Length >= 3
|
||||
? args[2]
|
||||
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
|
||||
|
||||
if (!Directory.Exists(DownloadFolder))
|
||||
{
|
||||
Directory.CreateDirectory(DownloadFolder);
|
||||
}
|
||||
|
||||
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
|
||||
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
|
||||
URI = new Uri(URL);
|
||||
FFUFileName = Path.GetFileName(URI.LocalPath);
|
||||
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
|
||||
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
|
||||
LogFile.Log("Downloading...", LogType.FileAndConsole);
|
||||
using (System.Net.WebClient myWebClient = new())
|
||||
{
|
||||
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
|
||||
}
|
||||
LogFile.Log("Download finished", LogType.FileAndConsole);
|
||||
App.Config.AddFfuToRepository(FFUFilePath);
|
||||
|
||||
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
|
||||
{
|
||||
throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
|
||||
}
|
||||
}
|
||||
Notifier.Stop();
|
||||
break;
|
||||
case "downloadallbyproducttype":
|
||||
@@ -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)
|
||||
{
|
||||
@@ -1773,233 +1519,10 @@ namespace WPinternals
|
||||
App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
|
||||
}
|
||||
|
||||
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
|
||||
{
|
||||
ProductType = "RM-1085";
|
||||
|
||||
URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
|
||||
DownloadFolder = args.Length >= 4
|
||||
? args[3]
|
||||
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
|
||||
|
||||
if (!Directory.Exists(DownloadFolder))
|
||||
{
|
||||
Directory.CreateDirectory(DownloadFolder);
|
||||
}
|
||||
|
||||
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
|
||||
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
|
||||
URI = new Uri(URL);
|
||||
FFUFileName = Path.GetFileName(URI.LocalPath);
|
||||
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
|
||||
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
|
||||
LogFile.Log("Downloading...", LogType.FileAndConsole);
|
||||
using (System.Net.WebClient myWebClient = new())
|
||||
{
|
||||
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
|
||||
}
|
||||
LogFile.Log("Download finished", LogType.FileAndConsole);
|
||||
App.Config.AddFfuToRepository(FFUFilePath);
|
||||
|
||||
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
|
||||
{
|
||||
throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "downloadallbyproductcode":
|
||||
LogFile.Log("Command: Download all by Product Code", LogType.FileAndConsole);
|
||||
if (args.Length < 3)
|
||||
{
|
||||
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadAllByProductCode <Product code> <Optional: Download folder>");
|
||||
}
|
||||
|
||||
ProductCode = args[2];
|
||||
LogFile.Log("Product code: " + ProductCode, LogType.FileAndConsole);
|
||||
URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
|
||||
DownloadFolder = args.Length >= 4
|
||||
? args[3]
|
||||
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
|
||||
|
||||
if (!Directory.Exists(DownloadFolder))
|
||||
{
|
||||
Directory.CreateDirectory(DownloadFolder);
|
||||
}
|
||||
|
||||
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
|
||||
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
|
||||
URI = new Uri(URL);
|
||||
FFUFileName = Path.GetFileName(URI.LocalPath);
|
||||
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
|
||||
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
|
||||
LogFile.Log("Downloading...", LogType.FileAndConsole);
|
||||
using (System.Net.WebClient myWebClient = new())
|
||||
{
|
||||
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
|
||||
}
|
||||
LogFile.Log("Download finished", LogType.FileAndConsole);
|
||||
App.Config.AddFfuToRepository(FFUFilePath);
|
||||
|
||||
URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
|
||||
if (URLs != null)
|
||||
{
|
||||
for (int i = 0; i < URLs.Length; i++)
|
||||
{
|
||||
LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
|
||||
URI = new Uri(URLs[i]);
|
||||
EmergencyFileName = Path.GetFileName(URI.LocalPath);
|
||||
LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
|
||||
EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
|
||||
if (i == 0)
|
||||
{
|
||||
ProgrammerPath = EmergencyFilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
PayloadPath = EmergencyFilePath;
|
||||
}
|
||||
|
||||
LogFile.Log("Downloading...", LogType.FileAndConsole);
|
||||
using (System.Net.WebClient myWebClient = new())
|
||||
{
|
||||
await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
|
||||
}
|
||||
LogFile.Log("Download finished", LogType.FileAndConsole);
|
||||
}
|
||||
App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
|
||||
}
|
||||
|
||||
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
|
||||
{
|
||||
ProductType = "RM-1085";
|
||||
|
||||
URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
|
||||
DownloadFolder = args.Length >= 4
|
||||
? args[3]
|
||||
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
|
||||
|
||||
if (!Directory.Exists(DownloadFolder))
|
||||
{
|
||||
Directory.CreateDirectory(DownloadFolder);
|
||||
}
|
||||
|
||||
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
|
||||
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
|
||||
URI = new Uri(URL);
|
||||
FFUFileName = Path.GetFileName(URI.LocalPath);
|
||||
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
|
||||
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
|
||||
LogFile.Log("Downloading...", LogType.FileAndConsole);
|
||||
using (System.Net.WebClient myWebClient = new())
|
||||
{
|
||||
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
|
||||
}
|
||||
LogFile.Log("Download finished", LogType.FileAndConsole);
|
||||
App.Config.AddFfuToRepository(FFUFilePath);
|
||||
|
||||
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
|
||||
{
|
||||
throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "downloadallbyoperatorcode":
|
||||
LogFile.Log("Command: Download FFU by Operator Code", LogType.FileAndConsole);
|
||||
if (args.Length < 4)
|
||||
{
|
||||
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadFFUbyOperatorCode <Product type> <Operator code> <Optional: Download folder>");
|
||||
}
|
||||
|
||||
ProductType = args[2];
|
||||
LogFile.Log("Product type: " + ProductType, LogType.FileAndConsole);
|
||||
OperatorCode = args[3];
|
||||
LogFile.Log("Operator code: " + OperatorCode, LogType.FileAndConsole);
|
||||
DownloadFolder = args.Length >= 5
|
||||
? args[4]
|
||||
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
|
||||
|
||||
if (!Directory.Exists(DownloadFolder))
|
||||
{
|
||||
Directory.CreateDirectory(DownloadFolder);
|
||||
}
|
||||
|
||||
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
|
||||
URL = LumiaDownloadModel.SearchFFU(ProductType, null, OperatorCode);
|
||||
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
|
||||
URI = new Uri(URL);
|
||||
FFUFileName = Path.GetFileName(URI.LocalPath);
|
||||
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
|
||||
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
|
||||
LogFile.Log("Downloading...", LogType.FileAndConsole);
|
||||
using (System.Net.WebClient myWebClient = new())
|
||||
{
|
||||
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
|
||||
}
|
||||
LogFile.Log("Download finished", LogType.FileAndConsole);
|
||||
App.Config.AddFfuToRepository(FFUFilePath);
|
||||
|
||||
URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
|
||||
if (URLs != null)
|
||||
{
|
||||
for (int i = 0; i < URLs.Length; i++)
|
||||
{
|
||||
LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
|
||||
URI = new Uri(URLs[i]);
|
||||
EmergencyFileName = Path.GetFileName(URI.LocalPath);
|
||||
LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
|
||||
EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
|
||||
if (i == 0)
|
||||
{
|
||||
ProgrammerPath = EmergencyFilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
PayloadPath = EmergencyFilePath;
|
||||
}
|
||||
|
||||
LogFile.Log("Downloading...", LogType.FileAndConsole);
|
||||
using (System.Net.WebClient myWebClient = new())
|
||||
{
|
||||
await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
|
||||
}
|
||||
LogFile.Log("Download finished", LogType.FileAndConsole);
|
||||
}
|
||||
App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
|
||||
}
|
||||
|
||||
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
|
||||
{
|
||||
ProductType = "RM-1085";
|
||||
|
||||
URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
|
||||
DownloadFolder = args.Length >= 5
|
||||
? args[4]
|
||||
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
|
||||
|
||||
if (!Directory.Exists(DownloadFolder))
|
||||
{
|
||||
Directory.CreateDirectory(DownloadFolder);
|
||||
}
|
||||
|
||||
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
|
||||
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
|
||||
URI = new Uri(URL);
|
||||
FFUFileName = Path.GetFileName(URI.LocalPath);
|
||||
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
|
||||
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
|
||||
LogFile.Log("Downloading...", LogType.FileAndConsole);
|
||||
using (System.Net.WebClient myWebClient = new())
|
||||
{
|
||||
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
|
||||
}
|
||||
LogFile.Log("Download finished", LogType.FileAndConsole);
|
||||
App.Config.AddFfuToRepository(FFUFilePath);
|
||||
|
||||
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
|
||||
{
|
||||
throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "rewritepartitionsfrommassstorage":
|
||||
if (args.Length < 2)
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
+11
-13
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using WPinternals.HelperClasses;
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
@@ -289,7 +289,7 @@ namespace WPinternals
|
||||
Partition Target = GPT.Partitions.Find(p => string.Equals(p.Name, Name, StringComparison.CurrentCultureIgnoreCase));
|
||||
if (Target == null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
throw new ArgumentOutOfRangeException(nameof(Name));
|
||||
}
|
||||
|
||||
return GetSectors((int)Target.FirstSector, (int)(Target.LastSector - Target.FirstSector + 1));
|
||||
@@ -315,7 +315,7 @@ namespace WPinternals
|
||||
Partition Target = GPT.Partitions.Find(p => string.Equals(p.Name, Name, StringComparison.CurrentCultureIgnoreCase));
|
||||
if (Target == null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
throw new ArgumentOutOfRangeException(nameof(Name));
|
||||
}
|
||||
|
||||
int FirstChunk = GetChunkIndexFromSectorIndex((int)Target.FirstSector);
|
||||
|
||||
@@ -24,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];
|
||||
}
|
||||
}
|
||||
}
|
||||
+41
-126
@@ -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,7 +302,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) =>
|
||||
@@ -309,7 +322,7 @@ namespace WPinternals
|
||||
JsonDocument ResultMessage = JsonDocument.Parse(System.Text.Encoding.ASCII.GetString(Buffer, 0, Length));
|
||||
|
||||
JsonElement? ResultToken = ResultMessage.RootElement.GetProperty("result");
|
||||
if ((ResultToken == null) || (ResultElement == null))
|
||||
if (ResultToken == null || ResultElement == null)
|
||||
{
|
||||
Callback(AsyncResultRead.AsyncState, null);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+43
-37
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -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
|
||||
}
|
||||
}
|
||||
+1
-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 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
|
||||
}
|
||||
}
|
||||
+160
-123
@@ -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 (Result.App == FlashAppType.FlashApp)
|
||||
if (ExtendedInfo && Result.State == PhoneInfoState.Basic)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
+11
-10
@@ -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
|
||||
}
|
||||
}
|
||||
+1
-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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+45
-107
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
-11
@@ -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']);
|
||||
}
|
||||
|
||||
+25
-3
@@ -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);
|
||||
}
|
||||
+1
-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
|
||||
{
|
||||
internal enum PhoneInfoState
|
||||
{
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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]);
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using WPinternals.HelperClasses;
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -22,6 +22,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using WPinternals.HelperClasses;
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
using MadWizard.WinUSBNet;
|
||||
using System;
|
||||
using System.IO.Ports;
|
||||
using WPinternals.HelperClasses;
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using WPinternals.HelperClasses;
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using WPinternals.HelperClasses;
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user