Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6be24faee0 | ||
|
|
e078bb10ed | ||
|
|
605b19aede | ||
|
|
d9da49915e | ||
|
|
7c18a168fa | ||
|
|
303c2d4b5a | ||
|
|
d700ae5911 | ||
|
|
14bf607111 | ||
|
|
57c9595d86 | ||
|
|
7fc332e912 | ||
|
|
bcec0a72e6 | ||
|
|
00407d6f24 | ||
|
|
2d5b0fd3db | ||
|
|
a982c119fb | ||
|
|
c6dee3fe33 | ||
|
|
91961b0e7b | ||
|
|
29c6ab06d4 | ||
|
|
b03b561724 | ||
|
|
91f534a7c3 | ||
|
|
f0f3268924 | ||
|
|
c269cfe839 | ||
|
|
7d8aad0e88 | ||
|
|
310d0b97c5 | ||
|
|
8e50c46357 | ||
|
|
e6555741b0 | ||
|
|
c21692491d | ||
|
|
350b6e8f1e | ||
|
|
0101477830 | ||
|
|
a6c017986b | ||
|
|
0174fc8b30 | ||
|
|
c6f6ef4429 | ||
|
|
ab0c35e879 | ||
|
|
676a95dd97 | ||
|
|
8981fd02e9 | ||
|
|
16d3f95971 | ||
|
|
293c649edb | ||
|
|
88efc77887 | ||
|
|
dc6085f185 | ||
|
|
e2cbb9c6fc | ||
|
|
4b7b9621b4 | ||
|
|
96c42a29b5 | ||
|
|
742c89b9bf | ||
|
|
dbd303fd07 | ||
|
|
8d35be447a | ||
|
|
83c09bdc81 | ||
|
|
93a5064751 | ||
|
|
ef6a962a01 | ||
|
|
d32788198d | ||
|
|
7798dd1c34 | ||
|
|
57cd052d61 | ||
|
|
5eb523530c | ||
|
|
8a17b05398 | ||
|
|
dc5ac1e7d4 | ||
|
|
1d14d79fab | ||
|
|
846ea41883 | ||
|
|
452393aaa7 | ||
|
|
17bc763761 | ||
|
|
668a9b7fe2 | ||
|
|
8293c18406 | ||
|
|
48fbfa77df | ||
|
|
709c91cec5 | ||
|
|
611ad122f9 | ||
|
|
d8fd0aa516 | ||
|
|
7f3c8b1777 | ||
|
|
087457fa0d | ||
|
|
bb9f614e82 |
@@ -0,0 +1,60 @@
|
|||||||
|
name: Bug Report
|
||||||
|
description: Create a bug report to help improve WPinternals
|
||||||
|
labels: [bug]
|
||||||
|
body:
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
description: A clear and concise description of what the bug is.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Steps To Reproduce
|
||||||
|
description: Steps to reproduce the behavior.
|
||||||
|
placeholder: |
|
||||||
|
1. Go to '....'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See the error
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Expected behavior
|
||||||
|
description: A clear and concise description of what you expected to happen.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: wpi-version
|
||||||
|
attributes:
|
||||||
|
label: WPinternals Version
|
||||||
|
description: What version of WPinternals are you using?
|
||||||
|
placeholder: v2.9.2
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: Windows Version
|
||||||
|
description: What version of Windows are you using? Press <kbd>Win</kbd> + <kbd>Pause/Break</kbd> and copy.
|
||||||
|
placeholder: e.g. Windows 11 21H2 22000.132
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: Phone model
|
||||||
|
description: What phone model did you reproduce the bug on (if applicable)
|
||||||
|
placeholder: e.g. Lumia 950 XL (RM-1085)
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Relevant Assets
|
||||||
|
description: |
|
||||||
|
A list of assets (logs, screenshots) relevant to this bug.
|
||||||
|
|
||||||
|
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
|
||||||
|
placeholder: |
|
||||||
|
To upload the log
|
||||||
|
- Copy the `WPinternals.log` files from `%ALLUSERSPROFILE%\WPinternals`
|
||||||
|
- Drag and drop them into this text area.
|
||||||
@@ -11,16 +11,16 @@ jobs:
|
|||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
architecture: [x86, x64]
|
architecture: [x86, x64, arm64]
|
||||||
platform: [win]
|
platform: [win]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install .NET SDK
|
- name: Install .NET SDK
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: "5.0.101"
|
dotnet-version: "8.0.x"
|
||||||
|
|
||||||
- name: Add MSBuild to PATH
|
- name: Add MSBuild to PATH
|
||||||
uses: microsoft/setup-msbuild@v1.0.2
|
uses: microsoft/setup-msbuild@v1.0.2
|
||||||
@@ -31,7 +31,7 @@ jobs:
|
|||||||
msbuild /m /t:restore,wpinternals:publish /p:Platform=${{ matrix.architecture }} /p:RuntimeIdentifier=${{ matrix.platform }}-${{ matrix.architecture }} /p:PublishDir=${{ github.workspace }}/artifacts/${{ matrix.platform }}-${{ matrix.architecture }} /p:PublishSingleFile=true /p:PublishTrimmed=false WPinternals.sln
|
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
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.platform }}-${{ matrix.architecture }}
|
name: ${{ matrix.platform }}-${{ matrix.architecture }}
|
||||||
path: ${{ github.workspace }}/artifacts/${{ matrix.platform }}-${{ matrix.architecture }}
|
path: ${{ github.workspace }}/artifacts/${{ matrix.platform }}-${{ matrix.architecture }}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
|
Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,860 +0,0 @@
|
|||||||
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Runtime.Serialization;
|
|
||||||
using System.Runtime.Serialization.Json;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Xml;
|
|
||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace WPinternals
|
|
||||||
{
|
|
||||||
internal static class LumiaDownloadModel
|
|
||||||
{
|
|
||||||
internal static string SearchFFU(string ProductType, string ProductCode, string OperatorCode)
|
|
||||||
{
|
|
||||||
return SearchFFU(ProductType, ProductCode, OperatorCode, out string FoundProductType);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string SearchFFU(string ProductType, string ProductCode, string OperatorCode, out string FoundProductType)
|
|
||||||
{
|
|
||||||
if (ProductType?.Length == 0)
|
|
||||||
{
|
|
||||||
ProductType = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ProductCode?.Length == 0)
|
|
||||||
{
|
|
||||||
ProductCode = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (OperatorCode?.Length == 0)
|
|
||||||
{
|
|
||||||
OperatorCode = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ProductCode != null)
|
|
||||||
{
|
|
||||||
ProductCode = ProductCode.ToUpper();
|
|
||||||
ProductType = null;
|
|
||||||
OperatorCode = null;
|
|
||||||
}
|
|
||||||
if (ProductType != null)
|
|
||||||
{
|
|
||||||
ProductType = ProductType.ToUpper();
|
|
||||||
if (ProductType.StartsWith("RM") && !ProductType.StartsWith("RM-"))
|
|
||||||
{
|
|
||||||
ProductType = "RM-" + ProductType[2..];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (OperatorCode != null)
|
|
||||||
{
|
|
||||||
OperatorCode = OperatorCode.ToUpper();
|
|
||||||
}
|
|
||||||
|
|
||||||
DiscoveryQueryParameters DiscoveryQueryParams = new()
|
|
||||||
{
|
|
||||||
manufacturerName = "Microsoft",
|
|
||||||
manufacturerProductLine = "Lumia",
|
|
||||||
packageType = "Firmware",
|
|
||||||
packageClass = "Public",
|
|
||||||
manufacturerHardwareModel = ProductType,
|
|
||||||
manufacturerHardwareVariant = ProductCode,
|
|
||||||
operatorName = OperatorCode
|
|
||||||
};
|
|
||||||
DiscoveryParameters DiscoveryParams = new()
|
|
||||||
{
|
|
||||||
query = DiscoveryQueryParams
|
|
||||||
};
|
|
||||||
|
|
||||||
DataContractJsonSerializer Serializer1 = new(typeof(DiscoveryParameters));
|
|
||||||
MemoryStream JsonStream1 = new();
|
|
||||||
Serializer1.WriteObject(JsonStream1, DiscoveryParams);
|
|
||||||
JsonStream1.Seek(0L, SeekOrigin.Begin);
|
|
||||||
string JsonContent = new StreamReader(JsonStream1).ReadToEnd();
|
|
||||||
|
|
||||||
Uri RequestUri = new("https://api.swrepository.com/rest-api/discovery/1/package");
|
|
||||||
|
|
||||||
HttpClient HttpClient = new();
|
|
||||||
HttpClient.DefaultRequestHeaders.UserAgent.TryParseAdd("SoftwareRepository");
|
|
||||||
HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
|
||||||
|
|
||||||
Task<HttpResponseMessage> HttpPostTask = HttpClient.PostAsync(RequestUri, new StringContent(JsonContent, Encoding.UTF8, "application/json"));
|
|
||||||
HttpPostTask.Wait();
|
|
||||||
HttpResponseMessage Response = HttpPostTask.Result;
|
|
||||||
|
|
||||||
string JsonResultString = "";
|
|
||||||
if (Response.StatusCode == HttpStatusCode.OK)
|
|
||||||
{
|
|
||||||
Task<string> ReadResponseTask = Response.Content.ReadAsStringAsync();
|
|
||||||
ReadResponseTask.Wait();
|
|
||||||
JsonResultString = ReadResponseTask.Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
SoftwarePackage Package = null;
|
|
||||||
using (MemoryStream JsonStream2 = new(Encoding.UTF8.GetBytes(JsonResultString)))
|
|
||||||
{
|
|
||||||
DataContractJsonSerializer Serializer2 = new(typeof(SoftwarePackages));
|
|
||||||
SoftwarePackages SoftwarePackages = (SoftwarePackages)Serializer2.ReadObject(JsonStream2);
|
|
||||||
if (SoftwarePackages != null)
|
|
||||||
{
|
|
||||||
Package = SoftwarePackages.softwarePackages.FirstOrDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Package == null)
|
|
||||||
{
|
|
||||||
throw new WPinternalsException("FFU not found", "No FFU has been found in the remote software repository for the requested model.");
|
|
||||||
}
|
|
||||||
|
|
||||||
FoundProductType = Package.manufacturerHardwareModel[0];
|
|
||||||
|
|
||||||
SoftwareFile FileInfo = Package.files.First(f => f.fileName.EndsWith(".ffu", StringComparison.OrdinalIgnoreCase));
|
|
||||||
|
|
||||||
Uri FileInfoUri = new("https://api.swrepository.com/rest-api/discovery/fileurl/1/" + Package.id + "/" + FileInfo.fileName);
|
|
||||||
Task<string> GetFileInfoTask = HttpClient.GetStringAsync(FileInfoUri);
|
|
||||||
GetFileInfoTask.Wait();
|
|
||||||
string FileInfoString = GetFileInfoTask.Result;
|
|
||||||
|
|
||||||
string FfuUrl = "";
|
|
||||||
FileUrlResult FileUrl = null;
|
|
||||||
using (MemoryStream JsonStream3 = new(Encoding.UTF8.GetBytes(FileInfoString)))
|
|
||||||
{
|
|
||||||
DataContractJsonSerializer Serializer3 = new(typeof(FileUrlResult));
|
|
||||||
FileUrl = (FileUrlResult)Serializer3.ReadObject(JsonStream3);
|
|
||||||
if (FileUrl != null)
|
|
||||||
{
|
|
||||||
FfuUrl = FileUrl.url.Replace("sr.azureedge.net", "softwarerepo.blob.core.windows.net");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpClient.Dispose();
|
|
||||||
|
|
||||||
return FfuUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string SearchENOSW(string ProductType, string PhoneFirmwareRevision)
|
|
||||||
{
|
|
||||||
if (ProductType?.Length == 0)
|
|
||||||
{
|
|
||||||
ProductType = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ProductType != null)
|
|
||||||
{
|
|
||||||
ProductType = ProductType.ToUpper();
|
|
||||||
if (ProductType.StartsWith("RM") && !ProductType.StartsWith("RM-"))
|
|
||||||
{
|
|
||||||
ProductType = "RM-" + ProductType[2..];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DiscoveryQueryParameters DiscoveryQueryParams = new()
|
|
||||||
{
|
|
||||||
manufacturerName = "Microsoft",
|
|
||||||
manufacturerProductLine = "Lumia",
|
|
||||||
packageType = "Test Mode",
|
|
||||||
packageClass = "Public",
|
|
||||||
manufacturerHardwareModel = ProductType
|
|
||||||
};
|
|
||||||
DiscoveryParameters DiscoveryParams = new()
|
|
||||||
{
|
|
||||||
query = DiscoveryQueryParams
|
|
||||||
};
|
|
||||||
|
|
||||||
DataContractJsonSerializer Serializer1 = new(typeof(DiscoveryParameters));
|
|
||||||
MemoryStream JsonStream1 = new();
|
|
||||||
Serializer1.WriteObject(JsonStream1, DiscoveryParams);
|
|
||||||
JsonStream1.Seek(0L, SeekOrigin.Begin);
|
|
||||||
string JsonContent = new StreamReader(JsonStream1).ReadToEnd();
|
|
||||||
|
|
||||||
Uri RequestUri = new("https://api.swrepository.com/rest-api/discovery/1/package");
|
|
||||||
|
|
||||||
HttpClient HttpClient = new();
|
|
||||||
HttpClient.DefaultRequestHeaders.UserAgent.TryParseAdd("SoftwareRepository");
|
|
||||||
HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
|
||||||
|
|
||||||
Task<HttpResponseMessage> HttpPostTask = HttpClient.PostAsync(RequestUri, new StringContent(JsonContent, Encoding.UTF8, "application/json"));
|
|
||||||
HttpPostTask.Wait();
|
|
||||||
HttpResponseMessage Response = HttpPostTask.Result;
|
|
||||||
|
|
||||||
string JsonResultString = "";
|
|
||||||
if (Response.StatusCode == HttpStatusCode.OK)
|
|
||||||
{
|
|
||||||
Task<string> ReadResponseTask = Response.Content.ReadAsStringAsync();
|
|
||||||
ReadResponseTask.Wait();
|
|
||||||
JsonResultString = ReadResponseTask.Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
SoftwarePackage Package = null;
|
|
||||||
using (MemoryStream JsonStream2 = new(Encoding.UTF8.GetBytes(JsonResultString)))
|
|
||||||
{
|
|
||||||
DataContractJsonSerializer Serializer2 = new(typeof(SoftwarePackages));
|
|
||||||
SoftwarePackages SoftwarePackages = (SoftwarePackages)Serializer2.ReadObject(JsonStream2);
|
|
||||||
if (SoftwarePackages != null)
|
|
||||||
{
|
|
||||||
foreach (SoftwarePackage pkg in SoftwarePackages.softwarePackages)
|
|
||||||
{
|
|
||||||
Package = SoftwarePackages.softwarePackages.FirstOrDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Package == null)
|
|
||||||
{
|
|
||||||
throw new WPinternalsException("ENOSW package not found", "No ENOSW package has been found in the remote software repository for the requested model.");
|
|
||||||
}
|
|
||||||
|
|
||||||
SoftwareFile FileInfo = Package.files.First(f => f.fileName.EndsWith(".secwim", StringComparison.OrdinalIgnoreCase));
|
|
||||||
|
|
||||||
SoftwareFile DPLF = Package.files.First(f => f.fileName.EndsWith(".dpl", StringComparison.OrdinalIgnoreCase));
|
|
||||||
Uri DPLUri = new("https://api.swrepository.com/rest-api/discovery/fileurl/1/" + Package.id + "/" + DPLF.fileName);
|
|
||||||
Task<string> GetDPLTask = HttpClient.GetStringAsync(DPLUri);
|
|
||||||
GetDPLTask.Wait();
|
|
||||||
string DPLString = GetDPLTask.Result;
|
|
||||||
|
|
||||||
string DPLUrl = "";
|
|
||||||
FileUrlResult FileUrlDPL = null;
|
|
||||||
using (MemoryStream JsonStream3 = new(Encoding.UTF8.GetBytes(DPLString)))
|
|
||||||
{
|
|
||||||
DataContractJsonSerializer Serializer3 = new(typeof(FileUrlResult));
|
|
||||||
FileUrlDPL = (FileUrlResult)Serializer3.ReadObject(JsonStream3);
|
|
||||||
if (FileUrlDPL != null)
|
|
||||||
{
|
|
||||||
DPLUrl = FileUrlDPL.url.Replace("sr.azureedge.net", "softwarerepo.blob.core.windows.net");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DPLUrl?.Length == 0)
|
|
||||||
{
|
|
||||||
throw new WPinternalsException("DPL not found", "No DPL has been found in the remote software repository for the requested model.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Task<string> GetDPLStrTask = HttpClient.GetStringAsync(DPLUrl);
|
|
||||||
GetDPLStrTask.Wait();
|
|
||||||
string DPLStrString = GetDPLStrTask.Result;
|
|
||||||
|
|
||||||
DPL.Package dpl;
|
|
||||||
XmlSerializer serializer = new(typeof(DPL.Package));
|
|
||||||
using (StringReader reader = new(DPLStrString.Replace("ft:", "").Replace("dpl:", "").Replace("typedes:", "")))
|
|
||||||
{
|
|
||||||
dpl = (DPL.Package)serializer.Deserialize(reader);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (DPL.File file in dpl.Content.Files.File)
|
|
||||||
{
|
|
||||||
string name = file.Name;
|
|
||||||
|
|
||||||
DPL.Range range = file.Extensions.MmosWimFile.UseCaseCompatibilities.Compatibility.FirstOrDefault().Range;
|
|
||||||
|
|
||||||
if (IsFirmwareBetween(PhoneFirmwareRevision, range.From, range.To))
|
|
||||||
{
|
|
||||||
FileInfo = Package.files.First(f => f.fileName.EndsWith(name, StringComparison.OrdinalIgnoreCase));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Uri FileInfoUri = new("https://api.swrepository.com/rest-api/discovery/fileurl/1/" + Package.id + "/" + FileInfo.fileName);
|
|
||||||
Task<string> GetFileInfoTask = HttpClient.GetStringAsync(FileInfoUri);
|
|
||||||
GetFileInfoTask.Wait();
|
|
||||||
string FileInfoString = GetFileInfoTask.Result;
|
|
||||||
|
|
||||||
string ENOSWUrl = "";
|
|
||||||
FileUrlResult FileUrl = null;
|
|
||||||
using (MemoryStream JsonStream3 = new(Encoding.UTF8.GetBytes(FileInfoString)))
|
|
||||||
{
|
|
||||||
DataContractJsonSerializer Serializer3 = new(typeof(FileUrlResult));
|
|
||||||
FileUrl = (FileUrlResult)Serializer3.ReadObject(JsonStream3);
|
|
||||||
if (FileUrl != null)
|
|
||||||
{
|
|
||||||
ENOSWUrl = FileUrl.url.Replace("sr.azureedge.net", "softwarerepo.blob.core.windows.net");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpClient.Dispose();
|
|
||||||
|
|
||||||
return ENOSWUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsFirmwareBetween(string PhoneFirmwareRevision, string Limit1, string Limit2)
|
|
||||||
{
|
|
||||||
var version = new Version(PhoneFirmwareRevision);
|
|
||||||
var version1 = new Version(Limit1);
|
|
||||||
var version2 = new Version(Limit2);
|
|
||||||
|
|
||||||
var result = version.CompareTo(version1);
|
|
||||||
var result2 = version.CompareTo(version2);
|
|
||||||
|
|
||||||
return result >= 0 && result2 <= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string[] SearchEmergencyFiles(string ProductType)
|
|
||||||
{
|
|
||||||
ProductType = ProductType.ToUpper();
|
|
||||||
if (ProductType.StartsWith("RM") && !ProductType.StartsWith("RM-"))
|
|
||||||
{
|
|
||||||
ProductType = "RM-" + ProductType[2..];
|
|
||||||
}
|
|
||||||
|
|
||||||
LogFile.Log("Getting Emergency files for: " + ProductType, LogType.FileAndConsole);
|
|
||||||
|
|
||||||
if ((ProductType == "RM-1072") || (ProductType == "RM-1073"))
|
|
||||||
{
|
|
||||||
LogFile.Log("Due to mix-up in online-repository, redirecting to emergency files of RM-1113", LogType.FileAndConsole);
|
|
||||||
ProductType = "RM-1113";
|
|
||||||
}
|
|
||||||
|
|
||||||
List<string> Result = new();
|
|
||||||
|
|
||||||
WebClient Client = new();
|
|
||||||
string Src;
|
|
||||||
string FileName;
|
|
||||||
string Config = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Config = Client.DownloadString("https://repairavoidance.blob.core.windows.net/packages/EmergencyFlash/" + ProductType + "/emergency_flash_config.xml");
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
LogFile.Log("Emergency files for " + ProductType + " not found", LogType.FileAndConsole);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Client.Dispose();
|
|
||||||
|
|
||||||
XmlDocument Doc = new();
|
|
||||||
Doc.LoadXml(Config);
|
|
||||||
|
|
||||||
// Hex
|
|
||||||
XmlNode Node = Doc.SelectSingleNode("//emergency_flash_config/hex_flasher");
|
|
||||||
if (Node != null)
|
|
||||||
{
|
|
||||||
FileName = Node.Attributes["image_path"].InnerText;
|
|
||||||
Src = "https://repairavoidance.blob.core.windows.net/packages/EmergencyFlash/" + ProductType + "/" + FileName;
|
|
||||||
LogFile.Log("Hex-file: " + Src);
|
|
||||||
Result.Add(Src);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mbn
|
|
||||||
Node = Doc.SelectSingleNode("//emergency_flash_config/mbn_image");
|
|
||||||
if (Node != null)
|
|
||||||
{
|
|
||||||
FileName = Node.Attributes["image_path"].InnerText;
|
|
||||||
Src = "https://repairavoidance.blob.core.windows.net/packages/EmergencyFlash/" + ProductType + "/" + FileName;
|
|
||||||
LogFile.Log("Mbn-file: " + Src);
|
|
||||||
Result.Add(Src);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ede
|
|
||||||
foreach (XmlNode SubNode in Doc.SelectNodes("//emergency_flash_config/first_boot_images/first_boot_image"))
|
|
||||||
{
|
|
||||||
FileName = SubNode.Attributes["image_path"].InnerText;
|
|
||||||
Src = "https://repairavoidance.blob.core.windows.net/packages/EmergencyFlash/" + ProductType + "/" + FileName;
|
|
||||||
LogFile.Log("Firehose-programmer-file: " + Src);
|
|
||||||
Result.Add(Src);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Edp
|
|
||||||
foreach (XmlNode SubNode in Doc.SelectNodes("//emergency_flash_config/second_boot_firehose_single_image/firehose_image"))
|
|
||||||
{
|
|
||||||
FileName = SubNode.Attributes["image_path"].InnerText;
|
|
||||||
Src = "https://repairavoidance.blob.core.windows.net/packages/EmergencyFlash/" + ProductType + "/" + FileName;
|
|
||||||
LogFile.Log("Firehose-payload-file: " + Src);
|
|
||||||
Result.Add(Src);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result.ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma warning disable 0649
|
|
||||||
[DataContract]
|
|
||||||
internal class FileUrlResult
|
|
||||||
{
|
|
||||||
[DataMember]
|
|
||||||
internal string url;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
internal List<string> alternateUrl;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
internal long fileSize;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
internal List<SoftwareFileChecksum> checksum;
|
|
||||||
}
|
|
||||||
#pragma warning restore 0649
|
|
||||||
|
|
||||||
[DataContract]
|
|
||||||
public class DiscoveryQueryParameters
|
|
||||||
{
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string customerName;
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public ExtendedAttributes extendedAttributes;
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string manufacturerHardwareModel;
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string manufacturerHardwareVariant;
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string manufacturerModelName;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public string manufacturerName;
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string manufacturerPackageId;
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string manufacturerPlatformId;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public string manufacturerProductLine;
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string manufacturerVariantName;
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string operatorName;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public string packageClass;
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string packageRevision;
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string packageState;
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string packageSubRevision;
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string packageSubtitle;
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string packageTitle;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public string packageType;
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataContract]
|
|
||||||
public class DiscoveryParameters
|
|
||||||
{
|
|
||||||
[DataMember(Name = "api-version")]
|
|
||||||
public string apiVersion;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public DiscoveryQueryParameters query;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public List<string> condition;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public List<string> response;
|
|
||||||
|
|
||||||
public DiscoveryParameters() : this(DiscoveryCondition.Default)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public DiscoveryParameters(DiscoveryCondition Condition)
|
|
||||||
{
|
|
||||||
this.apiVersion = "1";
|
|
||||||
this.query = new DiscoveryQueryParameters();
|
|
||||||
this.condition = new List<string>();
|
|
||||||
if (Condition == DiscoveryCondition.All)
|
|
||||||
{
|
|
||||||
this.condition.Add("all");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (Condition == DiscoveryCondition.Latest)
|
|
||||||
{
|
|
||||||
this.condition.Add("latest");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.condition.Add("default");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum DiscoveryCondition
|
|
||||||
{
|
|
||||||
Default,
|
|
||||||
All,
|
|
||||||
Latest
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
public class ExtendedAttributes : ISerializable
|
|
||||||
{
|
|
||||||
public Dictionary<string, string> Dictionary;
|
|
||||||
|
|
||||||
public ExtendedAttributes()
|
|
||||||
{
|
|
||||||
this.Dictionary = new Dictionary<string, string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ExtendedAttributes(SerializationInfo info, StreamingContext context)
|
|
||||||
{
|
|
||||||
if (info != null)
|
|
||||||
{
|
|
||||||
this.Dictionary = new Dictionary<string, string>();
|
|
||||||
SerializationInfoEnumerator Enumerator = info.GetEnumerator();
|
|
||||||
while (Enumerator.MoveNext())
|
|
||||||
{
|
|
||||||
this.Dictionary.Add(Enumerator.Current.Name, (string)Enumerator.Current.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
|
|
||||||
{
|
|
||||||
if (info != null)
|
|
||||||
{
|
|
||||||
foreach (string Current in this.Dictionary.Keys)
|
|
||||||
{
|
|
||||||
info.AddValue(Current, this.Dictionary[Current]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataContract]
|
|
||||||
public class SoftwareFileChecksum
|
|
||||||
{
|
|
||||||
[DataMember]
|
|
||||||
public string type;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public string value;
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataContract]
|
|
||||||
public class SoftwarePackages
|
|
||||||
{
|
|
||||||
[DataMember]
|
|
||||||
public List<SoftwarePackage> softwarePackages;
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataContract]
|
|
||||||
public class SoftwarePackage
|
|
||||||
{
|
|
||||||
[DataMember]
|
|
||||||
public List<string> customerName;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public ExtendedAttributes extendedAttributes;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public List<SoftwareFile> files;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public string id;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public List<string> manufacturerHardwareModel;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public List<string> manufacturerHardwareVariant;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public List<string> manufacturerModelName;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public string manufacturerName;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public string manufacturerPackageId;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public List<string> manufacturerPlatformId;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public string manufacturerProductLine;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public List<string> manufacturerVariantName;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public List<string> operatorName;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public List<string> packageClass;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public string packageDescription;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public string packageRevision;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public string packageState;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public string packageSubRevision;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public string packageSubtitle;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public string packageTitle;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public string packageType;
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataContract]
|
|
||||||
public class SoftwareFile
|
|
||||||
{
|
|
||||||
[DataMember]
|
|
||||||
public List<SoftwareFileChecksum> checksum;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public string fileName;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public long fileSize;
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public string fileType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class DPL
|
|
||||||
{
|
|
||||||
[XmlRoot(ElementName = "BasicProductCodes")]
|
|
||||||
public class BasicProductCodes
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "BasicProductCode")]
|
|
||||||
public List<string> BasicProductCode { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "Identification")]
|
|
||||||
public class Identification
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "TypeDesignator")]
|
|
||||||
public string TypeDesignator { get; set; }
|
|
||||||
[XmlElement(ElementName = "BasicProductCodes")]
|
|
||||||
public BasicProductCodes BasicProductCodes { get; set; }
|
|
||||||
[XmlElement(ElementName = "Purpose")]
|
|
||||||
public string Purpose { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "Extensions")]
|
|
||||||
public class Extensions
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "PackageType")]
|
|
||||||
public string PackageType { get; set; }
|
|
||||||
[XmlElement(ElementName = "Identification")]
|
|
||||||
public Identification Identification { get; set; }
|
|
||||||
[XmlElement(ElementName = "FileType")]
|
|
||||||
public string FileType { get; set; }
|
|
||||||
[XmlElement(ElementName = "MmosWimFile")]
|
|
||||||
public MmosWimFile MmosWimFile { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "PackageDescription")]
|
|
||||||
public class PackageDescription
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "Identifier")]
|
|
||||||
public string Identifier { get; set; }
|
|
||||||
[XmlElement(ElementName = "Revision")]
|
|
||||||
public string Revision { get; set; }
|
|
||||||
[XmlElement(ElementName = "Extensions")]
|
|
||||||
public Extensions Extensions { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "Digest")]
|
|
||||||
public class Digest
|
|
||||||
{
|
|
||||||
[XmlAttribute(AttributeName = "method")]
|
|
||||||
public string Method { get; set; }
|
|
||||||
[XmlAttribute(AttributeName = "encoding")]
|
|
||||||
public string Encoding { get; set; }
|
|
||||||
[XmlText]
|
|
||||||
public string Text { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "Digests")]
|
|
||||||
public class Digests
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "Digest")]
|
|
||||||
public List<Digest> Digest { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "Range")]
|
|
||||||
public class Range
|
|
||||||
{
|
|
||||||
[XmlAttribute(AttributeName = "from")]
|
|
||||||
public string From { get; set; }
|
|
||||||
[XmlAttribute(AttributeName = "to")]
|
|
||||||
public string To { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "Compatibility")]
|
|
||||||
public class Compatibility
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "Range")]
|
|
||||||
public Range Range { get; set; }
|
|
||||||
[XmlAttribute(AttributeName = "useCase")]
|
|
||||||
public string UseCase { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "UseCaseCompatibilities")]
|
|
||||||
public class UseCaseCompatibilities
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "Compatibility")]
|
|
||||||
public List<Compatibility> Compatibility { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "MmosWimFile")]
|
|
||||||
public class MmosWimFile
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "UseCaseCompatibilities")]
|
|
||||||
public UseCaseCompatibilities UseCaseCompatibilities { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "File")]
|
|
||||||
public class File
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "Name")]
|
|
||||||
public string Name { get; set; }
|
|
||||||
[XmlElement(ElementName = "Digests")]
|
|
||||||
public Digests Digests { get; set; }
|
|
||||||
[XmlElement(ElementName = "Revision")]
|
|
||||||
public string Revision { get; set; }
|
|
||||||
[XmlElement(ElementName = "Extensions")]
|
|
||||||
public Extensions Extensions { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "Files")]
|
|
||||||
public class Files
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "File")]
|
|
||||||
public List<File> File { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "Content")]
|
|
||||||
public class Content
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "PackageDescription")]
|
|
||||||
public PackageDescription PackageDescription { get; set; }
|
|
||||||
[XmlElement(ElementName = "Files")]
|
|
||||||
public Files Files { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "CanonicalizationMethod", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
|
|
||||||
public class CanonicalizationMethod
|
|
||||||
{
|
|
||||||
[XmlAttribute(AttributeName = "Algorithm")]
|
|
||||||
public string Algorithm { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "SignatureMethod", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
|
|
||||||
public class SignatureMethod
|
|
||||||
{
|
|
||||||
[XmlAttribute(AttributeName = "Algorithm")]
|
|
||||||
public string Algorithm { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "Transform", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
|
|
||||||
public class Transform
|
|
||||||
{
|
|
||||||
[XmlAttribute(AttributeName = "Algorithm")]
|
|
||||||
public string Algorithm { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "Transforms", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
|
|
||||||
public class Transforms
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "Transform", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
|
|
||||||
public Transform Transform { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "DigestMethod", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
|
|
||||||
public class DigestMethod
|
|
||||||
{
|
|
||||||
[XmlAttribute(AttributeName = "Algorithm")]
|
|
||||||
public string Algorithm { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "Reference", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
|
|
||||||
public class Reference
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "Transforms", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
|
|
||||||
public Transforms Transforms { get; set; }
|
|
||||||
[XmlElement(ElementName = "DigestMethod", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
|
|
||||||
public DigestMethod DigestMethod { get; set; }
|
|
||||||
[XmlElement(ElementName = "DigestValue", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
|
|
||||||
public string DigestValue { get; set; }
|
|
||||||
[XmlAttribute(AttributeName = "URI")]
|
|
||||||
public string URI { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "SignedInfo", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
|
|
||||||
public class SignedInfo
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "CanonicalizationMethod", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
|
|
||||||
public CanonicalizationMethod CanonicalizationMethod { get; set; }
|
|
||||||
[XmlElement(ElementName = "SignatureMethod", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
|
|
||||||
public SignatureMethod SignatureMethod { get; set; }
|
|
||||||
[XmlElement(ElementName = "Reference", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
|
|
||||||
public Reference Reference { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "KeyInfo", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
|
|
||||||
public class KeyInfo
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "KeyName", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
|
|
||||||
public string KeyName { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "Signature", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
|
|
||||||
public class Signature
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "SignedInfo", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
|
|
||||||
public SignedInfo SignedInfo { get; set; }
|
|
||||||
[XmlElement(ElementName = "SignatureValue", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
|
|
||||||
public string SignatureValue { get; set; }
|
|
||||||
[XmlElement(ElementName = "KeyInfo", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
|
|
||||||
public KeyInfo KeyInfo { get; set; }
|
|
||||||
[XmlAttribute(AttributeName = "xmlns")]
|
|
||||||
public string Xmlns { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "Package")]
|
|
||||||
public class Package
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "Content")]
|
|
||||||
public Content Content { get; set; }
|
|
||||||
[XmlElement(ElementName = "Signature", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
|
|
||||||
public Signature Signature { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Windows Phone Internals
|
||||||
|
|
||||||
|
Windows Phone Internals (WPinternals or WPI for short) is a tool designed to unlock the bootloader and/or secure boot of select Lumia devices made by Nokia and Microsoft.
|
||||||
|
Thanks to specifically crafted exploits/techniques the tool is able to disable Bootloader Security/SecureBoot on select Lumia models.
|
||||||
|
|
||||||
|
After unlocking your bootloader you will be able to notably perform the following actions:
|
||||||
|
|
||||||
|
- Boot other Operating Systems
|
||||||
|
- Enable Root Access (on select OS versions)
|
||||||
|
- Flash Custom ROMs
|
||||||
|
- Backup your current Windows Phone ROM
|
||||||
|
- Access your phone internal storage over USB
|
||||||
|
|
||||||
|
## Root Access
|
||||||
|
|
||||||
|
Root Access is a set of patches/hacks disabling security inside Windows Phone at its root. Kernel Security, Permission checks, application container security, deployment capability security and much gets disabled as part of enabling root access.
|
||||||
|
|
||||||
|
## How to get started?
|
||||||
|
|
||||||
|
The tool contains all the documentation you need to know more about the tool, we invite you to read the getting started section of the tool to know more.
|
||||||
|
|
||||||
|
## Where do I download the tool?
|
||||||
|
|
||||||
|
Here: https://github.com/ReneLergner/WPinternals/releases/latest
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<Application
|
||||||
|
x:Class="RootAccessTestUWP.App"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="using:RootAccessTestUWP"
|
||||||
|
RequestedTheme="Dark">
|
||||||
|
|
||||||
|
</Application>
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices.WindowsRuntime;
|
||||||
|
using Windows.ApplicationModel;
|
||||||
|
using Windows.ApplicationModel.Activation;
|
||||||
|
using Windows.Foundation;
|
||||||
|
using Windows.Foundation.Collections;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Controls.Primitives;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
using Windows.UI.Xaml.Input;
|
||||||
|
using Windows.UI.Xaml.Media;
|
||||||
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
|
||||||
|
namespace RootAccessTestUWP
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides application-specific behavior to supplement the default Application class.
|
||||||
|
/// </summary>
|
||||||
|
sealed partial class App : Application
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the singleton application object. This is the first line of authored code
|
||||||
|
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||||
|
/// </summary>
|
||||||
|
public App()
|
||||||
|
{
|
||||||
|
this.InitializeComponent();
|
||||||
|
this.Suspending += OnSuspending;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked when the application is launched normally by the end user. Other entry points
|
||||||
|
/// will be used such as when the application is launched to open a specific file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e">Details about the launch request and process.</param>
|
||||||
|
protected override void OnLaunched(LaunchActivatedEventArgs e)
|
||||||
|
{
|
||||||
|
Frame rootFrame = Window.Current.Content as Frame;
|
||||||
|
|
||||||
|
// Do not repeat app initialization when the Window already has content,
|
||||||
|
// just ensure that the window is active
|
||||||
|
if (rootFrame == null)
|
||||||
|
{
|
||||||
|
// Create a Frame to act as the navigation context and navigate to the first page
|
||||||
|
rootFrame = new Frame();
|
||||||
|
|
||||||
|
rootFrame.NavigationFailed += OnNavigationFailed;
|
||||||
|
|
||||||
|
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
|
||||||
|
{
|
||||||
|
//TODO: Load state from previously suspended application
|
||||||
|
}
|
||||||
|
|
||||||
|
// Place the frame in the current Window
|
||||||
|
Window.Current.Content = rootFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.PrelaunchActivated == false)
|
||||||
|
{
|
||||||
|
if (rootFrame.Content == null)
|
||||||
|
{
|
||||||
|
// When the navigation stack isn't restored navigate to the first page,
|
||||||
|
// configuring the new page by passing required information as a navigation
|
||||||
|
// parameter
|
||||||
|
rootFrame.Navigate(typeof(MainPage), e.Arguments);
|
||||||
|
}
|
||||||
|
// Ensure the current window is active
|
||||||
|
Window.Current.Activate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked when Navigation to a certain page fails
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The Frame which failed navigation</param>
|
||||||
|
/// <param name="e">Details about the navigation failure</param>
|
||||||
|
void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
|
||||||
|
{
|
||||||
|
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked when application execution is being suspended. Application state is saved
|
||||||
|
/// without knowing whether the application will be terminated or resumed with the contents
|
||||||
|
/// of memory still intact.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The source of the suspend request.</param>
|
||||||
|
/// <param name="e">Details about the suspend request.</param>
|
||||||
|
private void OnSuspending(object sender, SuspendingEventArgs e)
|
||||||
|
{
|
||||||
|
var deferral = e.SuspendingOperation.GetDeferral();
|
||||||
|
//TODO: Save application state and stop any background activity
|
||||||
|
deferral.Complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 7.5 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
@@ -0,0 +1,89 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace RootAccessTestUWP
|
||||||
|
{
|
||||||
|
public static class Core
|
||||||
|
{
|
||||||
|
[DllImport("KERNELBASE.DLL", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||||
|
private static extern int RegQueryValueEx(UIntPtr hKey, string lpValueName, int lpReserved, out Core.RegistryValueKind lpType, IntPtr lpData, ref int lpcbData);
|
||||||
|
|
||||||
|
[DllImport("KERNELBASE.DLL", CharSet = CharSet.Unicode)]
|
||||||
|
private static extern int RegOpenKeyEx(UIntPtr hKey, string subKey, int ulOptions, int samDesired, out UIntPtr hkResult);
|
||||||
|
|
||||||
|
[DllImport("KERNELBASE.DLL", SetLastError = true)]
|
||||||
|
private static extern int RegCloseKey(UIntPtr hKey);
|
||||||
|
|
||||||
|
internal static string RegReadStringValue(UIntPtr rootKey, string keyPath, string valueName)
|
||||||
|
{
|
||||||
|
UIntPtr hKey;
|
||||||
|
int num = Core.RegOpenKeyEx(rootKey, keyPath, 0, Core.KEY_READ, out hKey);
|
||||||
|
if (num != 0)
|
||||||
|
{
|
||||||
|
throw new COMException("Failed to open registry key", num);
|
||||||
|
}
|
||||||
|
int cb = 1024;
|
||||||
|
IntPtr intPtr = Marshal.AllocHGlobal(cb);
|
||||||
|
Core.RegistryValueKind registryValueKind;
|
||||||
|
num = Core.RegQueryValueEx(hKey, valueName, 0, out registryValueKind, intPtr, ref cb);
|
||||||
|
if (num != 0)
|
||||||
|
{
|
||||||
|
throw new COMException("Failed to read registry value", num);
|
||||||
|
}
|
||||||
|
if (registryValueKind != Core.RegistryValueKind.String)
|
||||||
|
{
|
||||||
|
throw new Exception("Wrong registry value type");
|
||||||
|
}
|
||||||
|
string result = Marshal.PtrToStringUni(intPtr);
|
||||||
|
Core.RegCloseKey(hKey);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static uint RegReadDwordValue(UIntPtr rootKey, string keyPath, string valueName)
|
||||||
|
{
|
||||||
|
UIntPtr hKey;
|
||||||
|
int num = Core.RegOpenKeyEx(rootKey, keyPath, 0, Core.KEY_READ, out hKey);
|
||||||
|
if (num != 0)
|
||||||
|
{
|
||||||
|
throw new COMException("Failed to open registry key", num);
|
||||||
|
}
|
||||||
|
int cb = 1024;
|
||||||
|
IntPtr intPtr = Marshal.AllocHGlobal(cb);
|
||||||
|
Core.RegistryValueKind registryValueKind;
|
||||||
|
num = Core.RegQueryValueEx(hKey, valueName, 0, out registryValueKind, intPtr, ref cb);
|
||||||
|
if (num != 0)
|
||||||
|
{
|
||||||
|
throw new COMException("Failed to read registry value", num);
|
||||||
|
}
|
||||||
|
if (registryValueKind != Core.RegistryValueKind.DWord)
|
||||||
|
{
|
||||||
|
throw new Exception("Wrong registry value type");
|
||||||
|
}
|
||||||
|
uint result = (uint)Marshal.ReadInt32(intPtr);
|
||||||
|
Core.RegCloseKey(hKey);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UIntPtr HKEY_CLASSES_ROOT = (UIntPtr)2147483648U;
|
||||||
|
|
||||||
|
public static UIntPtr HKEY_CURRENT_USER = (UIntPtr)2147483649U;
|
||||||
|
|
||||||
|
public static UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)2147483650U;
|
||||||
|
|
||||||
|
public static UIntPtr HKEY_USERS = (UIntPtr)2147483651U;
|
||||||
|
|
||||||
|
private static int KEY_READ = 131097;
|
||||||
|
|
||||||
|
public enum RegistryValueKind
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
String,
|
||||||
|
ExpandString,
|
||||||
|
Binary,
|
||||||
|
DWord,
|
||||||
|
MultiString = 7,
|
||||||
|
QWord = 11,
|
||||||
|
None = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<Page
|
||||||
|
x:Class="RootAccessTestUWP.MainPage"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="using:RootAccessTestUWP"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
|
||||||
|
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
|
<TextBlock x:Name="TextBlock"
|
||||||
|
Margin="10"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
Text=""
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
FontFamily="Courier New" />
|
||||||
|
</Grid>
|
||||||
|
</Page>
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices.WindowsRuntime;
|
||||||
|
using Windows.Foundation;
|
||||||
|
using Windows.Foundation.Collections;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Controls.Primitives;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
using Windows.UI.Xaml.Input;
|
||||||
|
using Windows.UI.Xaml.Media;
|
||||||
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
|
||||||
|
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
|
||||||
|
|
||||||
|
namespace RootAccessTestUWP
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class MainPage : Page
|
||||||
|
{
|
||||||
|
public MainPage()
|
||||||
|
{
|
||||||
|
this.InitializeComponent();
|
||||||
|
|
||||||
|
TextBlock.Text = "Reading: HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\PhoneProvisioner\\ColdBootDone" + Environment.NewLine + Environment.NewLine;
|
||||||
|
|
||||||
|
bool flag = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Core.RegReadDwordValue(Core.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\PhoneProvisioner", "ColdBootDone");
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag)
|
||||||
|
{
|
||||||
|
TextBlock.Text = string.Concat(new string[]
|
||||||
|
{
|
||||||
|
TextBlock.Text,
|
||||||
|
"Success!",
|
||||||
|
Environment.NewLine,
|
||||||
|
Environment.NewLine,
|
||||||
|
"Root Access: Enabled"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TextBlock.Text = string.Concat(new string[]
|
||||||
|
{
|
||||||
|
TextBlock.Text,
|
||||||
|
"Failed!",
|
||||||
|
Environment.NewLine,
|
||||||
|
Environment.NewLine,
|
||||||
|
"Root Access: Disabled"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<Package
|
||||||
|
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||||
|
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
|
||||||
|
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||||
|
IgnorableNamespaces="uap mp">
|
||||||
|
|
||||||
|
<Identity
|
||||||
|
Name="66bf96f4-f5ba-41f1-8ceb-ac4e9065ac52"
|
||||||
|
Publisher="CN=Rene"
|
||||||
|
Version="1.0.0.0" />
|
||||||
|
|
||||||
|
<mp:PhoneIdentity PhoneProductId="66bf96f4-f5ba-41f1-8ceb-ac4e9065ac52" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||||
|
|
||||||
|
<Properties>
|
||||||
|
<DisplayName>RootAccessTestUWP</DisplayName>
|
||||||
|
<PublisherDisplayName>Rene</PublisherDisplayName>
|
||||||
|
<Logo>Assets\StoreLogo.png</Logo>
|
||||||
|
</Properties>
|
||||||
|
|
||||||
|
<Dependencies>
|
||||||
|
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
|
||||||
|
</Dependencies>
|
||||||
|
|
||||||
|
<Resources>
|
||||||
|
<Resource Language="x-generate"/>
|
||||||
|
</Resources>
|
||||||
|
|
||||||
|
<Applications>
|
||||||
|
<Application Id="App"
|
||||||
|
Executable="$targetnametoken$.exe"
|
||||||
|
EntryPoint="RootAccessTestUWP.App">
|
||||||
|
<uap:VisualElements
|
||||||
|
DisplayName="RootAccessTestUWP"
|
||||||
|
Square150x150Logo="Assets\Square150x150Logo.png"
|
||||||
|
Square44x44Logo="Assets\Square44x44Logo.png"
|
||||||
|
Description="RootAccessTestUWP"
|
||||||
|
BackgroundColor="transparent">
|
||||||
|
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
|
||||||
|
<uap:SplashScreen Image="Assets\SplashScreen.png" />
|
||||||
|
</uap:VisualElements>
|
||||||
|
</Application>
|
||||||
|
</Applications>
|
||||||
|
|
||||||
|
<Capabilities>
|
||||||
|
<Capability Name="internetClient" />
|
||||||
|
</Capabilities>
|
||||||
|
</Package>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("RootAccessTestUWP")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("RootAccessTestUWP")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2021")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<!--
|
||||||
|
This file contains Runtime Directives used by .NET Native. The defaults here are suitable for most
|
||||||
|
developers. However, you can modify these parameters to modify the behavior of the .NET Native
|
||||||
|
optimizer.
|
||||||
|
|
||||||
|
Runtime Directives are documented at https://go.microsoft.com/fwlink/?LinkID=391919
|
||||||
|
|
||||||
|
To fully enable reflection for App1.MyClass and all of its public/private members
|
||||||
|
<Type Name="App1.MyClass" Dynamic="Required All"/>
|
||||||
|
|
||||||
|
To enable dynamic creation of the specific instantiation of AppClass<T> over System.Int32
|
||||||
|
<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32" Activate="Required Public" />
|
||||||
|
|
||||||
|
Using the Namespace directive to apply reflection policy to all the types in a particular namespace
|
||||||
|
<Namespace Name="DataClasses.ViewModels" Serialize="All" />
|
||||||
|
-->
|
||||||
|
|
||||||
|
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
|
||||||
|
<Application>
|
||||||
|
<!--
|
||||||
|
An Assembly element with Name="*Application*" applies to all assemblies in
|
||||||
|
the application package. The asterisks are not wildcards.
|
||||||
|
-->
|
||||||
|
<Assembly Name="*Application*" Dynamic="Required All" />
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Add your application specific runtime directives here. -->
|
||||||
|
|
||||||
|
|
||||||
|
</Application>
|
||||||
|
</Directives>
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||||
|
<ProjectGuid>{8B6AADBB-C750-492E-AF60-82F6323401CC}</ProjectGuid>
|
||||||
|
<OutputType>AppContainerExe</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>RootAccessTestUWP</RootNamespace>
|
||||||
|
<AssemblyName>RootAccessTestUWP</AssemblyName>
|
||||||
|
<DefaultLanguage>en-US</DefaultLanguage>
|
||||||
|
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||||
|
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.22000.0</TargetPlatformVersion>
|
||||||
|
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
|
||||||
|
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
|
<WindowsXamlEnableOverview>true</WindowsXamlEnableOverview>
|
||||||
|
<AppxPackageSigningEnabled>false</AppxPackageSigningEnabled>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||||
|
<NoWarn>;2008</NoWarn>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<Prefer32Bit>true</Prefer32Bit>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||||
|
<OutputPath>bin\x86\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<NoWarn>;2008</NoWarn>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<Prefer32Bit>true</Prefer32Bit>
|
||||||
|
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<OutputPath>bin\ARM\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||||
|
<NoWarn>;2008</NoWarn>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<PlatformTarget>ARM</PlatformTarget>
|
||||||
|
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<Prefer32Bit>true</Prefer32Bit>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
|
||||||
|
<OutputPath>bin\ARM\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<NoWarn>;2008</NoWarn>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<PlatformTarget>ARM</PlatformTarget>
|
||||||
|
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<Prefer32Bit>true</Prefer32Bit>
|
||||||
|
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM64'">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<OutputPath>bin\ARM64\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||||
|
<NoWarn>;2008</NoWarn>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<PlatformTarget>ARM64</PlatformTarget>
|
||||||
|
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<Prefer32Bit>true</Prefer32Bit>
|
||||||
|
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM64'">
|
||||||
|
<OutputPath>bin\ARM64\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<NoWarn>;2008</NoWarn>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<PlatformTarget>ARM64</PlatformTarget>
|
||||||
|
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<Prefer32Bit>true</Prefer32Bit>
|
||||||
|
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||||
|
<NoWarn>;2008</NoWarn>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
|
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<Prefer32Bit>true</Prefer32Bit>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||||
|
<OutputPath>bin\x64\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<NoWarn>;2008</NoWarn>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
|
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<Prefer32Bit>true</Prefer32Bit>
|
||||||
|
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="App.xaml.cs">
|
||||||
|
<DependentUpon>App.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Core.cs" />
|
||||||
|
<Compile Include="MainPage.xaml.cs">
|
||||||
|
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AppxManifest Include="Package.appxmanifest">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</AppxManifest>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Properties\Default.rd.xml" />
|
||||||
|
<Content Include="Assets\LockScreenLogo.scale-200.png" />
|
||||||
|
<Content Include="Assets\SplashScreen.scale-200.png" />
|
||||||
|
<Content Include="Assets\Square150x150Logo.scale-200.png" />
|
||||||
|
<Content Include="Assets\Square44x44Logo.scale-200.png" />
|
||||||
|
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
|
||||||
|
<Content Include="Assets\StoreLogo.png" />
|
||||||
|
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ApplicationDefinition Include="App.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</ApplicationDefinition>
|
||||||
|
<Page Include="MainPage.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Page>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
|
||||||
|
<Version>6.2.13</Version>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
||||||
|
<VisualStudioVersion>14.0</VisualStudioVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
||||||
@@ -1,918 +0,0 @@
|
|||||||
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace WPinternals
|
|
||||||
{
|
|
||||||
internal delegate void ModeSwitchProgressHandler(string Message, string SubMessage);
|
|
||||||
internal delegate void ModeSwitchErrorHandler(string Message);
|
|
||||||
internal delegate void ModeSwitchSuccessHandler(IDisposable NewModel, PhoneInterfaces NewInterface);
|
|
||||||
|
|
||||||
internal class SwitchModeViewModel : ContextViewModel
|
|
||||||
{
|
|
||||||
protected PhoneNotifierViewModel PhoneNotifier;
|
|
||||||
protected IDisposable CurrentModel;
|
|
||||||
protected PhoneInterfaces? CurrentMode;
|
|
||||||
protected PhoneInterfaces? TargetMode;
|
|
||||||
protected bool IsSwitching = false;
|
|
||||||
internal event ModeSwitchProgressHandler ModeSwitchProgress = delegate { };
|
|
||||||
internal event ModeSwitchErrorHandler ModeSwitchError = delegate { };
|
|
||||||
internal event ModeSwitchSuccessHandler ModeSwitchSuccess = delegate { };
|
|
||||||
internal new SetWorkingStatus SetWorkingStatus = (m, s, v, a, st) => { };
|
|
||||||
internal new UpdateWorkingStatus UpdateWorkingStatus = (m, s, v, st) => { };
|
|
||||||
private string MassStorageWarning = null;
|
|
||||||
|
|
||||||
internal SwitchModeViewModel(PhoneNotifierViewModel PhoneNotifier, PhoneInterfaces? TargetMode)
|
|
||||||
: base()
|
|
||||||
{
|
|
||||||
if ((PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Flash) && (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader) && (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Label) && (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Normal))
|
|
||||||
{
|
|
||||||
throw new ArgumentException();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.PhoneNotifier = PhoneNotifier;
|
|
||||||
this.CurrentModel = (NokiaPhoneModel)PhoneNotifier.CurrentModel;
|
|
||||||
this.CurrentMode = PhoneNotifier.CurrentInterface;
|
|
||||||
this.TargetMode = TargetMode;
|
|
||||||
|
|
||||||
if (this.CurrentMode == null)
|
|
||||||
{
|
|
||||||
LogFile.Log("Waiting for phone to connect...", LogType.FileAndConsole);
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Make sure this ViewModel has its View loaded before we continue,
|
|
||||||
// or else loading of Views can get mixed up.
|
|
||||||
if (SynchronizationContext.Current == null)
|
|
||||||
{
|
|
||||||
StartSwitch();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SynchronizationContext.Current.Post((s) => ((SwitchModeViewModel)s).StartSwitch(), this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal SwitchModeViewModel(PhoneNotifierViewModel PhoneNotifier, PhoneInterfaces? TargetMode, ModeSwitchProgressHandler ModeSwitchProgress, ModeSwitchErrorHandler ModeSwitchError, ModeSwitchSuccessHandler ModeSwitchSuccess, SetWorkingStatus SetWorkingStatus = null, UpdateWorkingStatus UpdateWorkingStatus = null)
|
|
||||||
: base()
|
|
||||||
{
|
|
||||||
if ((PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) && (TargetMode == PhoneInterfaces.Lumia_Flash))
|
|
||||||
{
|
|
||||||
PhoneInfo Info = ((NokiaFlashModel)PhoneNotifier.CurrentModel).ReadPhoneInfo(false);
|
|
||||||
if (Info.BootManagerProtocolVersionMajor >= 2)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// The implementation of SwitchToFlashAppContext() is improved
|
|
||||||
// SwitchToFlashAppContext() should only be used with BootMgr v2
|
|
||||||
// For switching from BootMgr to FlashApp, it will use NOKS
|
|
||||||
// That will switch to a charging state, whereas a normal context switch will not start charging
|
|
||||||
// The implementation of NOKS in BootMgr mode has changed in BootMgr v2
|
|
||||||
// It does not disconnect / reconnect anymore and the apptype is changed immediately
|
|
||||||
// NOKS still doesnt return a status
|
|
||||||
// BootMgr v1 uses normal NOKS and waits for arrival of FlashApp
|
|
||||||
((NokiaFlashModel)PhoneNotifier.CurrentModel).SwitchToFlashAppContext();
|
|
||||||
|
|
||||||
// But this was called as a real switch, so we will raise an arrival event.
|
|
||||||
PhoneNotifier.CurrentInterface = PhoneInterfaces.Lumia_Flash;
|
|
||||||
PhoneNotifier.NotifyArrival();
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PhoneNotifier.CurrentInterface == TargetMode)
|
|
||||||
{
|
|
||||||
ModeSwitchSuccess(PhoneNotifier.CurrentModel, (PhoneInterfaces)PhoneNotifier.CurrentInterface);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.PhoneNotifier = PhoneNotifier;
|
|
||||||
this.CurrentModel = (NokiaPhoneModel)PhoneNotifier.CurrentModel;
|
|
||||||
this.CurrentMode = PhoneNotifier.CurrentInterface;
|
|
||||||
this.TargetMode = TargetMode;
|
|
||||||
if (ModeSwitchProgress != null)
|
|
||||||
{
|
|
||||||
this.ModeSwitchProgress += ModeSwitchProgress;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ModeSwitchError != null)
|
|
||||||
{
|
|
||||||
this.ModeSwitchError += ModeSwitchError;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ModeSwitchSuccess != null)
|
|
||||||
{
|
|
||||||
this.ModeSwitchSuccess += ModeSwitchSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SetWorkingStatus != null)
|
|
||||||
{
|
|
||||||
this.SetWorkingStatus = SetWorkingStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UpdateWorkingStatus != null)
|
|
||||||
{
|
|
||||||
this.UpdateWorkingStatus = UpdateWorkingStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.CurrentMode == null)
|
|
||||||
{
|
|
||||||
LogFile.Log("Waiting for phone to connect...", LogType.FileAndConsole);
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Make sure this ViewModel has its View loaded before we continue,
|
|
||||||
// or else loading of Views can get mixed up.
|
|
||||||
if (SynchronizationContext.Current == null)
|
|
||||||
{
|
|
||||||
StartSwitch();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SynchronizationContext.Current.Post((s) => ((SwitchModeViewModel)s).StartSwitch(), this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ModeSwitchProgressWrapper(string Message, string SubMessage)
|
|
||||||
{
|
|
||||||
if ((UIContext == null) || (SynchronizationContext.Current == UIContext))
|
|
||||||
{
|
|
||||||
ModeSwitchProgress(Message, SubMessage);
|
|
||||||
SetWorkingStatus(Message, SubMessage);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UIContext.Post(s =>
|
|
||||||
{
|
|
||||||
ModeSwitchProgress(Message, SubMessage);
|
|
||||||
SetWorkingStatus(Message, SubMessage);
|
|
||||||
}, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ModeSwitchErrorWrapper(string Message)
|
|
||||||
{
|
|
||||||
IsSwitching = false;
|
|
||||||
if ((UIContext == null) || (SynchronizationContext.Current == UIContext))
|
|
||||||
{
|
|
||||||
ModeSwitchError(Message);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UIContext.Post(s => ModeSwitchError(Message), null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ModeSwitchSuccessWrapper()
|
|
||||||
{
|
|
||||||
IsSwitching = false;
|
|
||||||
if ((UIContext == null) || (SynchronizationContext.Current == UIContext))
|
|
||||||
{
|
|
||||||
if (PhoneNotifier.CurrentInterface == null)
|
|
||||||
{
|
|
||||||
ModeSwitchErrorWrapper("Phone disconnected");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ModeSwitchSuccess(PhoneNotifier.CurrentModel, (PhoneInterfaces)PhoneNotifier.CurrentInterface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (PhoneNotifier.CurrentInterface == null)
|
|
||||||
{
|
|
||||||
UIContext.Post(s => ModeSwitchErrorWrapper("Phone disconnected"), null);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UIContext.Post(s => ModeSwitchSuccess(PhoneNotifier.CurrentModel, (PhoneInterfaces)PhoneNotifier.CurrentInterface), null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~SwitchModeViewModel()
|
|
||||||
{
|
|
||||||
if (PhoneNotifier != null)
|
|
||||||
{
|
|
||||||
PhoneNotifier.NewDeviceArrived -= NewDeviceArrived;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void StartSwitch()
|
|
||||||
{
|
|
||||||
IsSwitching = true;
|
|
||||||
|
|
||||||
// Make switch and set message or navigate to error
|
|
||||||
switch (CurrentMode)
|
|
||||||
{
|
|
||||||
case PhoneInterfaces.Lumia_Normal:
|
|
||||||
case PhoneInterfaces.Lumia_Label:
|
|
||||||
string DeviceMode;
|
|
||||||
|
|
||||||
switch (TargetMode)
|
|
||||||
{
|
|
||||||
case PhoneInterfaces.Lumia_Normal:
|
|
||||||
DeviceMode = "Normal";
|
|
||||||
IsSwitchingInterface = true;
|
|
||||||
ModeSwitchProgressWrapper("Rebooting phone to Normal mode...", null);
|
|
||||||
LogFile.Log("Rebooting phone to Normal mode", LogType.FileAndConsole);
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Lumia_Bootloader:
|
|
||||||
DeviceMode = "Normal";
|
|
||||||
IsSwitchingInterface = true;
|
|
||||||
ModeSwitchProgressWrapper("Rebooting phone to Bootloader mode...", null);
|
|
||||||
LogFile.Log("Rebooting phone to Bootloader mode", LogType.FileAndConsole);
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Lumia_Flash:
|
|
||||||
DeviceMode = "Flash";
|
|
||||||
IsSwitchingInterface = true;
|
|
||||||
ModeSwitchProgressWrapper("Rebooting phone to Flash mode...", null);
|
|
||||||
LogFile.Log("Rebooting phone to Flash mode", LogType.FileAndConsole);
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Lumia_Label:
|
|
||||||
DeviceMode = "Flash";
|
|
||||||
IsSwitchingInterface = true;
|
|
||||||
ModeSwitchProgressWrapper("First rebooting phone to Flash mode...", null);
|
|
||||||
LogFile.Log("First rebooting phone to Flash mode (then attempt Label mode)", LogType.FileAndConsole);
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Lumia_MassStorage:
|
|
||||||
DeviceMode = "Flash";
|
|
||||||
IsSwitchingInterface = true;
|
|
||||||
ModeSwitchProgressWrapper("First rebooting phone to Flash mode...", null);
|
|
||||||
LogFile.Log("First rebooting phone to Flash mode (then attempt Mass Storage mode)", LogType.FileAndConsole);
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Qualcomm_Download: // Only available in new Lumia's
|
|
||||||
DeviceMode = "Flash";
|
|
||||||
IsSwitchingInterface = true;
|
|
||||||
ModeSwitchProgressWrapper("First rebooting phone to Flash mode...", null);
|
|
||||||
LogFile.Log("First rebooting phone to Flash mode (then attempt Qualcomm Download mode", LogType.FileAndConsole);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Dictionary<string, object> Params = new();
|
|
||||||
Params.Add("DeviceMode", DeviceMode);
|
|
||||||
Params.Add("ResetMethod", "HwReset");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
((NokiaPhoneModel)CurrentModel).ExecuteJsonMethodAsync("SetDeviceMode", Params);
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
|
||||||
}
|
|
||||||
catch (Exception Ex)
|
|
||||||
{
|
|
||||||
LogFile.LogException(Ex);
|
|
||||||
ModeSwitchErrorWrapper("Failed to switch to Qualcomm Download mode");
|
|
||||||
IsSwitchingInterface = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Lumia_Flash:
|
|
||||||
case PhoneInterfaces.Lumia_Bootloader:
|
|
||||||
byte[] BootModeFlagCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x58, 0x46, 0x57, 0x00, 0x55, 0x42, 0x46, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 }; // NOKFW UBF
|
|
||||||
byte[] RebootCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x52 }; // NOKR
|
|
||||||
byte[] RebootCommandResult;
|
|
||||||
IsSwitchingInterface = true;
|
|
||||||
switch (TargetMode)
|
|
||||||
{
|
|
||||||
case null:
|
|
||||||
((NokiaFlashModel)CurrentModel).Shutdown();
|
|
||||||
ModeSwitchProgressWrapper("Please disconnect your device. Waiting...", null);
|
|
||||||
LogFile.Log("Please disconnect your device. Waiting...", LogType.FileAndConsole);
|
|
||||||
new Thread(() =>
|
|
||||||
{
|
|
||||||
PhoneNotifier.WaitForRemoval().Wait();
|
|
||||||
ModeSwitchSuccessWrapper();
|
|
||||||
}).Start();
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Lumia_Normal:
|
|
||||||
((NokiaPhoneModel)CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
|
||||||
ModeSwitchProgressWrapper("Rebooting phone to Normal mode...", null);
|
|
||||||
LogFile.Log("Rebooting phone to Normal mode", LogType.FileAndConsole);
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Lumia_Bootloader:
|
|
||||||
((NokiaPhoneModel)CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
|
||||||
ModeSwitchProgressWrapper("Rebooting phone to Bootloader mode...", null);
|
|
||||||
LogFile.Log("Rebooting phone to Bootloader mode", LogType.FileAndConsole);
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Lumia_Label:
|
|
||||||
SwitchFromFlashToLabelMode();
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Lumia_Flash: // attempt to boot from limited flash to full flash
|
|
||||||
byte[] RebootToFlashCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x53 }; // NOKS
|
|
||||||
((NokiaPhoneModel)CurrentModel).ExecuteRawVoidMethod(RebootToFlashCommand);
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
|
||||||
ModeSwitchProgressWrapper("Rebooting phone to Flash mode...", null);
|
|
||||||
LogFile.Log("Rebooting phone to Flash mode", LogType.FileAndConsole);
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Lumia_MassStorage:
|
|
||||||
SwitchFromFlashToMassStorageMode();
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Qualcomm_Download:
|
|
||||||
byte[] RebootToQualcommDownloadCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x58, 0x43, 0x42, 0x45 }; // NOKXCBE
|
|
||||||
RebootCommandResult = ((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(RebootToQualcommDownloadCommand);
|
|
||||||
if (RebootCommandResult?.Length == 4) // This means fail: NOKU (unknow command)
|
|
||||||
{
|
|
||||||
IsSwitchingInterface = false;
|
|
||||||
ModeSwitchErrorWrapper("Failed to switch to Qualcomm Download mode");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
|
||||||
ModeSwitchProgressWrapper("Rebooting phone to Qualcomm Download mode...", null);
|
|
||||||
LogFile.Log("Rebooting phone to Qualcomm Download mode", LogType.FileAndConsole);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Lumia_MassStorage:
|
|
||||||
IsSwitchingInterface = true;
|
|
||||||
switch (TargetMode)
|
|
||||||
{
|
|
||||||
case PhoneInterfaces.Lumia_Normal:
|
|
||||||
((MassStorage)CurrentModel).Reboot();
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
|
||||||
ModeSwitchProgressWrapper("Rebooting phone to Normal mode...", null);
|
|
||||||
LogFile.Log("Rebooting phone to Normal mode", LogType.FileAndConsole);
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Lumia_Label:
|
|
||||||
((MassStorage)CurrentModel).Reboot();
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrivedFromMassStorageMode;
|
|
||||||
ModeSwitchProgressWrapper("Rebooting phone to Label mode...", null);
|
|
||||||
LogFile.Log("Rebooting phone to Label mode...", LogType.FileAndConsole);
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Lumia_Flash:
|
|
||||||
((MassStorage)CurrentModel).Reboot();
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrivedFromMassStorageMode;
|
|
||||||
ModeSwitchProgressWrapper("Rebooting phone to Flash mode...", null);
|
|
||||||
LogFile.Log("Rebooting phone to Flash mode...", LogType.FileAndConsole);
|
|
||||||
break;
|
|
||||||
case null:
|
|
||||||
((MassStorage)CurrentModel).Reboot();
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrivedFromMassStorageMode;
|
|
||||||
ModeSwitchProgressWrapper("First rebooting phone to Flash mode...", null);
|
|
||||||
LogFile.Log("First rebooting phone to Bootloader mode...", LogType.FileAndConsole);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Qualcomm_Download:
|
|
||||||
// TODO: don't know how to switch from Qualcomm Download mode to other mode
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void NewDeviceArrivedFromMassStorageMode(ArrivalEventArgs Args)
|
|
||||||
{
|
|
||||||
PhoneNotifier.NewDeviceArrived -= NewDeviceArrivedFromMassStorageMode;
|
|
||||||
|
|
||||||
CurrentModel = Args.NewModel;
|
|
||||||
CurrentMode = Args.NewInterface;
|
|
||||||
|
|
||||||
// After the mass storage mode reboot command, the phone must be in Bootloader mode.
|
|
||||||
// If it isn't, something unexpected happened and the phone can't be switched.
|
|
||||||
//
|
|
||||||
if (CurrentMode == PhoneInterfaces.Lumia_Bootloader)
|
|
||||||
{
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await SwitchToWithStatus(PhoneNotifier, TargetMode, SetWorkingStatus, UpdateWorkingStatus);
|
|
||||||
ModeSwitchSuccessWrapper();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
switch (TargetMode)
|
|
||||||
{
|
|
||||||
case PhoneInterfaces.Lumia_Flash:
|
|
||||||
ModeSwitchErrorWrapper("Failed to switch to Flash mode");
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Lumia_Label:
|
|
||||||
ModeSwitchErrorWrapper("Failed to switch to Label mode");
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Lumia_Normal:
|
|
||||||
ModeSwitchErrorWrapper("Failed to switch to Normal mode");
|
|
||||||
break;
|
|
||||||
case null:
|
|
||||||
ModeSwitchSuccessWrapper();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch (TargetMode)
|
|
||||||
{
|
|
||||||
case PhoneInterfaces.Lumia_Flash:
|
|
||||||
ModeSwitchErrorWrapper("Failed to switch to Flash mode");
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Lumia_Label:
|
|
||||||
ModeSwitchErrorWrapper("Failed to switch to Label mode");
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Lumia_Normal:
|
|
||||||
ModeSwitchErrorWrapper("Failed to switch to Normal mode");
|
|
||||||
break;
|
|
||||||
case null:
|
|
||||||
ModeSwitchErrorWrapper("Failed to shutdown");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void NewDeviceArrived(ArrivalEventArgs Args)
|
|
||||||
{
|
|
||||||
PhoneNotifier.NewDeviceArrived -= NewDeviceArrived;
|
|
||||||
|
|
||||||
CurrentModel = Args.NewModel;
|
|
||||||
CurrentMode = Args.NewInterface;
|
|
||||||
|
|
||||||
if ((CurrentMode == PhoneInterfaces.Lumia_Bootloader) && (TargetMode == PhoneInterfaces.Lumia_Flash))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Going from BootMgr to FlashApp
|
|
||||||
// SwitchToFlashAppContext() will only switch context. Phone will not charge.
|
|
||||||
// ResetPhoneToFlashMode() reboots to real flash app. Phone will charge. Works when in BootMgrApp, not when already in FlashApp.
|
|
||||||
|
|
||||||
((NokiaFlashModel)CurrentModel).ResetPhoneToFlashMode();
|
|
||||||
CurrentMode = PhoneInterfaces.Lumia_Flash;
|
|
||||||
PhoneNotifier.NotifyArrival();
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CurrentMode == TargetMode)
|
|
||||||
{
|
|
||||||
if (TargetMode == PhoneInterfaces.Lumia_Bootloader)
|
|
||||||
{
|
|
||||||
((NokiaFlashModel)CurrentModel).DisableRebootTimeOut();
|
|
||||||
}
|
|
||||||
|
|
||||||
ModeSwitchSuccessWrapper();
|
|
||||||
}
|
|
||||||
else if (!IsSwitching)
|
|
||||||
{
|
|
||||||
StartSwitch();
|
|
||||||
}
|
|
||||||
else if ((CurrentMode == PhoneInterfaces.Lumia_Bootloader) && (TargetMode == PhoneInterfaces.Lumia_Normal))
|
|
||||||
{
|
|
||||||
// Do nothing, because booting to Normal shortly goes into Flash mode too.
|
|
||||||
// Just wait to arrive in Normal mode;
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
|
||||||
}
|
|
||||||
else if ((CurrentMode == PhoneInterfaces.Lumia_Flash) && (TargetMode == PhoneInterfaces.Lumia_MassStorage))
|
|
||||||
{
|
|
||||||
SwitchFromFlashToMassStorageMode(Continuation: true);
|
|
||||||
}
|
|
||||||
else if ((CurrentMode == PhoneInterfaces.Lumia_Flash) && (TargetMode == PhoneInterfaces.Lumia_Label))
|
|
||||||
{
|
|
||||||
SwitchFromFlashToLabelMode(Continuation: true);
|
|
||||||
}
|
|
||||||
else if ((CurrentMode == PhoneInterfaces.Lumia_Flash) && (TargetMode == PhoneInterfaces.Qualcomm_Download))
|
|
||||||
{
|
|
||||||
byte[] RebootCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x52 };
|
|
||||||
byte[] RebootToQualcommDownloadCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x58, 0x43, 0x42, 0x45 }; // NOKXCBE
|
|
||||||
IsSwitchingInterface = true;
|
|
||||||
LogFile.Log("Sending command for rebooting to Emergency Download mode");
|
|
||||||
byte[] RebootCommandResult = ((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(RebootToQualcommDownloadCommand);
|
|
||||||
if (RebootCommandResult?.Length >= 8)
|
|
||||||
{
|
|
||||||
int ResultCode = (RebootCommandResult[6] << 8) + RebootCommandResult[7];
|
|
||||||
LogFile.Log("Resultcode: 0x" + ResultCode.ToString("X4"));
|
|
||||||
}
|
|
||||||
if (RebootCommandResult?.Length == 4) // This means fail: NOKU (unknow command)
|
|
||||||
{
|
|
||||||
ModeSwitchErrorWrapper("Failed to switch to Qualcomm Download mode");
|
|
||||||
IsSwitchingInterface = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
|
||||||
ModeSwitchProgressWrapper("And now rebooting phone to Qualcomm Download mode...", null);
|
|
||||||
LogFile.Log("Rebooting phone to Qualcomm Download mode");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch (TargetMode)
|
|
||||||
{
|
|
||||||
case PhoneInterfaces.Lumia_Normal:
|
|
||||||
ModeSwitchErrorWrapper("Failed to switch to Normal mode");
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Lumia_Flash:
|
|
||||||
ModeSwitchErrorWrapper("Failed to switch to Flash mode");
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Lumia_Label:
|
|
||||||
ModeSwitchErrorWrapper("Failed to switch to Label mode");
|
|
||||||
break;
|
|
||||||
case PhoneInterfaces.Lumia_MassStorage:
|
|
||||||
ModeSwitchErrorWrapper("Failed to switch to Mass Storage mode");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SwitchFromFlashToLabelMode(bool Continuation = false)
|
|
||||||
{
|
|
||||||
string ProgressText = Continuation ? "And now preparing to boot the phone to Label mode..." : "Preparing to boot the phone to Label mode...";
|
|
||||||
NokiaFlashModel FlashModel = (NokiaFlashModel)CurrentModel;
|
|
||||||
if (CurrentMode == PhoneInterfaces.Lumia_Bootloader)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
FlashModel.SwitchToFlashAppContext();
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
PhoneInfo Info = FlashModel.ReadPhoneInfo(ExtendedInfo: true);
|
|
||||||
|
|
||||||
if (Info.MmosOverUsbSupported)
|
|
||||||
{
|
|
||||||
new Thread(() =>
|
|
||||||
{
|
|
||||||
LogFile.BeginAction("SwitchToLabelMode");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ModeSwitchProgressWrapper(ProgressText, null);
|
|
||||||
string TempFolder = Environment.GetEnvironmentVariable("TEMP") + @"\WPInternals";
|
|
||||||
if (Info.Type == "RM-1152")
|
|
||||||
{
|
|
||||||
Info.Type = "RM-1151";
|
|
||||||
}
|
|
||||||
string ENOSWPackage = LumiaDownloadModel.SearchENOSW(Info.Type, Info.Firmware);
|
|
||||||
SetWorkingStatus("Downloading " + Info.Type + " Test Mode package...", MaxProgressValue: 100);
|
|
||||||
DownloadEntry downloadEntry = new(ENOSWPackage, TempFolder, null, null, null);
|
|
||||||
|
|
||||||
downloadEntry.PropertyChanged += (object sender, System.ComponentModel.PropertyChangedEventArgs e) =>
|
|
||||||
{
|
|
||||||
if (e.PropertyName == "Progress")
|
|
||||||
{
|
|
||||||
int progress = (sender as DownloadEntry)?.Progress ?? 0;
|
|
||||||
ulong.TryParse(progress.ToString(), out ulong progressret);
|
|
||||||
UpdateWorkingStatus(null, CurrentProgressValue: progressret);
|
|
||||||
|
|
||||||
if (progress == 100)
|
|
||||||
{
|
|
||||||
ModeSwitchProgressWrapper("Initializing Flash...", null);
|
|
||||||
|
|
||||||
string MMOSPath = TempFolder + "\\" + (sender as DownloadEntry)?.Name;
|
|
||||||
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
|
||||||
FileInfo info = new(MMOSPath);
|
|
||||||
uint length = uint.Parse(info.Length.ToString());
|
|
||||||
const int maximumbuffersize = 0x00240000;
|
|
||||||
uint totalcounts = (uint)Math.Truncate((decimal)length / maximumbuffersize);
|
|
||||||
|
|
||||||
SetWorkingStatus("Flashing Test Mode package...", MaxProgressValue: 100);
|
|
||||||
|
|
||||||
ProgressUpdater progressUpdater = new(totalcounts + 1, (int i, TimeSpan? time) => UpdateWorkingStatus(null, CurrentProgressValue: (ulong)i));
|
|
||||||
FlashModel.FlashMMOS(MMOSPath, progressUpdater);
|
|
||||||
|
|
||||||
SetWorkingStatus("And now booting phone to MMOS...", "If the phone stays on the lightning cog screen for a while, you may need to unplug and replug the phone to continue the boot process.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
catch (Exception Ex)
|
|
||||||
{
|
|
||||||
LogFile.LogException(Ex);
|
|
||||||
ModeSwitchErrorWrapper(Ex.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
LogFile.EndAction("SwitchToLabelMode");
|
|
||||||
}).Start();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
byte[] BootModeFlagCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x58, 0x46, 0x57, 0x00, 0x55, 0x42, 0x46, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 }; // NOKFW UBF
|
|
||||||
byte[] RebootCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x52 }; // NOKR
|
|
||||||
|
|
||||||
BootModeFlagCommand[0x0F] = 0x59;
|
|
||||||
((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(BootModeFlagCommand);
|
|
||||||
((NokiaPhoneModel)CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
|
||||||
ModeSwitchProgressWrapper("Rebooting phone to Label mode", null);
|
|
||||||
LogFile.Log("Rebooting phone to Label mode", LogType.FileAndConsole);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SwitchFromFlashToMassStorageMode(bool Continuation = false)
|
|
||||||
{
|
|
||||||
string ProgressText = Continuation ? "And now rebooting phone to Mass Storage mode..." : "Rebooting phone to Mass Storage mode...";
|
|
||||||
NokiaFlashModel FlashModel = (NokiaFlashModel)CurrentModel;
|
|
||||||
if (CurrentMode == PhoneInterfaces.Lumia_Bootloader)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
FlashModel.SwitchToFlashAppContext();
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
PhoneInfo Info = FlashModel.ReadPhoneInfo(ExtendedInfo: false);
|
|
||||||
|
|
||||||
MassStorageWarning = null;
|
|
||||||
if (Info.FlashAppProtocolVersionMajor < 2)
|
|
||||||
{
|
|
||||||
MassStorageWarning = "Switching to Mass Storage mode should take about 10 seconds. The phone should be unlocked using an Engineering SBL3 to enable Mass Storage mode. When you unlocked the bootloader, but you did not use an Engineering SBL3, an attempt to boot to Mass Storage mode may result in an unresponsive state. Installing drivers for this interface may also cause to hang the PC. So when this switch is taking too long, you should reboot both the PC and the phone. To reboot the phone, you have to perform a soft-reset. Press and hold the volume-down-button and the power-button at the same time for at least 10 seconds. This will trigger a power-cycle and the phone will reboot. Once fully booted, the phone may show strange behavior, like complaining about mail-accounts, showing old text-messages, inability to load https-websites, etc. This is expected behavior, because the time-settings of the phone are incorrect. Just wait a few seconds for the phone to get a data-connection and have the date/time synced. After that the strange behavior will stop automatically and normal operation is resumed.";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MassStorageWarning = "When the screen of the phone is black for a while, it could be that the phone is already in Mass Storage Mode, but there is no drive-letter assigned. To resolve this issue, open Device Manager and manually assign a drive-letter to the MainOS partition of your phone, or open a command-prompt and type: diskpart automount enable.";
|
|
||||||
if (App.IsPnPEventLogMissing)
|
|
||||||
{
|
|
||||||
MassStorageWarning += " It is also possible that the phone is in Mass Storage mode, but the Mass Storage driver on this PC failed. Your PC does not have an eventlog to detect this misbehaviour. But in this case you will see a device with an exclamation mark in Device Manager and then you need to manually reset the phone by pressing and holding the power-button for at least 10 seconds until it vibrates and reboots. After that Windows Phone Internals will revert the changes. After the phone has rebooted to the OS, you can retry to unlock the bootloader.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsOldLumia = Info.FlashAppProtocolVersionMajor < 2;
|
|
||||||
bool IsNewLumia = Info.FlashAppProtocolVersionMajor >= 2;
|
|
||||||
bool IsUnlockedNew = false;
|
|
||||||
if (IsNewLumia)
|
|
||||||
{
|
|
||||||
GPT GPT = FlashModel.ReadGPT();
|
|
||||||
IsUnlockedNew = (GPT.GetPartition("IS_UNLOCKED") != null) || (GPT.GetPartition("BACKUP_EFIESP") != null) || (GPT.GetPartition("BACKUP_BS_NV") != null);
|
|
||||||
}
|
|
||||||
bool IsOriginalEngineeringLumia = !Info.IsBootloaderSecure && !IsUnlockedNew;
|
|
||||||
|
|
||||||
if (IsOldLumia || IsOriginalEngineeringLumia)
|
|
||||||
{
|
|
||||||
byte[] BootModeFlagCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x58, 0x46, 0x57, 0x00, 0x55, 0x42, 0x46, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 }; // NOKFW UBF
|
|
||||||
byte[] RebootCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x52 };
|
|
||||||
byte[] RebootToMassStorageCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x4D }; // NOKM
|
|
||||||
IsSwitchingInterface = true;
|
|
||||||
byte[] RebootCommandResult = ((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(RebootToMassStorageCommand);
|
|
||||||
if (RebootCommandResult?.Length == 4) // This means fail: NOKU (unknown command)
|
|
||||||
{
|
|
||||||
BootModeFlagCommand[0x0F] = 0x4D;
|
|
||||||
byte[] BootFlagResult = ((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(BootModeFlagCommand);
|
|
||||||
UInt16 ResultCode = BitConverter.ToUInt16(BootFlagResult, 6);
|
|
||||||
if (ResultCode == 0)
|
|
||||||
{
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
|
||||||
((NokiaPhoneModel)CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
|
||||||
ModeSwitchProgressWrapper(ProgressText, MassStorageWarning);
|
|
||||||
LogFile.Log("Rebooting phone to Mass Storage mode");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ModeSwitchErrorWrapper("Failed to switch to Mass Storage mode");
|
|
||||||
IsSwitchingInterface = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
|
||||||
ModeSwitchProgressWrapper(ProgressText, MassStorageWarning);
|
|
||||||
LogFile.Log("Rebooting phone to Mass Storage mode");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (IsUnlockedNew)
|
|
||||||
{
|
|
||||||
new Thread(async () =>
|
|
||||||
{
|
|
||||||
LogFile.BeginAction("SwitchToMassStorageMode");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Implementation of writing a partition with SecureBoot variable to the phone
|
|
||||||
ModeSwitchProgressWrapper(ProgressText, MassStorageWarning);
|
|
||||||
LogFile.Log("Preparing phone for Mass Storage Mode", LogType.FileAndConsole);
|
|
||||||
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
|
|
||||||
|
|
||||||
// Magic!
|
|
||||||
// The SBMSM resource is a compressed version of a raw NV-variable-partition.
|
|
||||||
// In this partition the SecureBoot variable is disabled and an extra variable is added which triggers Mass Storage Mode on next reboot.
|
|
||||||
// It overwrites the variable in a different NV-partition than where this variable is stored usually.
|
|
||||||
// This normally leads to endless-loops when the NV-variables are enumerated.
|
|
||||||
// But the partition contains an extra hack to break out the endless loops.
|
|
||||||
using (var stream = assembly.GetManifestResourceStream("WPinternals.SBMSM"))
|
|
||||||
{
|
|
||||||
using DecompressedStream dec = new(stream);
|
|
||||||
using MemoryStream SB = new(); // Must be a seekable stream!
|
|
||||||
dec.CopyTo(SB);
|
|
||||||
|
|
||||||
// We don't need to check for the BACKUP_BS_NV partition here,
|
|
||||||
// because the SecureBoot flag is disabled here.
|
|
||||||
// So either the NV was already backupped or already overwritten.
|
|
||||||
|
|
||||||
GPT GPT = FlashModel.ReadGPT();
|
|
||||||
Partition Target = GPT.GetPartition("UEFI_BS_NV");
|
|
||||||
|
|
||||||
// We've been reading the GPT, so we let the phone reset once more to be sure that memory maps are the same
|
|
||||||
WPinternalsStatus LastStatus = WPinternalsStatus.Undefined;
|
|
||||||
List<FlashPart> Parts = new();
|
|
||||||
FlashPart Part = new();
|
|
||||||
Part.StartSector = (uint)Target.FirstSector;
|
|
||||||
Part.Stream = SB;
|
|
||||||
Parts.Add(Part);
|
|
||||||
await LumiaV2UnlockBootViewModel.LumiaV2CustomFlash(PhoneNotifier, null, false, false, Parts, DoResetFirst: true, ClearFlashingStatusAtEnd: false, ShowProgress: false,
|
|
||||||
SetWorkingStatus: (m, s, v, a, st) =>
|
|
||||||
{
|
|
||||||
if (SetWorkingStatus != null)
|
|
||||||
{
|
|
||||||
if ((st == WPinternalsStatus.Scanning) || (st == WPinternalsStatus.WaitingForManualReset))
|
|
||||||
{
|
|
||||||
SetWorkingStatus(m, s, v, a, st);
|
|
||||||
}
|
|
||||||
else if ((LastStatus == WPinternalsStatus.Scanning) || (LastStatus == WPinternalsStatus.WaitingForManualReset))
|
|
||||||
{
|
|
||||||
SetWorkingStatus(ProgressText, MassStorageWarning);
|
|
||||||
}
|
|
||||||
|
|
||||||
LastStatus = st;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
UpdateWorkingStatus: (m, s, v, st) =>
|
|
||||||
{
|
|
||||||
if (UpdateWorkingStatus != null)
|
|
||||||
{
|
|
||||||
if ((st == WPinternalsStatus.Scanning) || (st == WPinternalsStatus.WaitingForManualReset))
|
|
||||||
{
|
|
||||||
UpdateWorkingStatus(m, s, v, st);
|
|
||||||
}
|
|
||||||
else if ((LastStatus == WPinternalsStatus.Scanning) || (LastStatus == WPinternalsStatus.WaitingForManualReset))
|
|
||||||
{
|
|
||||||
SetWorkingStatus(ProgressText, MassStorageWarning);
|
|
||||||
}
|
|
||||||
|
|
||||||
LastStatus = st;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_BadMassStorage)
|
|
||||||
{
|
|
||||||
throw new WPinternalsException("Phone is in Mass Storage mode, but the driver on PC failed to start");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for bootloader
|
|
||||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_MassStorage)
|
|
||||||
{
|
|
||||||
LogFile.Log("Waiting for Mass Storage Mode (1)...", LogType.FileOnly);
|
|
||||||
await PhoneNotifier.WaitForArrival();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_BadMassStorage)
|
|
||||||
{
|
|
||||||
throw new WPinternalsException("Phone is in Mass Storage mode, but the driver on PC failed to start");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for mass storage mode
|
|
||||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_MassStorage)
|
|
||||||
{
|
|
||||||
LogFile.Log("Waiting for Mass Storage Mode (2)...", LogType.FileOnly);
|
|
||||||
await PhoneNotifier.WaitForArrival();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_BadMassStorage)
|
|
||||||
{
|
|
||||||
throw new WPinternalsException("Phone is in Mass Storage mode, but the driver on PC failed to start");
|
|
||||||
}
|
|
||||||
|
|
||||||
MassStorage Storage = null;
|
|
||||||
if (PhoneNotifier.CurrentModel is MassStorage)
|
|
||||||
{
|
|
||||||
Storage = (MassStorage)PhoneNotifier.CurrentModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Storage == null)
|
|
||||||
{
|
|
||||||
ModeSwitchErrorWrapper("Failed to switch to Mass Storage Mode");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ModeSwitchSuccessWrapper();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception Ex)
|
|
||||||
{
|
|
||||||
LogFile.LogException(Ex);
|
|
||||||
ModeSwitchErrorWrapper(Ex.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
LogFile.EndAction("SwitchToMassStorageMode");
|
|
||||||
}).Start();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ModeSwitchErrorWrapper("Bootloader was not unlocked. First unlock bootloader before you try to switch to Mass Storage Mode.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal async static Task<IDisposable> SwitchTo(PhoneNotifierViewModel Notifier, PhoneInterfaces? TargetMode, string RequestedVolumeForMassStorage = "MainOS")
|
|
||||||
{
|
|
||||||
return await SwitchToWithProgress(Notifier, TargetMode, null, RequestedVolumeForMassStorage);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal async static Task<IDisposable> SwitchToWithProgress(PhoneNotifierViewModel Notifier, PhoneInterfaces? TargetMode, ModeSwitchProgressHandler ModeSwitchProgress, string RequestedVolumeForMassStorage = "MainOS")
|
|
||||||
{
|
|
||||||
if (Notifier.CurrentInterface == TargetMode)
|
|
||||||
{
|
|
||||||
return Notifier.CurrentModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
IDisposable Result = null;
|
|
||||||
string LocalErrorMessage = null;
|
|
||||||
|
|
||||||
AsyncAutoResetEvent Event = new(false);
|
|
||||||
|
|
||||||
SwitchModeViewModel Switch = new(
|
|
||||||
Notifier,
|
|
||||||
TargetMode,
|
|
||||||
ModeSwitchProgress,
|
|
||||||
(string ErrorMessage) =>
|
|
||||||
{
|
|
||||||
LocalErrorMessage = ErrorMessage;
|
|
||||||
Event.Set();
|
|
||||||
},
|
|
||||||
(IDisposable NewModel, PhoneInterfaces NewInterface) =>
|
|
||||||
{
|
|
||||||
Result = NewModel;
|
|
||||||
Event.Set();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
await Event.WaitAsync(Timeout.InfiniteTimeSpan);
|
|
||||||
|
|
||||||
if (LocalErrorMessage != null)
|
|
||||||
{
|
|
||||||
throw new WPinternalsException(LocalErrorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal async static Task<IDisposable> SwitchToWithStatus(PhoneNotifierViewModel Notifier, PhoneInterfaces? TargetMode, SetWorkingStatus SetWorkingStatus = null, UpdateWorkingStatus UpdateWorkingStatus = null, string RequestedVolumeForMassStorage = "MainOS")
|
|
||||||
{
|
|
||||||
if (Notifier.CurrentInterface == TargetMode)
|
|
||||||
{
|
|
||||||
return Notifier.CurrentModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
IDisposable Result = null;
|
|
||||||
string LocalErrorMessage = null;
|
|
||||||
|
|
||||||
AsyncAutoResetEvent Event = new(false);
|
|
||||||
|
|
||||||
SwitchModeViewModel Switch = new(
|
|
||||||
Notifier,
|
|
||||||
TargetMode,
|
|
||||||
null,
|
|
||||||
(string ErrorMessage) =>
|
|
||||||
{
|
|
||||||
LocalErrorMessage = ErrorMessage;
|
|
||||||
Event.Set();
|
|
||||||
},
|
|
||||||
(IDisposable NewModel, PhoneInterfaces NewInterface) =>
|
|
||||||
{
|
|
||||||
Result = NewModel;
|
|
||||||
Event.Set();
|
|
||||||
}, SetWorkingStatus, UpdateWorkingStatus
|
|
||||||
);
|
|
||||||
|
|
||||||
await Event.WaitAsync(Timeout.InfiniteTimeSpan);
|
|
||||||
|
|
||||||
if (LocalErrorMessage != null)
|
|
||||||
{
|
|
||||||
throw new WPinternalsException(LocalErrorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -47,7 +47,7 @@ namespace SevenZip.CommandLineParser
|
|||||||
{
|
{
|
||||||
public bool ThereIs;
|
public bool ThereIs;
|
||||||
public bool WithMinus;
|
public bool WithMinus;
|
||||||
public ArrayList PostStrings = new();
|
public ArrayList PostStrings = [];
|
||||||
public int PostCharIndex;
|
public int PostCharIndex;
|
||||||
public SwitchResult()
|
public SwitchResult()
|
||||||
{
|
{
|
||||||
@@ -57,7 +57,7 @@ namespace SevenZip.CommandLineParser
|
|||||||
|
|
||||||
public class Parser
|
public class Parser
|
||||||
{
|
{
|
||||||
public ArrayList NonSwitchStrings = new();
|
public ArrayList NonSwitchStrings = [];
|
||||||
private readonly SwitchResult[] _switches;
|
private readonly SwitchResult[] _switches;
|
||||||
|
|
||||||
public Parser(int numSwitches)
|
public Parser(int numSwitches)
|
||||||
@@ -1518,10 +1518,10 @@ namespace SevenZip.Compression.LZMA
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static readonly string[] kMatchFinderIDs =
|
private static readonly string[] kMatchFinderIDs =
|
||||||
{
|
[
|
||||||
"BT2",
|
"BT2",
|
||||||
"BT4",
|
"BT4",
|
||||||
};
|
];
|
||||||
|
|
||||||
private static int FindMatchFinder(string s)
|
private static int FindMatchFinder(string s)
|
||||||
{
|
{
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
|
Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
|
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
@@ -20,9 +20,10 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using WPinternals.HelperClasses;
|
||||||
|
using WPinternals.Config;
|
||||||
|
|
||||||
namespace WPinternals
|
namespace WPinternals
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
|
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
@@ -26,6 +26,12 @@ using System.Linq;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
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
|
namespace WPinternals
|
||||||
{
|
{
|
||||||
@@ -83,18 +89,16 @@ namespace WPinternals
|
|||||||
{
|
{
|
||||||
FFU FFU = null;
|
FFU FFU = null;
|
||||||
PhoneNotifierViewModel Notifier;
|
PhoneNotifierViewModel Notifier;
|
||||||
NokiaFlashModel FlashModel;
|
LumiaFlashAppModel FlashModel;
|
||||||
NokiaPhoneModel NormalModel;
|
LumiaBootManagerAppModel BootMgrModel;
|
||||||
PhoneInfo Info;
|
NokiaCareSuiteModel NormalModel;
|
||||||
|
LumiaFlashAppPhoneInfo FlashInfo;
|
||||||
|
LumiaBootManagerPhoneInfo BootManagerInfo;
|
||||||
string ProductType;
|
string ProductType;
|
||||||
string ProductCode;
|
|
||||||
string OperatorCode;
|
|
||||||
string DownloadFolder;
|
string DownloadFolder;
|
||||||
string FFUFilePath;
|
string FFUFilePath;
|
||||||
string URL;
|
|
||||||
string[] URLs;
|
string[] URLs;
|
||||||
Uri URI;
|
Uri URI;
|
||||||
string FFUFileName;
|
|
||||||
string EmergencyFileName;
|
string EmergencyFileName;
|
||||||
string EmergencyFilePath;
|
string EmergencyFilePath;
|
||||||
string ProgrammerPath = "";
|
string ProgrammerPath = "";
|
||||||
@@ -114,7 +118,7 @@ namespace WPinternals
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (args[1].ToLower().TrimStart(new char[] { '-', '/' }))
|
switch (args[1].ToLower().TrimStart(['-', '/']))
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
case "test":
|
case "test":
|
||||||
@@ -152,8 +156,12 @@ namespace WPinternals
|
|||||||
? Convert.ToUInt64(args[2][2..], 16)
|
? Convert.ToUInt64(args[2][2..], 16)
|
||||||
: Convert.ToUInt64(args[2], 10);
|
: 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);
|
LogFile.Log("Bad start sector", LogType.ConsoleOnly);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -181,24 +189,13 @@ namespace WPinternals
|
|||||||
{
|
{
|
||||||
Notifier = new PhoneNotifierViewModel();
|
Notifier = new PhoneNotifierViewModel();
|
||||||
UIContext.Send(s => Notifier.Start(), null);
|
UIContext.Send(s => Notifier.Start(), null);
|
||||||
|
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader);
|
||||||
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader); // This also works for Bootloader Spec A
|
GPT GPT = await LumiaUnlockBootloaderViewModel.ReadGPTFromFlashOrBootMgr(Notifier);
|
||||||
|
|
||||||
GPT GPT = FlashModel.ReadGPT(); // May throw NotSupportedException
|
|
||||||
foreach (Partition Partition in GPT.Partitions)
|
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);
|
LogFile.Log(Partition.Name.PadRight(20) + "0x" + Partition.FirstSector.ToString("X8") + " - 0x" + Partition.LastSector.ToString("X8") + " " + Partition.Volume, LogType.ConsoleOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FlashModel.ReadPhoneInfo(false).FlashAppProtocolVersionMajor >= 2)
|
|
||||||
{
|
|
||||||
FlashModel.SwitchToFlashAppContext();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
|
||||||
}
|
|
||||||
|
|
||||||
Notifier.Stop();
|
Notifier.Stop();
|
||||||
}
|
}
|
||||||
catch (Exception Ex)
|
catch (Exception Ex)
|
||||||
@@ -221,11 +218,14 @@ namespace WPinternals
|
|||||||
{
|
{
|
||||||
Notifier = new PhoneNotifierViewModel();
|
Notifier = new PhoneNotifierViewModel();
|
||||||
UIContext.Send(s => Notifier.Start(), null);
|
UIContext.Send(s => Notifier.Start(), null);
|
||||||
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader);
|
||||||
GPT GPT = FlashModel.ReadGPT(); // May throw NotSupportedException
|
GPT GPT = await LumiaUnlockBootloaderViewModel.ReadGPTFromFlashOrBootMgr(Notifier);
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(args[2]));
|
string DirPath = Path.GetDirectoryName(args[2]);
|
||||||
|
if (!string.IsNullOrEmpty(DirPath) && !Directory.Exists(DirPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(DirPath);
|
||||||
|
}
|
||||||
GPT.WritePartitions(args[2]);
|
GPT.WritePartitions(args[2]);
|
||||||
FlashModel.SwitchToFlashAppContext();
|
|
||||||
Notifier.Stop();
|
Notifier.Stop();
|
||||||
}
|
}
|
||||||
catch (Exception Ex)
|
catch (Exception Ex)
|
||||||
@@ -237,6 +237,35 @@ namespace WPinternals
|
|||||||
LogFile.EndAction("BackupGPT");
|
LogFile.EndAction("BackupGPT");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "convertgpt":
|
||||||
|
if (args.Length < 4)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -ConvertGPT <Path to GPT-file> <Path to xml-file>");
|
||||||
|
}
|
||||||
|
|
||||||
|
LogFile.BeginAction("ConvertGPT");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using FileStream stream = File.OpenRead(args[2]);
|
||||||
|
byte[] GPTBuffer = new byte[34 * 0x200];
|
||||||
|
stream.Read(GPTBuffer, 0, 34 * 0x200);
|
||||||
|
GPT GPT = new(GPTBuffer);// May throw NotSupportedException
|
||||||
|
string DirPath = Path.GetDirectoryName(args[3]);
|
||||||
|
if (!string.IsNullOrEmpty(DirPath) && !Directory.Exists(DirPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(DirPath);
|
||||||
|
}
|
||||||
|
GPT.WritePartitions(args[3]);
|
||||||
|
}
|
||||||
|
catch (Exception Ex)
|
||||||
|
{
|
||||||
|
LogFile.LogException(Ex);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
LogFile.EndAction("ConvertGPT");
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "restoregpt":
|
case "restoregpt":
|
||||||
if (args.Length < 3)
|
if (args.Length < 3)
|
||||||
{
|
{
|
||||||
@@ -248,14 +277,12 @@ namespace WPinternals
|
|||||||
{
|
{
|
||||||
Notifier = new PhoneNotifierViewModel();
|
Notifier = new PhoneNotifierViewModel();
|
||||||
UIContext.Send(s => Notifier.Start(), null);
|
UIContext.Send(s => Notifier.Start(), null);
|
||||||
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
byte[] GptChunk = await LumiaUnlockBootloaderViewModel.GetGptChunkFromFlashOrBootMgr(Notifier, 0x20000);
|
||||||
byte[] GptChunk = LumiaUnlockBootloaderViewModel.GetGptChunk(FlashModel, 0x20000);
|
|
||||||
GPT GPT = new(GptChunk);
|
GPT GPT = new(GptChunk);
|
||||||
string Xml = File.ReadAllText(args[2]);
|
string Xml = File.ReadAllText(args[2]);
|
||||||
GPT.MergePartitions(Xml, false);
|
GPT.MergePartitions(Xml, false);
|
||||||
GPT.Rebuild();
|
GPT.Rebuild();
|
||||||
await LumiaV2UnlockBootViewModel.LumiaV2CustomFlash(Notifier, null, false, false, 0, GptChunk, true, true);
|
await LumiaV2UnlockBootViewModel.LumiaV2CustomFlash(Notifier, null, false, false, 0, GptChunk, true, true);
|
||||||
FlashModel.SwitchToFlashAppContext();
|
|
||||||
Notifier.Stop();
|
Notifier.Stop();
|
||||||
}
|
}
|
||||||
catch (Exception Ex)
|
catch (Exception Ex)
|
||||||
@@ -285,7 +312,10 @@ namespace WPinternals
|
|||||||
s = new FileStream(args[3], FileMode.Open, FileAccess.Read);
|
s = new FileStream(args[3], FileMode.Open, FileAccess.Read);
|
||||||
Archive = new ZipArchive(s);
|
Archive = new ZipArchive(s);
|
||||||
}
|
}
|
||||||
catch { }
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogFile.LogException(ex, LogType.FileOnly);
|
||||||
|
}
|
||||||
|
|
||||||
if (Archive == null)
|
if (Archive == null)
|
||||||
{
|
{
|
||||||
@@ -393,7 +423,11 @@ namespace WPinternals
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
string EfiPath = Path.Combine(args[3], Name);
|
string EfiPath = Path.Combine(args[3], Name);
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(EfiPath));
|
string DirPath = Path.GetDirectoryName(EfiPath);
|
||||||
|
if (!string.IsNullOrEmpty(DirPath) && !Directory.Exists(DirPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(DirPath);
|
||||||
|
}
|
||||||
File.WriteAllBytes(EfiPath, EfiBinary);
|
File.WriteAllBytes(EfiPath, EfiBinary);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -512,9 +546,9 @@ namespace WPinternals
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
UIContext.Send(s => Notifier.Start(), null);
|
UIContext.Send(s => Notifier.Start(), null);
|
||||||
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||||
Info = FlashModel.ReadPhoneInfo();
|
FlashInfo = FlashModel.ReadPhoneInfo();
|
||||||
Info.Log(LogType.ConsoleOnly);
|
FlashInfo.Log(LogType.ConsoleOnly);
|
||||||
|
|
||||||
FFU ProfileFFU = null;
|
FFU ProfileFFU = null;
|
||||||
FFU CurrentFFU;
|
FFU CurrentFFU;
|
||||||
@@ -527,7 +561,7 @@ namespace WPinternals
|
|||||||
string PlatformID = CurrentFFU.PlatformID;
|
string PlatformID = CurrentFFU.PlatformID;
|
||||||
|
|
||||||
// Check if the current FFU matches the connected phone, so that the FFU can be used for profiling.
|
// Check if the current FFU matches the connected phone, so that the FFU can be used for profiling.
|
||||||
if (Info.PlatformID.StartsWith(PlatformID, StringComparison.OrdinalIgnoreCase))
|
if (FlashInfo.PlatformID.StartsWith(PlatformID, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
ProfileFFU = CurrentFFU;
|
ProfileFFU = CurrentFFU;
|
||||||
}
|
}
|
||||||
@@ -536,7 +570,7 @@ namespace WPinternals
|
|||||||
|
|
||||||
if (ProfileFFU == null)
|
if (ProfileFFU == null)
|
||||||
{
|
{
|
||||||
List<FFUEntry> FFUs = App.Config.FFURepository.Where(e => Info.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
|
List<FFUEntry> FFUs = App.Config.FFURepository.Where(e => FlashInfo.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
|
||||||
ProfileFFU = FFUs.Count > 0
|
ProfileFFU = FFUs.Count > 0
|
||||||
? new FFU(FFUs[0].Path)
|
? new FFU(FFUs[0].Path)
|
||||||
: throw new WPinternalsException("Profile FFU missing", "No profile FFU has been found in the repository for your device. You can add a profile FFU within the download section of the tool or by using the command line.");
|
: throw new WPinternalsException("Profile FFU missing", "No profile FFU has been found in the repository for your device. You can add a profile FFU within the download section of the tool or by using the command line.");
|
||||||
@@ -661,9 +695,9 @@ namespace WPinternals
|
|||||||
LogFile.Log("Command: Show phone info", LogType.FileAndConsole);
|
LogFile.Log("Command: Show phone info", LogType.FileAndConsole);
|
||||||
Notifier = new PhoneNotifierViewModel();
|
Notifier = new PhoneNotifierViewModel();
|
||||||
UIContext.Send(s => Notifier.Start(), null);
|
UIContext.Send(s => Notifier.Start(), null);
|
||||||
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||||
Info = FlashModel.ReadPhoneInfo();
|
FlashInfo = FlashModel.ReadPhoneInfo();
|
||||||
Info.Log(LogType.ConsoleOnly);
|
FlashInfo.Log(LogType.ConsoleOnly);
|
||||||
Notifier.Stop();
|
Notifier.Stop();
|
||||||
break;
|
break;
|
||||||
case "unlockbootloader":
|
case "unlockbootloader":
|
||||||
@@ -673,9 +707,9 @@ namespace WPinternals
|
|||||||
LogFile.Log("Command: Unlock Bootloader", LogType.FileAndConsole);
|
LogFile.Log("Command: Unlock Bootloader", LogType.FileAndConsole);
|
||||||
Notifier = new PhoneNotifierViewModel();
|
Notifier = new PhoneNotifierViewModel();
|
||||||
UIContext.Send(s => Notifier.Start(), null);
|
UIContext.Send(s => Notifier.Start(), null);
|
||||||
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||||
Info = FlashModel.ReadPhoneInfo();
|
FlashInfo = FlashModel.ReadPhoneInfo();
|
||||||
Info.Log(LogType.ConsoleOnly);
|
FlashInfo.Log(LogType.ConsoleOnly);
|
||||||
|
|
||||||
FFU ProfileFFU = null;
|
FFU ProfileFFU = null;
|
||||||
FFU SupportedFFU = null;
|
FFU SupportedFFU = null;
|
||||||
@@ -689,7 +723,7 @@ namespace WPinternals
|
|||||||
string PlatformID = CurrentFFU.PlatformID;
|
string PlatformID = CurrentFFU.PlatformID;
|
||||||
|
|
||||||
// Check if the current FFU matches the connected phone, so that the FFU can be used for profiling.
|
// Check if the current FFU matches the connected phone, so that the FFU can be used for profiling.
|
||||||
if (Info.PlatformID.StartsWith(PlatformID, StringComparison.OrdinalIgnoreCase))
|
if (FlashInfo.PlatformID.StartsWith(PlatformID, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
ProfileFFU = CurrentFFU;
|
ProfileFFU = CurrentFFU;
|
||||||
}
|
}
|
||||||
@@ -704,7 +738,7 @@ namespace WPinternals
|
|||||||
|
|
||||||
if (ProfileFFU == null)
|
if (ProfileFFU == null)
|
||||||
{
|
{
|
||||||
List<FFUEntry> FFUs = App.Config.FFURepository.Where(e => Info.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
|
List<FFUEntry> FFUs = App.Config.FFURepository.Where(e => FlashInfo.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
|
||||||
ProfileFFU = FFUs.Count > 0
|
ProfileFFU = FFUs.Count > 0
|
||||||
? new FFU(FFUs[0].Path)
|
? new FFU(FFUs[0].Path)
|
||||||
: throw new WPinternalsException("Profile FFU missing", "No profile FFU has been found in the repository for your device. You can add a profile FFU within the download section of the tool or by using the command line.");
|
: throw new WPinternalsException("Profile FFU missing", "No profile FFU has been found in the repository for your device. You can add a profile FFU within the download section of the tool or by using the command line.");
|
||||||
@@ -746,9 +780,9 @@ namespace WPinternals
|
|||||||
LogFile.Log("Custom ROM: " + CustomRomPath, LogType.FileAndConsole);
|
LogFile.Log("Custom ROM: " + CustomRomPath, LogType.FileAndConsole);
|
||||||
Notifier = new PhoneNotifierViewModel();
|
Notifier = new PhoneNotifierViewModel();
|
||||||
UIContext.Send(s => Notifier.Start(), null);
|
UIContext.Send(s => Notifier.Start(), null);
|
||||||
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||||
Info = FlashModel.ReadPhoneInfo();
|
FlashInfo = FlashModel.ReadPhoneInfo();
|
||||||
Info.Log(LogType.ConsoleOnly);
|
FlashInfo.Log(LogType.ConsoleOnly);
|
||||||
LogFile.Log("Preparing to flash Custom ROM", LogType.FileAndConsole);
|
LogFile.Log("Preparing to flash Custom ROM", LogType.FileAndConsole);
|
||||||
await LumiaV2UnlockBootViewModel.LumiaV2FlashArchive(Notifier, CustomRomPath);
|
await LumiaV2UnlockBootViewModel.LumiaV2FlashArchive(Notifier, CustomRomPath);
|
||||||
LogFile.Log("Custom ROM flashed successfully", LogType.FileAndConsole);
|
LogFile.Log("Custom ROM flashed successfully", LogType.FileAndConsole);
|
||||||
@@ -777,11 +811,11 @@ namespace WPinternals
|
|||||||
LogFile.Log("FFU file: " + FFUPath, LogType.FileAndConsole);
|
LogFile.Log("FFU file: " + FFUPath, LogType.FileAndConsole);
|
||||||
Notifier = new PhoneNotifierViewModel();
|
Notifier = new PhoneNotifierViewModel();
|
||||||
UIContext.Send(s => Notifier.Start(), null);
|
UIContext.Send(s => Notifier.Start(), null);
|
||||||
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||||
Info = FlashModel.ReadPhoneInfo();
|
FlashInfo = FlashModel.ReadPhoneInfo();
|
||||||
Info.Log(LogType.ConsoleOnly);
|
FlashInfo.Log(LogType.ConsoleOnly);
|
||||||
LogFile.Log("Flashing FFU...", LogType.FileAndConsole);
|
LogFile.Log("Flashing FFU...", LogType.FileAndConsole);
|
||||||
await Task.Run(() => FlashModel.FlashFFU(new FFU(FFUPath), true, (byte)(!Info.IsBootloaderSecure ? FlashOptions.SkipSignatureCheck : 0)));
|
await Task.Run(() => FlashModel.FlashFFU(new FFU(FFUPath), true, (byte)(!FlashInfo.IsBootloaderSecure ? FlashOptions.SkipSignatureCheck : 0)));
|
||||||
LogFile.Log("FFU flashed successfully", LogType.FileAndConsole);
|
LogFile.Log("FFU flashed successfully", LogType.FileAndConsole);
|
||||||
Notifier.Stop();
|
Notifier.Stop();
|
||||||
}
|
}
|
||||||
@@ -1234,189 +1268,36 @@ namespace WPinternals
|
|||||||
|
|
||||||
LogFile.Log("Root access enabled on image", LogType.FileAndConsole);
|
LogFile.Log("Root access enabled on image", LogType.FileAndConsole);
|
||||||
break;
|
break;
|
||||||
case "downloadffu":
|
|
||||||
LogFile.Log("Command: Download FFU", LogType.FileAndConsole);
|
|
||||||
Notifier = new PhoneNotifierViewModel();
|
|
||||||
UIContext.Send(s => Notifier.Start(), null);
|
|
||||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
|
|
||||||
{
|
|
||||||
NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
|
|
||||||
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
|
|
||||||
}
|
|
||||||
else if ((Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) || (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash))
|
|
||||||
{
|
|
||||||
FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
|
|
||||||
Info = FlashModel.ReadPhoneInfo();
|
|
||||||
ProductCode = Info.ProductCode;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NormalModel = (NokiaPhoneModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
|
|
||||||
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
|
|
||||||
}
|
|
||||||
URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
|
|
||||||
DownloadFolder = args.Length >= 3
|
|
||||||
? args[4]
|
|
||||||
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
|
|
||||||
|
|
||||||
if (!Directory.Exists(DownloadFolder))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(DownloadFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
|
|
||||||
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
|
|
||||||
URI = new Uri(URL);
|
|
||||||
FFUFileName = Path.GetFileName(URI.LocalPath);
|
|
||||||
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
|
|
||||||
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
|
|
||||||
LogFile.Log("Downloading...", LogType.FileAndConsole);
|
|
||||||
using (System.Net.WebClient myWebClient = new())
|
|
||||||
{
|
|
||||||
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
|
|
||||||
}
|
|
||||||
LogFile.Log("Download finished", LogType.FileAndConsole);
|
|
||||||
App.Config.AddFfuToRepository(FFUFilePath);
|
|
||||||
Notifier.Stop();
|
|
||||||
break;
|
|
||||||
case "downloadffubyoperatorcode":
|
|
||||||
LogFile.Log("Command: Download FFU by Operator Code", LogType.FileAndConsole);
|
|
||||||
if (args.Length < 4)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadFFUbyOperatorCode <Product type> <Operator code> <Optional: Download folder>");
|
|
||||||
}
|
|
||||||
|
|
||||||
ProductType = args[2];
|
|
||||||
LogFile.Log("Product type: " + ProductType, LogType.FileAndConsole);
|
|
||||||
OperatorCode = args[3];
|
|
||||||
LogFile.Log("Operator code: " + OperatorCode, LogType.FileAndConsole);
|
|
||||||
DownloadFolder = args.Length >= 5
|
|
||||||
? args[4]
|
|
||||||
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
|
|
||||||
|
|
||||||
if (!Directory.Exists(DownloadFolder))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(DownloadFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
|
|
||||||
URL = LumiaDownloadModel.SearchFFU(ProductType, null, OperatorCode);
|
|
||||||
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
|
|
||||||
URI = new Uri(URL);
|
|
||||||
FFUFileName = Path.GetFileName(URI.LocalPath);
|
|
||||||
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
|
|
||||||
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
|
|
||||||
LogFile.Log("Downloading...", LogType.FileAndConsole);
|
|
||||||
using (System.Net.WebClient myWebClient = new())
|
|
||||||
{
|
|
||||||
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
|
|
||||||
}
|
|
||||||
LogFile.Log("Download finished", LogType.FileAndConsole);
|
|
||||||
App.Config.AddFfuToRepository(FFUFilePath);
|
|
||||||
break;
|
|
||||||
case "downloadffubyproductcode":
|
|
||||||
LogFile.Log("Command: Download FFU by Product Code", LogType.FileAndConsole);
|
|
||||||
if (args.Length < 3)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadFFUbyProductCode <Product code> <Optional: Download folder>");
|
|
||||||
}
|
|
||||||
|
|
||||||
ProductCode = args[2];
|
|
||||||
LogFile.Log("Product code: " + ProductCode, LogType.FileAndConsole);
|
|
||||||
URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
|
|
||||||
DownloadFolder = args.Length >= 4
|
|
||||||
? args[3]
|
|
||||||
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
|
|
||||||
|
|
||||||
if (!Directory.Exists(DownloadFolder))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(DownloadFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
|
|
||||||
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
|
|
||||||
URI = new Uri(URL);
|
|
||||||
FFUFileName = Path.GetFileName(URI.LocalPath);
|
|
||||||
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
|
|
||||||
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
|
|
||||||
LogFile.Log("Downloading...", LogType.FileAndConsole);
|
|
||||||
using (System.Net.WebClient myWebClient = new())
|
|
||||||
{
|
|
||||||
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
|
|
||||||
}
|
|
||||||
LogFile.Log("Download finished", LogType.FileAndConsole);
|
|
||||||
App.Config.AddFfuToRepository(FFUFilePath);
|
|
||||||
break;
|
|
||||||
case "downloadffubyproducttype":
|
|
||||||
LogFile.Log("Command: Download FFU by Product Type", LogType.FileAndConsole);
|
|
||||||
if (args.Length < 3)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadFFUbyProductType <Product type> <Optional: Download folder>");
|
|
||||||
}
|
|
||||||
|
|
||||||
ProductType = args[2];
|
|
||||||
LogFile.Log("Product type: " + ProductType, LogType.FileAndConsole);
|
|
||||||
DownloadFolder = args.Length >= 4
|
|
||||||
? args[3]
|
|
||||||
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
|
|
||||||
|
|
||||||
if (!Directory.Exists(DownloadFolder))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(DownloadFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
|
|
||||||
URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
|
|
||||||
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
|
|
||||||
URI = new Uri(URL);
|
|
||||||
FFUFileName = Path.GetFileName(URI.LocalPath);
|
|
||||||
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
|
|
||||||
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
|
|
||||||
LogFile.Log("Downloading...", LogType.FileAndConsole);
|
|
||||||
using (System.Net.WebClient myWebClient = new())
|
|
||||||
{
|
|
||||||
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
|
|
||||||
}
|
|
||||||
LogFile.Log("Download finished", LogType.FileAndConsole);
|
|
||||||
App.Config.AddFfuToRepository(FFUFilePath);
|
|
||||||
break;
|
|
||||||
case "searchffubyproducttype":
|
|
||||||
LogFile.Log("Command: Search FFU by Product Type", LogType.FileAndConsole);
|
|
||||||
if (args.Length < 3)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -SearchFFUbyProductType <Lumia model>");
|
|
||||||
}
|
|
||||||
|
|
||||||
ProductType = args[2];
|
|
||||||
LogFile.Log("Lumia model: " + ProductType, LogType.FileAndConsole);
|
|
||||||
URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
|
|
||||||
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
|
|
||||||
URI = new Uri(URL);
|
|
||||||
FFUFileName = Path.GetFileName(URI.LocalPath);
|
|
||||||
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
|
|
||||||
break;
|
|
||||||
case "downloademergency":
|
case "downloademergency":
|
||||||
LogFile.Log("Command: Download Emergency files", LogType.FileAndConsole);
|
LogFile.Log("Command: Download Emergency files", LogType.FileAndConsole);
|
||||||
Notifier = new PhoneNotifierViewModel();
|
Notifier = new PhoneNotifierViewModel();
|
||||||
UIContext.Send(s => Notifier.Start(), null);
|
UIContext.Send(s => Notifier.Start(), null);
|
||||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
|
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
|
||||||
{
|
{
|
||||||
NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
|
NormalModel = (NokiaCareSuiteModel)Notifier.CurrentModel;
|
||||||
ProductType = NormalModel.ExecuteJsonMethodAsString("ReadManufacturerModelName", "ManufacturerModelName");
|
ProductType = NormalModel.ExecuteJsonMethodAsString("ReadManufacturerModelName", "ManufacturerModelName");
|
||||||
if (ProductType.Contains('_'))
|
if (ProductType.Contains('_'))
|
||||||
{
|
{
|
||||||
ProductType = ProductType.Substring(0, ProductType.IndexOf('_'));
|
ProductType = ProductType.Substring(0, ProductType.IndexOf('_'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) || (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash))
|
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||||
{
|
{
|
||||||
FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
|
BootMgrModel = (LumiaBootManagerAppModel)Notifier.CurrentModel;
|
||||||
Info = FlashModel.ReadPhoneInfo();
|
BootManagerInfo = BootMgrModel.ReadPhoneInfo();
|
||||||
ProductType = Info.Type;
|
//ProductType = BootManagerInfo.Type; // TODO: FIXME
|
||||||
|
ProductType = "";
|
||||||
|
}
|
||||||
|
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash)
|
||||||
|
{
|
||||||
|
FlashModel = (LumiaFlashAppModel)Notifier.CurrentModel;
|
||||||
|
FlashInfo = FlashModel.ReadPhoneInfo();
|
||||||
|
//ProductType = FlashInfo.Type; // TODO: FIXME
|
||||||
|
ProductType = "";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NormalModel = (NokiaPhoneModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
|
NormalModel = (NokiaCareSuiteModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
|
||||||
ProductType = NormalModel.ExecuteJsonMethodAsString("ReadManufacturerModelName", "ManufacturerModelName");
|
ProductType = NormalModel.ExecuteJsonMethodAsString("ReadManufacturerModelName", "ManufacturerModelName");
|
||||||
if (ProductType.Contains('_'))
|
if (ProductType.Contains('_'))
|
||||||
{
|
{
|
||||||
@@ -1516,21 +1397,37 @@ namespace WPinternals
|
|||||||
UIContext.Send(s => Notifier.Start(), null);
|
UIContext.Send(s => Notifier.Start(), null);
|
||||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
|
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
|
||||||
{
|
{
|
||||||
NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
|
NormalModel = (NokiaCareSuiteModel)Notifier.CurrentModel;
|
||||||
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
|
ProductType = NormalModel.ExecuteJsonMethodAsString("ReadManufacturerModelName", "ManufacturerModelName");
|
||||||
|
if (ProductType.Contains('_'))
|
||||||
|
{
|
||||||
|
ProductType = ProductType.Substring(0, ProductType.IndexOf('_'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ((Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) || (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash))
|
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||||
{
|
{
|
||||||
FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
|
BootMgrModel = (LumiaBootManagerAppModel)Notifier.CurrentModel;
|
||||||
Info = FlashModel.ReadPhoneInfo();
|
BootManagerInfo = BootMgrModel.ReadPhoneInfo();
|
||||||
ProductCode = Info.ProductCode;
|
//ProductType = BootManagerInfo.Type; // TODO: FIXME
|
||||||
|
ProductType = "";
|
||||||
|
}
|
||||||
|
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash)
|
||||||
|
{
|
||||||
|
FlashModel = (LumiaFlashAppModel)Notifier.CurrentModel;
|
||||||
|
FlashInfo = FlashModel.ReadPhoneInfo();
|
||||||
|
//ProductType = FlashInfo.Type; // TODO: FIXME
|
||||||
|
ProductType = "";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NormalModel = (NokiaPhoneModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
|
NormalModel = (NokiaCareSuiteModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
|
||||||
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
|
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
|
DownloadFolder = args.Length >= 3
|
||||||
? args[2]
|
? args[2]
|
||||||
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
|
: Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
|
||||||
@@ -1540,20 +1437,6 @@ namespace WPinternals
|
|||||||
Directory.CreateDirectory(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);
|
URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
|
||||||
if (URLs != null)
|
if (URLs != null)
|
||||||
{
|
{
|
||||||
@@ -1585,36 +1468,7 @@ namespace WPinternals
|
|||||||
|
|
||||||
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
|
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";
|
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.");
|
||||||
|
|
||||||
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();
|
Notifier.Stop();
|
||||||
break;
|
break;
|
||||||
@@ -1636,21 +1490,6 @@ namespace WPinternals
|
|||||||
Directory.CreateDirectory(DownloadFolder);
|
Directory.CreateDirectory(DownloadFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
|
|
||||||
URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
|
|
||||||
LogFile.Log("URL: " + URL, LogType.FileAndConsole);
|
|
||||||
URI = new Uri(URL);
|
|
||||||
FFUFileName = Path.GetFileName(URI.LocalPath);
|
|
||||||
LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
|
|
||||||
FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
|
|
||||||
LogFile.Log("Downloading...", LogType.FileAndConsole);
|
|
||||||
using (System.Net.WebClient myWebClient = new())
|
|
||||||
{
|
|
||||||
await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
|
|
||||||
}
|
|
||||||
LogFile.Log("Download finished", LogType.FileAndConsole);
|
|
||||||
App.Config.AddFfuToRepository(FFUFilePath);
|
|
||||||
|
|
||||||
URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
|
URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
|
||||||
if (URLs != null)
|
if (URLs != null)
|
||||||
{
|
{
|
||||||
@@ -1682,230 +1521,7 @@ namespace WPinternals
|
|||||||
|
|
||||||
if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
|
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";
|
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.");
|
||||||
|
|
||||||
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;
|
break;
|
||||||
case "rewritepartitionsfrommassstorage":
|
case "rewritepartitionsfrommassstorage":
|
||||||
@@ -1968,6 +1584,7 @@ namespace WPinternals
|
|||||||
LogFile.Log("WPinternals -ClearNV", LogType.ConsoleOnly);
|
LogFile.Log("WPinternals -ClearNV", LogType.ConsoleOnly);
|
||||||
LogFile.Log("WPinternals -ReadGPT", LogType.ConsoleOnly);
|
LogFile.Log("WPinternals -ReadGPT", LogType.ConsoleOnly);
|
||||||
LogFile.Log("WPinternals -BackupGPT <Path to xml-file>", LogType.ConsoleOnly);
|
LogFile.Log("WPinternals -BackupGPT <Path to xml-file>", LogType.ConsoleOnly);
|
||||||
|
LogFile.Log("WPinternals -ConvertGPT <Path to GPT-file> <Path to xml-file>", LogType.ConsoleOnly);
|
||||||
LogFile.Log("WPinternals -RestoreGPT <Path to xml-file>", LogType.ConsoleOnly);
|
LogFile.Log("WPinternals -RestoreGPT <Path to xml-file>", LogType.ConsoleOnly);
|
||||||
LogFile.Log("WPinternals -MergeGPT <Path to input-xml-file> <Path to input-xml-file>", LogType.ConsoleOnly);
|
LogFile.Log("WPinternals -MergeGPT <Path to input-xml-file> <Path to input-xml-file>", LogType.ConsoleOnly);
|
||||||
LogFile.Log(" <Optional: Path to output-xml-file>", LogType.ConsoleOnly);
|
LogFile.Log(" <Optional: Path to output-xml-file>", LogType.ConsoleOnly);
|
||||||
@@ -2055,12 +1672,18 @@ namespace WPinternals
|
|||||||
Microsoft.Win32.SafeHandles.SafeFileHandle safeFileHandle = new(stdHandle, true);
|
Microsoft.Win32.SafeHandles.SafeFileHandle safeFileHandle = new(stdHandle, true);
|
||||||
FileStream fileStream = new(safeFileHandle, FileAccess.Write);
|
FileStream fileStream = new(safeFileHandle, FileAccess.Write);
|
||||||
Encoding encoding = Encoding.GetEncoding(MY_CODE_PAGE);
|
Encoding encoding = Encoding.GetEncoding(MY_CODE_PAGE);
|
||||||
StreamWriter standardOutput = new(fileStream, encoding);
|
StreamWriter standardOutput = new(fileStream, encoding)
|
||||||
standardOutput.AutoFlush = true;
|
{
|
||||||
|
AutoFlush = true
|
||||||
|
};
|
||||||
Console.SetOut(standardOutput);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
|
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
@@ -22,67 +22,11 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
|
using WPinternals.HelperClasses;
|
||||||
|
|
||||||
namespace WPinternals
|
namespace WPinternals.Config
|
||||||
{
|
{
|
||||||
internal static class Registration
|
|
||||||
{
|
|
||||||
#if PREVIEW
|
|
||||||
internal const bool IsPrerelease = true;
|
|
||||||
#else
|
|
||||||
internal const bool IsPrerelease = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
internal static readonly DateTime ExpirationDate = new(2019, 01, 06);
|
|
||||||
|
|
||||||
internal static void CheckExpiration()
|
|
||||||
{
|
|
||||||
#if PREVIEW
|
|
||||||
//if (IsPrerelease && (DateTime.Now >= ExpirationDate))
|
|
||||||
if (DateTime.Now >= ExpirationDate)
|
|
||||||
{
|
|
||||||
if (Environment.GetCommandLineArgs().Count() > 1)
|
|
||||||
{
|
|
||||||
Console.WriteLine("This prerelease version is expired!");
|
|
||||||
CommandLine.CloseConsole();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
MessageBox.Show("This prerelease version is expired!", "Windows Phone Internals", MessageBoxButton.OK, MessageBoxImage.Exclamation);
|
|
||||||
Environment.Exit(0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static bool IsRegistered()
|
|
||||||
{
|
|
||||||
bool Result = false;
|
|
||||||
if (App.Config.RegistrationName != null)
|
|
||||||
{
|
|
||||||
Result = CalcRegKey() == App.Config.RegistrationKey;
|
|
||||||
}
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string CalcRegKey()
|
|
||||||
{
|
|
||||||
string KeyBase = App.Config.RegistrationName;
|
|
||||||
if (Environment.MachineName == null)
|
|
||||||
{
|
|
||||||
KeyBase += "-Unknown";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
KeyBase += "-" + Environment.MachineName;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] KeyBytes = System.Text.Encoding.UTF8.GetBytes(KeyBase);
|
|
||||||
SHA1Managed sha = new();
|
|
||||||
byte[] Key = sha.ComputeHash(KeyBytes);
|
|
||||||
return Convert.ToBase64String(Key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class WPinternalsConfig
|
public class WPinternalsConfig
|
||||||
{
|
{
|
||||||
@@ -121,7 +65,7 @@ namespace WPinternals
|
|||||||
FileWriter.Close();
|
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);
|
FlashProfile Profile = GetProfile(PlatformID, PhoneFirmware, FfuFirmware);
|
||||||
if (Profile == null)
|
if (Profile == null)
|
||||||
@@ -147,10 +91,10 @@ namespace WPinternals
|
|||||||
|
|
||||||
internal FlashProfile GetProfile(string PlatformID, string PhoneFirmware, string FfuFirmware = null)
|
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)
|
internal void AddFfuToRepository(string FFUPath)
|
||||||
{
|
{
|
||||||
@@ -167,7 +111,7 @@ namespace WPinternals
|
|||||||
|
|
||||||
internal void AddFfuToRepository(string FFUPath, string PlatformID, string FirmwareVersion, string OSVersion)
|
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)
|
if (Entry == null)
|
||||||
{
|
{
|
||||||
LogFile.Log("Adding FFU to repository: " + FFUPath, LogType.FileAndConsole);
|
LogFile.Log("Adding FFU to repository: " + FFUPath, LogType.FileAndConsole);
|
||||||
@@ -217,14 +161,60 @@ namespace WPinternals
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<FFUEntry> FFURepository = new();
|
public List<FFUEntry> FFURepository = [];
|
||||||
|
|
||||||
public List<EmergencyFileEntry> EmergencyRepository = new();
|
internal void AddSecWimToRepository(string SecWimPath, string FirmwareVersion)
|
||||||
|
{
|
||||||
|
SecWimEntry Entry = SecWimRepository.Find(e => e.FirmwareVersion == FirmwareVersion && string.Equals(e.Path, SecWimPath, StringComparison.CurrentCultureIgnoreCase));
|
||||||
|
if (Entry == null)
|
||||||
|
{
|
||||||
|
LogFile.Log("Adding Secure WIM to repository: " + SecWimPath, LogType.FileAndConsole);
|
||||||
|
if (FirmwareVersion != null)
|
||||||
|
{
|
||||||
|
LogFile.Log("Firmware version: " + FirmwareVersion, LogType.FileAndConsole);
|
||||||
|
}
|
||||||
|
|
||||||
|
Entry = new SecWimEntry
|
||||||
|
{
|
||||||
|
Path = SecWimPath,
|
||||||
|
FirmwareVersion = FirmwareVersion
|
||||||
|
};
|
||||||
|
SecWimRepository.Add(Entry);
|
||||||
|
WriteConfig();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogFile.Log("Secure WIM not added, because it was already present in the repository.", LogType.FileAndConsole);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RemoveSecWimFromRepository(string SecWimPath)
|
||||||
|
{
|
||||||
|
int Count = 0;
|
||||||
|
SecWimRepository.Where(e => string.Equals(e.Path, SecWimPath, StringComparison.CurrentCultureIgnoreCase)).ToList().ForEach(e =>
|
||||||
|
{
|
||||||
|
Count++;
|
||||||
|
SecWimRepository.Remove(e);
|
||||||
|
});
|
||||||
|
if (Count == 0)
|
||||||
|
{
|
||||||
|
LogFile.Log("Secure WIM was not removed from repository because it was not present.", LogType.FileAndConsole);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogFile.Log("Removed Secure WIM from repository: " + SecWimPath, LogType.FileAndConsole);
|
||||||
|
WriteConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SecWimEntry> SecWimRepository = [];
|
||||||
|
|
||||||
|
public List<EmergencyFileEntry> EmergencyRepository = [];
|
||||||
|
|
||||||
internal void AddEmergencyToRepository(string Type, string ProgrammerPath, string PayloadPath)
|
internal void AddEmergencyToRepository(string Type, string ProgrammerPath, string PayloadPath)
|
||||||
{
|
{
|
||||||
EmergencyFileEntry Entry = EmergencyRepository.Find(e => (e.Type == Type) && string.Equals(e.ProgrammerPath, ProgrammerPath, 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)))
|
if (Entry != null && PayloadPath != null && !string.Equals(Entry.PayloadPath, PayloadPath, StringComparison.CurrentCultureIgnoreCase))
|
||||||
{
|
{
|
||||||
LogFile.Log("Updating emergency payload path in repository: " + PayloadPath, LogType.FileAndConsole);
|
LogFile.Log("Updating emergency payload path in repository: " + PayloadPath, LogType.FileAndConsole);
|
||||||
Entry.PayloadPath = PayloadPath;
|
Entry.PayloadPath = PayloadPath;
|
||||||
@@ -279,100 +269,4 @@ namespace WPinternals
|
|||||||
public string RegistrationTelegramID;
|
public string RegistrationTelegramID;
|
||||||
public string RegistrationKey;
|
public string RegistrationKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FlashProfile
|
|
||||||
{
|
|
||||||
public string Type;
|
|
||||||
public string PlatformID;
|
|
||||||
public string ProductCode;
|
|
||||||
public string PhoneFirmware;
|
|
||||||
public string FfuFirmware;
|
|
||||||
|
|
||||||
[XmlIgnore]
|
|
||||||
internal UInt32 FillSize;
|
|
||||||
[XmlIgnore]
|
|
||||||
internal UInt32 HeaderSize;
|
|
||||||
[XmlIgnore]
|
|
||||||
internal bool AssumeImageHeaderFallsInGap;
|
|
||||||
[XmlIgnore]
|
|
||||||
internal bool AllocateAsyncBuffersOnPhone;
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "Profile")]
|
|
||||||
public string ProfileAsString
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
byte[] ValueBuffer = new byte[10];
|
|
||||||
ValueBuffer[0] = 1; // Profile version
|
|
||||||
ByteOperations.WriteUInt32(ValueBuffer, 1, FillSize);
|
|
||||||
ByteOperations.WriteUInt32(ValueBuffer, 5, HeaderSize);
|
|
||||||
if (AssumeImageHeaderFallsInGap)
|
|
||||||
{
|
|
||||||
ValueBuffer[9] |= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AllocateAsyncBuffersOnPhone)
|
|
||||||
{
|
|
||||||
ValueBuffer[9] |= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Convert.ToBase64String(ValueBuffer);
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
byte[] ValueBuffer = Convert.FromBase64String(value);
|
|
||||||
byte Version = ValueBuffer[0];
|
|
||||||
FillSize = ByteOperations.ReadUInt32(ValueBuffer, 1);
|
|
||||||
HeaderSize = ByteOperations.ReadUInt32(ValueBuffer, 5);
|
|
||||||
AssumeImageHeaderFallsInGap = (ValueBuffer[9] & 1) != 0;
|
|
||||||
AllocateAsyncBuffersOnPhone = (ValueBuffer[9] & 2) != 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class FFUEntry
|
|
||||||
{
|
|
||||||
public string PlatformID;
|
|
||||||
public string FirmwareVersion;
|
|
||||||
public string OSVersion;
|
|
||||||
public string Path;
|
|
||||||
|
|
||||||
internal bool Exists()
|
|
||||||
{
|
|
||||||
return File.Exists(Path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class EmergencyFileEntry
|
|
||||||
{
|
|
||||||
public string Type;
|
|
||||||
|
|
||||||
[XmlIgnore]
|
|
||||||
public byte[] RKH;
|
|
||||||
[XmlElement(ElementName = "RKH")]
|
|
||||||
public string RKHAsString
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return RKH == null ? null : Converter.ConvertHexToString(RKH, "");
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
RKH = value == null ? null : Converter.ConvertStringToHex(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ProgrammerPath;
|
|
||||||
public string PayloadPath;
|
|
||||||
|
|
||||||
internal bool ProgrammerExists()
|
|
||||||
{
|
|
||||||
return File.Exists(ProgrammerPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal bool PayloadExists()
|
|
||||||
{
|
|
||||||
return File.Exists(PayloadPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -61,14 +61,14 @@ namespace DiscUtils.Internal
|
|||||||
/// <returns>The resultant array.</returns>
|
/// <returns>The resultant array.</returns>
|
||||||
public static U[] Map<T, U>(IEnumerable<T> source, Func<T, U> func)
|
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)
|
foreach (T sVal in source)
|
||||||
{
|
{
|
||||||
result.Add(func(sVal));
|
result.Add(func(sVal));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.ToArray();
|
return [.. result];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -48,15 +48,7 @@ namespace DiscUtils.Fat
|
|||||||
_fat = fileSystem.Fat;
|
_fat = fileSystem.Fat;
|
||||||
_length = length;
|
_length = length;
|
||||||
|
|
||||||
_knownClusters = new List<uint>();
|
_knownClusters = [firstCluster != 0 ? firstCluster : FatBuffer.EndOfChain];
|
||||||
if (firstCluster != 0)
|
|
||||||
{
|
|
||||||
_knownClusters.Add(firstCluster);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_knownClusters.Add(FatBuffer.EndOfChain);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_length == uint.MaxValue)
|
if (_length == uint.MaxValue)
|
||||||
{
|
{
|
||||||
@@ -64,7 +64,7 @@ namespace DiscUtils.Fat
|
|||||||
{
|
{
|
||||||
_type = type;
|
_type = type;
|
||||||
_buffer = buffer;
|
_buffer = buffer;
|
||||||
_dirtySectors = new Dictionary<uint, uint>();
|
_dirtySectors = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
internal int NumEntries
|
internal int NumEntries
|
||||||
@@ -220,7 +220,7 @@ namespace DiscUtils.Fat
|
|||||||
|
|
||||||
internal List<uint> GetChain(uint head)
|
internal List<uint> GetChain(uint head)
|
||||||
{
|
{
|
||||||
List<uint> result = new();
|
List<uint> result = [];
|
||||||
|
|
||||||
if (head != 0)
|
if (head != 0)
|
||||||
{
|
{
|
||||||
@@ -31,15 +31,15 @@ namespace DiscUtils.Fat
|
|||||||
private const byte SpaceByte = 0x20;
|
private const byte SpaceByte = 0x20;
|
||||||
|
|
||||||
public static readonly FileName SelfEntryName =
|
public static readonly FileName SelfEntryName =
|
||||||
new(new byte[] { 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }, 0);
|
new([0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20], 0);
|
||||||
|
|
||||||
public static readonly FileName ParentEntryName =
|
public static readonly FileName ParentEntryName =
|
||||||
new(new byte[] { 0x2E, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }, 0);
|
new([0x2E, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20], 0);
|
||||||
|
|
||||||
public static readonly FileName Null =
|
public static readonly FileName Null =
|
||||||
new(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0);
|
new([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], 0);
|
||||||
|
|
||||||
private static readonly byte[] InvalidBytes = { 0x22, 0x2A, 0x2B, 0x2C, 0x2E, 0x2F, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x5B, 0x5C, 0x5D, 0x7C };
|
private static readonly byte[] InvalidBytes = [0x22, 0x2A, 0x2B, 0x2C, 0x2E, 0x2F, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x5B, 0x5C, 0x5D, 0x7C];
|
||||||
|
|
||||||
private readonly byte[] _raw;
|
private readonly byte[] _raw;
|
||||||
|
|
||||||
@@ -33,10 +33,10 @@ namespace DiscUtils.Fat
|
|||||||
{
|
{
|
||||||
if (FatFileSystem.Detect(stream))
|
if (FatFileSystem.Detect(stream))
|
||||||
{
|
{
|
||||||
return new FileSystemInfo[] { new VfsFileSystemInfo("FAT", "Microsoft FAT", Open) };
|
return [new VfsFileSystemInfo("FAT", "Microsoft FAT", Open)];
|
||||||
}
|
}
|
||||||
|
|
||||||
return System.Array.Empty<FileSystemInfo>();
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
private DiscFileSystem Open(Stream stream, VolumeInfo volumeInfo, FileSystemParameters parameters)
|
private DiscFileSystem Open(Stream stream, VolumeInfo volumeInfo, FileSystemParameters parameters)
|
||||||
@@ -80,22 +80,22 @@ namespace DiscUtils.Fat
|
|||||||
{
|
{
|
||||||
// see http://home.teleport.com/~brainy/lfn.htm
|
// see http://home.teleport.com/~brainy/lfn.htm
|
||||||
// NOTE: we assume ordinals are ok here.
|
// NOTE: we assume ordinals are ok here.
|
||||||
char[] chars = new char[13];
|
char[] chars =
|
||||||
chars[0] = (char)((256 * buffer[2]) + buffer[1]);
|
[
|
||||||
chars[1] = (char)((256 * buffer[4]) + buffer[3]);
|
(char)((256 * buffer[2]) + buffer[1]),
|
||||||
chars[2] = (char)((256 * buffer[6]) + buffer[5]);
|
(char)((256 * buffer[4]) + buffer[3]),
|
||||||
chars[3] = (char)((256 * buffer[8]) + buffer[7]);
|
(char)((256 * buffer[6]) + buffer[5]),
|
||||||
chars[4] = (char)((256 * buffer[10]) + buffer[9]);
|
(char)((256 * buffer[8]) + buffer[7]),
|
||||||
|
(char)((256 * buffer[10]) + buffer[9]),
|
||||||
chars[5] = (char)((256 * buffer[15]) + buffer[14]);
|
(char)((256 * buffer[15]) + buffer[14]),
|
||||||
chars[6] = (char)((256 * buffer[17]) + buffer[16]);
|
(char)((256 * buffer[17]) + buffer[16]),
|
||||||
chars[7] = (char)((256 * buffer[19]) + buffer[18]);
|
(char)((256 * buffer[19]) + buffer[18]),
|
||||||
chars[8] = (char)((256 * buffer[21]) + buffer[20]);
|
(char)((256 * buffer[21]) + buffer[20]),
|
||||||
chars[9] = (char)((256 * buffer[23]) + buffer[22]);
|
(char)((256 * buffer[23]) + buffer[22]),
|
||||||
chars[10] = (char)((256 * buffer[25]) + buffer[24]);
|
(char)((256 * buffer[25]) + buffer[24]),
|
||||||
|
(char)((256 * buffer[29]) + buffer[28]),
|
||||||
chars[11] = (char)((256 * buffer[29]) + buffer[28]);
|
(char)((256 * buffer[31]) + buffer[30]),
|
||||||
chars[12] = (char)((256 * buffer[31]) + buffer[30]);
|
];
|
||||||
string chunk = new(chars);
|
string chunk = new(chars);
|
||||||
int zero = chunk.IndexOf('\0');
|
int zero = chunk.IndexOf('\0');
|
||||||
return zero >= 0 ? chunk.Substring(0, zero) : chunk;
|
return zero >= 0 ? chunk.Substring(0, zero) : chunk;
|
||||||
@@ -201,7 +201,7 @@ namespace DiscUtils.Fat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dirs.ToArray();
|
return [.. dirs];
|
||||||
}
|
}
|
||||||
|
|
||||||
public DirectoryEntry[] GetFiles()
|
public DirectoryEntry[] GetFiles()
|
||||||
@@ -215,7 +215,7 @@ namespace DiscUtils.Fat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return files.ToArray();
|
return [.. files];
|
||||||
}
|
}
|
||||||
|
|
||||||
public DirectoryEntry GetEntry(long id)
|
public DirectoryEntry GetEntry(long id)
|
||||||
@@ -452,8 +452,8 @@ namespace DiscUtils.Fat
|
|||||||
|
|
||||||
private void LoadEntries()
|
private void LoadEntries()
|
||||||
{
|
{
|
||||||
_entries = new Dictionary<long, DirectoryEntry>();
|
_entries = [];
|
||||||
_freeEntries = new List<long>();
|
_freeEntries = [];
|
||||||
|
|
||||||
_selfEntryLocation = -1;
|
_selfEntryLocation = -1;
|
||||||
_parentEntryLocation = -1;
|
_parentEntryLocation = -1;
|
||||||
@@ -94,7 +94,7 @@ namespace DiscUtils.Fat
|
|||||||
public FatFileSystem(Stream data)
|
public FatFileSystem(Stream data)
|
||||||
: base(new FatFileSystemOptions())
|
: base(new FatFileSystemOptions())
|
||||||
{
|
{
|
||||||
_dirCache = new Dictionary<uint, Directory>();
|
_dirCache = [];
|
||||||
_timeConverter = DefaultTimeConverter;
|
_timeConverter = DefaultTimeConverter;
|
||||||
Initialize(data);
|
Initialize(data);
|
||||||
}
|
}
|
||||||
@@ -111,7 +111,7 @@ namespace DiscUtils.Fat
|
|||||||
public FatFileSystem(Stream data, Ownership ownsData)
|
public FatFileSystem(Stream data, Ownership ownsData)
|
||||||
: base(new FatFileSystemOptions())
|
: base(new FatFileSystemOptions())
|
||||||
{
|
{
|
||||||
_dirCache = new Dictionary<uint, Directory>();
|
_dirCache = [];
|
||||||
_timeConverter = DefaultTimeConverter;
|
_timeConverter = DefaultTimeConverter;
|
||||||
Initialize(data);
|
Initialize(data);
|
||||||
_ownsData = ownsData;
|
_ownsData = ownsData;
|
||||||
@@ -125,7 +125,7 @@ namespace DiscUtils.Fat
|
|||||||
public FatFileSystem(Stream data, TimeConverter timeConverter)
|
public FatFileSystem(Stream data, TimeConverter timeConverter)
|
||||||
: base(new FatFileSystemOptions())
|
: base(new FatFileSystemOptions())
|
||||||
{
|
{
|
||||||
_dirCache = new Dictionary<uint, Directory>();
|
_dirCache = [];
|
||||||
_timeConverter = timeConverter;
|
_timeConverter = timeConverter;
|
||||||
Initialize(data);
|
Initialize(data);
|
||||||
}
|
}
|
||||||
@@ -140,7 +140,7 @@ namespace DiscUtils.Fat
|
|||||||
public FatFileSystem(Stream data, Ownership ownsData, TimeConverter timeConverter)
|
public FatFileSystem(Stream data, Ownership ownsData, TimeConverter timeConverter)
|
||||||
: base(new FatFileSystemOptions())
|
: base(new FatFileSystemOptions())
|
||||||
{
|
{
|
||||||
_dirCache = new Dictionary<uint, Directory>();
|
_dirCache = [];
|
||||||
_timeConverter = timeConverter;
|
_timeConverter = timeConverter;
|
||||||
Initialize(data);
|
Initialize(data);
|
||||||
_ownsData = ownsData;
|
_ownsData = ownsData;
|
||||||
@@ -156,7 +156,7 @@ namespace DiscUtils.Fat
|
|||||||
public FatFileSystem(Stream data, Ownership ownsData, FileSystemParameters parameters)
|
public FatFileSystem(Stream data, Ownership ownsData, FileSystemParameters parameters)
|
||||||
: base(new FatFileSystemOptions(parameters))
|
: base(new FatFileSystemOptions(parameters))
|
||||||
{
|
{
|
||||||
_dirCache = new Dictionary<uint, Directory>();
|
_dirCache = [];
|
||||||
|
|
||||||
if (parameters?.TimeConverter != null)
|
if (parameters?.TimeConverter != null)
|
||||||
{
|
{
|
||||||
@@ -1258,7 +1258,7 @@ namespace DiscUtils.Fat
|
|||||||
dirs.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding)));
|
dirs.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return dirs.ToArray();
|
return [.. dirs];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1273,9 +1273,9 @@ namespace DiscUtils.Fat
|
|||||||
{
|
{
|
||||||
Regex re = Utilities.ConvertWildcardsToRegEx(searchPattern);
|
Regex re = Utilities.ConvertWildcardsToRegEx(searchPattern);
|
||||||
|
|
||||||
List<string> dirs = new();
|
List<string> dirs = [];
|
||||||
DoSearch(dirs, path, re, searchOption == SearchOption.AllDirectories, true, false);
|
DoSearch(dirs, path, re, searchOption == SearchOption.AllDirectories, true, false);
|
||||||
return dirs.ToArray();
|
return [.. dirs];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1294,7 +1294,7 @@ namespace DiscUtils.Fat
|
|||||||
files.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding)));
|
files.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return files.ToArray();
|
return [.. files];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1309,9 +1309,9 @@ namespace DiscUtils.Fat
|
|||||||
{
|
{
|
||||||
Regex re = Utilities.ConvertWildcardsToRegEx(searchPattern);
|
Regex re = Utilities.ConvertWildcardsToRegEx(searchPattern);
|
||||||
|
|
||||||
List<string> results = new();
|
List<string> results = [];
|
||||||
DoSearch(results, path, re, searchOption == SearchOption.AllDirectories, false, true);
|
DoSearch(results, path, re, searchOption == SearchOption.AllDirectories, false, true);
|
||||||
return results.ToArray();
|
return [.. results];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1330,7 +1330,7 @@ namespace DiscUtils.Fat
|
|||||||
result.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding)));
|
result.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.ToArray();
|
return [.. result];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1356,7 +1356,7 @@ namespace DiscUtils.Fat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.ToArray();
|
return [.. result];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1915,9 +1915,7 @@ namespace DiscUtils.Fat
|
|||||||
throw new DirectoryNotFoundException(string.Format(CultureInfo.InvariantCulture, "The directory '{0}' was not found", path));
|
throw new DirectoryNotFoundException(string.Format(CultureInfo.InvariantCulture, "The directory '{0}' was not found", path));
|
||||||
}
|
}
|
||||||
|
|
||||||
DirectoryEntry[] entries = dir.Entries;
|
foreach (DirectoryEntry de in dir.Entries)
|
||||||
|
|
||||||
foreach (DirectoryEntry de in entries)
|
|
||||||
{
|
{
|
||||||
bool isDir = (de.Attributes & FatAttributes.Directory) != 0;
|
bool isDir = (de.Attributes & FatAttributes.Directory) != 0;
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
|
Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
|
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
@@ -24,6 +24,7 @@ using System.Globalization;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
|
using WPinternals.HelperClasses;
|
||||||
|
|
||||||
namespace WPinternals
|
namespace WPinternals
|
||||||
{
|
{
|
||||||
@@ -149,7 +150,7 @@ namespace WPinternals
|
|||||||
|
|
||||||
protected override Size MeasureOverride(Size availableSize)
|
protected override Size MeasureOverride(Size availableSize)
|
||||||
{
|
{
|
||||||
var resultSize = new Size(availableSize.Width, 0);
|
Size resultSize = new Size(availableSize.Width, 0);
|
||||||
|
|
||||||
#if NETCORE
|
#if NETCORE
|
||||||
FormattedText formatted = new FormattedText(
|
FormattedText formatted = new FormattedText(
|
||||||
@@ -316,13 +317,19 @@ namespace WPinternals
|
|||||||
{
|
{
|
||||||
filename = System.IO.Path.GetFileName(Text);
|
filename = System.IO.Path.GetFileName(Text);
|
||||||
}
|
}
|
||||||
catch { }
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogFile.LogException(ex, LogType.FileOnly);
|
||||||
|
}
|
||||||
string directory = "";
|
string directory = "";
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
directory = System.IO.Path.GetDirectoryName(Text);
|
directory = System.IO.Path.GetDirectoryName(Text);
|
||||||
}
|
}
|
||||||
catch { }
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogFile.LogException(ex, LogType.FileOnly);
|
||||||
|
}
|
||||||
FormattedText formatted;
|
FormattedText formatted;
|
||||||
bool widthOK = false;
|
bool widthOK = false;
|
||||||
bool changedWidth = false;
|
bool changedWidth = false;
|
||||||
@@ -423,9 +430,10 @@ namespace WPinternals
|
|||||||
|
|
||||||
if (SaveDialog)
|
if (SaveDialog)
|
||||||
{
|
{
|
||||||
Microsoft.Win32.SaveFileDialog savedlg = new();
|
Microsoft.Win32.SaveFileDialog savedlg = new()
|
||||||
|
{
|
||||||
savedlg.FileName = Path ?? DefaultFileName;
|
FileName = Path ?? DefaultFileName
|
||||||
|
};
|
||||||
|
|
||||||
// Show open file dialog box
|
// Show open file dialog box
|
||||||
result = savedlg.ShowDialog();
|
result = savedlg.ShowDialog();
|
||||||
@@ -440,9 +448,10 @@ namespace WPinternals
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Select file
|
// Select file
|
||||||
Microsoft.Win32.OpenFileDialog dlg = new();
|
Microsoft.Win32.OpenFileDialog dlg = new()
|
||||||
|
{
|
||||||
dlg.FileName = Path ?? DefaultFileName;
|
FileName = Path ?? DefaultFileName
|
||||||
|
};
|
||||||
|
|
||||||
// Show open file dialog box
|
// Show open file dialog box
|
||||||
result = dlg.ShowDialog();
|
result = dlg.ShowDialog();
|
||||||
@@ -79,7 +79,7 @@ namespace WPinternals
|
|||||||
/// <returns>True if the user presses OK else false</returns>
|
/// <returns>True if the user presses OK else false</returns>
|
||||||
public bool ShowDialog(IntPtr hWndOwner)
|
public bool ShowDialog(IntPtr hWndOwner)
|
||||||
{
|
{
|
||||||
var fbd = new FolderBrowserDialog
|
FolderBrowserDialog fbd = new FolderBrowserDialog
|
||||||
{
|
{
|
||||||
Description = this.Title,
|
Description = this.Title,
|
||||||
SelectedPath = this.InitialDirectory,
|
SelectedPath = this.InitialDirectory,
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
// Some of the classes and functions in this file were found online.
|
||||||
|
// Where possible the original authors are referenced.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace WPinternals.HelperClasses
|
||||||
|
{
|
||||||
|
internal class ArrivalEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public PhoneInterfaces NewInterface;
|
||||||
|
public IDisposable NewModel;
|
||||||
|
|
||||||
|
public ArrivalEventArgs(PhoneInterfaces NewInterface, IDisposable NewModel)
|
||||||
|
: base()
|
||||||
|
{
|
||||||
|
this.NewInterface = NewInterface;
|
||||||
|
this.NewModel = NewModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
// Some of the classes and functions in this file were found online.
|
||||||
|
// Where possible the original authors are referenced.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace WPinternals.HelperClasses
|
||||||
|
{
|
||||||
|
internal class AsyncAutoResetEvent
|
||||||
|
{
|
||||||
|
private readonly LinkedList<TaskCompletionSource<bool>> waiters =
|
||||||
|
new();
|
||||||
|
|
||||||
|
private bool isSignaled;
|
||||||
|
|
||||||
|
public AsyncAutoResetEvent(bool signaled)
|
||||||
|
{
|
||||||
|
isSignaled = signaled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<bool> WaitAsync(TimeSpan timeout)
|
||||||
|
{
|
||||||
|
return WaitAsync(timeout, CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> WaitAsync(TimeSpan timeout, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
TaskCompletionSource<bool> tcs;
|
||||||
|
|
||||||
|
lock (waiters)
|
||||||
|
{
|
||||||
|
if (isSignaled)
|
||||||
|
{
|
||||||
|
isSignaled = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (timeout == TimeSpan.Zero)
|
||||||
|
{
|
||||||
|
return isSignaled;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tcs = new TaskCompletionSource<bool>();
|
||||||
|
waiters.AddLast(tcs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Task winner = await Task.WhenAny(tcs.Task, Task.Delay(timeout, cancellationToken));
|
||||||
|
if (winner == tcs.Task)
|
||||||
|
{
|
||||||
|
// The task was signaled.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We timed-out; remove our reference to the task.
|
||||||
|
// This is an O(n) operation since waiters is a LinkedList<T>.
|
||||||
|
lock (waiters)
|
||||||
|
{
|
||||||
|
bool removed = waiters.Remove(tcs);
|
||||||
|
System.Diagnostics.Debug.Assert(removed);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Set()
|
||||||
|
{
|
||||||
|
TaskCompletionSource<bool> toRelease = null;
|
||||||
|
|
||||||
|
lock (waiters)
|
||||||
|
{
|
||||||
|
if (waiters.Count > 0)
|
||||||
|
{
|
||||||
|
// Signal the first task in the waiters list.
|
||||||
|
toRelease = waiters.First.Value;
|
||||||
|
waiters.RemoveFirst();
|
||||||
|
}
|
||||||
|
else if (!isSignaled)
|
||||||
|
{
|
||||||
|
// No tasks are pending
|
||||||
|
isSignaled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toRelease?.SetResult(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
};
|
||||||
|
}
|
||||||