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 |
@@ -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.400"
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,64 +1,64 @@
|
|||||||
// Common/CRC.cs
|
// Common/CRC.cs
|
||||||
|
|
||||||
namespace SevenZip
|
namespace SevenZip
|
||||||
{
|
{
|
||||||
internal class CRC
|
internal class CRC
|
||||||
{
|
{
|
||||||
public static readonly uint[] Table;
|
public static readonly uint[] Table;
|
||||||
|
|
||||||
static CRC()
|
static CRC()
|
||||||
{
|
{
|
||||||
Table = new uint[256];
|
Table = new uint[256];
|
||||||
const uint kPoly = 0xEDB88320;
|
const uint kPoly = 0xEDB88320;
|
||||||
for (uint i = 0; i < 256; i++)
|
for (uint i = 0; i < 256; i++)
|
||||||
{
|
{
|
||||||
uint r = i;
|
uint r = i;
|
||||||
for (int j = 0; j < 8; j++)
|
for (int j = 0; j < 8; j++)
|
||||||
{
|
{
|
||||||
if ((r & 1) != 0)
|
if ((r & 1) != 0)
|
||||||
{
|
{
|
||||||
r = (r >> 1) ^ kPoly;
|
r = (r >> 1) ^ kPoly;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
r >>= 1;
|
r >>= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Table[i] = r;
|
Table[i] = r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private uint _value = 0xFFFFFFFF;
|
private uint _value = 0xFFFFFFFF;
|
||||||
|
|
||||||
public void Init() { _value = 0xFFFFFFFF; }
|
public void Init() { _value = 0xFFFFFFFF; }
|
||||||
|
|
||||||
public void UpdateByte(byte b)
|
public void UpdateByte(byte b)
|
||||||
{
|
{
|
||||||
_value = Table[((byte)_value) ^ b] ^ (_value >> 8);
|
_value = Table[((byte)_value) ^ b] ^ (_value >> 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update(byte[] data, uint offset, uint size)
|
public void Update(byte[] data, uint offset, uint size)
|
||||||
{
|
{
|
||||||
for (uint i = 0; i < size; i++)
|
for (uint i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
_value = Table[((byte)_value) ^ data[offset + i]] ^ (_value >> 8);
|
_value = Table[((byte)_value) ^ data[offset + i]] ^ (_value >> 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint GetDigest() { return _value ^ 0xFFFFFFFF; }
|
public uint GetDigest() { return _value ^ 0xFFFFFFFF; }
|
||||||
|
|
||||||
private static uint CalculateDigest(byte[] data, uint offset, uint size)
|
private static uint CalculateDigest(byte[] data, uint offset, uint size)
|
||||||
{
|
{
|
||||||
CRC crc = new();
|
CRC crc = new();
|
||||||
// crc.Init();
|
// crc.Init();
|
||||||
crc.Update(data, offset, size);
|
crc.Update(data, offset, size);
|
||||||
return crc.GetDigest();
|
return crc.GetDigest();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size)
|
private static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size)
|
||||||
{
|
{
|
||||||
return CalculateDigest(data, offset, size) == digest;
|
return CalculateDigest(data, offset, size) == digest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,325 +1,325 @@
|
|||||||
// CommandLineParser.cs
|
// CommandLineParser.cs
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
|
||||||
namespace SevenZip.CommandLineParser
|
namespace SevenZip.CommandLineParser
|
||||||
{
|
{
|
||||||
public enum SwitchType
|
public enum SwitchType
|
||||||
{
|
{
|
||||||
Simple,
|
Simple,
|
||||||
PostMinus,
|
PostMinus,
|
||||||
LimitedPostString,
|
LimitedPostString,
|
||||||
UnLimitedPostString,
|
UnLimitedPostString,
|
||||||
PostChar
|
PostChar
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SwitchForm
|
public class SwitchForm
|
||||||
{
|
{
|
||||||
public string IDString;
|
public string IDString;
|
||||||
public SwitchType Type;
|
public SwitchType Type;
|
||||||
public bool Multi;
|
public bool Multi;
|
||||||
public int MinLen;
|
public int MinLen;
|
||||||
public int MaxLen;
|
public int MaxLen;
|
||||||
public string PostCharSet;
|
public string PostCharSet;
|
||||||
|
|
||||||
public SwitchForm(string idString, SwitchType type, bool multi,
|
public SwitchForm(string idString, SwitchType type, bool multi,
|
||||||
int minLen, int maxLen, string postCharSet)
|
int minLen, int maxLen, string postCharSet)
|
||||||
{
|
{
|
||||||
IDString = idString;
|
IDString = idString;
|
||||||
Type = type;
|
Type = type;
|
||||||
Multi = multi;
|
Multi = multi;
|
||||||
MinLen = minLen;
|
MinLen = minLen;
|
||||||
MaxLen = maxLen;
|
MaxLen = maxLen;
|
||||||
PostCharSet = postCharSet;
|
PostCharSet = postCharSet;
|
||||||
}
|
}
|
||||||
public SwitchForm(string idString, SwitchType type, bool multi, int minLen) :
|
public SwitchForm(string idString, SwitchType type, bool multi, int minLen) :
|
||||||
this(idString, type, multi, minLen, 0, "")
|
this(idString, type, multi, minLen, 0, "")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
public SwitchForm(string idString, SwitchType type, bool multi) :
|
public SwitchForm(string idString, SwitchType type, bool multi) :
|
||||||
this(idString, type, multi, 0)
|
this(idString, type, multi, 0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SwitchResult
|
public class SwitchResult
|
||||||
{
|
{
|
||||||
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()
|
||||||
{
|
{
|
||||||
ThereIs = false;
|
ThereIs = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
_switches = new SwitchResult[numSwitches];
|
_switches = new SwitchResult[numSwitches];
|
||||||
for (int i = 0; i < numSwitches; i++)
|
for (int i = 0; i < numSwitches; i++)
|
||||||
{
|
{
|
||||||
_switches[i] = new SwitchResult();
|
_switches[i] = new SwitchResult();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ParseString(string srcString, SwitchForm[] switchForms)
|
private bool ParseString(string srcString, SwitchForm[] switchForms)
|
||||||
{
|
{
|
||||||
int len = srcString.Length;
|
int len = srcString.Length;
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
if (!IsItSwitchChar(srcString[pos]))
|
if (!IsItSwitchChar(srcString[pos]))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (pos < len)
|
while (pos < len)
|
||||||
{
|
{
|
||||||
if (IsItSwitchChar(srcString[pos]))
|
if (IsItSwitchChar(srcString[pos]))
|
||||||
{
|
{
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int kNoLen = -1;
|
const int kNoLen = -1;
|
||||||
int matchedSwitchIndex = 0;
|
int matchedSwitchIndex = 0;
|
||||||
int maxLen = kNoLen;
|
int maxLen = kNoLen;
|
||||||
for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++)
|
for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++)
|
||||||
{
|
{
|
||||||
int switchLen = switchForms[switchIndex].IDString.Length;
|
int switchLen = switchForms[switchIndex].IDString.Length;
|
||||||
if (switchLen <= maxLen || pos + switchLen > len)
|
if (switchLen <= maxLen || pos + switchLen > len)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (String.Compare(switchForms[switchIndex].IDString, 0,
|
if (String.Compare(switchForms[switchIndex].IDString, 0,
|
||||||
srcString, pos, switchLen, true) == 0)
|
srcString, pos, switchLen, true) == 0)
|
||||||
{
|
{
|
||||||
matchedSwitchIndex = switchIndex;
|
matchedSwitchIndex = switchIndex;
|
||||||
maxLen = switchLen;
|
maxLen = switchLen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (maxLen == kNoLen)
|
if (maxLen == kNoLen)
|
||||||
{
|
{
|
||||||
throw new Exception("maxLen == kNoLen");
|
throw new Exception("maxLen == kNoLen");
|
||||||
}
|
}
|
||||||
|
|
||||||
SwitchResult matchedSwitch = _switches[matchedSwitchIndex];
|
SwitchResult matchedSwitch = _switches[matchedSwitchIndex];
|
||||||
SwitchForm switchForm = switchForms[matchedSwitchIndex];
|
SwitchForm switchForm = switchForms[matchedSwitchIndex];
|
||||||
if ((!switchForm.Multi) && matchedSwitch.ThereIs)
|
if ((!switchForm.Multi) && matchedSwitch.ThereIs)
|
||||||
{
|
{
|
||||||
throw new Exception("switch must be single");
|
throw new Exception("switch must be single");
|
||||||
}
|
}
|
||||||
|
|
||||||
matchedSwitch.ThereIs = true;
|
matchedSwitch.ThereIs = true;
|
||||||
pos += maxLen;
|
pos += maxLen;
|
||||||
int tailSize = len - pos;
|
int tailSize = len - pos;
|
||||||
SwitchType type = switchForm.Type;
|
SwitchType type = switchForm.Type;
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case SwitchType.PostMinus:
|
case SwitchType.PostMinus:
|
||||||
{
|
{
|
||||||
if (tailSize == 0)
|
if (tailSize == 0)
|
||||||
{
|
{
|
||||||
matchedSwitch.WithMinus = false;
|
matchedSwitch.WithMinus = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
matchedSwitch.WithMinus = srcString[pos] == kSwitchMinus;
|
matchedSwitch.WithMinus = srcString[pos] == kSwitchMinus;
|
||||||
if (matchedSwitch.WithMinus)
|
if (matchedSwitch.WithMinus)
|
||||||
{
|
{
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SwitchType.PostChar:
|
case SwitchType.PostChar:
|
||||||
{
|
{
|
||||||
if (tailSize < switchForm.MinLen)
|
if (tailSize < switchForm.MinLen)
|
||||||
{
|
{
|
||||||
throw new Exception("switch is not full");
|
throw new Exception("switch is not full");
|
||||||
}
|
}
|
||||||
|
|
||||||
string charSet = switchForm.PostCharSet;
|
string charSet = switchForm.PostCharSet;
|
||||||
const int kEmptyCharValue = -1;
|
const int kEmptyCharValue = -1;
|
||||||
if (tailSize == 0)
|
if (tailSize == 0)
|
||||||
{
|
{
|
||||||
matchedSwitch.PostCharIndex = kEmptyCharValue;
|
matchedSwitch.PostCharIndex = kEmptyCharValue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int index = charSet.IndexOf(srcString[pos]);
|
int index = charSet.IndexOf(srcString[pos]);
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
{
|
{
|
||||||
matchedSwitch.PostCharIndex = kEmptyCharValue;
|
matchedSwitch.PostCharIndex = kEmptyCharValue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
matchedSwitch.PostCharIndex = index;
|
matchedSwitch.PostCharIndex = index;
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SwitchType.LimitedPostString:
|
case SwitchType.LimitedPostString:
|
||||||
case SwitchType.UnLimitedPostString:
|
case SwitchType.UnLimitedPostString:
|
||||||
{
|
{
|
||||||
int minLen = switchForm.MinLen;
|
int minLen = switchForm.MinLen;
|
||||||
if (tailSize < minLen)
|
if (tailSize < minLen)
|
||||||
{
|
{
|
||||||
throw new Exception("switch is not full");
|
throw new Exception("switch is not full");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == SwitchType.UnLimitedPostString)
|
if (type == SwitchType.UnLimitedPostString)
|
||||||
{
|
{
|
||||||
matchedSwitch.PostStrings.Add(srcString[pos..]);
|
matchedSwitch.PostStrings.Add(srcString[pos..]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
String stringSwitch = srcString.Substring(pos, minLen);
|
String stringSwitch = srcString.Substring(pos, minLen);
|
||||||
pos += minLen;
|
pos += minLen;
|
||||||
for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++)
|
for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++)
|
||||||
{
|
{
|
||||||
char c = srcString[pos];
|
char c = srcString[pos];
|
||||||
if (IsItSwitchChar(c))
|
if (IsItSwitchChar(c))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
stringSwitch += c;
|
stringSwitch += c;
|
||||||
}
|
}
|
||||||
matchedSwitch.PostStrings.Add(stringSwitch);
|
matchedSwitch.PostStrings.Add(stringSwitch);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings)
|
public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings)
|
||||||
{
|
{
|
||||||
int numCommandStrings = commandStrings.Length;
|
int numCommandStrings = commandStrings.Length;
|
||||||
bool stopSwitch = false;
|
bool stopSwitch = false;
|
||||||
for (int i = 0; i < numCommandStrings; i++)
|
for (int i = 0; i < numCommandStrings; i++)
|
||||||
{
|
{
|
||||||
string s = commandStrings[i];
|
string s = commandStrings[i];
|
||||||
if (stopSwitch)
|
if (stopSwitch)
|
||||||
{
|
{
|
||||||
NonSwitchStrings.Add(s);
|
NonSwitchStrings.Add(s);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (s == kStopSwitchParsing)
|
if (s == kStopSwitchParsing)
|
||||||
{
|
{
|
||||||
stopSwitch = true;
|
stopSwitch = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (!ParseString(s, switchForms))
|
if (!ParseString(s, switchForms))
|
||||||
{
|
{
|
||||||
NonSwitchStrings.Add(s);
|
NonSwitchStrings.Add(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SwitchResult this[int index] { get { return _switches[index]; } }
|
public SwitchResult this[int index] { get { return _switches[index]; } }
|
||||||
|
|
||||||
public static int ParseCommand(CommandForm[] commandForms, string commandString,
|
public static int ParseCommand(CommandForm[] commandForms, string commandString,
|
||||||
out string postString)
|
out string postString)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < commandForms.Length; i++)
|
for (int i = 0; i < commandForms.Length; i++)
|
||||||
{
|
{
|
||||||
string id = commandForms[i].IDString;
|
string id = commandForms[i].IDString;
|
||||||
if (commandForms[i].PostStringMode)
|
if (commandForms[i].PostStringMode)
|
||||||
{
|
{
|
||||||
if (commandString.IndexOf(id) == 0)
|
if (commandString.IndexOf(id) == 0)
|
||||||
{
|
{
|
||||||
postString = commandString[id.Length..];
|
postString = commandString[id.Length..];
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (commandString == id)
|
if (commandString == id)
|
||||||
{
|
{
|
||||||
postString = "";
|
postString = "";
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
postString = "";
|
postString = "";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms,
|
private static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms,
|
||||||
string commandString, ArrayList indices)
|
string commandString, ArrayList indices)
|
||||||
{
|
{
|
||||||
indices.Clear();
|
indices.Clear();
|
||||||
int numUsedChars = 0;
|
int numUsedChars = 0;
|
||||||
for (int i = 0; i < numForms; i++)
|
for (int i = 0; i < numForms; i++)
|
||||||
{
|
{
|
||||||
CommandSubCharsSet charsSet = forms[i];
|
CommandSubCharsSet charsSet = forms[i];
|
||||||
int currentIndex = -1;
|
int currentIndex = -1;
|
||||||
int len = charsSet.Chars.Length;
|
int len = charsSet.Chars.Length;
|
||||||
for (int j = 0; j < len; j++)
|
for (int j = 0; j < len; j++)
|
||||||
{
|
{
|
||||||
char c = charsSet.Chars[j];
|
char c = charsSet.Chars[j];
|
||||||
int newIndex = commandString.IndexOf(c);
|
int newIndex = commandString.IndexOf(c);
|
||||||
if (newIndex >= 0)
|
if (newIndex >= 0)
|
||||||
{
|
{
|
||||||
if (currentIndex >= 0)
|
if (currentIndex >= 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (commandString.IndexOf(c, newIndex + 1) >= 0)
|
if (commandString.IndexOf(c, newIndex + 1) >= 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentIndex = j;
|
currentIndex = j;
|
||||||
numUsedChars++;
|
numUsedChars++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentIndex == -1 && !charsSet.EmptyAllowed)
|
if (currentIndex == -1 && !charsSet.EmptyAllowed)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
indices.Add(currentIndex);
|
indices.Add(currentIndex);
|
||||||
}
|
}
|
||||||
return numUsedChars == commandString.Length;
|
return numUsedChars == commandString.Length;
|
||||||
}
|
}
|
||||||
private const char kSwitchID1 = '-';
|
private const char kSwitchID1 = '-';
|
||||||
private const char kSwitchID2 = '/';
|
private const char kSwitchID2 = '/';
|
||||||
|
|
||||||
private const char kSwitchMinus = '-';
|
private const char kSwitchMinus = '-';
|
||||||
private const string kStopSwitchParsing = "--";
|
private const string kStopSwitchParsing = "--";
|
||||||
|
|
||||||
private static bool IsItSwitchChar(char c)
|
private static bool IsItSwitchChar(char c)
|
||||||
{
|
{
|
||||||
return c == kSwitchID1 || c == kSwitchID2;
|
return c == kSwitchID1 || c == kSwitchID2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CommandForm
|
public class CommandForm
|
||||||
{
|
{
|
||||||
public string IDString = "";
|
public string IDString = "";
|
||||||
public bool PostStringMode = false;
|
public bool PostStringMode = false;
|
||||||
public CommandForm(string idString, bool postStringMode)
|
public CommandForm(string idString, bool postStringMode)
|
||||||
{
|
{
|
||||||
IDString = idString;
|
IDString = idString;
|
||||||
PostStringMode = postStringMode;
|
PostStringMode = postStringMode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class CommandSubCharsSet
|
internal class CommandSubCharsSet
|
||||||
{
|
{
|
||||||
public string Chars = "";
|
public string Chars = "";
|
||||||
public bool EmptyAllowed = false;
|
public bool EmptyAllowed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,78 +1,78 @@
|
|||||||
// InBuffer.cs
|
// InBuffer.cs
|
||||||
|
|
||||||
namespace SevenZip.Buffer
|
namespace SevenZip.Buffer
|
||||||
{
|
{
|
||||||
public class InBuffer
|
public class InBuffer
|
||||||
{
|
{
|
||||||
private readonly byte[] m_Buffer;
|
private readonly byte[] m_Buffer;
|
||||||
private uint m_Pos;
|
private uint m_Pos;
|
||||||
private uint m_Limit;
|
private uint m_Limit;
|
||||||
private readonly uint m_BufferSize;
|
private readonly uint m_BufferSize;
|
||||||
private System.IO.Stream m_Stream;
|
private System.IO.Stream m_Stream;
|
||||||
private bool m_StreamWasExhausted;
|
private bool m_StreamWasExhausted;
|
||||||
private ulong m_ProcessedSize;
|
private ulong m_ProcessedSize;
|
||||||
|
|
||||||
public InBuffer(uint bufferSize)
|
public InBuffer(uint bufferSize)
|
||||||
{
|
{
|
||||||
m_Buffer = new byte[bufferSize];
|
m_Buffer = new byte[bufferSize];
|
||||||
m_BufferSize = bufferSize;
|
m_BufferSize = bufferSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init(System.IO.Stream stream)
|
public void Init(System.IO.Stream stream)
|
||||||
{
|
{
|
||||||
m_Stream = stream;
|
m_Stream = stream;
|
||||||
m_ProcessedSize = 0;
|
m_ProcessedSize = 0;
|
||||||
m_Limit = 0;
|
m_Limit = 0;
|
||||||
m_Pos = 0;
|
m_Pos = 0;
|
||||||
m_StreamWasExhausted = false;
|
m_StreamWasExhausted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ReadBlock()
|
public bool ReadBlock()
|
||||||
{
|
{
|
||||||
if (m_StreamWasExhausted)
|
if (m_StreamWasExhausted)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ProcessedSize += m_Pos;
|
m_ProcessedSize += m_Pos;
|
||||||
int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize);
|
int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize);
|
||||||
m_Pos = 0;
|
m_Pos = 0;
|
||||||
m_Limit = (uint)aNumProcessedBytes;
|
m_Limit = (uint)aNumProcessedBytes;
|
||||||
m_StreamWasExhausted = aNumProcessedBytes == 0;
|
m_StreamWasExhausted = aNumProcessedBytes == 0;
|
||||||
return !m_StreamWasExhausted;
|
return !m_StreamWasExhausted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReleaseStream()
|
public void ReleaseStream()
|
||||||
{
|
{
|
||||||
// m_Stream.Close();
|
// m_Stream.Close();
|
||||||
m_Stream = null;
|
m_Stream = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ReadByte(byte b) // check it
|
public bool ReadByte(byte b) // check it
|
||||||
{
|
{
|
||||||
if (m_Pos >= m_Limit && !ReadBlock())
|
if (m_Pos >= m_Limit && !ReadBlock())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
b = m_Buffer[m_Pos++];
|
b = m_Buffer[m_Pos++];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte ReadByte()
|
public byte ReadByte()
|
||||||
{
|
{
|
||||||
// return (byte)m_Stream.ReadByte();
|
// return (byte)m_Stream.ReadByte();
|
||||||
if (m_Pos >= m_Limit && !ReadBlock())
|
if (m_Pos >= m_Limit && !ReadBlock())
|
||||||
{
|
{
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_Buffer[m_Pos++];
|
return m_Buffer[m_Pos++];
|
||||||
}
|
}
|
||||||
|
|
||||||
public ulong GetProcessedSize()
|
public ulong GetProcessedSize()
|
||||||
{
|
{
|
||||||
return m_ProcessedSize + m_Pos;
|
return m_ProcessedSize + m_Pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,52 +1,52 @@
|
|||||||
// OutBuffer.cs
|
// OutBuffer.cs
|
||||||
|
|
||||||
namespace SevenZip.Buffer
|
namespace SevenZip.Buffer
|
||||||
{
|
{
|
||||||
public class OutBuffer
|
public class OutBuffer
|
||||||
{
|
{
|
||||||
private readonly byte[] m_Buffer;
|
private readonly byte[] m_Buffer;
|
||||||
private uint m_Pos;
|
private uint m_Pos;
|
||||||
private readonly uint m_BufferSize;
|
private readonly uint m_BufferSize;
|
||||||
private System.IO.Stream m_Stream;
|
private System.IO.Stream m_Stream;
|
||||||
private ulong m_ProcessedSize;
|
private ulong m_ProcessedSize;
|
||||||
|
|
||||||
public OutBuffer(uint bufferSize)
|
public OutBuffer(uint bufferSize)
|
||||||
{
|
{
|
||||||
m_Buffer = new byte[bufferSize];
|
m_Buffer = new byte[bufferSize];
|
||||||
m_BufferSize = bufferSize;
|
m_BufferSize = bufferSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetStream(System.IO.Stream stream) { m_Stream = stream; }
|
public void SetStream(System.IO.Stream stream) { m_Stream = stream; }
|
||||||
public void FlushStream() { m_Stream.Flush(); }
|
public void FlushStream() { m_Stream.Flush(); }
|
||||||
public void CloseStream() { m_Stream.Close(); }
|
public void CloseStream() { m_Stream.Close(); }
|
||||||
public void ReleaseStream() { m_Stream = null; }
|
public void ReleaseStream() { m_Stream = null; }
|
||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
m_ProcessedSize = 0;
|
m_ProcessedSize = 0;
|
||||||
m_Pos = 0;
|
m_Pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteByte(byte b)
|
public void WriteByte(byte b)
|
||||||
{
|
{
|
||||||
m_Buffer[m_Pos++] = b;
|
m_Buffer[m_Pos++] = b;
|
||||||
if (m_Pos >= m_BufferSize)
|
if (m_Pos >= m_BufferSize)
|
||||||
{
|
{
|
||||||
FlushData();
|
FlushData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FlushData()
|
public void FlushData()
|
||||||
{
|
{
|
||||||
if (m_Pos == 0)
|
if (m_Pos == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Stream.Write(m_Buffer, 0, (int)m_Pos);
|
m_Stream.Write(m_Buffer, 0, (int)m_Pos);
|
||||||
m_Pos = 0;
|
m_Pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; }
|
public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,24 +1,24 @@
|
|||||||
// IMatchFinder.cs
|
// IMatchFinder.cs
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace SevenZip.Compression.LZ
|
namespace SevenZip.Compression.LZ
|
||||||
{
|
{
|
||||||
internal interface IInWindowStream
|
internal interface IInWindowStream
|
||||||
{
|
{
|
||||||
void SetStream(System.IO.Stream inStream);
|
void SetStream(System.IO.Stream inStream);
|
||||||
void Init();
|
void Init();
|
||||||
void ReleaseStream();
|
void ReleaseStream();
|
||||||
Byte GetIndexByte(Int32 index);
|
Byte GetIndexByte(Int32 index);
|
||||||
UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit);
|
UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit);
|
||||||
UInt32 GetNumAvailableBytes();
|
UInt32 GetNumAvailableBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal interface IMatchFinder : IInWindowStream
|
internal interface IMatchFinder : IInWindowStream
|
||||||
{
|
{
|
||||||
void Create(UInt32 historySize, UInt32 keepAddBufferBefore,
|
void Create(UInt32 historySize, UInt32 keepAddBufferBefore,
|
||||||
UInt32 matchMaxLen, UInt32 keepAddBufferAfter);
|
UInt32 matchMaxLen, UInt32 keepAddBufferAfter);
|
||||||
UInt32 GetMatches(UInt32[] distances);
|
UInt32 GetMatches(UInt32[] distances);
|
||||||
void Skip(UInt32 num);
|
void Skip(UInt32 num);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,408 +1,408 @@
|
|||||||
// LzBinTree.cs
|
// LzBinTree.cs
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace SevenZip.Compression.LZ
|
namespace SevenZip.Compression.LZ
|
||||||
{
|
{
|
||||||
public class BinTree : InWindow, IMatchFinder
|
public class BinTree : InWindow, IMatchFinder
|
||||||
{
|
{
|
||||||
private UInt32 _cyclicBufferPos;
|
private UInt32 _cyclicBufferPos;
|
||||||
private UInt32 _cyclicBufferSize = 0;
|
private UInt32 _cyclicBufferSize = 0;
|
||||||
private UInt32 _matchMaxLen;
|
private UInt32 _matchMaxLen;
|
||||||
|
|
||||||
private UInt32[] _son;
|
private UInt32[] _son;
|
||||||
private UInt32[] _hash;
|
private UInt32[] _hash;
|
||||||
|
|
||||||
private UInt32 _cutValue = 0xFF;
|
private UInt32 _cutValue = 0xFF;
|
||||||
private UInt32 _hashMask;
|
private UInt32 _hashMask;
|
||||||
private UInt32 _hashSizeSum = 0;
|
private UInt32 _hashSizeSum = 0;
|
||||||
|
|
||||||
private bool HASH_ARRAY = true;
|
private bool HASH_ARRAY = true;
|
||||||
|
|
||||||
private const UInt32 kHash2Size = 1 << 10;
|
private const UInt32 kHash2Size = 1 << 10;
|
||||||
private const UInt32 kHash3Size = 1 << 16;
|
private const UInt32 kHash3Size = 1 << 16;
|
||||||
private const UInt32 kBT2HashSize = 1 << 16;
|
private const UInt32 kBT2HashSize = 1 << 16;
|
||||||
private const UInt32 kStartMaxLen = 1;
|
private const UInt32 kStartMaxLen = 1;
|
||||||
private const UInt32 kHash3Offset = kHash2Size;
|
private const UInt32 kHash3Offset = kHash2Size;
|
||||||
private const UInt32 kEmptyHashValue = 0;
|
private const UInt32 kEmptyHashValue = 0;
|
||||||
private const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1;
|
private const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1;
|
||||||
|
|
||||||
private UInt32 kNumHashDirectBytes = 0;
|
private UInt32 kNumHashDirectBytes = 0;
|
||||||
private UInt32 kMinMatchCheck = 4;
|
private UInt32 kMinMatchCheck = 4;
|
||||||
private UInt32 kFixHashSize = kHash2Size + kHash3Size;
|
private UInt32 kFixHashSize = kHash2Size + kHash3Size;
|
||||||
|
|
||||||
public void SetType(int numHashBytes)
|
public void SetType(int numHashBytes)
|
||||||
{
|
{
|
||||||
HASH_ARRAY = numHashBytes > 2;
|
HASH_ARRAY = numHashBytes > 2;
|
||||||
if (HASH_ARRAY)
|
if (HASH_ARRAY)
|
||||||
{
|
{
|
||||||
kNumHashDirectBytes = 0;
|
kNumHashDirectBytes = 0;
|
||||||
kMinMatchCheck = 4;
|
kMinMatchCheck = 4;
|
||||||
kFixHashSize = kHash2Size + kHash3Size;
|
kFixHashSize = kHash2Size + kHash3Size;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
kNumHashDirectBytes = 2;
|
kNumHashDirectBytes = 2;
|
||||||
kMinMatchCheck = 2 + 1;
|
kMinMatchCheck = 2 + 1;
|
||||||
kFixHashSize = 0;
|
kFixHashSize = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); }
|
public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); }
|
||||||
public new void ReleaseStream() { base.ReleaseStream(); }
|
public new void ReleaseStream() { base.ReleaseStream(); }
|
||||||
|
|
||||||
public new void Init()
|
public new void Init()
|
||||||
{
|
{
|
||||||
base.Init();
|
base.Init();
|
||||||
for (UInt32 i = 0; i < _hashSizeSum; i++)
|
for (UInt32 i = 0; i < _hashSizeSum; i++)
|
||||||
{
|
{
|
||||||
_hash[i] = kEmptyHashValue;
|
_hash[i] = kEmptyHashValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
_cyclicBufferPos = 0;
|
_cyclicBufferPos = 0;
|
||||||
ReduceOffsets(-1);
|
ReduceOffsets(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public new void MovePos()
|
public new void MovePos()
|
||||||
{
|
{
|
||||||
if (++_cyclicBufferPos >= _cyclicBufferSize)
|
if (++_cyclicBufferPos >= _cyclicBufferSize)
|
||||||
{
|
{
|
||||||
_cyclicBufferPos = 0;
|
_cyclicBufferPos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
base.MovePos();
|
base.MovePos();
|
||||||
if (_pos == kMaxValForNormalize)
|
if (_pos == kMaxValForNormalize)
|
||||||
{
|
{
|
||||||
Normalize();
|
Normalize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); }
|
public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); }
|
||||||
|
|
||||||
public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
|
public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
|
||||||
{ return base.GetMatchLen(index, distance, limit); }
|
{ return base.GetMatchLen(index, distance, limit); }
|
||||||
|
|
||||||
public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); }
|
public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); }
|
||||||
|
|
||||||
public void Create(UInt32 historySize, UInt32 keepAddBufferBefore,
|
public void Create(UInt32 historySize, UInt32 keepAddBufferBefore,
|
||||||
UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
|
UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
|
||||||
{
|
{
|
||||||
if (historySize > kMaxValForNormalize - 256)
|
if (historySize > kMaxValForNormalize - 256)
|
||||||
{
|
{
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
_cutValue = 16 + (matchMaxLen >> 1);
|
_cutValue = 16 + (matchMaxLen >> 1);
|
||||||
|
|
||||||
UInt32 windowReservSize = ((historySize + keepAddBufferBefore +
|
UInt32 windowReservSize = ((historySize + keepAddBufferBefore +
|
||||||
matchMaxLen + keepAddBufferAfter) / 2) + 256;
|
matchMaxLen + keepAddBufferAfter) / 2) + 256;
|
||||||
|
|
||||||
Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize);
|
Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize);
|
||||||
|
|
||||||
_matchMaxLen = matchMaxLen;
|
_matchMaxLen = matchMaxLen;
|
||||||
|
|
||||||
UInt32 cyclicBufferSize = historySize + 1;
|
UInt32 cyclicBufferSize = historySize + 1;
|
||||||
if (_cyclicBufferSize != cyclicBufferSize)
|
if (_cyclicBufferSize != cyclicBufferSize)
|
||||||
{
|
{
|
||||||
_son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2];
|
_son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 hs = kBT2HashSize;
|
UInt32 hs = kBT2HashSize;
|
||||||
|
|
||||||
if (HASH_ARRAY)
|
if (HASH_ARRAY)
|
||||||
{
|
{
|
||||||
hs = historySize - 1;
|
hs = historySize - 1;
|
||||||
hs |= hs >> 1;
|
hs |= hs >> 1;
|
||||||
hs |= hs >> 2;
|
hs |= hs >> 2;
|
||||||
hs |= hs >> 4;
|
hs |= hs >> 4;
|
||||||
hs |= hs >> 8;
|
hs |= hs >> 8;
|
||||||
hs >>= 1;
|
hs >>= 1;
|
||||||
hs |= 0xFFFF;
|
hs |= 0xFFFF;
|
||||||
if (hs > (1 << 24))
|
if (hs > (1 << 24))
|
||||||
{
|
{
|
||||||
hs >>= 1;
|
hs >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_hashMask = hs;
|
_hashMask = hs;
|
||||||
hs++;
|
hs++;
|
||||||
hs += kFixHashSize;
|
hs += kFixHashSize;
|
||||||
}
|
}
|
||||||
if (hs != _hashSizeSum)
|
if (hs != _hashSizeSum)
|
||||||
{
|
{
|
||||||
_hash = new UInt32[_hashSizeSum = hs];
|
_hash = new UInt32[_hashSizeSum = hs];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public UInt32 GetMatches(UInt32[] distances)
|
public UInt32 GetMatches(UInt32[] distances)
|
||||||
{
|
{
|
||||||
UInt32 lenLimit;
|
UInt32 lenLimit;
|
||||||
if (_pos + _matchMaxLen <= _streamPos)
|
if (_pos + _matchMaxLen <= _streamPos)
|
||||||
{
|
{
|
||||||
lenLimit = _matchMaxLen;
|
lenLimit = _matchMaxLen;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lenLimit = _streamPos - _pos;
|
lenLimit = _streamPos - _pos;
|
||||||
if (lenLimit < kMinMatchCheck)
|
if (lenLimit < kMinMatchCheck)
|
||||||
{
|
{
|
||||||
MovePos();
|
MovePos();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 offset = 0;
|
UInt32 offset = 0;
|
||||||
UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
|
UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
|
||||||
UInt32 cur = _bufferOffset + _pos;
|
UInt32 cur = _bufferOffset + _pos;
|
||||||
UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize;
|
UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize;
|
||||||
UInt32 hashValue, hash2Value = 0, hash3Value = 0;
|
UInt32 hashValue, hash2Value = 0, hash3Value = 0;
|
||||||
|
|
||||||
if (HASH_ARRAY)
|
if (HASH_ARRAY)
|
||||||
{
|
{
|
||||||
UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];
|
UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];
|
||||||
hash2Value = temp & (kHash2Size - 1);
|
hash2Value = temp & (kHash2Size - 1);
|
||||||
temp ^= (UInt32)_bufferBase[cur + 2] << 8;
|
temp ^= (UInt32)_bufferBase[cur + 2] << 8;
|
||||||
hash3Value = temp & (kHash3Size - 1);
|
hash3Value = temp & (kHash3Size - 1);
|
||||||
hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;
|
hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hashValue = _bufferBase[cur] ^ ((UInt32)_bufferBase[cur + 1] << 8);
|
hashValue = _bufferBase[cur] ^ ((UInt32)_bufferBase[cur + 1] << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 curMatch = _hash[kFixHashSize + hashValue];
|
UInt32 curMatch = _hash[kFixHashSize + hashValue];
|
||||||
if (HASH_ARRAY)
|
if (HASH_ARRAY)
|
||||||
{
|
{
|
||||||
UInt32 curMatch2 = _hash[hash2Value];
|
UInt32 curMatch2 = _hash[hash2Value];
|
||||||
UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];
|
UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];
|
||||||
_hash[hash2Value] = _pos;
|
_hash[hash2Value] = _pos;
|
||||||
_hash[kHash3Offset + hash3Value] = _pos;
|
_hash[kHash3Offset + hash3Value] = _pos;
|
||||||
if (curMatch2 > matchMinPos && _bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur])
|
if (curMatch2 > matchMinPos && _bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur])
|
||||||
{
|
{
|
||||||
distances[offset++] = maxLen = 2;
|
distances[offset++] = maxLen = 2;
|
||||||
distances[offset++] = _pos - curMatch2 - 1;
|
distances[offset++] = _pos - curMatch2 - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curMatch3 > matchMinPos && _bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur])
|
if (curMatch3 > matchMinPos && _bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur])
|
||||||
{
|
{
|
||||||
if (curMatch3 == curMatch2)
|
if (curMatch3 == curMatch2)
|
||||||
{
|
{
|
||||||
offset -= 2;
|
offset -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
distances[offset++] = maxLen = 3;
|
distances[offset++] = maxLen = 3;
|
||||||
distances[offset++] = _pos - curMatch3 - 1;
|
distances[offset++] = _pos - curMatch3 - 1;
|
||||||
curMatch2 = curMatch3;
|
curMatch2 = curMatch3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset != 0 && curMatch2 == curMatch)
|
if (offset != 0 && curMatch2 == curMatch)
|
||||||
{
|
{
|
||||||
offset -= 2;
|
offset -= 2;
|
||||||
maxLen = kStartMaxLen;
|
maxLen = kStartMaxLen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_hash[kFixHashSize + hashValue] = _pos;
|
_hash[kFixHashSize + hashValue] = _pos;
|
||||||
|
|
||||||
UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
|
UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
|
||||||
UInt32 ptr1 = _cyclicBufferPos << 1;
|
UInt32 ptr1 = _cyclicBufferPos << 1;
|
||||||
|
|
||||||
UInt32 len0, len1;
|
UInt32 len0, len1;
|
||||||
len0 = len1 = kNumHashDirectBytes;
|
len0 = len1 = kNumHashDirectBytes;
|
||||||
|
|
||||||
if (kNumHashDirectBytes != 0 && curMatch > matchMinPos)
|
if (kNumHashDirectBytes != 0 && curMatch > matchMinPos)
|
||||||
{
|
{
|
||||||
if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] !=
|
if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] !=
|
||||||
_bufferBase[cur + kNumHashDirectBytes])
|
_bufferBase[cur + kNumHashDirectBytes])
|
||||||
{
|
{
|
||||||
distances[offset++] = maxLen = kNumHashDirectBytes;
|
distances[offset++] = maxLen = kNumHashDirectBytes;
|
||||||
distances[offset++] = _pos - curMatch - 1;
|
distances[offset++] = _pos - curMatch - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 count = _cutValue;
|
UInt32 count = _cutValue;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (curMatch <= matchMinPos || count-- == 0)
|
if (curMatch <= matchMinPos || count-- == 0)
|
||||||
{
|
{
|
||||||
_son[ptr0] = _son[ptr1] = kEmptyHashValue;
|
_son[ptr0] = _son[ptr1] = kEmptyHashValue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
UInt32 delta = _pos - curMatch;
|
UInt32 delta = _pos - curMatch;
|
||||||
UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
|
UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
|
||||||
(_cyclicBufferPos - delta) :
|
(_cyclicBufferPos - delta) :
|
||||||
(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
|
(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
|
||||||
|
|
||||||
UInt32 pby1 = _bufferOffset + curMatch;
|
UInt32 pby1 = _bufferOffset + curMatch;
|
||||||
UInt32 len = Math.Min(len0, len1);
|
UInt32 len = Math.Min(len0, len1);
|
||||||
if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
|
if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
|
||||||
{
|
{
|
||||||
while (++len != lenLimit)
|
while (++len != lenLimit)
|
||||||
{
|
{
|
||||||
if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
|
if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxLen < len)
|
if (maxLen < len)
|
||||||
{
|
{
|
||||||
distances[offset++] = maxLen = len;
|
distances[offset++] = maxLen = len;
|
||||||
distances[offset++] = delta - 1;
|
distances[offset++] = delta - 1;
|
||||||
if (len == lenLimit)
|
if (len == lenLimit)
|
||||||
{
|
{
|
||||||
_son[ptr1] = _son[cyclicPos];
|
_son[ptr1] = _son[cyclicPos];
|
||||||
_son[ptr0] = _son[cyclicPos + 1];
|
_son[ptr0] = _son[cyclicPos + 1];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
|
if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
|
||||||
{
|
{
|
||||||
_son[ptr1] = curMatch;
|
_son[ptr1] = curMatch;
|
||||||
ptr1 = cyclicPos + 1;
|
ptr1 = cyclicPos + 1;
|
||||||
curMatch = _son[ptr1];
|
curMatch = _son[ptr1];
|
||||||
len1 = len;
|
len1 = len;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_son[ptr0] = curMatch;
|
_son[ptr0] = curMatch;
|
||||||
ptr0 = cyclicPos;
|
ptr0 = cyclicPos;
|
||||||
curMatch = _son[ptr0];
|
curMatch = _son[ptr0];
|
||||||
len0 = len;
|
len0 = len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MovePos();
|
MovePos();
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Skip(UInt32 num)
|
public void Skip(UInt32 num)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
UInt32 lenLimit;
|
UInt32 lenLimit;
|
||||||
if (_pos + _matchMaxLen <= _streamPos)
|
if (_pos + _matchMaxLen <= _streamPos)
|
||||||
{
|
{
|
||||||
lenLimit = _matchMaxLen;
|
lenLimit = _matchMaxLen;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lenLimit = _streamPos - _pos;
|
lenLimit = _streamPos - _pos;
|
||||||
if (lenLimit < kMinMatchCheck)
|
if (lenLimit < kMinMatchCheck)
|
||||||
{
|
{
|
||||||
MovePos();
|
MovePos();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
|
UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
|
||||||
UInt32 cur = _bufferOffset + _pos;
|
UInt32 cur = _bufferOffset + _pos;
|
||||||
|
|
||||||
UInt32 hashValue;
|
UInt32 hashValue;
|
||||||
|
|
||||||
if (HASH_ARRAY)
|
if (HASH_ARRAY)
|
||||||
{
|
{
|
||||||
UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];
|
UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];
|
||||||
UInt32 hash2Value = temp & (kHash2Size - 1);
|
UInt32 hash2Value = temp & (kHash2Size - 1);
|
||||||
_hash[hash2Value] = _pos;
|
_hash[hash2Value] = _pos;
|
||||||
temp ^= (UInt32)_bufferBase[cur + 2] << 8;
|
temp ^= (UInt32)_bufferBase[cur + 2] << 8;
|
||||||
UInt32 hash3Value = temp & (kHash3Size - 1);
|
UInt32 hash3Value = temp & (kHash3Size - 1);
|
||||||
_hash[kHash3Offset + hash3Value] = _pos;
|
_hash[kHash3Offset + hash3Value] = _pos;
|
||||||
hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;
|
hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hashValue = _bufferBase[cur] ^ ((UInt32)_bufferBase[cur + 1] << 8);
|
hashValue = _bufferBase[cur] ^ ((UInt32)_bufferBase[cur + 1] << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 curMatch = _hash[kFixHashSize + hashValue];
|
UInt32 curMatch = _hash[kFixHashSize + hashValue];
|
||||||
_hash[kFixHashSize + hashValue] = _pos;
|
_hash[kFixHashSize + hashValue] = _pos;
|
||||||
|
|
||||||
UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
|
UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
|
||||||
UInt32 ptr1 = _cyclicBufferPos << 1;
|
UInt32 ptr1 = _cyclicBufferPos << 1;
|
||||||
|
|
||||||
UInt32 len0, len1;
|
UInt32 len0, len1;
|
||||||
len0 = len1 = kNumHashDirectBytes;
|
len0 = len1 = kNumHashDirectBytes;
|
||||||
|
|
||||||
UInt32 count = _cutValue;
|
UInt32 count = _cutValue;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (curMatch <= matchMinPos || count-- == 0)
|
if (curMatch <= matchMinPos || count-- == 0)
|
||||||
{
|
{
|
||||||
_son[ptr0] = _son[ptr1] = kEmptyHashValue;
|
_son[ptr0] = _son[ptr1] = kEmptyHashValue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 delta = _pos - curMatch;
|
UInt32 delta = _pos - curMatch;
|
||||||
UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
|
UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
|
||||||
(_cyclicBufferPos - delta) :
|
(_cyclicBufferPos - delta) :
|
||||||
(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
|
(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
|
||||||
|
|
||||||
UInt32 pby1 = _bufferOffset + curMatch;
|
UInt32 pby1 = _bufferOffset + curMatch;
|
||||||
UInt32 len = Math.Min(len0, len1);
|
UInt32 len = Math.Min(len0, len1);
|
||||||
if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
|
if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
|
||||||
{
|
{
|
||||||
while (++len != lenLimit)
|
while (++len != lenLimit)
|
||||||
{
|
{
|
||||||
if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
|
if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len == lenLimit)
|
if (len == lenLimit)
|
||||||
{
|
{
|
||||||
_son[ptr1] = _son[cyclicPos];
|
_son[ptr1] = _son[cyclicPos];
|
||||||
_son[ptr0] = _son[cyclicPos + 1];
|
_son[ptr0] = _son[cyclicPos + 1];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
|
if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
|
||||||
{
|
{
|
||||||
_son[ptr1] = curMatch;
|
_son[ptr1] = curMatch;
|
||||||
ptr1 = cyclicPos + 1;
|
ptr1 = cyclicPos + 1;
|
||||||
curMatch = _son[ptr1];
|
curMatch = _son[ptr1];
|
||||||
len1 = len;
|
len1 = len;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_son[ptr0] = curMatch;
|
_son[ptr0] = curMatch;
|
||||||
ptr0 = cyclicPos;
|
ptr0 = cyclicPos;
|
||||||
curMatch = _son[ptr0];
|
curMatch = _son[ptr0];
|
||||||
len0 = len;
|
len0 = len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MovePos();
|
MovePos();
|
||||||
}
|
}
|
||||||
while (--num != 0);
|
while (--num != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue)
|
private void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue)
|
||||||
{
|
{
|
||||||
for (UInt32 i = 0; i < numItems; i++)
|
for (UInt32 i = 0; i < numItems; i++)
|
||||||
{
|
{
|
||||||
UInt32 value = items[i];
|
UInt32 value = items[i];
|
||||||
if (value <= subValue)
|
if (value <= subValue)
|
||||||
{
|
{
|
||||||
value = kEmptyHashValue;
|
value = kEmptyHashValue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
value -= subValue;
|
value -= subValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
items[i] = value;
|
items[i] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Normalize()
|
private void Normalize()
|
||||||
{
|
{
|
||||||
UInt32 subValue = _pos - _cyclicBufferSize;
|
UInt32 subValue = _pos - _cyclicBufferSize;
|
||||||
NormalizeLinks(_son, _cyclicBufferSize * 2, subValue);
|
NormalizeLinks(_son, _cyclicBufferSize * 2, subValue);
|
||||||
NormalizeLinks(_hash, _hashSizeSum, subValue);
|
NormalizeLinks(_hash, _hashSizeSum, subValue);
|
||||||
ReduceOffsets((Int32)subValue);
|
ReduceOffsets((Int32)subValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; }
|
public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,155 +1,155 @@
|
|||||||
// LzInWindow.cs
|
// LzInWindow.cs
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace SevenZip.Compression.LZ
|
namespace SevenZip.Compression.LZ
|
||||||
{
|
{
|
||||||
public class InWindow
|
public class InWindow
|
||||||
{
|
{
|
||||||
public Byte[] _bufferBase = null; // pointer to buffer with data
|
public Byte[] _bufferBase = null; // pointer to buffer with data
|
||||||
private System.IO.Stream _stream;
|
private System.IO.Stream _stream;
|
||||||
private UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done
|
private UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done
|
||||||
private bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream
|
private bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream
|
||||||
|
|
||||||
private UInt32 _pointerToLastSafePosition;
|
private UInt32 _pointerToLastSafePosition;
|
||||||
|
|
||||||
public UInt32 _bufferOffset;
|
public UInt32 _bufferOffset;
|
||||||
|
|
||||||
public UInt32 _blockSize; // Size of Allocated memory block
|
public UInt32 _blockSize; // Size of Allocated memory block
|
||||||
public UInt32 _pos; // offset (from _buffer) of curent byte
|
public UInt32 _pos; // offset (from _buffer) of curent byte
|
||||||
private UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos
|
private UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos
|
||||||
private UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos
|
private UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos
|
||||||
public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream
|
public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream
|
||||||
|
|
||||||
public void MoveBlock()
|
public void MoveBlock()
|
||||||
{
|
{
|
||||||
UInt32 offset = _bufferOffset + _pos - _keepSizeBefore;
|
UInt32 offset = _bufferOffset + _pos - _keepSizeBefore;
|
||||||
// we need one additional byte, since MovePos moves on 1 byte.
|
// we need one additional byte, since MovePos moves on 1 byte.
|
||||||
if (offset > 0)
|
if (offset > 0)
|
||||||
{
|
{
|
||||||
offset--;
|
offset--;
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 numBytes = _bufferOffset + _streamPos - offset;
|
UInt32 numBytes = _bufferOffset + _streamPos - offset;
|
||||||
|
|
||||||
// check negative offset ????
|
// check negative offset ????
|
||||||
for (UInt32 i = 0; i < numBytes; i++)
|
for (UInt32 i = 0; i < numBytes; i++)
|
||||||
{
|
{
|
||||||
_bufferBase[i] = _bufferBase[offset + i];
|
_bufferBase[i] = _bufferBase[offset + i];
|
||||||
}
|
}
|
||||||
|
|
||||||
_bufferOffset -= offset;
|
_bufferOffset -= offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void ReadBlock()
|
public virtual void ReadBlock()
|
||||||
{
|
{
|
||||||
if (_streamEndWasReached)
|
if (_streamEndWasReached)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
int size = (int)(0 - _bufferOffset + _blockSize - _streamPos);
|
int size = (int)(0 - _bufferOffset + _blockSize - _streamPos);
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size);
|
int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size);
|
||||||
if (numReadBytes == 0)
|
if (numReadBytes == 0)
|
||||||
{
|
{
|
||||||
_posLimit = _streamPos;
|
_posLimit = _streamPos;
|
||||||
UInt32 pointerToPostion = _bufferOffset + _posLimit;
|
UInt32 pointerToPostion = _bufferOffset + _posLimit;
|
||||||
if (pointerToPostion > _pointerToLastSafePosition)
|
if (pointerToPostion > _pointerToLastSafePosition)
|
||||||
{
|
{
|
||||||
_posLimit = _pointerToLastSafePosition - _bufferOffset;
|
_posLimit = _pointerToLastSafePosition - _bufferOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
_streamEndWasReached = true;
|
_streamEndWasReached = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_streamPos += (UInt32)numReadBytes;
|
_streamPos += (UInt32)numReadBytes;
|
||||||
if (_streamPos >= _pos + _keepSizeAfter)
|
if (_streamPos >= _pos + _keepSizeAfter)
|
||||||
{
|
{
|
||||||
_posLimit = _streamPos - _keepSizeAfter;
|
_posLimit = _streamPos - _keepSizeAfter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Free() { _bufferBase = null; }
|
private void Free() { _bufferBase = null; }
|
||||||
|
|
||||||
public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv)
|
public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv)
|
||||||
{
|
{
|
||||||
_keepSizeBefore = keepSizeBefore;
|
_keepSizeBefore = keepSizeBefore;
|
||||||
_keepSizeAfter = keepSizeAfter;
|
_keepSizeAfter = keepSizeAfter;
|
||||||
UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;
|
UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;
|
||||||
if (_bufferBase == null || _blockSize != blockSize)
|
if (_bufferBase == null || _blockSize != blockSize)
|
||||||
{
|
{
|
||||||
Free();
|
Free();
|
||||||
_blockSize = blockSize;
|
_blockSize = blockSize;
|
||||||
_bufferBase = new Byte[_blockSize];
|
_bufferBase = new Byte[_blockSize];
|
||||||
}
|
}
|
||||||
_pointerToLastSafePosition = _blockSize - keepSizeAfter;
|
_pointerToLastSafePosition = _blockSize - keepSizeAfter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetStream(System.IO.Stream stream) { _stream = stream; }
|
public void SetStream(System.IO.Stream stream) { _stream = stream; }
|
||||||
public void ReleaseStream() { _stream = null; }
|
public void ReleaseStream() { _stream = null; }
|
||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
_bufferOffset = 0;
|
_bufferOffset = 0;
|
||||||
_pos = 0;
|
_pos = 0;
|
||||||
_streamPos = 0;
|
_streamPos = 0;
|
||||||
_streamEndWasReached = false;
|
_streamEndWasReached = false;
|
||||||
ReadBlock();
|
ReadBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MovePos()
|
public void MovePos()
|
||||||
{
|
{
|
||||||
_pos++;
|
_pos++;
|
||||||
if (_pos > _posLimit)
|
if (_pos > _posLimit)
|
||||||
{
|
{
|
||||||
UInt32 pointerToPostion = _bufferOffset + _pos;
|
UInt32 pointerToPostion = _bufferOffset + _pos;
|
||||||
if (pointerToPostion > _pointerToLastSafePosition)
|
if (pointerToPostion > _pointerToLastSafePosition)
|
||||||
{
|
{
|
||||||
MoveBlock();
|
MoveBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadBlock();
|
ReadBlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; }
|
public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; }
|
||||||
|
|
||||||
// index + limit have not to exceed _keepSizeAfter;
|
// index + limit have not to exceed _keepSizeAfter;
|
||||||
public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
|
public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
|
||||||
{
|
{
|
||||||
if (_streamEndWasReached && _pos + index + limit > _streamPos)
|
if (_streamEndWasReached && _pos + index + limit > _streamPos)
|
||||||
{
|
{
|
||||||
limit = _streamPos - (UInt32)(_pos + index);
|
limit = _streamPos - (UInt32)(_pos + index);
|
||||||
}
|
}
|
||||||
|
|
||||||
distance++;
|
distance++;
|
||||||
// Byte *pby = _buffer + (size_t)_pos + index;
|
// Byte *pby = _buffer + (size_t)_pos + index;
|
||||||
UInt32 pby = _bufferOffset + _pos + (UInt32)index;
|
UInt32 pby = _bufferOffset + _pos + (UInt32)index;
|
||||||
|
|
||||||
UInt32 i;
|
UInt32 i;
|
||||||
for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++)
|
for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; }
|
public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; }
|
||||||
|
|
||||||
public void ReduceOffsets(Int32 subValue)
|
public void ReduceOffsets(Int32 subValue)
|
||||||
{
|
{
|
||||||
_bufferOffset += (UInt32)subValue;
|
_bufferOffset += (UInt32)subValue;
|
||||||
_posLimit -= (UInt32)subValue;
|
_posLimit -= (UInt32)subValue;
|
||||||
_pos -= (UInt32)subValue;
|
_pos -= (UInt32)subValue;
|
||||||
_streamPos -= (UInt32)subValue;
|
_streamPos -= (UInt32)subValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,137 +1,137 @@
|
|||||||
// LzOutWindow.cs
|
// LzOutWindow.cs
|
||||||
|
|
||||||
namespace SevenZip.Compression.LZ
|
namespace SevenZip.Compression.LZ
|
||||||
{
|
{
|
||||||
public class OutWindow
|
public class OutWindow
|
||||||
{
|
{
|
||||||
private byte[] _buffer = null;
|
private byte[] _buffer = null;
|
||||||
private uint _pos;
|
private uint _pos;
|
||||||
private uint _windowSize = 0;
|
private uint _windowSize = 0;
|
||||||
private uint _streamPos;
|
private uint _streamPos;
|
||||||
private System.IO.Stream _stream;
|
private System.IO.Stream _stream;
|
||||||
|
|
||||||
public uint TrainSize = 0;
|
public uint TrainSize = 0;
|
||||||
|
|
||||||
public void Create(uint windowSize)
|
public void Create(uint windowSize)
|
||||||
{
|
{
|
||||||
if (_windowSize != windowSize)
|
if (_windowSize != windowSize)
|
||||||
{
|
{
|
||||||
// System.GC.Collect();
|
// System.GC.Collect();
|
||||||
_buffer = new byte[windowSize];
|
_buffer = new byte[windowSize];
|
||||||
}
|
}
|
||||||
_windowSize = windowSize;
|
_windowSize = windowSize;
|
||||||
_pos = 0;
|
_pos = 0;
|
||||||
_streamPos = 0;
|
_streamPos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init(System.IO.Stream stream, bool solid)
|
public void Init(System.IO.Stream stream, bool solid)
|
||||||
{
|
{
|
||||||
ReleaseStream();
|
ReleaseStream();
|
||||||
_stream = stream;
|
_stream = stream;
|
||||||
if (!solid)
|
if (!solid)
|
||||||
{
|
{
|
||||||
_streamPos = 0;
|
_streamPos = 0;
|
||||||
_pos = 0;
|
_pos = 0;
|
||||||
TrainSize = 0;
|
TrainSize = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Train(System.IO.Stream stream)
|
public bool Train(System.IO.Stream stream)
|
||||||
{
|
{
|
||||||
long len = stream.Length;
|
long len = stream.Length;
|
||||||
uint size = (len < _windowSize) ? (uint)len : _windowSize;
|
uint size = (len < _windowSize) ? (uint)len : _windowSize;
|
||||||
TrainSize = size;
|
TrainSize = size;
|
||||||
stream.Position = len - size;
|
stream.Position = len - size;
|
||||||
_streamPos = _pos = 0;
|
_streamPos = _pos = 0;
|
||||||
while (size > 0)
|
while (size > 0)
|
||||||
{
|
{
|
||||||
uint curSize = _windowSize - _pos;
|
uint curSize = _windowSize - _pos;
|
||||||
if (size < curSize)
|
if (size < curSize)
|
||||||
{
|
{
|
||||||
curSize = size;
|
curSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize);
|
int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize);
|
||||||
if (numReadBytes == 0)
|
if (numReadBytes == 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size -= (uint)numReadBytes;
|
size -= (uint)numReadBytes;
|
||||||
_pos += (uint)numReadBytes;
|
_pos += (uint)numReadBytes;
|
||||||
_streamPos += (uint)numReadBytes;
|
_streamPos += (uint)numReadBytes;
|
||||||
if (_pos == _windowSize)
|
if (_pos == _windowSize)
|
||||||
{
|
{
|
||||||
_streamPos = _pos = 0;
|
_streamPos = _pos = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReleaseStream()
|
public void ReleaseStream()
|
||||||
{
|
{
|
||||||
Flush();
|
Flush();
|
||||||
_stream = null;
|
_stream = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Flush()
|
public void Flush()
|
||||||
{
|
{
|
||||||
uint size = _pos - _streamPos;
|
uint size = _pos - _streamPos;
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_stream.Write(_buffer, (int)_streamPos, (int)size);
|
_stream.Write(_buffer, (int)_streamPos, (int)size);
|
||||||
if (_pos >= _windowSize)
|
if (_pos >= _windowSize)
|
||||||
{
|
{
|
||||||
_pos = 0;
|
_pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_streamPos = _pos;
|
_streamPos = _pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CopyBlock(uint distance, uint len)
|
public void CopyBlock(uint distance, uint len)
|
||||||
{
|
{
|
||||||
uint pos = _pos - distance - 1;
|
uint pos = _pos - distance - 1;
|
||||||
if (pos >= _windowSize)
|
if (pos >= _windowSize)
|
||||||
{
|
{
|
||||||
pos += _windowSize;
|
pos += _windowSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; len > 0; len--)
|
for (; len > 0; len--)
|
||||||
{
|
{
|
||||||
if (pos >= _windowSize)
|
if (pos >= _windowSize)
|
||||||
{
|
{
|
||||||
pos = 0;
|
pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_buffer[_pos++] = _buffer[pos++];
|
_buffer[_pos++] = _buffer[pos++];
|
||||||
if (_pos >= _windowSize)
|
if (_pos >= _windowSize)
|
||||||
{
|
{
|
||||||
Flush();
|
Flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PutByte(byte b)
|
public void PutByte(byte b)
|
||||||
{
|
{
|
||||||
_buffer[_pos++] = b;
|
_buffer[_pos++] = b;
|
||||||
if (_pos >= _windowSize)
|
if (_pos >= _windowSize)
|
||||||
{
|
{
|
||||||
Flush();
|
Flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte GetByte(uint distance)
|
public byte GetByte(uint distance)
|
||||||
{
|
{
|
||||||
uint pos = _pos - distance - 1;
|
uint pos = _pos - distance - 1;
|
||||||
if (pos >= _windowSize)
|
if (pos >= _windowSize)
|
||||||
{
|
{
|
||||||
pos += _windowSize;
|
pos += _windowSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _buffer[pos];
|
return _buffer[pos];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,88 +1,88 @@
|
|||||||
// LzmaBase.cs
|
// LzmaBase.cs
|
||||||
|
|
||||||
namespace SevenZip.Compression.LZMA
|
namespace SevenZip.Compression.LZMA
|
||||||
{
|
{
|
||||||
internal abstract class Base
|
internal abstract class Base
|
||||||
{
|
{
|
||||||
public const uint kNumRepDistances = 4;
|
public const uint kNumRepDistances = 4;
|
||||||
public const uint kNumStates = 12;
|
public const uint kNumStates = 12;
|
||||||
|
|
||||||
// static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
|
// static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
|
||||||
// static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
|
// static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
|
||||||
// static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
|
// static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
|
||||||
// static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
|
// static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
|
||||||
|
|
||||||
public struct State
|
public struct State
|
||||||
{
|
{
|
||||||
public uint Index;
|
public uint Index;
|
||||||
public void Init() { Index = 0; }
|
public void Init() { Index = 0; }
|
||||||
public void UpdateChar()
|
public void UpdateChar()
|
||||||
{
|
{
|
||||||
if (Index < 4)
|
if (Index < 4)
|
||||||
{
|
{
|
||||||
Index = 0;
|
Index = 0;
|
||||||
}
|
}
|
||||||
else if (Index < 10)
|
else if (Index < 10)
|
||||||
{
|
{
|
||||||
Index -= 3;
|
Index -= 3;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Index -= 6;
|
Index -= 6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); }
|
public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); }
|
||||||
public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); }
|
public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); }
|
||||||
public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); }
|
public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); }
|
||||||
public bool IsCharState() { return Index < 7; }
|
public bool IsCharState() { return Index < 7; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public const int kNumPosSlotBits = 6;
|
public const int kNumPosSlotBits = 6;
|
||||||
public const int kDicLogSizeMin = 0;
|
public const int kDicLogSizeMin = 0;
|
||||||
// public const int kDicLogSizeMax = 30;
|
// public const int kDicLogSizeMax = 30;
|
||||||
// public const uint kDistTableSizeMax = kDicLogSizeMax * 2;
|
// public const uint kDistTableSizeMax = kDicLogSizeMax * 2;
|
||||||
|
|
||||||
public const int kNumLenToPosStatesBits = 2; // it's for speed optimization
|
public const int kNumLenToPosStatesBits = 2; // it's for speed optimization
|
||||||
public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits;
|
public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits;
|
||||||
|
|
||||||
public const uint kMatchMinLen = 2;
|
public const uint kMatchMinLen = 2;
|
||||||
|
|
||||||
public static uint GetLenToPosState(uint len)
|
public static uint GetLenToPosState(uint len)
|
||||||
{
|
{
|
||||||
len -= kMatchMinLen;
|
len -= kMatchMinLen;
|
||||||
if (len < kNumLenToPosStates)
|
if (len < kNumLenToPosStates)
|
||||||
{
|
{
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
return kNumLenToPosStates - 1;
|
return kNumLenToPosStates - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public const int kNumAlignBits = 4;
|
public const int kNumAlignBits = 4;
|
||||||
public const uint kAlignTableSize = 1 << kNumAlignBits;
|
public const uint kAlignTableSize = 1 << kNumAlignBits;
|
||||||
public const uint kAlignMask = kAlignTableSize - 1;
|
public const uint kAlignMask = kAlignTableSize - 1;
|
||||||
|
|
||||||
public const uint kStartPosModelIndex = 4;
|
public const uint kStartPosModelIndex = 4;
|
||||||
public const uint kEndPosModelIndex = 14;
|
public const uint kEndPosModelIndex = 14;
|
||||||
public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;
|
public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;
|
||||||
|
|
||||||
public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2);
|
public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2);
|
||||||
|
|
||||||
public const uint kNumLitPosStatesBitsEncodingMax = 4;
|
public const uint kNumLitPosStatesBitsEncodingMax = 4;
|
||||||
public const uint kNumLitContextBitsMax = 8;
|
public const uint kNumLitContextBitsMax = 8;
|
||||||
|
|
||||||
public const int kNumPosStatesBitsMax = 4;
|
public const int kNumPosStatesBitsMax = 4;
|
||||||
public const uint kNumPosStatesMax = 1 << kNumPosStatesBitsMax;
|
public const uint kNumPosStatesMax = 1 << kNumPosStatesBitsMax;
|
||||||
public const int kNumPosStatesBitsEncodingMax = 4;
|
public const int kNumPosStatesBitsEncodingMax = 4;
|
||||||
public const uint kNumPosStatesEncodingMax = 1 << kNumPosStatesBitsEncodingMax;
|
public const uint kNumPosStatesEncodingMax = 1 << kNumPosStatesBitsEncodingMax;
|
||||||
|
|
||||||
public const int kNumLowLenBits = 3;
|
public const int kNumLowLenBits = 3;
|
||||||
public const int kNumMidLenBits = 3;
|
public const int kNumMidLenBits = 3;
|
||||||
public const int kNumHighLenBits = 8;
|
public const int kNumHighLenBits = 8;
|
||||||
public const uint kNumLowLenSymbols = 1 << kNumLowLenBits;
|
public const uint kNumLowLenSymbols = 1 << kNumLowLenBits;
|
||||||
public const uint kNumMidLenSymbols = 1 << kNumMidLenBits;
|
public const uint kNumMidLenSymbols = 1 << kNumMidLenBits;
|
||||||
public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols +
|
public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols +
|
||||||
(1 << kNumHighLenBits);
|
(1 << kNumHighLenBits);
|
||||||
public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1;
|
public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,465 +1,465 @@
|
|||||||
// LzmaDecoder.cs
|
// LzmaDecoder.cs
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace SevenZip.Compression.LZMA
|
namespace SevenZip.Compression.LZMA
|
||||||
{
|
{
|
||||||
using RangeCoder;
|
using RangeCoder;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream
|
public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream
|
||||||
{
|
{
|
||||||
private class LenDecoder
|
private class LenDecoder
|
||||||
{
|
{
|
||||||
private BitDecoder m_Choice = new();
|
private BitDecoder m_Choice = new();
|
||||||
private BitDecoder m_Choice2 = new();
|
private BitDecoder m_Choice2 = new();
|
||||||
private readonly BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
|
private readonly BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
|
||||||
private readonly BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
|
private readonly BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
|
||||||
private readonly BitTreeDecoder m_HighCoder = new(Base.kNumHighLenBits);
|
private readonly BitTreeDecoder m_HighCoder = new(Base.kNumHighLenBits);
|
||||||
private uint m_NumPosStates = 0;
|
private uint m_NumPosStates = 0;
|
||||||
|
|
||||||
public void Create(uint numPosStates)
|
public void Create(uint numPosStates)
|
||||||
{
|
{
|
||||||
for (uint posState = m_NumPosStates; posState < numPosStates; posState++)
|
for (uint posState = m_NumPosStates; posState < numPosStates; posState++)
|
||||||
{
|
{
|
||||||
m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits);
|
m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits);
|
||||||
m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits);
|
m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits);
|
||||||
}
|
}
|
||||||
m_NumPosStates = numPosStates;
|
m_NumPosStates = numPosStates;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
m_Choice.Init();
|
m_Choice.Init();
|
||||||
for (uint posState = 0; posState < m_NumPosStates; posState++)
|
for (uint posState = 0; posState < m_NumPosStates; posState++)
|
||||||
{
|
{
|
||||||
m_LowCoder[posState].Init();
|
m_LowCoder[posState].Init();
|
||||||
m_MidCoder[posState].Init();
|
m_MidCoder[posState].Init();
|
||||||
}
|
}
|
||||||
m_Choice2.Init();
|
m_Choice2.Init();
|
||||||
m_HighCoder.Init();
|
m_HighCoder.Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState)
|
public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState)
|
||||||
{
|
{
|
||||||
if (m_Choice.Decode(rangeDecoder) == 0)
|
if (m_Choice.Decode(rangeDecoder) == 0)
|
||||||
{
|
{
|
||||||
return m_LowCoder[posState].Decode(rangeDecoder);
|
return m_LowCoder[posState].Decode(rangeDecoder);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint symbol = Base.kNumLowLenSymbols;
|
uint symbol = Base.kNumLowLenSymbols;
|
||||||
if (m_Choice2.Decode(rangeDecoder) == 0)
|
if (m_Choice2.Decode(rangeDecoder) == 0)
|
||||||
{
|
{
|
||||||
symbol += m_MidCoder[posState].Decode(rangeDecoder);
|
symbol += m_MidCoder[posState].Decode(rangeDecoder);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
symbol += Base.kNumMidLenSymbols;
|
symbol += Base.kNumMidLenSymbols;
|
||||||
symbol += m_HighCoder.Decode(rangeDecoder);
|
symbol += m_HighCoder.Decode(rangeDecoder);
|
||||||
}
|
}
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LiteralDecoder
|
private class LiteralDecoder
|
||||||
{
|
{
|
||||||
private struct Decoder2
|
private struct Decoder2
|
||||||
{
|
{
|
||||||
private BitDecoder[] m_Decoders;
|
private BitDecoder[] m_Decoders;
|
||||||
public void Create() { m_Decoders = new BitDecoder[0x300]; }
|
public void Create() { m_Decoders = new BitDecoder[0x300]; }
|
||||||
public void Init() { for (int i = 0; i < 0x300; i++)
|
public void Init() { for (int i = 0; i < 0x300; i++)
|
||||||
{
|
{
|
||||||
m_Decoders[i].Init();
|
m_Decoders[i].Init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte DecodeNormal(RangeCoder.Decoder rangeDecoder)
|
public byte DecodeNormal(RangeCoder.Decoder rangeDecoder)
|
||||||
{
|
{
|
||||||
uint symbol = 1;
|
uint symbol = 1;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
|
symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
|
||||||
}
|
}
|
||||||
while (symbol < 0x100);
|
while (symbol < 0x100);
|
||||||
return (byte)symbol;
|
return (byte)symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte)
|
public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte)
|
||||||
{
|
{
|
||||||
uint symbol = 1;
|
uint symbol = 1;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
uint matchBit = (uint)(matchByte >> 7) & 1;
|
uint matchBit = (uint)(matchByte >> 7) & 1;
|
||||||
matchByte <<= 1;
|
matchByte <<= 1;
|
||||||
uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder);
|
uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder);
|
||||||
symbol = (symbol << 1) | bit;
|
symbol = (symbol << 1) | bit;
|
||||||
if (matchBit != bit)
|
if (matchBit != bit)
|
||||||
{
|
{
|
||||||
while (symbol < 0x100)
|
while (symbol < 0x100)
|
||||||
{
|
{
|
||||||
symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
|
symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (symbol < 0x100);
|
while (symbol < 0x100);
|
||||||
return (byte)symbol;
|
return (byte)symbol;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Decoder2[] m_Coders;
|
private Decoder2[] m_Coders;
|
||||||
private int m_NumPrevBits;
|
private int m_NumPrevBits;
|
||||||
private int m_NumPosBits;
|
private int m_NumPosBits;
|
||||||
private uint m_PosMask;
|
private uint m_PosMask;
|
||||||
|
|
||||||
public void Create(int numPosBits, int numPrevBits)
|
public void Create(int numPosBits, int numPrevBits)
|
||||||
{
|
{
|
||||||
if (m_Coders != null && m_NumPrevBits == numPrevBits &&
|
if (m_Coders != null && m_NumPrevBits == numPrevBits &&
|
||||||
m_NumPosBits == numPosBits)
|
m_NumPosBits == numPosBits)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_NumPosBits = numPosBits;
|
m_NumPosBits = numPosBits;
|
||||||
m_PosMask = ((uint)1 << numPosBits) - 1;
|
m_PosMask = ((uint)1 << numPosBits) - 1;
|
||||||
m_NumPrevBits = numPrevBits;
|
m_NumPrevBits = numPrevBits;
|
||||||
uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
|
uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
|
||||||
m_Coders = new Decoder2[numStates];
|
m_Coders = new Decoder2[numStates];
|
||||||
for (uint i = 0; i < numStates; i++)
|
for (uint i = 0; i < numStates; i++)
|
||||||
{
|
{
|
||||||
m_Coders[i].Create();
|
m_Coders[i].Create();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
|
uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
|
||||||
for (uint i = 0; i < numStates; i++)
|
for (uint i = 0; i < numStates; i++)
|
||||||
{
|
{
|
||||||
m_Coders[i].Init();
|
m_Coders[i].Init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private uint GetState(uint pos, byte prevByte)
|
private uint GetState(uint pos, byte prevByte)
|
||||||
{ return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); }
|
{ return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); }
|
||||||
|
|
||||||
public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte)
|
public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte)
|
||||||
{ return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); }
|
{ return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); }
|
||||||
|
|
||||||
public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte)
|
public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte)
|
||||||
{ return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); }
|
{ return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); }
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly LZ.OutWindow m_OutWindow = new();
|
private readonly LZ.OutWindow m_OutWindow = new();
|
||||||
private readonly RangeCoder.Decoder m_RangeDecoder = new();
|
private readonly RangeCoder.Decoder m_RangeDecoder = new();
|
||||||
|
|
||||||
private readonly BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
|
private readonly BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
|
||||||
private readonly BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates];
|
private readonly BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates];
|
||||||
private readonly BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates];
|
private readonly BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates];
|
||||||
private readonly BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates];
|
private readonly BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates];
|
||||||
private readonly BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates];
|
private readonly BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates];
|
||||||
private readonly BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
|
private readonly BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
|
||||||
|
|
||||||
private readonly BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates];
|
private readonly BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates];
|
||||||
private readonly BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex];
|
private readonly BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex];
|
||||||
|
|
||||||
private readonly BitTreeDecoder m_PosAlignDecoder = new(Base.kNumAlignBits);
|
private readonly BitTreeDecoder m_PosAlignDecoder = new(Base.kNumAlignBits);
|
||||||
|
|
||||||
private readonly LenDecoder m_LenDecoder = new();
|
private readonly LenDecoder m_LenDecoder = new();
|
||||||
private readonly LenDecoder m_RepLenDecoder = new();
|
private readonly LenDecoder m_RepLenDecoder = new();
|
||||||
|
|
||||||
private readonly LiteralDecoder m_LiteralDecoder = new();
|
private readonly LiteralDecoder m_LiteralDecoder = new();
|
||||||
|
|
||||||
private uint m_DictionarySize;
|
private uint m_DictionarySize;
|
||||||
private uint m_DictionarySizeCheck;
|
private uint m_DictionarySizeCheck;
|
||||||
|
|
||||||
private uint m_PosStateMask;
|
private uint m_PosStateMask;
|
||||||
|
|
||||||
public Decoder()
|
public Decoder()
|
||||||
{
|
{
|
||||||
m_DictionarySize = 0xFFFFFFFF;
|
m_DictionarySize = 0xFFFFFFFF;
|
||||||
for (int i = 0; i < Base.kNumLenToPosStates; i++)
|
for (int i = 0; i < Base.kNumLenToPosStates; i++)
|
||||||
{
|
{
|
||||||
m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits);
|
m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetDictionarySize(uint dictionarySize)
|
private void SetDictionarySize(uint dictionarySize)
|
||||||
{
|
{
|
||||||
if (m_DictionarySize != dictionarySize)
|
if (m_DictionarySize != dictionarySize)
|
||||||
{
|
{
|
||||||
m_DictionarySize = dictionarySize;
|
m_DictionarySize = dictionarySize;
|
||||||
m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1);
|
m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1);
|
||||||
uint blockSize = Math.Max(m_DictionarySizeCheck, 1 << 12);
|
uint blockSize = Math.Max(m_DictionarySizeCheck, 1 << 12);
|
||||||
m_OutWindow.Create(blockSize);
|
m_OutWindow.Create(blockSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetLiteralProperties(int lp, int lc)
|
private void SetLiteralProperties(int lp, int lc)
|
||||||
{
|
{
|
||||||
if (lp > 8)
|
if (lp > 8)
|
||||||
{
|
{
|
||||||
throw new InvalidParamException();
|
throw new InvalidParamException();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lc > 8)
|
if (lc > 8)
|
||||||
{
|
{
|
||||||
throw new InvalidParamException();
|
throw new InvalidParamException();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_LiteralDecoder.Create(lp, lc);
|
m_LiteralDecoder.Create(lp, lc);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetPosBitsProperties(int pb)
|
private void SetPosBitsProperties(int pb)
|
||||||
{
|
{
|
||||||
if (pb > Base.kNumPosStatesBitsMax)
|
if (pb > Base.kNumPosStatesBitsMax)
|
||||||
{
|
{
|
||||||
throw new InvalidParamException();
|
throw new InvalidParamException();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint numPosStates = (uint)1 << pb;
|
uint numPosStates = (uint)1 << pb;
|
||||||
m_LenDecoder.Create(numPosStates);
|
m_LenDecoder.Create(numPosStates);
|
||||||
m_RepLenDecoder.Create(numPosStates);
|
m_RepLenDecoder.Create(numPosStates);
|
||||||
m_PosStateMask = numPosStates - 1;
|
m_PosStateMask = numPosStates - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool _solid = false;
|
private bool _solid = false;
|
||||||
private void Init(System.IO.Stream inStream, System.IO.Stream outStream)
|
private void Init(System.IO.Stream inStream, System.IO.Stream outStream)
|
||||||
{
|
{
|
||||||
m_RangeDecoder.Init(inStream);
|
m_RangeDecoder.Init(inStream);
|
||||||
m_OutWindow.Init(outStream, _solid);
|
m_OutWindow.Init(outStream, _solid);
|
||||||
|
|
||||||
uint i;
|
uint i;
|
||||||
for (i = 0; i < Base.kNumStates; i++)
|
for (i = 0; i < Base.kNumStates; i++)
|
||||||
{
|
{
|
||||||
for (uint j = 0; j <= m_PosStateMask; j++)
|
for (uint j = 0; j <= m_PosStateMask; j++)
|
||||||
{
|
{
|
||||||
uint index = (i << Base.kNumPosStatesBitsMax) + j;
|
uint index = (i << Base.kNumPosStatesBitsMax) + j;
|
||||||
m_IsMatchDecoders[index].Init();
|
m_IsMatchDecoders[index].Init();
|
||||||
m_IsRep0LongDecoders[index].Init();
|
m_IsRep0LongDecoders[index].Init();
|
||||||
}
|
}
|
||||||
m_IsRepDecoders[i].Init();
|
m_IsRepDecoders[i].Init();
|
||||||
m_IsRepG0Decoders[i].Init();
|
m_IsRepG0Decoders[i].Init();
|
||||||
m_IsRepG1Decoders[i].Init();
|
m_IsRepG1Decoders[i].Init();
|
||||||
m_IsRepG2Decoders[i].Init();
|
m_IsRepG2Decoders[i].Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_LiteralDecoder.Init();
|
m_LiteralDecoder.Init();
|
||||||
for (i = 0; i < Base.kNumLenToPosStates; i++)
|
for (i = 0; i < Base.kNumLenToPosStates; i++)
|
||||||
{
|
{
|
||||||
m_PosSlotDecoder[i].Init();
|
m_PosSlotDecoder[i].Init();
|
||||||
}
|
}
|
||||||
// m_PosSpecDecoder.Init();
|
// m_PosSpecDecoder.Init();
|
||||||
for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)
|
for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)
|
||||||
{
|
{
|
||||||
m_PosDecoders[i].Init();
|
m_PosDecoders[i].Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_LenDecoder.Init();
|
m_LenDecoder.Init();
|
||||||
m_RepLenDecoder.Init();
|
m_RepLenDecoder.Init();
|
||||||
m_PosAlignDecoder.Init();
|
m_PosAlignDecoder.Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Code(System.IO.Stream inStream, System.IO.Stream outStream,
|
public void Code(System.IO.Stream inStream, System.IO.Stream outStream,
|
||||||
Int64 inSize, Int64 outSize, ICodeProgress progress, CancellationToken? token = null)
|
Int64 inSize, Int64 outSize, ICodeProgress progress, CancellationToken? token = null)
|
||||||
{
|
{
|
||||||
Init(inStream, outStream);
|
Init(inStream, outStream);
|
||||||
|
|
||||||
Base.State state = new();
|
Base.State state = new();
|
||||||
state.Init();
|
state.Init();
|
||||||
uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
|
uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
|
||||||
|
|
||||||
UInt64 nowPos64 = 0;
|
UInt64 nowPos64 = 0;
|
||||||
UInt64 outSize64 = (UInt64)outSize;
|
UInt64 outSize64 = (UInt64)outSize;
|
||||||
if (nowPos64 < outSize64)
|
if (nowPos64 < outSize64)
|
||||||
{
|
{
|
||||||
if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0)
|
if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0)
|
||||||
{
|
{
|
||||||
throw new DataErrorException();
|
throw new DataErrorException();
|
||||||
}
|
}
|
||||||
|
|
||||||
state.UpdateChar();
|
state.UpdateChar();
|
||||||
byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0);
|
byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0);
|
||||||
m_OutWindow.PutByte(b);
|
m_OutWindow.PutByte(b);
|
||||||
nowPos64++;
|
nowPos64++;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
while (nowPos64 < outSize64)
|
while (nowPos64 < outSize64)
|
||||||
{
|
{
|
||||||
token?.ThrowIfCancellationRequested();
|
token?.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
// UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64);
|
// UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64);
|
||||||
// while(nowPos64 < next)
|
// while(nowPos64 < next)
|
||||||
{
|
{
|
||||||
uint posState = (uint)nowPos64 & m_PosStateMask;
|
uint posState = (uint)nowPos64 & m_PosStateMask;
|
||||||
if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
|
if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
|
||||||
{
|
{
|
||||||
byte b;
|
byte b;
|
||||||
byte prevByte = m_OutWindow.GetByte(0);
|
byte prevByte = m_OutWindow.GetByte(0);
|
||||||
b = !state.IsCharState()
|
b = !state.IsCharState()
|
||||||
? m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder,
|
? m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder,
|
||||||
(uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0))
|
(uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0))
|
||||||
: m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte);
|
: m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte);
|
||||||
|
|
||||||
m_OutWindow.PutByte(b);
|
m_OutWindow.PutByte(b);
|
||||||
state.UpdateChar();
|
state.UpdateChar();
|
||||||
nowPos64++;
|
nowPos64++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint len;
|
uint len;
|
||||||
if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1)
|
if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1)
|
||||||
{
|
{
|
||||||
if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0)
|
if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0)
|
||||||
{
|
{
|
||||||
if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
|
if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
|
||||||
{
|
{
|
||||||
state.UpdateShortRep();
|
state.UpdateShortRep();
|
||||||
m_OutWindow.PutByte(m_OutWindow.GetByte(rep0));
|
m_OutWindow.PutByte(m_OutWindow.GetByte(rep0));
|
||||||
nowPos64++;
|
nowPos64++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UInt32 distance;
|
UInt32 distance;
|
||||||
if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0)
|
if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0)
|
||||||
{
|
{
|
||||||
distance = rep1;
|
distance = rep1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0)
|
if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0)
|
||||||
{
|
{
|
||||||
distance = rep2;
|
distance = rep2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
distance = rep3;
|
distance = rep3;
|
||||||
rep3 = rep2;
|
rep3 = rep2;
|
||||||
}
|
}
|
||||||
rep2 = rep1;
|
rep2 = rep1;
|
||||||
}
|
}
|
||||||
rep1 = rep0;
|
rep1 = rep0;
|
||||||
rep0 = distance;
|
rep0 = distance;
|
||||||
}
|
}
|
||||||
len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen;
|
len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen;
|
||||||
state.UpdateRep();
|
state.UpdateRep();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rep3 = rep2;
|
rep3 = rep2;
|
||||||
rep2 = rep1;
|
rep2 = rep1;
|
||||||
rep1 = rep0;
|
rep1 = rep0;
|
||||||
len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState);
|
len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState);
|
||||||
state.UpdateMatch();
|
state.UpdateMatch();
|
||||||
uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder);
|
uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder);
|
||||||
if (posSlot >= Base.kStartPosModelIndex)
|
if (posSlot >= Base.kStartPosModelIndex)
|
||||||
{
|
{
|
||||||
int numDirectBits = (int)((posSlot >> 1) - 1);
|
int numDirectBits = (int)((posSlot >> 1) - 1);
|
||||||
rep0 = (2 | (posSlot & 1)) << numDirectBits;
|
rep0 = (2 | (posSlot & 1)) << numDirectBits;
|
||||||
if (posSlot < Base.kEndPosModelIndex)
|
if (posSlot < Base.kEndPosModelIndex)
|
||||||
{
|
{
|
||||||
rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders,
|
rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders,
|
||||||
rep0 - posSlot - 1, m_RangeDecoder, numDirectBits);
|
rep0 - posSlot - 1, m_RangeDecoder, numDirectBits);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rep0 += m_RangeDecoder.DecodeDirectBits(
|
rep0 += m_RangeDecoder.DecodeDirectBits(
|
||||||
numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits;
|
numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits;
|
||||||
rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);
|
rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rep0 = posSlot;
|
rep0 = posSlot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck)
|
if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck)
|
||||||
{
|
{
|
||||||
if (rep0 == 0xFFFFFFFF)
|
if (rep0 == 0xFFFFFFFF)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new DataErrorException();
|
throw new DataErrorException();
|
||||||
}
|
}
|
||||||
m_OutWindow.CopyBlock(rep0, len);
|
m_OutWindow.CopyBlock(rep0, len);
|
||||||
nowPos64 += len;
|
nowPos64 += len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
m_OutWindow.Flush();
|
m_OutWindow.Flush();
|
||||||
m_OutWindow.ReleaseStream();
|
m_OutWindow.ReleaseStream();
|
||||||
m_RangeDecoder.ReleaseStream();
|
m_RangeDecoder.ReleaseStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetDecoderProperties(byte[] properties)
|
public void SetDecoderProperties(byte[] properties)
|
||||||
{
|
{
|
||||||
if (properties.Length < 5)
|
if (properties.Length < 5)
|
||||||
{
|
{
|
||||||
throw new InvalidParamException();
|
throw new InvalidParamException();
|
||||||
}
|
}
|
||||||
|
|
||||||
int lc = properties[0] % 9;
|
int lc = properties[0] % 9;
|
||||||
int remainder = properties[0] / 9;
|
int remainder = properties[0] / 9;
|
||||||
int lp = remainder % 5;
|
int lp = remainder % 5;
|
||||||
int pb = remainder / 5;
|
int pb = remainder / 5;
|
||||||
if (pb > Base.kNumPosStatesBitsMax)
|
if (pb > Base.kNumPosStatesBitsMax)
|
||||||
{
|
{
|
||||||
throw new InvalidParamException();
|
throw new InvalidParamException();
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 dictionarySize = 0;
|
UInt32 dictionarySize = 0;
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
dictionarySize += ((UInt32)properties[1 + i]) << (i * 8);
|
dictionarySize += ((UInt32)properties[1 + i]) << (i * 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDictionarySize(dictionarySize);
|
SetDictionarySize(dictionarySize);
|
||||||
SetLiteralProperties(lp, lc);
|
SetLiteralProperties(lp, lc);
|
||||||
SetPosBitsProperties(pb);
|
SetPosBitsProperties(pb);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Train(System.IO.Stream stream)
|
public bool Train(System.IO.Stream stream)
|
||||||
{
|
{
|
||||||
_solid = true;
|
_solid = true;
|
||||||
return m_OutWindow.Train(stream);
|
return m_OutWindow.Train(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
public override bool CanRead { get { return true; }}
|
public override bool CanRead { get { return true; }}
|
||||||
public override bool CanWrite { get { return true; }}
|
public override bool CanWrite { get { return true; }}
|
||||||
public override bool CanSeek { get { return true; }}
|
public override bool CanSeek { get { return true; }}
|
||||||
public override long Length { get { return 0; }}
|
public override long Length { get { return 0; }}
|
||||||
public override long Position
|
public override long Position
|
||||||
{
|
{
|
||||||
get { return 0; }
|
get { return 0; }
|
||||||
set { }
|
set { }
|
||||||
}
|
}
|
||||||
public override void Flush() { }
|
public override void Flush() { }
|
||||||
public override int Read(byte[] buffer, int offset, int count)
|
public override int Read(byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
public override void Write(byte[] buffer, int offset, int count)
|
public override void Write(byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
public override long Seek(long offset, System.IO.SeekOrigin origin)
|
public override long Seek(long offset, System.IO.SeekOrigin origin)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
public override void SetLength(long value) {}
|
public override void SetLength(long value) {}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,243 +1,243 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace SevenZip.Compression.RangeCoder
|
namespace SevenZip.Compression.RangeCoder
|
||||||
{
|
{
|
||||||
internal class Encoder
|
internal class Encoder
|
||||||
{
|
{
|
||||||
public const uint kTopValue = 1 << 24;
|
public const uint kTopValue = 1 << 24;
|
||||||
|
|
||||||
private System.IO.Stream Stream;
|
private System.IO.Stream Stream;
|
||||||
|
|
||||||
public UInt64 Low;
|
public UInt64 Low;
|
||||||
public uint Range;
|
public uint Range;
|
||||||
private uint _cacheSize;
|
private uint _cacheSize;
|
||||||
private byte _cache;
|
private byte _cache;
|
||||||
|
|
||||||
private long StartPosition;
|
private long StartPosition;
|
||||||
|
|
||||||
public void SetStream(System.IO.Stream stream)
|
public void SetStream(System.IO.Stream stream)
|
||||||
{
|
{
|
||||||
Stream = stream;
|
Stream = stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReleaseStream()
|
public void ReleaseStream()
|
||||||
{
|
{
|
||||||
Stream = null;
|
Stream = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
StartPosition = Stream.Position;
|
StartPosition = Stream.Position;
|
||||||
|
|
||||||
Low = 0;
|
Low = 0;
|
||||||
Range = 0xFFFFFFFF;
|
Range = 0xFFFFFFFF;
|
||||||
_cacheSize = 1;
|
_cacheSize = 1;
|
||||||
_cache = 0;
|
_cache = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FlushData()
|
public void FlushData()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 5; i++)
|
for (int i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
ShiftLow();
|
ShiftLow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FlushStream()
|
public void FlushStream()
|
||||||
{
|
{
|
||||||
Stream.Flush();
|
Stream.Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CloseStream()
|
public void CloseStream()
|
||||||
{
|
{
|
||||||
Stream.Close();
|
Stream.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Encode(uint start, uint size, uint total)
|
public void Encode(uint start, uint size, uint total)
|
||||||
{
|
{
|
||||||
Low += start * (Range /= total);
|
Low += start * (Range /= total);
|
||||||
Range *= size;
|
Range *= size;
|
||||||
while (Range < kTopValue)
|
while (Range < kTopValue)
|
||||||
{
|
{
|
||||||
Range <<= 8;
|
Range <<= 8;
|
||||||
ShiftLow();
|
ShiftLow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShiftLow()
|
public void ShiftLow()
|
||||||
{
|
{
|
||||||
if ((uint)Low < 0xFF000000 || (uint)(Low >> 32) == 1)
|
if ((uint)Low < 0xFF000000 || (uint)(Low >> 32) == 1)
|
||||||
{
|
{
|
||||||
byte temp = _cache;
|
byte temp = _cache;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
Stream.WriteByte((byte)(temp + (Low >> 32)));
|
Stream.WriteByte((byte)(temp + (Low >> 32)));
|
||||||
temp = 0xFF;
|
temp = 0xFF;
|
||||||
}
|
}
|
||||||
while (--_cacheSize != 0);
|
while (--_cacheSize != 0);
|
||||||
_cache = (byte)(((uint)Low) >> 24);
|
_cache = (byte)(((uint)Low) >> 24);
|
||||||
}
|
}
|
||||||
_cacheSize++;
|
_cacheSize++;
|
||||||
Low = ((uint)Low) << 8;
|
Low = ((uint)Low) << 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EncodeDirectBits(uint v, int numTotalBits)
|
public void EncodeDirectBits(uint v, int numTotalBits)
|
||||||
{
|
{
|
||||||
for (int i = numTotalBits - 1; i >= 0; i--)
|
for (int i = numTotalBits - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
Range >>= 1;
|
Range >>= 1;
|
||||||
if (((v >> i) & 1) == 1)
|
if (((v >> i) & 1) == 1)
|
||||||
{
|
{
|
||||||
Low += Range;
|
Low += Range;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Range < kTopValue)
|
if (Range < kTopValue)
|
||||||
{
|
{
|
||||||
Range <<= 8;
|
Range <<= 8;
|
||||||
ShiftLow();
|
ShiftLow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EncodeBit(uint size0, int numTotalBits, uint symbol)
|
public void EncodeBit(uint size0, int numTotalBits, uint symbol)
|
||||||
{
|
{
|
||||||
uint newBound = (Range >> numTotalBits) * size0;
|
uint newBound = (Range >> numTotalBits) * size0;
|
||||||
if (symbol == 0)
|
if (symbol == 0)
|
||||||
{
|
{
|
||||||
Range = newBound;
|
Range = newBound;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Low += newBound;
|
Low += newBound;
|
||||||
Range -= newBound;
|
Range -= newBound;
|
||||||
}
|
}
|
||||||
while (Range < kTopValue)
|
while (Range < kTopValue)
|
||||||
{
|
{
|
||||||
Range <<= 8;
|
Range <<= 8;
|
||||||
ShiftLow();
|
ShiftLow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long GetProcessedSizeAdd()
|
public long GetProcessedSizeAdd()
|
||||||
{
|
{
|
||||||
return _cacheSize +
|
return _cacheSize +
|
||||||
Stream.Position - StartPosition + 4;
|
Stream.Position - StartPosition + 4;
|
||||||
// (long)Stream.GetProcessedSize();
|
// (long)Stream.GetProcessedSize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class Decoder
|
internal class Decoder
|
||||||
{
|
{
|
||||||
public const uint kTopValue = 1 << 24;
|
public const uint kTopValue = 1 << 24;
|
||||||
public uint Range;
|
public uint Range;
|
||||||
public uint Code;
|
public uint Code;
|
||||||
// public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16);
|
// public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16);
|
||||||
public System.IO.Stream Stream;
|
public System.IO.Stream Stream;
|
||||||
|
|
||||||
public void Init(System.IO.Stream stream)
|
public void Init(System.IO.Stream stream)
|
||||||
{
|
{
|
||||||
// Stream.Init(stream);
|
// Stream.Init(stream);
|
||||||
Stream = stream;
|
Stream = stream;
|
||||||
|
|
||||||
Code = 0;
|
Code = 0;
|
||||||
Range = 0xFFFFFFFF;
|
Range = 0xFFFFFFFF;
|
||||||
for (int i = 0; i < 5; i++)
|
for (int i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
Code = (Code << 8) | (byte)Stream.ReadByte();
|
Code = (Code << 8) | (byte)Stream.ReadByte();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReleaseStream()
|
public void ReleaseStream()
|
||||||
{
|
{
|
||||||
// Stream.ReleaseStream();
|
// Stream.ReleaseStream();
|
||||||
Stream = null;
|
Stream = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CloseStream()
|
public void CloseStream()
|
||||||
{
|
{
|
||||||
Stream.Close();
|
Stream.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Normalize()
|
public void Normalize()
|
||||||
{
|
{
|
||||||
while (Range < kTopValue)
|
while (Range < kTopValue)
|
||||||
{
|
{
|
||||||
Code = (Code << 8) | (byte)Stream.ReadByte();
|
Code = (Code << 8) | (byte)Stream.ReadByte();
|
||||||
Range <<= 8;
|
Range <<= 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Normalize2()
|
public void Normalize2()
|
||||||
{
|
{
|
||||||
if (Range < kTopValue)
|
if (Range < kTopValue)
|
||||||
{
|
{
|
||||||
Code = (Code << 8) | (byte)Stream.ReadByte();
|
Code = (Code << 8) | (byte)Stream.ReadByte();
|
||||||
Range <<= 8;
|
Range <<= 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint GetThreshold(uint total)
|
public uint GetThreshold(uint total)
|
||||||
{
|
{
|
||||||
return Code / (Range /= total);
|
return Code / (Range /= total);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Decode(uint start, uint size, uint total)
|
public void Decode(uint start, uint size, uint total)
|
||||||
{
|
{
|
||||||
Code -= start * Range;
|
Code -= start * Range;
|
||||||
Range *= size;
|
Range *= size;
|
||||||
Normalize();
|
Normalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint DecodeDirectBits(int numTotalBits)
|
public uint DecodeDirectBits(int numTotalBits)
|
||||||
{
|
{
|
||||||
uint range = Range;
|
uint range = Range;
|
||||||
uint code = Code;
|
uint code = Code;
|
||||||
uint result = 0;
|
uint result = 0;
|
||||||
for (int i = numTotalBits; i > 0; i--)
|
for (int i = numTotalBits; i > 0; i--)
|
||||||
{
|
{
|
||||||
range >>= 1;
|
range >>= 1;
|
||||||
/*
|
/*
|
||||||
result <<= 1;
|
result <<= 1;
|
||||||
if (code >= range)
|
if (code >= range)
|
||||||
{
|
{
|
||||||
code -= range;
|
code -= range;
|
||||||
result |= 1;
|
result |= 1;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
uint t = (code - range) >> 31;
|
uint t = (code - range) >> 31;
|
||||||
code -= range & (t - 1);
|
code -= range & (t - 1);
|
||||||
result = (result << 1) | (1 - t);
|
result = (result << 1) | (1 - t);
|
||||||
|
|
||||||
if (range < kTopValue)
|
if (range < kTopValue)
|
||||||
{
|
{
|
||||||
code = (code << 8) | (byte)Stream.ReadByte();
|
code = (code << 8) | (byte)Stream.ReadByte();
|
||||||
range <<= 8;
|
range <<= 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Range = range;
|
Range = range;
|
||||||
Code = code;
|
Code = code;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint DecodeBit(uint size0, int numTotalBits)
|
public uint DecodeBit(uint size0, int numTotalBits)
|
||||||
{
|
{
|
||||||
uint newBound = (Range >> numTotalBits) * size0;
|
uint newBound = (Range >> numTotalBits) * size0;
|
||||||
uint symbol;
|
uint symbol;
|
||||||
if (Code < newBound)
|
if (Code < newBound)
|
||||||
{
|
{
|
||||||
symbol = 0;
|
symbol = 0;
|
||||||
Range = newBound;
|
Range = newBound;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
symbol = 1;
|
symbol = 1;
|
||||||
Code -= newBound;
|
Code -= newBound;
|
||||||
Range -= newBound;
|
Range -= newBound;
|
||||||
}
|
}
|
||||||
Normalize();
|
Normalize();
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ulong GetProcessedSize() {return Stream.GetProcessedSize(); }
|
// ulong GetProcessedSize() {return Stream.GetProcessedSize(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,127 +1,127 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace SevenZip.Compression.RangeCoder
|
namespace SevenZip.Compression.RangeCoder
|
||||||
{
|
{
|
||||||
internal struct BitEncoder
|
internal struct BitEncoder
|
||||||
{
|
{
|
||||||
public const int kNumBitModelTotalBits = 11;
|
public const int kNumBitModelTotalBits = 11;
|
||||||
public const uint kBitModelTotal = 1 << kNumBitModelTotalBits;
|
public const uint kBitModelTotal = 1 << kNumBitModelTotalBits;
|
||||||
private const int kNumMoveBits = 5;
|
private const int kNumMoveBits = 5;
|
||||||
private const int kNumMoveReducingBits = 2;
|
private const int kNumMoveReducingBits = 2;
|
||||||
public const int kNumBitPriceShiftBits = 6;
|
public const int kNumBitPriceShiftBits = 6;
|
||||||
|
|
||||||
private uint Prob;
|
private uint Prob;
|
||||||
|
|
||||||
public void Init() { Prob = kBitModelTotal >> 1; }
|
public void Init() { Prob = kBitModelTotal >> 1; }
|
||||||
|
|
||||||
public void UpdateModel(uint symbol)
|
public void UpdateModel(uint symbol)
|
||||||
{
|
{
|
||||||
if (symbol == 0)
|
if (symbol == 0)
|
||||||
{
|
{
|
||||||
Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
|
Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Prob -= Prob >> kNumMoveBits;
|
Prob -= Prob >> kNumMoveBits;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Encode(Encoder encoder, uint symbol)
|
public void Encode(Encoder encoder, uint symbol)
|
||||||
{
|
{
|
||||||
// encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol);
|
// encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol);
|
||||||
// UpdateModel(symbol);
|
// UpdateModel(symbol);
|
||||||
uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob;
|
uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob;
|
||||||
if (symbol == 0)
|
if (symbol == 0)
|
||||||
{
|
{
|
||||||
encoder.Range = newBound;
|
encoder.Range = newBound;
|
||||||
Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
|
Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
encoder.Low += newBound;
|
encoder.Low += newBound;
|
||||||
encoder.Range -= newBound;
|
encoder.Range -= newBound;
|
||||||
Prob -= Prob >> kNumMoveBits;
|
Prob -= Prob >> kNumMoveBits;
|
||||||
}
|
}
|
||||||
if (encoder.Range < Encoder.kTopValue)
|
if (encoder.Range < Encoder.kTopValue)
|
||||||
{
|
{
|
||||||
encoder.Range <<= 8;
|
encoder.Range <<= 8;
|
||||||
encoder.ShiftLow();
|
encoder.ShiftLow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits];
|
private static readonly UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits];
|
||||||
|
|
||||||
static BitEncoder()
|
static BitEncoder()
|
||||||
{
|
{
|
||||||
const int kNumBits = kNumBitModelTotalBits - kNumMoveReducingBits;
|
const int kNumBits = kNumBitModelTotalBits - kNumMoveReducingBits;
|
||||||
for (int i = kNumBits - 1; i >= 0; i--)
|
for (int i = kNumBits - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
UInt32 start = (UInt32)1 << (kNumBits - i - 1);
|
UInt32 start = (UInt32)1 << (kNumBits - i - 1);
|
||||||
UInt32 end = (UInt32)1 << (kNumBits - i);
|
UInt32 end = (UInt32)1 << (kNumBits - i);
|
||||||
for (UInt32 j = start; j < end; j++)
|
for (UInt32 j = start; j < end; j++)
|
||||||
{
|
{
|
||||||
ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) +
|
ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) +
|
||||||
(((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1));
|
(((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint GetPrice(uint symbol)
|
public uint GetPrice(uint symbol)
|
||||||
{
|
{
|
||||||
return ProbPrices[(((Prob - symbol) ^ (-(int)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];
|
return ProbPrices[(((Prob - symbol) ^ (-(int)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];
|
||||||
}
|
}
|
||||||
public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; }
|
public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; }
|
||||||
public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; }
|
public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal struct BitDecoder
|
internal struct BitDecoder
|
||||||
{
|
{
|
||||||
public const int kNumBitModelTotalBits = 11;
|
public const int kNumBitModelTotalBits = 11;
|
||||||
public const uint kBitModelTotal = 1 << kNumBitModelTotalBits;
|
public const uint kBitModelTotal = 1 << kNumBitModelTotalBits;
|
||||||
private const int kNumMoveBits = 5;
|
private const int kNumMoveBits = 5;
|
||||||
|
|
||||||
private uint Prob;
|
private uint Prob;
|
||||||
|
|
||||||
public void UpdateModel(int numMoveBits, uint symbol)
|
public void UpdateModel(int numMoveBits, uint symbol)
|
||||||
{
|
{
|
||||||
if (symbol == 0)
|
if (symbol == 0)
|
||||||
{
|
{
|
||||||
Prob += (kBitModelTotal - Prob) >> numMoveBits;
|
Prob += (kBitModelTotal - Prob) >> numMoveBits;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Prob -= Prob >> numMoveBits;
|
Prob -= Prob >> numMoveBits;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init() { Prob = kBitModelTotal >> 1; }
|
public void Init() { Prob = kBitModelTotal >> 1; }
|
||||||
|
|
||||||
public uint Decode(Decoder rangeDecoder)
|
public uint Decode(Decoder rangeDecoder)
|
||||||
{
|
{
|
||||||
uint newBound = (rangeDecoder.Range >> kNumBitModelTotalBits) * Prob;
|
uint newBound = (rangeDecoder.Range >> kNumBitModelTotalBits) * Prob;
|
||||||
if (rangeDecoder.Code < newBound)
|
if (rangeDecoder.Code < newBound)
|
||||||
{
|
{
|
||||||
rangeDecoder.Range = newBound;
|
rangeDecoder.Range = newBound;
|
||||||
Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
|
Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
|
||||||
if (rangeDecoder.Range < Decoder.kTopValue)
|
if (rangeDecoder.Range < Decoder.kTopValue)
|
||||||
{
|
{
|
||||||
rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
|
rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
|
||||||
rangeDecoder.Range <<= 8;
|
rangeDecoder.Range <<= 8;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rangeDecoder.Range -= newBound;
|
rangeDecoder.Range -= newBound;
|
||||||
rangeDecoder.Code -= newBound;
|
rangeDecoder.Code -= newBound;
|
||||||
Prob -= Prob >> kNumMoveBits;
|
Prob -= Prob >> kNumMoveBits;
|
||||||
if (rangeDecoder.Range < Decoder.kTopValue)
|
if (rangeDecoder.Range < Decoder.kTopValue)
|
||||||
{
|
{
|
||||||
rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
|
rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
|
||||||
rangeDecoder.Range <<= 8;
|
rangeDecoder.Range <<= 8;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,164 +1,164 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace SevenZip.Compression.RangeCoder
|
namespace SevenZip.Compression.RangeCoder
|
||||||
{
|
{
|
||||||
internal struct BitTreeEncoder
|
internal struct BitTreeEncoder
|
||||||
{
|
{
|
||||||
private readonly BitEncoder[] Models;
|
private readonly BitEncoder[] Models;
|
||||||
private readonly int NumBitLevels;
|
private readonly int NumBitLevels;
|
||||||
|
|
||||||
public BitTreeEncoder(int numBitLevels)
|
public BitTreeEncoder(int numBitLevels)
|
||||||
{
|
{
|
||||||
NumBitLevels = numBitLevels;
|
NumBitLevels = numBitLevels;
|
||||||
Models = new BitEncoder[1 << numBitLevels];
|
Models = new BitEncoder[1 << numBitLevels];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
for (uint i = 1; i < (1 << NumBitLevels); i++)
|
for (uint i = 1; i < (1 << NumBitLevels); i++)
|
||||||
{
|
{
|
||||||
Models[i].Init();
|
Models[i].Init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Encode(Encoder rangeEncoder, UInt32 symbol)
|
public void Encode(Encoder rangeEncoder, UInt32 symbol)
|
||||||
{
|
{
|
||||||
UInt32 m = 1;
|
UInt32 m = 1;
|
||||||
for (int bitIndex = NumBitLevels; bitIndex > 0;)
|
for (int bitIndex = NumBitLevels; bitIndex > 0;)
|
||||||
{
|
{
|
||||||
bitIndex--;
|
bitIndex--;
|
||||||
UInt32 bit = (symbol >> bitIndex) & 1;
|
UInt32 bit = (symbol >> bitIndex) & 1;
|
||||||
Models[m].Encode(rangeEncoder, bit);
|
Models[m].Encode(rangeEncoder, bit);
|
||||||
m = (m << 1) | bit;
|
m = (m << 1) | bit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol)
|
public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol)
|
||||||
{
|
{
|
||||||
UInt32 m = 1;
|
UInt32 m = 1;
|
||||||
for (UInt32 i = 0; i < NumBitLevels; i++)
|
for (UInt32 i = 0; i < NumBitLevels; i++)
|
||||||
{
|
{
|
||||||
UInt32 bit = symbol & 1;
|
UInt32 bit = symbol & 1;
|
||||||
Models[m].Encode(rangeEncoder, bit);
|
Models[m].Encode(rangeEncoder, bit);
|
||||||
m = (m << 1) | bit;
|
m = (m << 1) | bit;
|
||||||
symbol >>= 1;
|
symbol >>= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public UInt32 GetPrice(UInt32 symbol)
|
public UInt32 GetPrice(UInt32 symbol)
|
||||||
{
|
{
|
||||||
UInt32 price = 0;
|
UInt32 price = 0;
|
||||||
UInt32 m = 1;
|
UInt32 m = 1;
|
||||||
for (int bitIndex = NumBitLevels; bitIndex > 0;)
|
for (int bitIndex = NumBitLevels; bitIndex > 0;)
|
||||||
{
|
{
|
||||||
bitIndex--;
|
bitIndex--;
|
||||||
UInt32 bit = (symbol >> bitIndex) & 1;
|
UInt32 bit = (symbol >> bitIndex) & 1;
|
||||||
price += Models[m].GetPrice(bit);
|
price += Models[m].GetPrice(bit);
|
||||||
m = (m << 1) + bit;
|
m = (m << 1) + bit;
|
||||||
}
|
}
|
||||||
return price;
|
return price;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UInt32 ReverseGetPrice(UInt32 symbol)
|
public UInt32 ReverseGetPrice(UInt32 symbol)
|
||||||
{
|
{
|
||||||
UInt32 price = 0;
|
UInt32 price = 0;
|
||||||
UInt32 m = 1;
|
UInt32 m = 1;
|
||||||
for (int i = NumBitLevels; i > 0; i--)
|
for (int i = NumBitLevels; i > 0; i--)
|
||||||
{
|
{
|
||||||
UInt32 bit = symbol & 1;
|
UInt32 bit = symbol & 1;
|
||||||
symbol >>= 1;
|
symbol >>= 1;
|
||||||
price += Models[m].GetPrice(bit);
|
price += Models[m].GetPrice(bit);
|
||||||
m = (m << 1) | bit;
|
m = (m << 1) | bit;
|
||||||
}
|
}
|
||||||
return price;
|
return price;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex,
|
public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex,
|
||||||
int NumBitLevels, UInt32 symbol)
|
int NumBitLevels, UInt32 symbol)
|
||||||
{
|
{
|
||||||
UInt32 price = 0;
|
UInt32 price = 0;
|
||||||
UInt32 m = 1;
|
UInt32 m = 1;
|
||||||
for (int i = NumBitLevels; i > 0; i--)
|
for (int i = NumBitLevels; i > 0; i--)
|
||||||
{
|
{
|
||||||
UInt32 bit = symbol & 1;
|
UInt32 bit = symbol & 1;
|
||||||
symbol >>= 1;
|
symbol >>= 1;
|
||||||
price += Models[startIndex + m].GetPrice(bit);
|
price += Models[startIndex + m].GetPrice(bit);
|
||||||
m = (m << 1) | bit;
|
m = (m << 1) | bit;
|
||||||
}
|
}
|
||||||
return price;
|
return price;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex,
|
public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex,
|
||||||
Encoder rangeEncoder, int NumBitLevels, UInt32 symbol)
|
Encoder rangeEncoder, int NumBitLevels, UInt32 symbol)
|
||||||
{
|
{
|
||||||
UInt32 m = 1;
|
UInt32 m = 1;
|
||||||
for (int i = 0; i < NumBitLevels; i++)
|
for (int i = 0; i < NumBitLevels; i++)
|
||||||
{
|
{
|
||||||
UInt32 bit = symbol & 1;
|
UInt32 bit = symbol & 1;
|
||||||
Models[startIndex + m].Encode(rangeEncoder, bit);
|
Models[startIndex + m].Encode(rangeEncoder, bit);
|
||||||
m = (m << 1) | bit;
|
m = (m << 1) | bit;
|
||||||
symbol >>= 1;
|
symbol >>= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal struct BitTreeDecoder
|
internal struct BitTreeDecoder
|
||||||
{
|
{
|
||||||
private readonly BitDecoder[] Models;
|
private readonly BitDecoder[] Models;
|
||||||
private readonly int NumBitLevels;
|
private readonly int NumBitLevels;
|
||||||
|
|
||||||
public BitTreeDecoder(int numBitLevels)
|
public BitTreeDecoder(int numBitLevels)
|
||||||
{
|
{
|
||||||
NumBitLevels = numBitLevels;
|
NumBitLevels = numBitLevels;
|
||||||
Models = new BitDecoder[1 << numBitLevels];
|
Models = new BitDecoder[1 << numBitLevels];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
for (uint i = 1; i < (1 << NumBitLevels); i++)
|
for (uint i = 1; i < (1 << NumBitLevels); i++)
|
||||||
{
|
{
|
||||||
Models[i].Init();
|
Models[i].Init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint Decode(Decoder rangeDecoder)
|
public uint Decode(Decoder rangeDecoder)
|
||||||
{
|
{
|
||||||
uint m = 1;
|
uint m = 1;
|
||||||
for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--)
|
for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--)
|
||||||
{
|
{
|
||||||
m = (m << 1) + Models[m].Decode(rangeDecoder);
|
m = (m << 1) + Models[m].Decode(rangeDecoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
return m - ((uint)1 << NumBitLevels);
|
return m - ((uint)1 << NumBitLevels);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint ReverseDecode(Decoder rangeDecoder)
|
public uint ReverseDecode(Decoder rangeDecoder)
|
||||||
{
|
{
|
||||||
uint m = 1;
|
uint m = 1;
|
||||||
uint symbol = 0;
|
uint symbol = 0;
|
||||||
for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
|
for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
|
||||||
{
|
{
|
||||||
uint bit = Models[m].Decode(rangeDecoder);
|
uint bit = Models[m].Decode(rangeDecoder);
|
||||||
m <<= 1;
|
m <<= 1;
|
||||||
m += bit;
|
m += bit;
|
||||||
symbol |= bit << bitIndex;
|
symbol |= bit << bitIndex;
|
||||||
}
|
}
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex,
|
public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex,
|
||||||
Decoder rangeDecoder, int NumBitLevels)
|
Decoder rangeDecoder, int NumBitLevels)
|
||||||
{
|
{
|
||||||
uint m = 1;
|
uint m = 1;
|
||||||
uint symbol = 0;
|
uint symbol = 0;
|
||||||
for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
|
for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
|
||||||
{
|
{
|
||||||
uint bit = Models[startIndex + m].Decode(rangeDecoder);
|
uint bit = Models[startIndex + m].Decode(rangeDecoder);
|
||||||
m <<= 1;
|
m <<= 1;
|
||||||
m += bit;
|
m += bit;
|
||||||
symbol |= bit << bitIndex;
|
symbol |= bit << bitIndex;
|
||||||
}
|
}
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,173 +1,173 @@
|
|||||||
// ICoder.h
|
// ICoder.h
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace SevenZip
|
namespace SevenZip
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The exception that is thrown when an error in input stream occurs during decoding.
|
/// The exception that is thrown when an error in input stream occurs during decoding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class DataErrorException : ApplicationException
|
internal class DataErrorException : ApplicationException
|
||||||
{
|
{
|
||||||
public DataErrorException() : base("Data Error") { }
|
public DataErrorException() : base("Data Error") { }
|
||||||
|
|
||||||
public DataErrorException(string message) : base(message)
|
public DataErrorException(string message) : base(message)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataErrorException(string message, Exception innerException) : base(message, innerException)
|
public DataErrorException(string message, Exception innerException) : base(message, innerException)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The exception that is thrown when the value of an argument is outside the allowable range.
|
/// The exception that is thrown when the value of an argument is outside the allowable range.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class InvalidParamException : ApplicationException
|
internal class InvalidParamException : ApplicationException
|
||||||
{
|
{
|
||||||
public InvalidParamException() : base("Invalid Parameter") { }
|
public InvalidParamException() : base("Invalid Parameter") { }
|
||||||
|
|
||||||
public InvalidParamException(string message) : base(message)
|
public InvalidParamException(string message) : base(message)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public InvalidParamException(string message, Exception innerException) : base(message, innerException)
|
public InvalidParamException(string message, Exception innerException) : base(message, innerException)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ICodeProgress
|
public interface ICodeProgress
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Callback progress.
|
/// Callback progress.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="inSize">
|
/// <param name="inSize">
|
||||||
/// input size. -1 if unknown.
|
/// input size. -1 if unknown.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="outSize">
|
/// <param name="outSize">
|
||||||
/// output size. -1 if unknown.
|
/// output size. -1 if unknown.
|
||||||
/// </param>
|
/// </param>
|
||||||
void SetProgress(Int64 inSize, Int64 outSize);
|
void SetProgress(Int64 inSize, Int64 outSize);
|
||||||
};
|
};
|
||||||
|
|
||||||
public interface ICoder
|
public interface ICoder
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Codes streams.
|
/// Codes streams.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="inStream">
|
/// <param name="inStream">
|
||||||
/// input Stream.
|
/// input Stream.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="outStream">
|
/// <param name="outStream">
|
||||||
/// output Stream.
|
/// output Stream.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="inSize">
|
/// <param name="inSize">
|
||||||
/// input Size. -1 if unknown.
|
/// input Size. -1 if unknown.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="outSize">
|
/// <param name="outSize">
|
||||||
/// output Size. -1 if unknown.
|
/// output Size. -1 if unknown.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="progress">
|
/// <param name="progress">
|
||||||
/// callback progress reference.
|
/// callback progress reference.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <exception cref="DataErrorException">
|
/// <exception cref="DataErrorException">
|
||||||
/// if input stream is not valid
|
/// if input stream is not valid
|
||||||
/// </exception>
|
/// </exception>
|
||||||
void Code(System.IO.Stream inStream, System.IO.Stream outStream,
|
void Code(System.IO.Stream inStream, System.IO.Stream outStream,
|
||||||
Int64 inSize, Int64 outSize, ICodeProgress progress, CancellationToken? token = null);
|
Int64 inSize, Int64 outSize, ICodeProgress progress, CancellationToken? token = null);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
public interface ICoder2
|
public interface ICoder2
|
||||||
{
|
{
|
||||||
void Code(ISequentialInStream []inStreams,
|
void Code(ISequentialInStream []inStreams,
|
||||||
const UInt64 []inSizes,
|
const UInt64 []inSizes,
|
||||||
ISequentialOutStream []outStreams,
|
ISequentialOutStream []outStreams,
|
||||||
UInt64 []outSizes,
|
UInt64 []outSizes,
|
||||||
ICodeProgress progress);
|
ICodeProgress progress);
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides the fields that represent properties idenitifiers for compressing.
|
/// Provides the fields that represent properties idenitifiers for compressing.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum CoderPropID
|
public enum CoderPropID
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies default property.
|
/// Specifies default property.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
DefaultProp = 0,
|
DefaultProp = 0,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies size of dictionary.
|
/// Specifies size of dictionary.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
DictionarySize,
|
DictionarySize,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies size of memory for PPM*.
|
/// Specifies size of memory for PPM*.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
UsedMemorySize,
|
UsedMemorySize,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies order for PPM methods.
|
/// Specifies order for PPM methods.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Order,
|
Order,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies Block Size.
|
/// Specifies Block Size.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
BlockSize,
|
BlockSize,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies number of postion state bits for LZMA (0 <= x <= 4).
|
/// Specifies number of postion state bits for LZMA (0 <= x <= 4).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
PosStateBits,
|
PosStateBits,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies number of literal context bits for LZMA (0 <= x <= 8).
|
/// Specifies number of literal context bits for LZMA (0 <= x <= 8).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
LitContextBits,
|
LitContextBits,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies number of literal position bits for LZMA (0 <= x <= 4).
|
/// Specifies number of literal position bits for LZMA (0 <= x <= 4).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
LitPosBits,
|
LitPosBits,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies number of fast bytes for LZ*.
|
/// Specifies number of fast bytes for LZ*.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
NumFastBytes,
|
NumFastBytes,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B".
|
/// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B".
|
||||||
/// </summary>
|
/// </summary>
|
||||||
MatchFinder,
|
MatchFinder,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies the number of match finder cyckes.
|
/// Specifies the number of match finder cyckes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
MatchFinderCycles,
|
MatchFinderCycles,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies number of passes.
|
/// Specifies number of passes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
NumPasses,
|
NumPasses,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies number of algorithm.
|
/// Specifies number of algorithm.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Algorithm,
|
Algorithm,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies the number of threads.
|
/// Specifies the number of threads.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
NumThreads,
|
NumThreads,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies mode with end marker.
|
/// Specifies mode with end marker.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
EndMarker
|
EndMarker
|
||||||
};
|
};
|
||||||
|
|
||||||
public interface ISetCoderProperties
|
public interface ISetCoderProperties
|
||||||
{
|
{
|
||||||
void SetCoderProperties(CoderPropID[] propIDs, object[] properties);
|
void SetCoderProperties(CoderPropID[] propIDs, object[] properties);
|
||||||
};
|
};
|
||||||
|
|
||||||
public interface IWriteCoderProperties
|
public interface IWriteCoderProperties
|
||||||
{
|
{
|
||||||
void WriteCoderProperties(System.IO.Stream outStream);
|
void WriteCoderProperties(System.IO.Stream outStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ISetDecoderProperties
|
public interface ISetDecoderProperties
|
||||||
{
|
{
|
||||||
void SetDecoderProperties(byte[] properties);
|
void SetDecoderProperties(byte[] properties);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,112 +1,112 @@
|
|||||||
<!--
|
<!--
|
||||||
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"),
|
||||||
to deal in the Software without restriction, including without limitation
|
to deal in the Software without restriction, including without limitation
|
||||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
and/or sell copies of the Software, and to permit persons to whom the
|
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:
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
The above copyright notice and this permission notice shall be included in
|
||||||
all copies or substantial portions of the Software.
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
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
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
DEALINGS IN THE SOFTWARE.
|
DEALINGS IN THE SOFTWARE.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<Application x:Class="WPinternals.App"
|
<Application x:Class="WPinternals.App"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
StartupUri="Views\StartupWindow.xaml"
|
StartupUri="Views\StartupWindow.xaml"
|
||||||
xmlns:ComponentModel="clr-namespace:System.ComponentModel;assembly=PresentationFramework"
|
xmlns:ComponentModel="clr-namespace:System.ComponentModel;assembly=PresentationFramework"
|
||||||
>
|
>
|
||||||
<Application.Resources>
|
<Application.Resources>
|
||||||
<Style TargetType="{x:Type UserControl}">
|
<Style TargetType="{x:Type UserControl}">
|
||||||
<Style.Triggers>
|
<Style.Triggers>
|
||||||
<Trigger Property="ComponentModel:DesignerProperties.IsInDesignMode"
|
<Trigger Property="ComponentModel:DesignerProperties.IsInDesignMode"
|
||||||
Value="true">
|
Value="true">
|
||||||
<Setter Property="Background"
|
<Setter Property="Background"
|
||||||
Value="White" />
|
Value="White" />
|
||||||
</Trigger>
|
</Trigger>
|
||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
</Style>
|
</Style>
|
||||||
<ControlTemplate x:Key="TopicExpanderTemplate" TargetType="{x:Type Expander}">
|
<ControlTemplate x:Key="TopicExpanderTemplate" TargetType="{x:Type Expander}">
|
||||||
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="3" SnapsToDevicePixels="True">
|
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="3" SnapsToDevicePixels="True">
|
||||||
<DockPanel>
|
<DockPanel>
|
||||||
<ToggleButton x:Name="HeaderSite" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" DockPanel.Dock="Top" Foreground="{TemplateBinding Foreground}" FontWeight="{TemplateBinding FontWeight}" FontStyle="{TemplateBinding FontStyle}" FontStretch="{TemplateBinding FontStretch}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" MinWidth="0" MinHeight="0" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}">
|
<ToggleButton x:Name="HeaderSite" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" DockPanel.Dock="Top" Foreground="{TemplateBinding Foreground}" FontWeight="{TemplateBinding FontWeight}" FontStyle="{TemplateBinding FontStyle}" FontStretch="{TemplateBinding FontStretch}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" MinWidth="0" MinHeight="0" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}">
|
||||||
<ToggleButton.FocusVisualStyle>
|
<ToggleButton.FocusVisualStyle>
|
||||||
<Style>
|
<Style>
|
||||||
<Setter Property="Control.Template">
|
<Setter Property="Control.Template">
|
||||||
<Setter.Value>
|
<Setter.Value>
|
||||||
<ControlTemplate>
|
<ControlTemplate>
|
||||||
<Border>
|
<Border>
|
||||||
<Rectangle Margin="0" SnapsToDevicePixels="True" Stroke="Black" StrokeThickness="1" StrokeDashArray="1 2"/>
|
<Rectangle Margin="0" SnapsToDevicePixels="True" Stroke="Black" StrokeThickness="1" StrokeDashArray="1 2"/>
|
||||||
</Border>
|
</Border>
|
||||||
</ControlTemplate>
|
</ControlTemplate>
|
||||||
</Setter.Value>
|
</Setter.Value>
|
||||||
</Setter>
|
</Setter>
|
||||||
</Style>
|
</Style>
|
||||||
</ToggleButton.FocusVisualStyle>
|
</ToggleButton.FocusVisualStyle>
|
||||||
<ToggleButton.Style>
|
<ToggleButton.Style>
|
||||||
<Style TargetType="{x:Type ToggleButton}">
|
<Style TargetType="{x:Type ToggleButton}">
|
||||||
<Setter Property="Template">
|
<Setter Property="Template">
|
||||||
<Setter.Value>
|
<Setter.Value>
|
||||||
<ControlTemplate TargetType="{x:Type ToggleButton}">
|
<ControlTemplate TargetType="{x:Type ToggleButton}">
|
||||||
<Border Padding="{TemplateBinding Padding}">
|
<Border Padding="{TemplateBinding Padding}">
|
||||||
<Grid Background="Transparent" SnapsToDevicePixels="False">
|
<Grid Background="Transparent" SnapsToDevicePixels="False">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="19"/>
|
<ColumnDefinition Width="19"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Ellipse x:Name="circle" Fill="White" HorizontalAlignment="Center" Height="19" Stroke="#FF333333" VerticalAlignment="Center" Width="19" Grid.Column="1" />
|
<Ellipse x:Name="circle" Fill="White" HorizontalAlignment="Center" Height="19" Stroke="#FF333333" VerticalAlignment="Center" Width="19" Grid.Column="1" />
|
||||||
<Path x:Name="arrow" Data="M1,1.5L4.5,5 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="False" Stroke="#FF333333" StrokeThickness="2" VerticalAlignment="Center" Grid.Column="1" />
|
<Path x:Name="arrow" Data="M1,1.5L4.5,5 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="False" Stroke="#FF333333" StrokeThickness="2" VerticalAlignment="Center" Grid.Column="1" />
|
||||||
<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="0" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="Left" Margin="0,0,0,0" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Center" TextBlock.FontSize="18" TextBlock.FontWeight="Bold" TextBlock.Foreground="#FF3753A6"/>
|
<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="0" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="Left" Margin="0,0,0,0" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Center" TextBlock.FontSize="18" TextBlock.FontWeight="Bold" TextBlock.Foreground="#FF3753A6"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
<ControlTemplate.Triggers>
|
<ControlTemplate.Triggers>
|
||||||
<Trigger Property="IsChecked" Value="True">
|
<Trigger Property="IsChecked" Value="True">
|
||||||
<Setter Property="Data" TargetName="arrow" Value="M1,4.5L4.5,1 8,4.5"/>
|
<Setter Property="Data" TargetName="arrow" Value="M1,4.5L4.5,1 8,4.5"/>
|
||||||
</Trigger>
|
</Trigger>
|
||||||
<Trigger Property="IsMouseOver" Value="True">
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
<Setter Property="Stroke" TargetName="circle" Value="#FF5593FF"/>
|
<Setter Property="Stroke" TargetName="circle" Value="#FF5593FF"/>
|
||||||
<Setter Property="Fill" TargetName="circle" Value="#FFF3F9FF"/>
|
<Setter Property="Fill" TargetName="circle" Value="#FFF3F9FF"/>
|
||||||
<Setter Property="Stroke" TargetName="arrow" Value="Black"/>
|
<Setter Property="Stroke" TargetName="arrow" Value="Black"/>
|
||||||
</Trigger>
|
</Trigger>
|
||||||
<Trigger Property="IsPressed" Value="True">
|
<Trigger Property="IsPressed" Value="True">
|
||||||
<Setter Property="Stroke" TargetName="circle" Value="#FF3C77DD"/>
|
<Setter Property="Stroke" TargetName="circle" Value="#FF3C77DD"/>
|
||||||
<Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
|
<Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
|
||||||
<Setter Property="Fill" TargetName="circle" Value="#FFD9ECFF"/>
|
<Setter Property="Fill" TargetName="circle" Value="#FFD9ECFF"/>
|
||||||
<Setter Property="Stroke" TargetName="arrow" Value="Black"/>
|
<Setter Property="Stroke" TargetName="arrow" Value="Black"/>
|
||||||
</Trigger>
|
</Trigger>
|
||||||
<Trigger Property="IsEnabled" Value="False">
|
<Trigger Property="IsEnabled" Value="False">
|
||||||
<Setter Property="Stroke" TargetName="circle" Value="#FFBCBCBC"/>
|
<Setter Property="Stroke" TargetName="circle" Value="#FFBCBCBC"/>
|
||||||
<Setter Property="Fill" TargetName="circle" Value="#FFE6E6E6"/>
|
<Setter Property="Fill" TargetName="circle" Value="#FFE6E6E6"/>
|
||||||
<Setter Property="Stroke" TargetName="arrow" Value="#FF707070"/>
|
<Setter Property="Stroke" TargetName="arrow" Value="#FF707070"/>
|
||||||
</Trigger>
|
</Trigger>
|
||||||
</ControlTemplate.Triggers>
|
</ControlTemplate.Triggers>
|
||||||
</ControlTemplate>
|
</ControlTemplate>
|
||||||
</Setter.Value>
|
</Setter.Value>
|
||||||
</Setter>
|
</Setter>
|
||||||
</Style>
|
</Style>
|
||||||
</ToggleButton.Style>
|
</ToggleButton.Style>
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
<ContentPresenter x:Name="ExpandSite" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" DockPanel.Dock="Bottom" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" Visibility="Collapsed" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
|
<ContentPresenter x:Name="ExpandSite" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" DockPanel.Dock="Bottom" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" Visibility="Collapsed" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
</Border>
|
</Border>
|
||||||
<ControlTemplate.Triggers>
|
<ControlTemplate.Triggers>
|
||||||
<Trigger Property="IsExpanded" Value="True">
|
<Trigger Property="IsExpanded" Value="True">
|
||||||
<Setter Property="Visibility" TargetName="ExpandSite" Value="Visible"/>
|
<Setter Property="Visibility" TargetName="ExpandSite" Value="Visible"/>
|
||||||
</Trigger>
|
</Trigger>
|
||||||
<Trigger Property="IsEnabled" Value="False">
|
<Trigger Property="IsEnabled" Value="False">
|
||||||
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
|
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
|
||||||
</Trigger>
|
</Trigger>
|
||||||
</ControlTemplate.Triggers>
|
</ControlTemplate.Triggers>
|
||||||
</ControlTemplate>
|
</ControlTemplate>
|
||||||
</Application.Resources>
|
</Application.Resources>
|
||||||
</Application>
|
</Application>
|
||||||
@@ -1,103 +1,104 @@
|
|||||||
// 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"),
|
||||||
// to deal in the Software without restriction, including without limitation
|
// to deal in the Software without restriction, including without limitation
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
// 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:
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// The above copyright notice and this permission notice shall be included in
|
||||||
// all copies or substantial portions of the Software.
|
// all copies or substantial portions of the Software.
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
// 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
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
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
|
||||||
/// <summary>
|
{
|
||||||
/// Interaction logic for App.xaml
|
/// <summary>
|
||||||
/// </summary>
|
/// Interaction logic for App.xaml
|
||||||
public partial class App : Application
|
/// </summary>
|
||||||
{
|
public partial class App : Application
|
||||||
internal static Action NavigateToGettingStarted;
|
{
|
||||||
internal static Action NavigateToUnlockBoot;
|
internal static Action NavigateToGettingStarted;
|
||||||
internal static PatchEngine PatchEngine;
|
internal static Action NavigateToUnlockBoot;
|
||||||
internal static WPinternalsConfig Config;
|
internal static PatchEngine PatchEngine;
|
||||||
internal static Mutex mutex = new(false, "Global\\WPinternalsRunning");
|
internal static WPinternalsConfig Config;
|
||||||
internal static DownloadsViewModel DownloadManager;
|
internal static Mutex mutex = new(false, "Global\\WPinternalsRunning");
|
||||||
internal static bool InterruptBoot = false;
|
internal static DownloadsViewModel DownloadManager;
|
||||||
internal static bool IsPnPEventLogMissing = true;
|
internal static bool InterruptBoot = false;
|
||||||
|
internal static bool IsPnPEventLogMissing = true;
|
||||||
public App()
|
|
||||||
: base()
|
public App()
|
||||||
{
|
: base()
|
||||||
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
{
|
||||||
|
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
||||||
#if NETCORE
|
|
||||||
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
|
#if NETCORE
|
||||||
#endif
|
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
|
||||||
|
#endif
|
||||||
if (Environment.GetCommandLineArgs().Length > 1)
|
|
||||||
{
|
if (Environment.GetCommandLineArgs().Length > 1)
|
||||||
CommandLine.OpenConsole();
|
{
|
||||||
}
|
CommandLine.OpenConsole();
|
||||||
|
}
|
||||||
try
|
|
||||||
{
|
try
|
||||||
if (!mutex.WaitOne(0, false))
|
{
|
||||||
{
|
if (!mutex.WaitOne(0, false))
|
||||||
if (Environment.GetCommandLineArgs().Length > 1)
|
{
|
||||||
{
|
if (Environment.GetCommandLineArgs().Length > 1)
|
||||||
Console.WriteLine("Windows Phone Internals is already running");
|
{
|
||||||
CommandLine.CloseConsole();
|
Console.WriteLine("Windows Phone Internals is already running");
|
||||||
}
|
CommandLine.CloseConsole();
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
MessageBox.Show("Windows Phone Internals is already running.", "Windows Phone Internals", MessageBoxButton.OK, MessageBoxImage.Exclamation);
|
{
|
||||||
}
|
MessageBox.Show("Windows Phone Internals is already running.", "Windows Phone Internals", MessageBoxButton.OK, MessageBoxImage.Exclamation);
|
||||||
|
}
|
||||||
Environment.Exit(0);
|
|
||||||
}
|
Environment.Exit(0);
|
||||||
}
|
}
|
||||||
catch (AbandonedMutexException) { }
|
}
|
||||||
|
catch (AbandonedMutexException) { }
|
||||||
Registration.CheckExpiration();
|
|
||||||
|
Registration.CheckExpiration();
|
||||||
string PatchDefintionsXml;
|
|
||||||
string PatchDefintionsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PatchDefintions.xml");
|
string PatchDefintionsXml;
|
||||||
if (File.Exists(PatchDefintionsPath))
|
string PatchDefintionsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PatchDefintions.xml");
|
||||||
{
|
if (File.Exists(PatchDefintionsPath))
|
||||||
PatchDefintionsXml = File.ReadAllText(PatchDefintionsPath);
|
{
|
||||||
}
|
PatchDefintionsXml = File.ReadAllText(PatchDefintionsPath);
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
using Stream stream = System.Reflection.Assembly.GetEntryAssembly().GetManifestResourceStream("WPinternals.PatchDefinitions.xml");
|
{
|
||||||
using StreamReader sr = new(stream);
|
using Stream stream = System.Reflection.Assembly.GetEntryAssembly().GetManifestResourceStream("WPinternals.PatchDefinitions.xml");
|
||||||
PatchDefintionsXml = sr.ReadToEnd();
|
using StreamReader sr = new(stream);
|
||||||
}
|
PatchDefintionsXml = sr.ReadToEnd();
|
||||||
PatchEngine = new PatchEngine(PatchDefintionsXml);
|
}
|
||||||
|
PatchEngine = new PatchEngine(PatchDefintionsXml);
|
||||||
Config = WPinternalsConfig.ReadConfig();
|
|
||||||
}
|
Config = WPinternalsConfig.ReadConfig();
|
||||||
|
}
|
||||||
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
|
||||||
{
|
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||||
if (e.ExceptionObject is Exception)
|
{
|
||||||
{
|
if (e.ExceptionObject is Exception)
|
||||||
LogFile.LogException(e.ExceptionObject as Exception);
|
{
|
||||||
}
|
LogFile.LogException(e.ExceptionObject as Exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@@ -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,378 +1,272 @@
|
|||||||
// 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"),
|
||||||
// to deal in the Software without restriction, including without limitation
|
// to deal in the Software without restriction, including without limitation
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
// 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:
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// The above copyright notice and this permission notice shall be included in
|
||||||
// all copies or substantial portions of the Software.
|
// all copies or substantial portions of the Software.
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
// 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
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
using System;
|
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
|
|
||||||
{
|
public class WPinternalsConfig
|
||||||
#if PREVIEW
|
{
|
||||||
internal const bool IsPrerelease = true;
|
internal static WPinternalsConfig ReadConfig()
|
||||||
#else
|
{
|
||||||
internal const bool IsPrerelease = false;
|
string FilePath = Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\WPInternals.config");
|
||||||
#endif
|
if (File.Exists(FilePath))
|
||||||
|
{
|
||||||
internal static readonly DateTime ExpirationDate = new(2019, 01, 06);
|
string XmlString = File.ReadAllText(FilePath);
|
||||||
|
XmlSerializer x = new(typeof(WPinternalsConfig), "");
|
||||||
internal static void CheckExpiration()
|
MemoryStream s = new(System.Text.Encoding.UTF8.GetBytes(XmlString));
|
||||||
{
|
return (WPinternalsConfig)x.Deserialize(s);
|
||||||
#if PREVIEW
|
}
|
||||||
//if (IsPrerelease && (DateTime.Now >= ExpirationDate))
|
else
|
||||||
if (DateTime.Now >= ExpirationDate)
|
{
|
||||||
{
|
return new WPinternalsConfig();
|
||||||
if (Environment.GetCommandLineArgs().Count() > 1)
|
}
|
||||||
{
|
}
|
||||||
Console.WriteLine("This prerelease version is expired!");
|
|
||||||
CommandLine.CloseConsole();
|
internal void WriteConfig()
|
||||||
}
|
{
|
||||||
else
|
string DirPath = Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals");
|
||||||
MessageBox.Show("This prerelease version is expired!", "Windows Phone Internals", MessageBoxButton.OK, MessageBoxImage.Exclamation);
|
if (!Directory.Exists(DirPath))
|
||||||
Environment.Exit(0);
|
{
|
||||||
}
|
Directory.CreateDirectory(DirPath);
|
||||||
#endif
|
}
|
||||||
}
|
|
||||||
|
string FilePath = Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\WPInternals.config");
|
||||||
internal static bool IsRegistered()
|
|
||||||
{
|
XmlSerializer x = new(typeof(WPinternalsConfig), "");
|
||||||
bool Result = false;
|
|
||||||
if (App.Config.RegistrationName != null)
|
XmlSerializerNamespaces ns = new();
|
||||||
{
|
ns.Add("", "");
|
||||||
Result = CalcRegKey() == App.Config.RegistrationKey;
|
StreamWriter FileWriter = new(FilePath);
|
||||||
}
|
x.Serialize(FileWriter, this, ns);
|
||||||
return Result;
|
FileWriter.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static string CalcRegKey()
|
internal void SetProfile(string Type, string PlatformID, string ProductCode, string PhoneFirmware, string FfuFirmware, uint FillSize, uint HeaderSize, bool AssumeImageHeaderFallsInGap, bool AllocateAsyncBuffersOnPhone)
|
||||||
{
|
{
|
||||||
string KeyBase = App.Config.RegistrationName;
|
FlashProfile Profile = GetProfile(PlatformID, PhoneFirmware, FfuFirmware);
|
||||||
if (Environment.MachineName == null)
|
if (Profile == null)
|
||||||
{
|
{
|
||||||
KeyBase += "-Unknown";
|
Profile = new FlashProfile
|
||||||
}
|
{
|
||||||
else
|
Type = Type,
|
||||||
{
|
PlatformID = PlatformID,
|
||||||
KeyBase += "-" + Environment.MachineName;
|
ProductCode = ProductCode,
|
||||||
}
|
PhoneFirmware = PhoneFirmware,
|
||||||
|
FfuFirmware = FfuFirmware
|
||||||
byte[] KeyBytes = System.Text.Encoding.UTF8.GetBytes(KeyBase);
|
};
|
||||||
SHA1Managed sha = new();
|
FlashProfiles.Add(Profile);
|
||||||
byte[] Key = sha.ComputeHash(KeyBytes);
|
}
|
||||||
return Convert.ToBase64String(Key);
|
|
||||||
}
|
Profile.FillSize = FillSize;
|
||||||
}
|
Profile.HeaderSize = HeaderSize;
|
||||||
|
Profile.AssumeImageHeaderFallsInGap = AssumeImageHeaderFallsInGap;
|
||||||
public class WPinternalsConfig
|
Profile.AllocateAsyncBuffersOnPhone = AllocateAsyncBuffersOnPhone;
|
||||||
{
|
|
||||||
internal static WPinternalsConfig ReadConfig()
|
WriteConfig();
|
||||||
{
|
}
|
||||||
string FilePath = Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\WPInternals.config");
|
|
||||||
if (File.Exists(FilePath))
|
internal FlashProfile GetProfile(string PlatformID, string PhoneFirmware, string FfuFirmware = null)
|
||||||
{
|
{
|
||||||
string XmlString = File.ReadAllText(FilePath);
|
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)));
|
||||||
XmlSerializer x = new(typeof(WPinternalsConfig), "");
|
}
|
||||||
MemoryStream s = new(System.Text.Encoding.UTF8.GetBytes(XmlString));
|
|
||||||
return (WPinternalsConfig)x.Deserialize(s);
|
public List<FlashProfile> FlashProfiles = [];
|
||||||
}
|
|
||||||
else
|
internal void AddFfuToRepository(string FFUPath)
|
||||||
{
|
{
|
||||||
return new WPinternalsConfig();
|
try
|
||||||
}
|
{
|
||||||
}
|
FFU NewFFU = new(FFUPath);
|
||||||
|
AddFfuToRepository(FFUPath, NewFFU.PlatformID, NewFFU.GetFirmwareVersion(), NewFFU.GetOSVersion());
|
||||||
internal void WriteConfig()
|
}
|
||||||
{
|
catch (Exception Ex)
|
||||||
string DirPath = Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals");
|
{
|
||||||
if (!Directory.Exists(DirPath))
|
LogFile.LogException(Ex, LogType.FileAndConsole);
|
||||||
{
|
}
|
||||||
Directory.CreateDirectory(DirPath);
|
}
|
||||||
}
|
|
||||||
|
internal void AddFfuToRepository(string FFUPath, string PlatformID, string FirmwareVersion, string OSVersion)
|
||||||
string FilePath = Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\WPInternals.config");
|
{
|
||||||
|
FFUEntry Entry = FFURepository.Find(e => e.PlatformID == PlatformID && e.FirmwareVersion == FirmwareVersion && string.Equals(e.Path, FFUPath, StringComparison.CurrentCultureIgnoreCase));
|
||||||
XmlSerializer x = new(typeof(WPinternalsConfig), "");
|
if (Entry == null)
|
||||||
|
{
|
||||||
XmlSerializerNamespaces ns = new();
|
LogFile.Log("Adding FFU to repository: " + FFUPath, LogType.FileAndConsole);
|
||||||
ns.Add("", "");
|
LogFile.Log("Platform ID: " + PlatformID, LogType.FileAndConsole);
|
||||||
StreamWriter FileWriter = new(FilePath);
|
if (FirmwareVersion != null)
|
||||||
x.Serialize(FileWriter, this, ns);
|
{
|
||||||
FileWriter.Close();
|
LogFile.Log("Firmware version: " + FirmwareVersion, LogType.FileAndConsole);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void SetProfile(string Type, string PlatformID, string ProductCode, string PhoneFirmware, string FfuFirmware, UInt32 FillSize, UInt32 HeaderSize, bool AssumeImageHeaderFallsInGap, bool AllocateAsyncBuffersOnPhone)
|
if (OSVersion != null)
|
||||||
{
|
{
|
||||||
FlashProfile Profile = GetProfile(PlatformID, PhoneFirmware, FfuFirmware);
|
LogFile.Log("OS version: " + OSVersion, LogType.FileAndConsole);
|
||||||
if (Profile == null)
|
}
|
||||||
{
|
|
||||||
Profile = new FlashProfile
|
Entry = new FFUEntry
|
||||||
{
|
{
|
||||||
Type = Type,
|
Path = FFUPath,
|
||||||
PlatformID = PlatformID,
|
PlatformID = PlatformID,
|
||||||
ProductCode = ProductCode,
|
FirmwareVersion = FirmwareVersion,
|
||||||
PhoneFirmware = PhoneFirmware,
|
OSVersion = OSVersion
|
||||||
FfuFirmware = FfuFirmware
|
};
|
||||||
};
|
FFURepository.Add(Entry);
|
||||||
FlashProfiles.Add(Profile);
|
WriteConfig();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
Profile.FillSize = FillSize;
|
{
|
||||||
Profile.HeaderSize = HeaderSize;
|
LogFile.Log("FFU not added, because it was already present in the repository.", LogType.FileAndConsole);
|
||||||
Profile.AssumeImageHeaderFallsInGap = AssumeImageHeaderFallsInGap;
|
}
|
||||||
Profile.AllocateAsyncBuffersOnPhone = AllocateAsyncBuffersOnPhone;
|
}
|
||||||
|
|
||||||
WriteConfig();
|
internal void RemoveFfuFromRepository(string FFUPath)
|
||||||
}
|
{
|
||||||
|
int Count = 0;
|
||||||
internal FlashProfile GetProfile(string PlatformID, string PhoneFirmware, string FfuFirmware = null)
|
FFURepository.Where(e => string.Equals(e.Path, FFUPath, StringComparison.CurrentCultureIgnoreCase)).ToList().ForEach(e =>
|
||||||
{
|
{
|
||||||
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)));
|
Count++;
|
||||||
}
|
FFURepository.Remove(e);
|
||||||
|
});
|
||||||
public List<FlashProfile> FlashProfiles = new();
|
if (Count == 0)
|
||||||
|
{
|
||||||
internal void AddFfuToRepository(string FFUPath)
|
LogFile.Log("FFU was not removed from repository because it was not present.", LogType.FileAndConsole);
|
||||||
{
|
}
|
||||||
try
|
else
|
||||||
{
|
{
|
||||||
FFU NewFFU = new(FFUPath);
|
LogFile.Log("Removed FFU from repository: " + FFUPath, LogType.FileAndConsole);
|
||||||
AddFfuToRepository(FFUPath, NewFFU.PlatformID, NewFFU.GetFirmwareVersion(), NewFFU.GetOSVersion());
|
WriteConfig();
|
||||||
}
|
}
|
||||||
catch (Exception Ex)
|
}
|
||||||
{
|
|
||||||
LogFile.LogException(Ex, LogType.FileAndConsole);
|
public List<FFUEntry> FFURepository = [];
|
||||||
}
|
|
||||||
}
|
internal void AddSecWimToRepository(string SecWimPath, string FirmwareVersion)
|
||||||
|
{
|
||||||
internal void AddFfuToRepository(string FFUPath, string PlatformID, string FirmwareVersion, string OSVersion)
|
SecWimEntry Entry = SecWimRepository.Find(e => e.FirmwareVersion == FirmwareVersion && string.Equals(e.Path, SecWimPath, StringComparison.CurrentCultureIgnoreCase));
|
||||||
{
|
if (Entry == null)
|
||||||
FFUEntry Entry = FFURepository.Find(e => (e.PlatformID == PlatformID) && (e.FirmwareVersion == FirmwareVersion) && string.Equals(e.Path, FFUPath, StringComparison.CurrentCultureIgnoreCase));
|
{
|
||||||
if (Entry == null)
|
LogFile.Log("Adding Secure WIM to repository: " + SecWimPath, LogType.FileAndConsole);
|
||||||
{
|
if (FirmwareVersion != null)
|
||||||
LogFile.Log("Adding FFU to repository: " + FFUPath, LogType.FileAndConsole);
|
{
|
||||||
LogFile.Log("Platform ID: " + PlatformID, LogType.FileAndConsole);
|
LogFile.Log("Firmware version: " + FirmwareVersion, LogType.FileAndConsole);
|
||||||
if (FirmwareVersion != null)
|
}
|
||||||
{
|
|
||||||
LogFile.Log("Firmware version: " + FirmwareVersion, LogType.FileAndConsole);
|
Entry = new SecWimEntry
|
||||||
}
|
{
|
||||||
|
Path = SecWimPath,
|
||||||
if (OSVersion != null)
|
FirmwareVersion = FirmwareVersion
|
||||||
{
|
};
|
||||||
LogFile.Log("OS version: " + OSVersion, LogType.FileAndConsole);
|
SecWimRepository.Add(Entry);
|
||||||
}
|
WriteConfig();
|
||||||
|
}
|
||||||
Entry = new FFUEntry
|
else
|
||||||
{
|
{
|
||||||
Path = FFUPath,
|
LogFile.Log("Secure WIM not added, because it was already present in the repository.", LogType.FileAndConsole);
|
||||||
PlatformID = PlatformID,
|
}
|
||||||
FirmwareVersion = FirmwareVersion,
|
}
|
||||||
OSVersion = OSVersion
|
|
||||||
};
|
internal void RemoveSecWimFromRepository(string SecWimPath)
|
||||||
FFURepository.Add(Entry);
|
{
|
||||||
WriteConfig();
|
int Count = 0;
|
||||||
}
|
SecWimRepository.Where(e => string.Equals(e.Path, SecWimPath, StringComparison.CurrentCultureIgnoreCase)).ToList().ForEach(e =>
|
||||||
else
|
{
|
||||||
{
|
Count++;
|
||||||
LogFile.Log("FFU not added, because it was already present in the repository.", LogType.FileAndConsole);
|
SecWimRepository.Remove(e);
|
||||||
}
|
});
|
||||||
}
|
if (Count == 0)
|
||||||
|
{
|
||||||
internal void RemoveFfuFromRepository(string FFUPath)
|
LogFile.Log("Secure WIM was not removed from repository because it was not present.", LogType.FileAndConsole);
|
||||||
{
|
}
|
||||||
int Count = 0;
|
else
|
||||||
FFURepository.Where(e => string.Equals(e.Path, FFUPath, StringComparison.CurrentCultureIgnoreCase)).ToList().ForEach(e =>
|
{
|
||||||
{
|
LogFile.Log("Removed Secure WIM from repository: " + SecWimPath, LogType.FileAndConsole);
|
||||||
Count++;
|
WriteConfig();
|
||||||
FFURepository.Remove(e);
|
}
|
||||||
});
|
}
|
||||||
if (Count == 0)
|
|
||||||
{
|
public List<SecWimEntry> SecWimRepository = [];
|
||||||
LogFile.Log("FFU was not removed from repository because it was not present.", LogType.FileAndConsole);
|
|
||||||
}
|
public List<EmergencyFileEntry> EmergencyRepository = [];
|
||||||
else
|
|
||||||
{
|
internal void AddEmergencyToRepository(string Type, string ProgrammerPath, string PayloadPath)
|
||||||
LogFile.Log("Removed FFU from repository: " + FFUPath, LogType.FileAndConsole);
|
{
|
||||||
WriteConfig();
|
EmergencyFileEntry Entry = EmergencyRepository.Find(e => e.Type == Type && string.Equals(e.ProgrammerPath, ProgrammerPath, StringComparison.CurrentCultureIgnoreCase));
|
||||||
}
|
if (Entry != null && PayloadPath != null && !string.Equals(Entry.PayloadPath, PayloadPath, StringComparison.CurrentCultureIgnoreCase))
|
||||||
}
|
{
|
||||||
|
LogFile.Log("Updating emergency payload path in repository: " + PayloadPath, LogType.FileAndConsole);
|
||||||
public List<FFUEntry> FFURepository = new();
|
Entry.PayloadPath = PayloadPath;
|
||||||
|
WriteConfig();
|
||||||
public List<EmergencyFileEntry> EmergencyRepository = new();
|
}
|
||||||
|
else if (Entry == null)
|
||||||
internal void AddEmergencyToRepository(string Type, string ProgrammerPath, string PayloadPath)
|
{
|
||||||
{
|
LogFile.Log("Adding emergency files to repository: " + ProgrammerPath, LogType.FileAndConsole);
|
||||||
EmergencyFileEntry Entry = EmergencyRepository.Find(e => (e.Type == Type) && string.Equals(e.ProgrammerPath, ProgrammerPath, StringComparison.CurrentCultureIgnoreCase));
|
LogFile.Log("Type: " + Type, LogType.FileAndConsole);
|
||||||
if ((Entry != null) && (PayloadPath != null) && (!string.Equals(Entry.PayloadPath, PayloadPath, StringComparison.CurrentCultureIgnoreCase)))
|
|
||||||
{
|
Entry = new EmergencyFileEntry
|
||||||
LogFile.Log("Updating emergency payload path in repository: " + PayloadPath, LogType.FileAndConsole);
|
{
|
||||||
Entry.PayloadPath = PayloadPath;
|
Type = Type,
|
||||||
WriteConfig();
|
ProgrammerPath = ProgrammerPath,
|
||||||
}
|
PayloadPath = PayloadPath
|
||||||
else if (Entry == null)
|
};
|
||||||
{
|
|
||||||
LogFile.Log("Adding emergency files to repository: " + ProgrammerPath, LogType.FileAndConsole);
|
QualcommPartition Programmer = new(ProgrammerPath);
|
||||||
LogFile.Log("Type: " + Type, LogType.FileAndConsole);
|
Entry.RKH = Programmer.RootKeyHash;
|
||||||
|
|
||||||
Entry = new EmergencyFileEntry
|
EmergencyRepository.Add(Entry);
|
||||||
{
|
WriteConfig();
|
||||||
Type = Type,
|
}
|
||||||
ProgrammerPath = ProgrammerPath,
|
else
|
||||||
PayloadPath = PayloadPath
|
{
|
||||||
};
|
LogFile.Log("Emergency files not added, because they were already present in the repository.", LogType.FileAndConsole);
|
||||||
|
}
|
||||||
QualcommPartition Programmer = new(ProgrammerPath);
|
}
|
||||||
Entry.RKH = Programmer.RootKeyHash;
|
|
||||||
|
internal void RemoveEmergencyFromRepository(string ProgrammerPath)
|
||||||
EmergencyRepository.Add(Entry);
|
{
|
||||||
WriteConfig();
|
int Count = 0;
|
||||||
}
|
EmergencyRepository.Where(e => string.Equals(e.ProgrammerPath, ProgrammerPath, StringComparison.CurrentCultureIgnoreCase)).ToList().ForEach(e =>
|
||||||
else
|
{
|
||||||
{
|
Count++;
|
||||||
LogFile.Log("Emergency files not added, because they were already present in the repository.", LogType.FileAndConsole);
|
EmergencyRepository.Remove(e);
|
||||||
}
|
});
|
||||||
}
|
if (Count == 0)
|
||||||
|
{
|
||||||
internal void RemoveEmergencyFromRepository(string ProgrammerPath)
|
LogFile.Log("Emergency file was not removed from repository because it was not present.", LogType.FileAndConsole);
|
||||||
{
|
}
|
||||||
int Count = 0;
|
else
|
||||||
EmergencyRepository.Where(e => string.Equals(e.ProgrammerPath, ProgrammerPath, StringComparison.CurrentCultureIgnoreCase)).ToList().ForEach(e =>
|
{
|
||||||
{
|
LogFile.Log("Removed Emergency file from repository: " + ProgrammerPath, LogType.FileAndConsole);
|
||||||
Count++;
|
WriteConfig();
|
||||||
EmergencyRepository.Remove(e);
|
}
|
||||||
});
|
}
|
||||||
if (Count == 0)
|
|
||||||
{
|
public string RegistrationName;
|
||||||
LogFile.Log("Emergency file was not removed from repository because it was not present.", LogType.FileAndConsole);
|
public string RegistrationEmail;
|
||||||
}
|
public string RegistrationSkypeID;
|
||||||
else
|
public string RegistrationTelegramID;
|
||||||
{
|
public string RegistrationKey;
|
||||||
LogFile.Log("Removed Emergency file from repository: " + ProgrammerPath, LogType.FileAndConsole);
|
}
|
||||||
WriteConfig();
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string RegistrationName;
|
|
||||||
public string RegistrationEmail;
|
|
||||||
public string RegistrationSkypeID;
|
|
||||||
public string RegistrationTelegramID;
|
|
||||||
public string RegistrationKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class FlashProfile
|
|
||||||
{
|
|
||||||
public string Type;
|
|
||||||
public string PlatformID;
|
|
||||||
public string ProductCode;
|
|
||||||
public string PhoneFirmware;
|
|
||||||
public string FfuFirmware;
|
|
||||||
|
|
||||||
[XmlIgnore]
|
|
||||||
internal UInt32 FillSize;
|
|
||||||
[XmlIgnore]
|
|
||||||
internal UInt32 HeaderSize;
|
|
||||||
[XmlIgnore]
|
|
||||||
internal bool AssumeImageHeaderFallsInGap;
|
|
||||||
[XmlIgnore]
|
|
||||||
internal bool AllocateAsyncBuffersOnPhone;
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "Profile")]
|
|
||||||
public string ProfileAsString
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
byte[] ValueBuffer = new byte[10];
|
|
||||||
ValueBuffer[0] = 1; // Profile version
|
|
||||||
ByteOperations.WriteUInt32(ValueBuffer, 1, FillSize);
|
|
||||||
ByteOperations.WriteUInt32(ValueBuffer, 5, HeaderSize);
|
|
||||||
if (AssumeImageHeaderFallsInGap)
|
|
||||||
{
|
|
||||||
ValueBuffer[9] |= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AllocateAsyncBuffersOnPhone)
|
|
||||||
{
|
|
||||||
ValueBuffer[9] |= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Convert.ToBase64String(ValueBuffer);
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
byte[] ValueBuffer = Convert.FromBase64String(value);
|
|
||||||
byte Version = ValueBuffer[0];
|
|
||||||
FillSize = ByteOperations.ReadUInt32(ValueBuffer, 1);
|
|
||||||
HeaderSize = ByteOperations.ReadUInt32(ValueBuffer, 5);
|
|
||||||
AssumeImageHeaderFallsInGap = (ValueBuffer[9] & 1) != 0;
|
|
||||||
AllocateAsyncBuffersOnPhone = (ValueBuffer[9] & 2) != 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class FFUEntry
|
|
||||||
{
|
|
||||||
public string PlatformID;
|
|
||||||
public string FirmwareVersion;
|
|
||||||
public string OSVersion;
|
|
||||||
public string Path;
|
|
||||||
|
|
||||||
internal bool Exists()
|
|
||||||
{
|
|
||||||
return File.Exists(Path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class EmergencyFileEntry
|
|
||||||
{
|
|
||||||
public string Type;
|
|
||||||
|
|
||||||
[XmlIgnore]
|
|
||||||
public byte[] RKH;
|
|
||||||
[XmlElement(ElementName = "RKH")]
|
|
||||||
public string RKHAsString
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return RKH == null ? null : Converter.ConvertHexToString(RKH, "");
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
RKH = value == null ? null : Converter.ConvertStringToHex(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ProgrammerPath;
|
|
||||||
public string PayloadPath;
|
|
||||||
|
|
||||||
internal bool ProgrammerExists()
|
|
||||||
{
|
|
||||||
return File.Exists(ProgrammerPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal bool PayloadExists()
|
|
||||||
{
|
|
||||||
return File.Exists(PayloadPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -61,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,41 +1,41 @@
|
|||||||
<!--
|
<!--
|
||||||
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"),
|
||||||
to deal in the Software without restriction, including without limitation
|
to deal in the Software without restriction, including without limitation
|
||||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
and/or sell copies of the Software, and to permit persons to whom the
|
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:
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
The above copyright notice and this permission notice shall be included in
|
||||||
all copies or substantial portions of the Software.
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
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
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
DEALINGS IN THE SOFTWARE.
|
DEALINGS IN THE SOFTWARE.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<UserControl
|
<UserControl
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:WPinternals" x:Class="WPinternals.FilePickerBase"
|
xmlns:local="clr-namespace:WPinternals" x:Class="WPinternals.FilePickerBase"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="100" d:DesignWidth="300"
|
d:DesignHeight="100" d:DesignWidth="300"
|
||||||
x:Name="FilePickerControlName"
|
x:Name="FilePickerControlName"
|
||||||
SizeChanged="SizeChangedHandler" Loaded="LoadedHandler"
|
SizeChanged="SizeChangedHandler" Loaded="LoadedHandler"
|
||||||
>
|
>
|
||||||
<Grid>
|
<Grid>
|
||||||
<TextBlock x:Name="CaptionTextBlock" HorizontalAlignment="Left" Text=""/>
|
<TextBlock x:Name="CaptionTextBlock" HorizontalAlignment="Left" Text=""/>
|
||||||
<TextBlock x:Name="PathTextBlock" FontWeight="Bold" HorizontalAlignment="Left" Text="Path here"/>
|
<TextBlock x:Name="PathTextBlock" FontWeight="Bold" HorizontalAlignment="Left" Text="Path here"/>
|
||||||
<TextBlock x:Name="SelectLink" Margin="150,0,0,0" HorizontalAlignment="Left"><Hyperlink NavigateUri="Select" Click="SelectLink_Click"><TextBlock Text="{Binding Path=SelectionText, ElementName=FilePickerControlName}"/></Hyperlink></TextBlock>
|
<TextBlock x:Name="SelectLink" Margin="150,0,0,0" HorizontalAlignment="Left"><Hyperlink NavigateUri="Select" Click="SelectLink_Click"><TextBlock Text="{Binding Path=SelectionText, ElementName=FilePickerControlName}"/></Hyperlink></TextBlock>
|
||||||
<TextBlock x:Name="ChangeLink" Margin="210,0,0,0" HorizontalAlignment="Left"><Hyperlink NavigateUri="Change" Click="ChangeLink_Click">Change</Hyperlink></TextBlock>
|
<TextBlock x:Name="ChangeLink" Margin="210,0,0,0" HorizontalAlignment="Left"><Hyperlink NavigateUri="Change" Click="ChangeLink_Click">Change</Hyperlink></TextBlock>
|
||||||
<TextBlock x:Name="ClearLink" Margin="260,0,0,0" HorizontalAlignment="Left"><Hyperlink NavigateUri="Clear" Click="ClearLink_Click">Clear</Hyperlink></TextBlock>
|
<TextBlock x:Name="ClearLink" Margin="260,0,0,0" HorizontalAlignment="Left"><Hyperlink NavigateUri="Clear" Click="ClearLink_Click">Clear</Hyperlink></TextBlock>
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@@ -1,120 +1,120 @@
|
|||||||
// This class was found online.
|
// This class was found online.
|
||||||
// Original author is probably: Swizzy
|
// Original author is probably: Swizzy
|
||||||
// https://github.com/ttgxdinger/Random/blob/master/CPUKey%20Checker/CPUKey%20Checker/FolderSelectDialog.cs
|
// https://github.com/ttgxdinger/Random/blob/master/CPUKey%20Checker/CPUKey%20Checker/FolderSelectDialog.cs
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace WPinternals
|
namespace WPinternals
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Wraps System.Windows.Forms.OpenFileDialog to make it present
|
/// Wraps System.Windows.Forms.OpenFileDialog to make it present
|
||||||
/// a vista-style dialog.
|
/// a vista-style dialog.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class FolderSelectDialog
|
public class FolderSelectDialog
|
||||||
{
|
{
|
||||||
// Wrapped dialog
|
// Wrapped dialog
|
||||||
private readonly OpenFileDialog ofd = null;
|
private readonly OpenFileDialog ofd = null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default constructor
|
/// Default constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public FolderSelectDialog()
|
public FolderSelectDialog()
|
||||||
{
|
{
|
||||||
ofd = new OpenFileDialog
|
ofd = new OpenFileDialog
|
||||||
{
|
{
|
||||||
Filter = "Folders|\n",
|
Filter = "Folders|\n",
|
||||||
AddExtension = false,
|
AddExtension = false,
|
||||||
CheckFileExists = false,
|
CheckFileExists = false,
|
||||||
DereferenceLinks = true,
|
DereferenceLinks = true,
|
||||||
Multiselect = false
|
Multiselect = false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets/Sets the initial folder to be selected. A null value selects the current directory.
|
/// Gets/Sets the initial folder to be selected. A null value selects the current directory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string InitialDirectory
|
public string InitialDirectory
|
||||||
{
|
{
|
||||||
get { return ofd.InitialDirectory; }
|
get { return ofd.InitialDirectory; }
|
||||||
set { ofd.InitialDirectory = string.IsNullOrEmpty(value) ? Environment.CurrentDirectory : value; }
|
set { ofd.InitialDirectory = string.IsNullOrEmpty(value) ? Environment.CurrentDirectory : value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets/Sets the title to show in the dialog
|
/// Gets/Sets the title to show in the dialog
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Title
|
public string Title
|
||||||
{
|
{
|
||||||
get { return ofd.Title; }
|
get { return ofd.Title; }
|
||||||
set { ofd.Title = value ?? "Select a folder"; }
|
set { ofd.Title = value ?? "Select a folder"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the selected folder
|
/// Gets the selected folder
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string FileName
|
public string FileName
|
||||||
{
|
{
|
||||||
get { return ofd.FileName; }
|
get { return ofd.FileName; }
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Methods
|
#region Methods
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shows the dialog
|
/// Shows the dialog
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>True if the user presses OK else false</returns>
|
/// <returns>True if the user presses OK else false</returns>
|
||||||
public bool ShowDialog()
|
public bool ShowDialog()
|
||||||
{
|
{
|
||||||
return ShowDialog(IntPtr.Zero);
|
return ShowDialog(IntPtr.Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shows the dialog
|
/// Shows the dialog
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="hWndOwner">Handle of the control to be parent</param>
|
/// <param name="hWndOwner">Handle of the control to be parent</param>
|
||||||
/// <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,
|
||||||
ShowNewFolderButton = false
|
ShowNewFolderButton = false
|
||||||
};
|
};
|
||||||
if (fbd.ShowDialog(new WindowWrapper(hWndOwner)) != DialogResult.OK)
|
if (fbd.ShowDialog(new WindowWrapper(hWndOwner)) != DialogResult.OK)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ofd.FileName = fbd.SelectedPath;
|
ofd.FileName = fbd.SelectedPath;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates IWin32Window around an IntPtr
|
/// Creates IWin32Window around an IntPtr
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class WindowWrapper : IWin32Window
|
public class WindowWrapper : IWin32Window
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor
|
/// Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="handle">Handle to wrap</param>
|
/// <param name="handle">Handle to wrap</param>
|
||||||
public WindowWrapper(IntPtr handle)
|
public WindowWrapper(IntPtr handle)
|
||||||
{
|
{
|
||||||
Handle = handle;
|
Handle = handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Original ptr
|
/// Original ptr
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IntPtr Handle { get; }
|
public IntPtr Handle { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
// Some of the classes and functions in this file were found online.
|
||||||
|
// Where possible the original authors are referenced.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace WPinternals.HelperClasses
|
||||||
|
{
|
||||||
|
internal class ArrivalEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public PhoneInterfaces NewInterface;
|
||||||
|
public IDisposable NewModel;
|
||||||
|
|
||||||
|
public ArrivalEventArgs(PhoneInterfaces NewInterface, IDisposable NewModel)
|
||||||
|
: base()
|
||||||
|
{
|
||||||
|
this.NewInterface = NewInterface;
|
||||||
|
this.NewModel = NewModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
};
|
||||||
|
}
|
||||||