Some cleanup

This commit is contained in:
Gustave Monce
2024-10-12 14:09:19 +02:00
parent 7fc332e912
commit 57c9595d86
153 changed files with 5490 additions and 3613 deletions
+2
View File
@@ -22,6 +22,8 @@ using System;
using System.IO;
using System.Threading;
using System.Windows;
using WPinternals.HelperClasses;
using WPinternals.Config;
namespace WPinternals
{
+15 -8
View File
@@ -26,6 +26,13 @@ using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using WPinternals.Config;
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia.MSR;
using WPinternals.Models.Lumia.NCSd;
using WPinternals.Models.UEFIApps.BootMgr;
using WPinternals.Models.UEFIApps.Flash;
using WPinternals.Models.UEFIApps.PhoneInfo;
namespace WPinternals
{
@@ -86,7 +93,7 @@ namespace WPinternals
LumiaFlashAppModel FlashModel;
LumiaBootManagerAppModel BootMgrModel;
LumiaPhoneInfoAppModel PhoneInfoModel;
NokiaPhoneModel NormalModel;
NokiaCareSuiteModel NormalModel;
LumiaFlashAppPhoneInfo FlashInfo;
LumiaPhoneInfoAppPhoneInfo PhoneInfo;
LumiaBootManagerPhoneInfo BootManagerInfo;
@@ -244,7 +251,7 @@ namespace WPinternals
LogFile.BeginAction("ConvertGPT");
try
{
using var stream = File.OpenRead(args[2]);
using FileStream stream = File.OpenRead(args[2]);
byte[] GPTBuffer = new byte[34 * 0x200];
stream.Read(GPTBuffer, 0, 34 * 0x200);
GPT GPT = new(GPTBuffer);// May throw NotSupportedException
@@ -1273,7 +1280,7 @@ namespace WPinternals
UIContext.Send(s => Notifier.Start(), null);
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
{
NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
NormalModel = (NokiaCareSuiteModel)Notifier.CurrentModel;
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
}
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
@@ -1328,7 +1335,7 @@ namespace WPinternals
}
else
{
NormalModel = (NokiaPhoneModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
NormalModel = (NokiaCareSuiteModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
}
URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
@@ -1478,7 +1485,7 @@ namespace WPinternals
UIContext.Send(s => Notifier.Start(), null);
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
{
NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
NormalModel = (NokiaCareSuiteModel)Notifier.CurrentModel;
ProductType = NormalModel.ExecuteJsonMethodAsString("ReadManufacturerModelName", "ManufacturerModelName");
if (ProductType.Contains('_'))
{
@@ -1501,7 +1508,7 @@ namespace WPinternals
}
else
{
NormalModel = (NokiaPhoneModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
NormalModel = (NokiaCareSuiteModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
ProductType = NormalModel.ExecuteJsonMethodAsString("ReadManufacturerModelName", "ManufacturerModelName");
if (ProductType.Contains('_'))
{
@@ -1601,7 +1608,7 @@ namespace WPinternals
UIContext.Send(s => Notifier.Start(), null);
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
{
NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
NormalModel = (NokiaCareSuiteModel)Notifier.CurrentModel;
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
}
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
@@ -1620,7 +1627,7 @@ namespace WPinternals
}
else
{
NormalModel = (NokiaPhoneModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
NormalModel = (NokiaCareSuiteModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
}
URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
+59
View File
@@ -0,0 +1,59 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.IO;
using System.Xml.Serialization;
using WPinternals.HelperClasses;
namespace WPinternals.Config
{
public class EmergencyFileEntry
{
public string Type;
[XmlIgnore]
public byte[] RKH;
[XmlElement(ElementName = "RKH")]
public string RKHAsString
{
get
{
return RKH == null ? null : Converter.ConvertHexToString(RKH, "");
}
set
{
RKH = value == null ? null : Converter.ConvertStringToHex(value);
}
}
public string ProgrammerPath;
public string PayloadPath;
internal bool ProgrammerExists()
{
return File.Exists(ProgrammerPath);
}
internal bool PayloadExists()
{
return File.Exists(PayloadPath);
}
}
}
@@ -18,23 +18,20 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
namespace WPinternals
{
internal class CommonPhoneInfo
{
public PhoneInfoState State = PhoneInfoState.Empty;
using System.IO;
public FlashAppType App;
public byte VersionMajor;
public byte VersionMinor;
public byte ProtocolVersionMajor;
public byte ProtocolVersionMinor;
internal void Log(LogType Type)
namespace WPinternals.Config
{
LogFile.Log($"App: {VersionMajor}.{VersionMinor}", Type);
LogFile.Log($"Protocol: {ProtocolVersionMajor}.{ProtocolVersionMinor}", Type);
public class FFUEntry
{
public string PlatformID;
public string FirmwareVersion;
public string OSVersion;
public string Path;
internal bool Exists()
{
return File.Exists(Path);
}
}
}
+75
View File
@@ -0,0 +1,75 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Xml.Serialization;
namespace WPinternals.Config
{
public class FlashProfile
{
public string Type;
public string PlatformID;
public string ProductCode;
public string PhoneFirmware;
public string FfuFirmware;
[XmlIgnore]
internal uint FillSize;
[XmlIgnore]
internal uint HeaderSize;
[XmlIgnore]
internal bool AssumeImageHeaderFallsInGap;
[XmlIgnore]
internal bool AllocateAsyncBuffersOnPhone;
[XmlElement(ElementName = "Profile")]
public string ProfileAsString
{
get
{
byte[] ValueBuffer = new byte[10];
ValueBuffer[0] = 1; // Profile version
ByteOperations.WriteUInt32(ValueBuffer, 1, FillSize);
ByteOperations.WriteUInt32(ValueBuffer, 5, HeaderSize);
if (AssumeImageHeaderFallsInGap)
{
ValueBuffer[9] |= 1;
}
if (AllocateAsyncBuffersOnPhone)
{
ValueBuffer[9] |= 2;
}
return Convert.ToBase64String(ValueBuffer);
}
set
{
byte[] ValueBuffer = Convert.FromBase64String(value);
byte Version = ValueBuffer[0];
FillSize = ByteOperations.ReadUInt32(ValueBuffer, 1);
HeaderSize = ByteOperations.ReadUInt32(ValueBuffer, 5);
AssumeImageHeaderFallsInGap = (ValueBuffer[9] & 1) != 0;
AllocateAsyncBuffersOnPhone = (ValueBuffer[9] & 2) != 0;
}
}
}
}
+84
View File
@@ -0,0 +1,84 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Windows;
namespace WPinternals.Config
{
internal static class Registration
{
#if PREVIEW
internal const bool IsPrerelease = true;
#else
internal const bool IsPrerelease = false;
#endif
internal static readonly DateTime ExpirationDate = new(2024, 12, 21);
internal static void CheckExpiration()
{
#if PREVIEW
//if (IsPrerelease && (DateTime.Now >= ExpirationDate))
if (DateTime.Now >= ExpirationDate)
{
if (Environment.GetCommandLineArgs().Count() > 1)
{
Console.WriteLine("This prerelease version is expired!");
CommandLine.CloseConsole();
}
else
MessageBox.Show("This prerelease version is expired!", "Windows Phone Internals", MessageBoxButton.OK, MessageBoxImage.Exclamation);
Environment.Exit(0);
}
#endif
}
internal static bool IsRegistered()
{
bool Result = false;
if (App.Config.RegistrationName != null)
{
Result = CalcRegKey() == App.Config.RegistrationKey;
}
return Result;
}
internal static string CalcRegKey()
{
string KeyBase = App.Config.RegistrationName;
if (Environment.MachineName == null)
{
KeyBase += "-Unknown";
}
else
{
KeyBase += "-" + Environment.MachineName;
}
byte[] KeyBytes = System.Text.Encoding.UTF8.GetBytes(KeyBase);
SHA1Managed sha = new();
byte[] Key = sha.ComputeHash(KeyBytes);
return Convert.ToBase64String(Key);
}
}
}
+35
View File
@@ -0,0 +1,35 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.IO;
namespace WPinternals.Config
{
public class SecWimEntry
{
public string FirmwareVersion;
public string Path;
internal bool Exists()
{
return File.Exists(Path);
}
}
}
@@ -22,68 +22,11 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Windows;
using System.Xml.Serialization;
using WPinternals.HelperClasses;
namespace WPinternals
namespace WPinternals.Config
{
internal static class Registration
{
#if PREVIEW
internal const bool IsPrerelease = true;
#else
internal const bool IsPrerelease = false;
#endif
internal static readonly DateTime ExpirationDate = new(2024, 12, 21);
internal static void CheckExpiration()
{
#if PREVIEW
//if (IsPrerelease && (DateTime.Now >= ExpirationDate))
if (DateTime.Now >= ExpirationDate)
{
if (Environment.GetCommandLineArgs().Count() > 1)
{
Console.WriteLine("This prerelease version is expired!");
CommandLine.CloseConsole();
}
else
MessageBox.Show("This prerelease version is expired!", "Windows Phone Internals", MessageBoxButton.OK, MessageBoxImage.Exclamation);
Environment.Exit(0);
}
#endif
}
internal static bool IsRegistered()
{
bool Result = false;
if (App.Config.RegistrationName != null)
{
Result = CalcRegKey() == App.Config.RegistrationKey;
}
return Result;
}
internal static string CalcRegKey()
{
string KeyBase = App.Config.RegistrationName;
if (Environment.MachineName == null)
{
KeyBase += "-Unknown";
}
else
{
KeyBase += "-" + Environment.MachineName;
}
byte[] KeyBytes = System.Text.Encoding.UTF8.GetBytes(KeyBase);
SHA1Managed sha = new();
byte[] Key = sha.ComputeHash(KeyBytes);
return Convert.ToBase64String(Key);
}
}
public class WPinternalsConfig
{
@@ -122,7 +65,7 @@ namespace WPinternals
FileWriter.Close();
}
internal void SetProfile(string Type, string PlatformID, string ProductCode, string PhoneFirmware, string FfuFirmware, UInt32 FillSize, UInt32 HeaderSize, bool AssumeImageHeaderFallsInGap, bool AllocateAsyncBuffersOnPhone)
internal void SetProfile(string Type, string PlatformID, string ProductCode, string PhoneFirmware, string FfuFirmware, uint FillSize, uint HeaderSize, bool AssumeImageHeaderFallsInGap, bool AllocateAsyncBuffersOnPhone)
{
FlashProfile Profile = GetProfile(PlatformID, PhoneFirmware, FfuFirmware);
if (Profile == null)
@@ -148,7 +91,7 @@ namespace WPinternals
internal FlashProfile GetProfile(string PlatformID, string PhoneFirmware, string FfuFirmware = null)
{
return FlashProfiles.Find(p => string.Equals(p.PlatformID, PlatformID, StringComparison.CurrentCultureIgnoreCase) && string.Equals(p.PhoneFirmware, PhoneFirmware, StringComparison.CurrentCultureIgnoreCase) && ((FfuFirmware == null) || string.Equals(p.FfuFirmware, FfuFirmware, StringComparison.CurrentCultureIgnoreCase)));
return FlashProfiles.Find(p => string.Equals(p.PlatformID, PlatformID, StringComparison.CurrentCultureIgnoreCase) && string.Equals(p.PhoneFirmware, PhoneFirmware, StringComparison.CurrentCultureIgnoreCase) && (FfuFirmware == null || string.Equals(p.FfuFirmware, FfuFirmware, StringComparison.CurrentCultureIgnoreCase)));
}
public List<FlashProfile> FlashProfiles = [];
@@ -168,7 +111,7 @@ namespace WPinternals
internal void AddFfuToRepository(string FFUPath, string PlatformID, string FirmwareVersion, string OSVersion)
{
FFUEntry Entry = FFURepository.Find(e => (e.PlatformID == PlatformID) && (e.FirmwareVersion == FirmwareVersion) && string.Equals(e.Path, FFUPath, StringComparison.CurrentCultureIgnoreCase));
FFUEntry Entry = FFURepository.Find(e => e.PlatformID == PlatformID && e.FirmwareVersion == FirmwareVersion && string.Equals(e.Path, FFUPath, StringComparison.CurrentCultureIgnoreCase));
if (Entry == null)
{
LogFile.Log("Adding FFU to repository: " + FFUPath, LogType.FileAndConsole);
@@ -222,7 +165,7 @@ namespace WPinternals
internal void AddSecWimToRepository(string SecWimPath, string FirmwareVersion)
{
SecWimEntry Entry = SecWimRepository.Find(e => (e.FirmwareVersion == FirmwareVersion) && string.Equals(e.Path, SecWimPath, StringComparison.CurrentCultureIgnoreCase));
SecWimEntry Entry = SecWimRepository.Find(e => e.FirmwareVersion == FirmwareVersion && string.Equals(e.Path, SecWimPath, StringComparison.CurrentCultureIgnoreCase));
if (Entry == null)
{
LogFile.Log("Adding Secure WIM to repository: " + SecWimPath, LogType.FileAndConsole);
@@ -270,8 +213,8 @@ namespace WPinternals
internal void AddEmergencyToRepository(string Type, string ProgrammerPath, string PayloadPath)
{
EmergencyFileEntry Entry = EmergencyRepository.Find(e => (e.Type == Type) && string.Equals(e.ProgrammerPath, ProgrammerPath, StringComparison.CurrentCultureIgnoreCase));
if ((Entry != null) && (PayloadPath != null) && (!string.Equals(Entry.PayloadPath, PayloadPath, StringComparison.CurrentCultureIgnoreCase)))
EmergencyFileEntry Entry = EmergencyRepository.Find(e => e.Type == Type && string.Equals(e.ProgrammerPath, ProgrammerPath, StringComparison.CurrentCultureIgnoreCase));
if (Entry != null && PayloadPath != null && !string.Equals(Entry.PayloadPath, PayloadPath, StringComparison.CurrentCultureIgnoreCase))
{
LogFile.Log("Updating emergency payload path in repository: " + PayloadPath, LogType.FileAndConsole);
Entry.PayloadPath = PayloadPath;
@@ -326,111 +269,4 @@ namespace WPinternals
public string RegistrationTelegramID;
public string RegistrationKey;
}
public class FlashProfile
{
public string Type;
public string PlatformID;
public string ProductCode;
public string PhoneFirmware;
public string FfuFirmware;
[XmlIgnore]
internal UInt32 FillSize;
[XmlIgnore]
internal UInt32 HeaderSize;
[XmlIgnore]
internal bool AssumeImageHeaderFallsInGap;
[XmlIgnore]
internal bool AllocateAsyncBuffersOnPhone;
[XmlElement(ElementName = "Profile")]
public string ProfileAsString
{
get
{
byte[] ValueBuffer = new byte[10];
ValueBuffer[0] = 1; // Profile version
ByteOperations.WriteUInt32(ValueBuffer, 1, FillSize);
ByteOperations.WriteUInt32(ValueBuffer, 5, HeaderSize);
if (AssumeImageHeaderFallsInGap)
{
ValueBuffer[9] |= 1;
}
if (AllocateAsyncBuffersOnPhone)
{
ValueBuffer[9] |= 2;
}
return Convert.ToBase64String(ValueBuffer);
}
set
{
byte[] ValueBuffer = Convert.FromBase64String(value);
byte Version = ValueBuffer[0];
FillSize = ByteOperations.ReadUInt32(ValueBuffer, 1);
HeaderSize = ByteOperations.ReadUInt32(ValueBuffer, 5);
AssumeImageHeaderFallsInGap = (ValueBuffer[9] & 1) != 0;
AllocateAsyncBuffersOnPhone = (ValueBuffer[9] & 2) != 0;
}
}
}
public class FFUEntry
{
public string PlatformID;
public string FirmwareVersion;
public string OSVersion;
public string Path;
internal bool Exists()
{
return File.Exists(Path);
}
}
public class SecWimEntry
{
public string FirmwareVersion;
public string Path;
internal bool Exists()
{
return File.Exists(Path);
}
}
public class EmergencyFileEntry
{
public string Type;
[XmlIgnore]
public byte[] RKH;
[XmlElement(ElementName = "RKH")]
public string RKHAsString
{
get
{
return RKH == null ? null : Converter.ConvertHexToString(RKH, "");
}
set
{
RKH = value == null ? null : Converter.ConvertStringToHex(value);
}
}
public string ProgrammerPath;
public string PayloadPath;
internal bool ProgrammerExists()
{
return File.Exists(ProgrammerPath);
}
internal bool PayloadExists()
{
return File.Exists(PayloadPath);
}
}
}
+2 -1
View File
@@ -24,6 +24,7 @@ using System.Globalization;
using System.Threading;
using System.Windows;
using System.Windows.Media;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -149,7 +150,7 @@ namespace WPinternals
protected override Size MeasureOverride(Size availableSize)
{
var resultSize = new Size(availableSize.Width, 0);
Size resultSize = new Size(availableSize.Width, 0);
#if NETCORE
FormattedText formatted = new FormattedText(
+1 -1
View File
@@ -79,7 +79,7 @@ namespace WPinternals
/// <returns>True if the user presses OK else false</returns>
public bool ShowDialog(IntPtr hWndOwner)
{
var fbd = new FolderBrowserDialog
FolderBrowserDialog fbd = new FolderBrowserDialog
{
Description = this.Title,
SelectedPath = this.InitialDirectory,
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,40 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
namespace WPinternals.HelperClasses
{
internal class ArrivalEventArgs : EventArgs
{
public PhoneInterfaces NewInterface;
public IDisposable NewModel;
public ArrivalEventArgs(PhoneInterfaces NewInterface, IDisposable NewModel)
: base()
{
this.NewInterface = NewInterface;
this.NewModel = NewModel;
}
}
}
@@ -0,0 +1,111 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace WPinternals.HelperClasses
{
internal class AsyncAutoResetEvent
{
private readonly LinkedList<TaskCompletionSource<bool>> waiters =
new();
private bool isSignaled;
public AsyncAutoResetEvent(bool signaled)
{
isSignaled = signaled;
}
public Task<bool> WaitAsync(TimeSpan timeout)
{
return WaitAsync(timeout, CancellationToken.None);
}
public async Task<bool> WaitAsync(TimeSpan timeout, CancellationToken cancellationToken)
{
TaskCompletionSource<bool> tcs;
lock (waiters)
{
if (isSignaled)
{
isSignaled = false;
return true;
}
else if (timeout == TimeSpan.Zero)
{
return isSignaled;
}
else
{
tcs = new TaskCompletionSource<bool>();
waiters.AddLast(tcs);
}
}
Task winner = await Task.WhenAny(tcs.Task, Task.Delay(timeout, cancellationToken));
if (winner == tcs.Task)
{
// The task was signaled.
return true;
}
else
{
// We timed-out; remove our reference to the task.
// This is an O(n) operation since waiters is a LinkedList<T>.
lock (waiters)
{
bool removed = waiters.Remove(tcs);
System.Diagnostics.Debug.Assert(removed);
return false;
}
}
}
public void Set()
{
TaskCompletionSource<bool> toRelease = null;
lock (waiters)
{
if (waiters.Count > 0)
{
// Signal the first task in the waiters list.
toRelease = waiters.First.Value;
waiters.RemoveFirst();
}
else if (!isSignaled)
{
// No tasks are pending
isSignaled = true;
}
}
toRelease?.SetResult(true);
}
}
}
+162
View File
@@ -0,0 +1,162 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace WPinternals.HelperClasses
{
// This class was found online.
// Original author is probably: John Melville
// https://social.msdn.microsoft.com/Forums/en-US/163ef755-ff7b-4ea5-b226-bbe8ef5f4796/is-there-a-pattern-for-calling-an-async-method-synchronously?forum=async
public static class AsyncHelpers
{
/// <summary>
/// Execute's an async Task<T> method which has a void return value synchronously
/// </summary>
/// <param name="task">Task<T> method to execute</param>
public static void RunSync(Func<Task> task)
{
SynchronizationContext oldContext = SynchronizationContext.Current;
ExclusiveSynchronizationContext synch = new ExclusiveSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(synch);
synch.Post(async _ =>
{
try
{
await task();
}
catch (Exception e)
{
synch.InnerException = e;
throw;
}
finally
{
synch.EndMessageLoop();
}
}, null);
synch.BeginMessageLoop();
SynchronizationContext.SetSynchronizationContext(oldContext);
}
/// <summary>
/// Execute's an async Task<T> method which has a T return type synchronously
/// </summary>
/// <typeparam name="T">Return Type</typeparam>
/// <param name="task">Task<T> method to execute</param>
/// <returns></returns>
public static T RunSync<T>(Func<Task<T>> task)
{
SynchronizationContext oldContext = SynchronizationContext.Current;
ExclusiveSynchronizationContext synch = new ExclusiveSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(synch);
T ret = default;
synch.Post(async _ =>
{
try
{
ret = await task();
}
catch (Exception e)
{
synch.InnerException = e;
throw;
}
finally
{
synch.EndMessageLoop();
}
}, null);
synch.BeginMessageLoop();
SynchronizationContext.SetSynchronizationContext(oldContext);
return ret;
}
private class ExclusiveSynchronizationContext : SynchronizationContext
{
private bool done;
public Exception InnerException
{
get; set;
}
private readonly AutoResetEvent workItemsWaiting = new(false);
private readonly Queue<Tuple<SendOrPostCallback, object>> items =
new();
public override void Send(SendOrPostCallback d, object state)
{
throw new NotSupportedException("We cannot send to our same thread");
}
public override void Post(SendOrPostCallback d, object state)
{
lock (items)
{
items.Enqueue(Tuple.Create(d, state));
}
workItemsWaiting.Set();
}
public void EndMessageLoop()
{
Post(_ => done = true, null);
}
public void BeginMessageLoop()
{
while (!done)
{
Tuple<SendOrPostCallback, object> task = null;
lock (items)
{
if (items.Count > 0)
{
task = items.Dequeue();
}
}
if (task != null)
{
task.Item1(task.Item2);
if (InnerException != null) // the method threw an exeption
{
throw new AggregateException("AsyncHelpers.Run method threw an exception.", InnerException);
}
}
else
{
workItemsWaiting.WaitOne();
}
}
}
public override SynchronizationContext CreateCopy()
{
return this;
}
}
}
}
+125
View File
@@ -0,0 +1,125 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
namespace WPinternals.HelperClasses
{
internal static class BigEndian
{
public static byte[] GetBytes(object Value)
{
byte[] Bytes;
if (Value is short)
{
Bytes = BitConverter.GetBytes((short)Value);
}
else if (Value is ushort)
{
Bytes = BitConverter.GetBytes((ushort)Value);
}
else if (Value is int)
{
Bytes = BitConverter.GetBytes((int)Value);
}
else
{
Bytes = Value is uint ? BitConverter.GetBytes((uint)Value) : throw new NotSupportedException();
}
byte[] Result = new byte[Bytes.Length];
for (int i = 0; i < Bytes.Length; i++)
{
Result[i] = Bytes[Bytes.Length - 1 - i];
}
return Result;
}
public static byte[] GetBytes(object Value, int Width)
{
byte[] Result;
byte[] BigEndianBytes = GetBytes(Value);
if (BigEndianBytes.Length == Width)
{
return BigEndianBytes;
}
else if (BigEndianBytes.Length > Width)
{
Result = new byte[Width];
Buffer.BlockCopy(BigEndianBytes, BigEndianBytes.Length - Width, Result, 0, Width);
return Result;
}
else
{
Result = new byte[Width];
Buffer.BlockCopy(BigEndianBytes, 0, Result, Width - BigEndianBytes.Length, BigEndianBytes.Length);
return Result;
}
}
public static ushort ToUInt16(byte[] Buffer, int Offset)
{
byte[] Bytes = new byte[2];
for (int i = 0; i < 2; i++)
{
Bytes[i] = Buffer[Offset + 1 - i];
}
return BitConverter.ToUInt16(Bytes, 0);
}
public static short ToInt16(byte[] Buffer, int Offset)
{
byte[] Bytes = new byte[2];
for (int i = 0; i < 2; i++)
{
Bytes[i] = Buffer[Offset + 1 - i];
}
return BitConverter.ToInt16(Bytes, 0);
}
public static uint ToUInt32(byte[] Buffer, int Offset)
{
byte[] Bytes = new byte[4];
for (int i = 0; i < 4; i++)
{
Bytes[i] = Buffer[Offset + 3 - i];
}
return BitConverter.ToUInt32(Bytes, 0);
}
public static int ToInt32(byte[] Buffer, int Offset)
{
byte[] Bytes = new byte[4];
for (int i = 0; i < 4; i++)
{
Bytes[i] = Buffer[Offset + 3 - i];
}
return BitConverter.ToInt32(Bytes, 0);
}
}
}
@@ -0,0 +1,138 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace WPinternals.HelperClasses
{
public class BooleanConverter : DependencyObject, IValueConverter
{
public static readonly DependencyProperty OnTrueProperty =
DependencyProperty.Register("OnTrue", typeof(object), typeof(BooleanConverter),
new PropertyMetadata(default(object)));
public static readonly DependencyProperty OnFalseProperty =
DependencyProperty.Register("OnFalse", typeof(object), typeof(BooleanConverter),
new PropertyMetadata(default(object)));
public static readonly DependencyProperty OnNullProperty =
DependencyProperty.Register("OnNull", typeof(object), typeof(BooleanConverter),
new PropertyMetadata(default(object)));
public object OnTrue
{
get
{
return GetValue(OnTrueProperty);
}
set
{
SetValue(OnTrueProperty, value);
}
}
public object OnFalse
{
get
{
return GetValue(OnFalseProperty);
}
set
{
SetValue(OnFalseProperty, value);
}
}
public object OnNull
{
get
{
return GetValue(OnNullProperty);
}
set
{
SetValue(OnNullProperty, value);
}
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null
? OnNull ?? Default(targetType)
: string.Equals(value.ToString(), false.ToString(), StringComparison.CurrentCultureIgnoreCase)
? OnFalse
: OnTrue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == OnNull)
{
return Default(targetType);
}
if (value == OnFalse)
{
return false;
}
if (value == OnTrue)
{
return true;
}
if (value == null)
{
return null;
}
if (OnNull != null &&
string.Equals(value.ToString(), OnNull.ToString(), StringComparison.CurrentCultureIgnoreCase))
{
return Default(targetType);
}
if (OnFalse != null &&
string.Equals(value.ToString(), OnFalse.ToString(), StringComparison.CurrentCultureIgnoreCase))
{
return false;
}
if (OnTrue != null &&
string.Equals(value.ToString(), OnTrue.ToString(), StringComparison.CurrentCultureIgnoreCase))
{
return true;
}
return null;
}
public static object Default(Type type)
{
return type.IsValueType ? Activator.CreateInstance(type) : null;
}
}
}
@@ -0,0 +1,59 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Windows;
using System.Windows.Documents;
namespace WPinternals.HelperClasses
{
internal class CollapsibleRun : Run
{
private string CollapsibleText;
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
CollapsibleText = Text;
}
public bool IsVisible
{
get
{
return (bool)GetValue(IsVisibleProperty);
}
set
{
SetValue(IsVisibleProperty, value);
}
}
public static readonly DependencyProperty IsVisibleProperty = DependencyProperty.Register(
"IsVisible", typeof(bool), typeof(CollapsibleRun), new PropertyMetadata(true, IsVisibleChanged));
public static void IsVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((CollapsibleRun)d).Text = (bool)e.NewValue ? ((CollapsibleRun)d).CollapsibleText : string.Empty;
}
}
}
@@ -0,0 +1,79 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Documents;
namespace WPinternals.HelperClasses
{
internal class CollapsibleSection : Section
{
public CollapsibleSection()
{
CollapsibleBlocks = [];
}
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
foreach (Block Block in Blocks)
{
CollapsibleBlocks.Add(Block);
}
Blocks.Clear();
}
public List<Block> CollapsibleBlocks
{
get;
}
public bool IsCollapsed
{
get
{
return (bool)GetValue(IsCollapsedProperty);
}
set
{
SetValue(IsCollapsedProperty, value);
Blocks.Clear();
if (IsInitialized && !value)
{
foreach (Block Block in CollapsibleBlocks)
{
Blocks.Add(Block);
}
}
}
}
public static readonly DependencyProperty IsCollapsedProperty = DependencyProperty.Register(
"IsCollapsed", typeof(bool), typeof(CollapsibleSection), new PropertyMetadata(false));
}
}
@@ -0,0 +1,136 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.IO;
using System.IO.Compression;
using System.Text;
namespace WPinternals.HelperClasses
{
// For writing a compressed stream
internal class CompressedStream : Stream
{
private readonly uint HeaderSize;
private ulong WritePosition;
private readonly GZipStream UnderlyingStream;
internal CompressedStream(Stream OutputStream, ulong TotalDecompressedStreamLength)
{
// Write header
HeaderSize = (uint)(0x12 + "CompressedPartition".Length);
OutputStream.WriteByte(0xFF);
OutputStream.Write(Encoding.ASCII.GetBytes("CompressedPartition"), 0, "CompressedPartition".Length);
OutputStream.WriteByte(0x00);
OutputStream.Write(BitConverter.GetBytes((uint)1), 0, 4); // Format version = 1
OutputStream.Write(BitConverter.GetBytes(HeaderSize), 0, 4); // Headersize
OutputStream.Write(BitConverter.GetBytes(TotalDecompressedStreamLength), 0, 8);
UnderlyingStream = new GZipStream(OutputStream, CompressionLevel.Optimal, false);
WritePosition = 0;
}
public override bool CanRead
{
get
{
return false;
}
}
public override bool CanSeek
{
get
{
return false;
}
}
public override int Read(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override long Position
{
get
{
return (long)WritePosition;
}
set
{
throw new NotSupportedException();
}
}
public override bool CanTimeout
{
get
{
return UnderlyingStream.CanTimeout;
}
}
public override bool CanWrite
{
get
{
return true;
}
}
public override long Length
{
get
{
return (long)WritePosition;
}
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
WritePosition += (ulong)count;
UnderlyingStream.Write(buffer, offset, count);
}
public override void Flush()
{
UnderlyingStream.Flush();
}
public override void Close()
{
UnderlyingStream.Close();
}
public new void Dispose()
{
UnderlyingStream.Dispose();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
UnderlyingStream.Dispose();
}
}
}
}
+60
View File
@@ -0,0 +1,60 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System.Collections;
using System.IO;
using System.IO.Compression;
namespace WPinternals.HelperClasses
{
internal static class Compression
{
internal static Stream GetDecompressedStreamWithSeek(Stream InputStream)
{
long P = InputStream.Position;
byte[] GZipHeader = new byte[3];
InputStream.Read(GZipHeader, 0, 3);
InputStream.Position = P;
if (StructuralComparisons.StructuralEqualityComparer.Equals(GZipHeader, new byte[] { 0x1F, 0x8B, 0x08 }))
{
return new GZipStream(InputStream, CompressionMode.Decompress, false);
}
else
{
return InputStream;
}
}
internal static bool IsCompressedStream(Stream InputStream)
{
byte[] GZipHeader = new byte[3];
InputStream.Read(GZipHeader, 0, 3);
return StructuralComparisons.StructuralEqualityComparer.Equals(GZipHeader, new byte[] { 0x1F, 0x8B, 0x08 });
}
internal static GZipStream GetDecompressedStream(Stream InputStream)
{
return new GZipStream(InputStream, CompressionMode.Decompress, false);
}
}
}
+74
View File
@@ -0,0 +1,74 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Text;
namespace WPinternals.HelperClasses
{
public static class Converter
{
public static string ConvertHexToString(byte[] Bytes, string Separator)
{
StringBuilder s = new(1000);
for (int i = Bytes.GetLowerBound(0); i <= Bytes.GetUpperBound(0); i++)
{
if (i != Bytes.GetLowerBound(0))
{
s.Append(Separator);
}
s.Append(Bytes[i].ToString("X2"));
}
return s.ToString();
}
public static byte[] ConvertStringToHex(string HexString)
{
if (HexString.Length % 2 == 1)
{
throw new Exception("The binary key cannot have an odd number of digits");
}
byte[] arr = new byte[HexString.Length >> 1];
for (int i = 0; i < HexString.Length >> 1; ++i)
{
arr[i] = (byte)((GetHexVal(HexString[i << 1]) << 4) + GetHexVal(HexString[(i << 1) + 1]));
}
return arr;
}
public static int GetHexVal(char hex)
{
int val = hex;
//For uppercase A-F letters:
//return val - (val < 58 ? 48 : 55);
//For lowercase a-f letters:
//return val - (val < 58 ? 48 : 87);
//Or the two combined, but a bit slower:
return val - (val < 58 ? 48 : val < 97 ? 55 : 87);
}
}
}
@@ -0,0 +1,181 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Collections;
using System.IO;
using System.IO.Compression;
using System.Text;
namespace WPinternals.HelperClasses
{
// For reading a compressed stream or normal stream
internal class DecompressedStream : Stream
{
private readonly Stream UnderlyingStream;
private readonly bool IsSourceCompressed;
private readonly ulong DecompressedLength;
private long ReadPosition = 0;
// For reading a compressed stream
internal DecompressedStream(Stream InputStream)
{
UnderlyingStream = new ReadSeekableStream(InputStream, 0x100);
byte[] Signature = new byte["CompressedPartition".Length + 2];
Signature[0x00] = 0xFF;
Buffer.BlockCopy(Encoding.ASCII.GetBytes("CompressedPartition"), 0, Signature, 0x01, "CompressedPartition".Length);
Signature["CompressedPartition".Length + 1] = 0x00;
int PrimaryHeaderSize = 0x0A + "CompressedPartition".Length;
byte[] SignatureRead = new byte[Signature.Length];
UnderlyingStream.Read(SignatureRead, 0, Signature.Length);
IsSourceCompressed = StructuralComparisons.StructuralEqualityComparer.Equals(Signature, SignatureRead);
if (IsSourceCompressed)
{
byte[] FormatVersionBytes = new byte[4];
UnderlyingStream.Read(FormatVersionBytes, 0, 4);
if (BitConverter.ToUInt32(FormatVersionBytes, 0) > 1) // Max supported format version = 1
{
throw new InvalidDataException();
}
byte[] HeaderSizeBytes = new byte[4];
UnderlyingStream.Read(HeaderSizeBytes, 0, 4);
uint HeaderSize = BitConverter.ToUInt32(HeaderSizeBytes, 0);
if (HeaderSize >= Signature.Length + 0x10)
{
byte[] DecompressedLengthBytes = new byte[8];
UnderlyingStream.Read(DecompressedLengthBytes, 0, 8);
DecompressedLength = BitConverter.ToUInt64(DecompressedLengthBytes, 0);
}
else
{
throw new InvalidDataException();
}
uint HeaderBytesRemaining = (uint)(HeaderSize - Signature.Length - 0x10);
if (HeaderBytesRemaining > 0)
{
byte[] HeaderBytes = new byte[HeaderBytesRemaining];
UnderlyingStream.Read(HeaderBytes, 0, (int)HeaderBytesRemaining);
}
UnderlyingStream = new GZipStream(UnderlyingStream, CompressionMode.Decompress, false);
}
else
{
UnderlyingStream.Position = 0;
}
}
public override bool CanRead
{
get
{
return true;
}
}
public override bool CanSeek
{
get
{
return false;
}
}
public override int Read(byte[] buffer, int offset, int count)
{
int RealCount = UnderlyingStream.Read(buffer, offset, count);
ReadPosition += RealCount;
return RealCount;
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override long Position
{
get
{
return ReadPosition;
}
set
{
throw new NotSupportedException();
}
}
public override bool CanTimeout
{
get
{
return UnderlyingStream.CanTimeout;
}
}
public override bool CanWrite
{
get
{
return true;
}
}
public override long Length
{
get
{
if (IsSourceCompressed)
{
return (long)DecompressedLength;
}
else
{
return UnderlyingStream.Length;
}
}
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
public override void Flush()
{
UnderlyingStream.Flush();
}
public override void Close()
{
UnderlyingStream.Close();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
UnderlyingStream.Dispose();
}
}
}
}
@@ -0,0 +1,51 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
namespace WPinternals.HelperClasses
{
// This class is taken from the Prism library by Microsoft Patterns & Practices
// License: http://compositewpf.codeplex.com/license
public class DelegateCommand : DelegateCommandBase
{
public DelegateCommand(Action executeMethod)
: this(executeMethod, () => true)
{
}
public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod) : base(o => executeMethod(), f => canExecuteMethod())
{
}
public bool CanExecute()
{
return CanExecute(null);
}
public void Execute()
{
Execute(null);
}
}
}
@@ -0,0 +1,118 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Collections.Generic;
using System.Windows.Input;
namespace WPinternals.HelperClasses
{
// This class is taken from the Prism library by Microsoft Patterns & Practices
// License: http://compositewpf.codeplex.com/license
public abstract class DelegateCommandBase : ICommand, IActiveAware
{
private List<WeakReference> _canExecuteChangedHandlers;
private bool _isActive;
private readonly Func<object, bool> canExecuteMethod;
private readonly Action<object> executeMethod;
public event EventHandler CanExecuteChanged
{
add
{
WeakEventHandlerManager.AddWeakReferenceHandler(ref _canExecuteChangedHandlers, value, 2);
}
remove
{
WeakEventHandlerManager.RemoveWeakReferenceHandler(_canExecuteChangedHandlers, value);
}
}
public event EventHandler IsActiveChanged;
protected DelegateCommandBase(Action<object> executeMethod, Func<object, bool> canExecuteMethod)
{
if (executeMethod == null || canExecuteMethod == null)
{
throw new ArgumentNullException(nameof(executeMethod), "Delegate Command Delegates Cannot Be Null");
}
this.executeMethod = executeMethod;
this.canExecuteMethod = canExecuteMethod;
}
protected bool CanExecute(object parameter)
{
if (canExecuteMethod != null)
{
return canExecuteMethod(parameter);
}
return true;
}
protected void Execute(object parameter)
{
executeMethod(parameter);
}
protected virtual void OnCanExecuteChanged()
{
WeakEventHandlerManager.CallWeakReferenceHandlers(this, _canExecuteChangedHandlers);
}
protected virtual void OnIsActiveChanged()
{
IsActiveChanged?.Invoke(this, EventArgs.Empty);
}
public void RaiseCanExecuteChanged()
{
OnCanExecuteChanged();
}
bool ICommand.CanExecute(object parameter)
{
return CanExecute(parameter);
}
void ICommand.Execute(object parameter)
{
Execute(parameter);
}
public bool IsActive
{
get
{
return _isActive;
}
set
{
if (_isActive != value)
{
_isActive = value;
OnIsActiveChanged();
}
}
}
}
}
@@ -0,0 +1,49 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Threading;
using System.Threading.Tasks;
namespace WPinternals.HelperClasses
{
internal static class ExtensionMethods
{
// This method was written by: Lawrence Johnston
// https://stackoverflow.com/a/22078975
public static async Task<TResult> TimeoutAfter<TResult>(this Task<TResult> task, TimeSpan timeout)
{
using CancellationTokenSource timeoutCancellationTokenSource = new CancellationTokenSource();
Task completedTask = await Task.WhenAny(task, Task.Delay(timeout, timeoutCancellationTokenSource.Token));
if (completedTask == task)
{
timeoutCancellationTokenSource.Cancel();
return await task; // Very important in order to propagate exceptions
}
else
{
throw new TimeoutException("The operation has timed out.");
}
}
}
}
@@ -0,0 +1,35 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System.Windows.Controls;
using System.Windows.Input;
namespace WPinternals.HelperClasses
{
internal class FlowDocumentScrollViewerNoMouseWheel : FlowDocumentScrollViewer
{
protected override void OnMouseWheel(MouseWheelEventArgs e)
{
}
}
}
+150
View File
@@ -0,0 +1,150 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
namespace WPinternals.HelperClasses
{
// This class was found online.
// Original author is probably: mdm20
// https://stackoverflow.com/questions/5566330/get-gif-to-play-in-wpf-with-gifimage-class/5568703#5568703
internal class GifImage : Image
{
private bool _isInitialized;
private GifBitmapDecoder _gifDecoder;
private Int32Animation _animation;
public int FrameIndex
{
get
{
return (int)GetValue(FrameIndexProperty);
}
set
{
SetValue(FrameIndexProperty, value);
}
}
private void Initialize()
{
_gifDecoder = new GifBitmapDecoder(new Uri("pack://application:,,," + GifSource), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
_animation = new Int32Animation(0, _gifDecoder.Frames.Count - 1, new Duration(new TimeSpan(0, 0, 0, _gifDecoder.Frames.Count / 10, (int)((_gifDecoder.Frames.Count / 10.0 - _gifDecoder.Frames.Count / 10) * 1000))))
{
RepeatBehavior = RepeatBehavior.Forever
};
Source = _gifDecoder.Frames[0];
_isInitialized = true;
}
static GifImage()
{
VisibilityProperty.OverrideMetadata(typeof(GifImage),
new FrameworkPropertyMetadata(VisibilityPropertyChanged));
}
private static void VisibilityPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
if ((Visibility)e.NewValue == Visibility.Visible)
{
((GifImage)sender).StartAnimation();
}
else
{
((GifImage)sender).StopAnimation();
}
}
public static readonly DependencyProperty FrameIndexProperty =
DependencyProperty.Register("FrameIndex", typeof(int), typeof(GifImage), new UIPropertyMetadata(0, new PropertyChangedCallback(ChangingFrameIndex)));
private static void ChangingFrameIndex(DependencyObject obj, DependencyPropertyChangedEventArgs ev)
{
GifImage gifImage = obj as GifImage;
gifImage.Source = gifImage._gifDecoder.Frames[(int)ev.NewValue];
}
public bool AutoStart
{
get
{
return (bool)GetValue(AutoStartProperty);
}
set
{
SetValue(AutoStartProperty, value);
}
}
public static readonly DependencyProperty AutoStartProperty =
DependencyProperty.Register("AutoStart", typeof(bool), typeof(GifImage), new UIPropertyMetadata(false, AutoStartPropertyChanged));
private static void AutoStartPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue)
{
(sender as GifImage)?.StartAnimation();
}
}
public string GifSource
{
get
{
return (string)GetValue(GifSourceProperty);
}
set
{
SetValue(GifSourceProperty, value);
}
}
public static readonly DependencyProperty GifSourceProperty =
DependencyProperty.Register("GifSource", typeof(string), typeof(GifImage), new UIPropertyMetadata(string.Empty, GifSourcePropertyChanged));
private static void GifSourcePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
(sender as GifImage)?.Initialize();
}
public void StartAnimation()
{
if (!_isInitialized)
{
Initialize();
}
BeginAnimation(FrameIndexProperty, _animation);
}
public void StopAnimation()
{
BeginAnimation(FrameIndexProperty, null);
}
}
}
@@ -0,0 +1,321 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
namespace WPinternals.HelperClasses
{
// This class was written by: Rolf Wessels
// https://github.com/rolfwessels/lazycowprojects/tree/master/Wpf
/// <summary>
/// Static class used to attach to wpf control
/// </summary>
public static class GridViewColumnResize
{
#region DependencyProperties
public static readonly DependencyProperty WidthProperty =
DependencyProperty.RegisterAttached("Width", typeof(string), typeof(GridViewColumnResize),
new PropertyMetadata(OnSetWidthCallback));
public static readonly DependencyProperty GridViewColumnResizeBehaviorProperty =
DependencyProperty.RegisterAttached("GridViewColumnResizeBehavior",
typeof(GridViewColumnResizeBehavior), typeof(GridViewColumnResize),
null);
public static readonly DependencyProperty EnabledProperty =
DependencyProperty.RegisterAttached("Enabled", typeof(bool), typeof(GridViewColumnResize),
new PropertyMetadata(OnSetEnabledCallback));
public static readonly DependencyProperty ListViewResizeBehaviorProperty =
DependencyProperty.RegisterAttached("ListViewResizeBehaviorProperty",
typeof(ListViewResizeBehavior), typeof(GridViewColumnResize), null);
#endregion
public static string GetWidth(DependencyObject obj)
{
return (string)obj.GetValue(WidthProperty);
}
public static void SetWidth(DependencyObject obj, string value)
{
obj.SetValue(WidthProperty, value);
}
public static bool GetEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(EnabledProperty);
}
public static void SetEnabled(DependencyObject obj, bool value)
{
obj.SetValue(EnabledProperty, value);
}
#region CallBack
private static void OnSetWidthCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
if (dependencyObject is GridViewColumn element)
{
GridViewColumnResizeBehavior behavior = GetOrCreateBehavior(element);
behavior.Width = e.NewValue as string;
}
else
{
Console.Error.WriteLine("Error: Expected type GridViewColumn but found " +
dependencyObject.GetType().Name);
}
}
private static void OnSetEnabledCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
if (dependencyObject is ListView element)
{
ListViewResizeBehavior behavior = GetOrCreateBehavior(element);
behavior.Enabled = (bool)e.NewValue;
}
else
{
Console.Error.WriteLine("Error: Expected type ListView but found " + dependencyObject.GetType().Name);
}
}
private static ListViewResizeBehavior GetOrCreateBehavior(ListView element)
{
if (element.GetValue(GridViewColumnResizeBehaviorProperty) is not ListViewResizeBehavior behavior)
{
behavior = new ListViewResizeBehavior(element);
element.SetValue(ListViewResizeBehaviorProperty, behavior);
}
return behavior;
}
private static GridViewColumnResizeBehavior GetOrCreateBehavior(GridViewColumn element)
{
if (element.GetValue(GridViewColumnResizeBehaviorProperty) is not GridViewColumnResizeBehavior behavior)
{
behavior = new GridViewColumnResizeBehavior(element);
element.SetValue(GridViewColumnResizeBehaviorProperty, behavior);
}
return behavior;
}
#endregion
#region Nested type: GridViewColumnResizeBehavior
// This class was written by: Rolf Wessels
// https://github.com/rolfwessels/lazycowprojects/tree/master/Wpf
/// <summary>
/// GridViewColumn class that gets attached to the GridViewColumn control
/// </summary>
public class GridViewColumnResizeBehavior
{
private readonly GridViewColumn _element;
public GridViewColumnResizeBehavior(GridViewColumn element)
{
_element = element;
}
public string Width
{
get; set;
}
public bool IsStatic
{
get
{
return StaticWidth >= 0;
}
}
public double StaticWidth
{
get
{
return double.TryParse(Width, out double result) ? result : -1;
}
}
public double Percentage
{
get
{
if (!IsStatic)
{
return Mulitplier * 100;
}
return 0;
}
}
public double Mulitplier
{
get
{
if (Width == "*" || Width == "1*")
{
return 1;
}
if (Width.EndsWith("*") && double.TryParse(Width[0..^1], out double perc))
{
return perc;
}
return 1;
}
}
public void SetWidth(double allowedSpace, double totalPercentage)
{
if (IsStatic)
{
_element.Width = StaticWidth;
}
else
{
_element.Width = (double)Math.Max(allowedSpace * (Percentage / totalPercentage), 0);
}
}
}
#endregion
#region Nested type: ListViewResizeBehavior
// This class was written by: Rolf Wessels
// https://github.com/rolfwessels/lazycowprojects/tree/master/Wpf
/// <summary>
/// ListViewResizeBehavior class that gets attached to the ListView control
/// </summary>
public class ListViewResizeBehavior
{
private const int Margin = 25;
private const long RefreshTime = Timeout.Infinite;
private const long Delay = 500;
private readonly ListView _element;
private readonly Timer _timer;
public ListViewResizeBehavior(ListView element)
{
_element = element ?? throw new ArgumentNullException(nameof(element));
element.Loaded += OnLoaded;
// Action for resizing and re-enable the size lookup
// This stops the columns from constantly resizing to improve performance
Action resizeAndEnableSize = () =>
{
Resize();
_element.SizeChanged += OnSizeChanged;
};
_timer = new Timer(x => Application.Current.Dispatcher.BeginInvoke(resizeAndEnableSize), null, Delay,
RefreshTime);
}
public bool Enabled
{
get; set;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
_element.SizeChanged += OnSizeChanged;
}
private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
if (e.WidthChanged)
{
_element.SizeChanged -= OnSizeChanged;
_timer.Change(Delay, RefreshTime);
}
}
private void Resize()
{
if (Enabled)
{
double totalWidth = _element.ActualWidth;
if (_element.View is GridView gv)
{
double allowedSpace = totalWidth - GetAllocatedSpace(gv);
allowedSpace -= Margin;
double totalPercentage = GridViewColumnResizeBehaviors(gv).Sum(x => x.Percentage);
foreach (GridViewColumnResizeBehavior behavior in GridViewColumnResizeBehaviors(gv))
{
behavior.SetWidth(allowedSpace, totalPercentage);
}
}
}
}
private static IEnumerable<GridViewColumnResizeBehavior> GridViewColumnResizeBehaviors(GridView gv)
{
foreach (GridViewColumn t in gv.Columns)
{
if (t.GetValue(GridViewColumnResizeBehaviorProperty) is GridViewColumnResizeBehavior gridViewColumnResizeBehavior)
{
yield return gridViewColumnResizeBehavior;
}
}
}
private static double GetAllocatedSpace(GridView gv)
{
double totalWidth = 0;
foreach (GridViewColumn t in gv.Columns)
{
if (t.GetValue(GridViewColumnResizeBehaviorProperty) is GridViewColumnResizeBehavior gridViewColumnResizeBehavior)
{
if (gridViewColumnResizeBehavior.IsStatic)
{
totalWidth += gridViewColumnResizeBehavior.StaticWidth;
}
}
else
{
totalWidth += t.ActualWidth;
}
}
return totalWidth;
}
}
#endregion
}
}
@@ -0,0 +1,30 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
namespace WPinternals.HelperClasses
{
internal delegate void SetWorkingStatus(string Message, string SubMessage = null, ulong? MaxProgressValue = null, bool ShowAnimation = true, WPinternalsStatus Status = WPinternalsStatus.Undefined);
internal delegate void UpdateWorkingStatus(string Message, string SubMessage = null, ulong? CurrentProgressValue = null, WPinternalsStatus Status = WPinternalsStatus.Undefined);
internal delegate void ExitSuccess(string Message, string SubMessage = null);
internal delegate void ExitFailure(string Message, string SubMessage = null);
}
+82
View File
@@ -0,0 +1,82 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Globalization;
using System.Text;
using System.Windows;
using System.Windows.Data;
namespace WPinternals.HelperClasses
{
public class HexConverter : DependencyObject, IValueConverter
{
public static readonly DependencyProperty SeparatorProperty =
DependencyProperty.Register("OnTrue", typeof(object), typeof(HexConverter),
new PropertyMetadata(" "));
public object Separator
{
get
{
return GetValue(SeparatorProperty);
}
set
{
SetValue(SeparatorProperty, value);
}
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is byte[] bytes)
{
StringBuilder s = new(1000);
for (int i = bytes.GetLowerBound(0); i <= bytes.GetUpperBound(0); i++)
{
if (i != bytes.GetLowerBound(0))
{
s.Append(Separator);
}
s.Append(bytes[i].ToString("X2"));
}
return s.ToString();
}
else
{
return "";
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public static object Default(Type type)
{
return type.IsValueType ? Activator.CreateInstance(type) : null;
}
}
}
+46
View File
@@ -0,0 +1,46 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
namespace WPinternals.HelperClasses
{
// This interface is taken from the Prism library by Microsoft Patterns & Practices
// License: http://compositewpf.codeplex.com/license
public interface IActiveAware
{
/// <summary>
/// Gets or sets a value indicating whether the object is active.
/// </summary>
/// <value><see langword="true" /> if the object is active; otherwise <see langword="false" />.</value>
bool IsActive
{
get; set;
}
/// <summary>
/// Notifies that the value for <see cref="IsActive"/> property has changed.
/// </summary>
event EventHandler IsActiveChanged;
}
}
@@ -0,0 +1,55 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace WPinternals.HelperClasses
{
public class InverseObjectToVisibilityConverter : DependencyObject, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
{
return "Visible";
}
else
{
return "Collapsed";
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public static object Default(Type type)
{
return type.IsValueType ? Activator.CreateInstance(type) : null;
}
}
}
+202
View File
@@ -0,0 +1,202 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text;
namespace WPinternals.HelperClasses
{
internal static class LogFile
{
private static readonly StreamWriter w = null;
private static readonly object lockobject = new();
#if PREVIEW
private static string LogAction = null;
private static StringBuilder LogBuilder;
#endif
static LogFile()
{
try
{
if (!Directory.Exists(Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals")))
{
Directory.CreateDirectory(Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals"));
}
w = File.AppendText(Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\WPInternals.log"));
}
catch { }
}
public static void Log(string logMessage, LogType Type = LogType.FileOnly)
{
if (w == null)
{
return;
}
lock (lockobject)
{
if (Type == LogType.FileOnly || Type == LogType.FileAndConsole)
{
DateTime Now = DateTime.Now;
string Text = Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + ": " + logMessage;
w.WriteLine(Text);
w.Flush();
#if PREVIEW
if (LogAction != null)
LogBuilder.AppendLine(Text);
#endif
}
if (CommandLine.IsConsoleVisible && (Type == LogType.ConsoleOnly || Type == LogType.FileAndConsole))
{
Console.WriteLine(logMessage);
}
}
}
public static void LogException(Exception Ex, LogType Type = LogType.FileAndConsole, string AdditionalInfo = null)
{
string Indent = "";
Exception CurrentEx = Ex;
while (CurrentEx != null)
{
Log(Indent + "Error: " + RemoveBadChars(CurrentEx.Message).Replace("of type '.' ", "") + (AdditionalInfo == null ? "" : " - " + AdditionalInfo), Type);
AdditionalInfo = null;
if (CurrentEx is WPinternalsException)
{
Log(Indent + ((WPinternalsException)CurrentEx).SubMessage, Type);
}
#if DEBUG
if (CurrentEx.StackTrace != null)
{
Log(Indent + CurrentEx.StackTrace, LogType.FileOnly);
}
#endif
Indent += " ";
CurrentEx = CurrentEx.InnerException;
}
}
private static string RemoveBadChars(string Text)
{
return System.Text.RegularExpressions.Regex.Replace(Text, @"[^\u0020-\u007E]+", string.Empty);
}
public static void DumpLog(StreamReader r)
{
string line;
while ((line = r.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
public static void LogApplicationVersion()
{
Log("Windows Phone Internals version " +
Assembly.GetExecutingAssembly().GetName().Version.Major.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Minor.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Build.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Revision.ToString(), LogType.FileAndConsole);
Log("Copyright Heathcliff74", LogType.FileAndConsole);
}
internal static void BeginAction(string Action)
{
#if PREVIEW
if (LogAction == null)
{
LogAction = Action;
LogBuilder = new StringBuilder();
LogBuilder.AppendLine("Windows Phone Internals version " +
Assembly.GetExecutingAssembly().GetName().Version.Major.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Minor.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Build.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Revision.ToString());
LogBuilder.AppendLine("Copyright Heathcliff74");
LogBuilder.AppendLine("Action: " + Action);
if (App.Config.RegistrationName != null)
LogBuilder.AppendLine("Name: " + App.Config.RegistrationName);
if (App.Config.RegistrationEmail != null)
LogBuilder.AppendLine("Mail: " + App.Config.RegistrationEmail);
if (App.Config.RegistrationSkypeID != null)
LogBuilder.AppendLine("Skype: " + App.Config.RegistrationSkypeID);
if (App.Config.RegistrationTelegramID != null)
LogBuilder.AppendLine("Telegram: " + App.Config.RegistrationTelegramID);
if (Environment.MachineName != null)
LogBuilder.AppendLine("Machine: " + Environment.MachineName);
}
#endif
}
internal static void EndAction()
{
EndAction(null);
}
internal static void EndAction(string Action)
{
#if PREVIEW
if (LogAction != null && (Action == null || LogAction == Action))
{
Action = LogAction;
LogAction = null;
string FileName = "";
if (App.Config.RegistrationName != null)
FileName += App.Config.RegistrationName + " - ";
FileName += DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture) + " - " + Action + " - " +
Assembly.GetExecutingAssembly().GetName().Version.Major.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Minor.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Build.ToString() + "." +
Assembly.GetExecutingAssembly().GetName().Version.Revision.ToString() + ".log";
// Normalize filename
try
{
FileName = Encoding.ASCII.GetString(Encoding.GetEncoding("ISO-8859-8").GetBytes(FileName));
}
catch { }
FileName = FileName.Replace("?", "");
if (Action.ToLower() == "registration")
Uploader.Upload(FileName, LogBuilder.ToString());
else
{
try
{
Uploader.Upload(FileName, LogBuilder.ToString());
}
catch { }
}
}
#endif
}
}
}
+32
View File
@@ -0,0 +1,32 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
namespace WPinternals.HelperClasses
{
internal enum LogType
{
FileOnly,
FileAndConsole,
ConsoleOnly
};
}
@@ -0,0 +1,55 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace WPinternals.HelperClasses
{
public class ObjectToVisibilityConverter : DependencyObject, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
{
return "Collapsed";
}
else
{
return "Visible";
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public static object Default(Type type)
{
return type.IsValueType ? Activator.CreateInstance(type) : null;
}
}
}
+128
View File
@@ -0,0 +1,128 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
namespace WPinternals.HelperClasses
{
internal static class PE
{
internal static byte[] GetResource(byte[] PEfile, int[] Index)
{
// Explanation of PE header here:
// https://msdn.microsoft.com/en-us/library/ms809762.aspx?f=255&MSPPError=-2147217396
uint PEPointer = ByteOperations.ReadUInt32(PEfile, 0x3C);
ushort OptionalHeaderSize = ByteOperations.ReadUInt16(PEfile, PEPointer + 0x14);
uint SectionTablePointer = PEPointer + 0x18 + OptionalHeaderSize;
ushort SectionCount = ByteOperations.ReadUInt16(PEfile, PEPointer + 0x06);
uint? ResourceSectionEntryPointer = null;
for (int i = 0; i < SectionCount; i++)
{
string SectionName = ByteOperations.ReadAsciiString(PEfile, (uint)(SectionTablePointer + i * 0x28), 8);
int e = SectionName.IndexOf('\0');
if (e >= 0)
{
SectionName = SectionName.Substring(0, e);
}
if (SectionName == ".rsrc")
{
ResourceSectionEntryPointer = (uint)(SectionTablePointer + i * 0x28);
break;
}
}
if (ResourceSectionEntryPointer == null)
{
throw new WPinternalsException("Resource-section not found");
}
uint ResourceRawSize = ByteOperations.ReadUInt32(PEfile, (uint)ResourceSectionEntryPointer + 0x10);
uint ResourceRawPointer = ByteOperations.ReadUInt32(PEfile, (uint)ResourceSectionEntryPointer + 0x14);
uint ResourceVirtualPointer = ByteOperations.ReadUInt32(PEfile, (uint)ResourceSectionEntryPointer + 0x0C);
uint p = ResourceRawPointer;
for (int i = 0; i < Index.Length; i++)
{
ushort ResourceNamedEntryCount = ByteOperations.ReadUInt16(PEfile, p + 0x0c);
ushort ResourceIdEntryCount = ByteOperations.ReadUInt16(PEfile, p + 0x0e);
for (int j = ResourceNamedEntryCount; j < ResourceNamedEntryCount + ResourceIdEntryCount; j++)
{
uint ResourceID = ByteOperations.ReadUInt32(PEfile, (uint)(p + 0x10 + j * 8));
uint NextPointer = ByteOperations.ReadUInt32(PEfile, (uint)(p + 0x10 + j * 8 + 4));
if (ResourceID == (uint)Index[i])
{
// Check high bit
if ((NextPointer & 0x80000000) == 0 != (i == Index.Length - 1))
{
throw new WPinternalsException("Bad resource path");
}
p = ResourceRawPointer + (NextPointer & 0x7fffffff);
break;
}
}
}
uint ResourceValuePointer = ByteOperations.ReadUInt32(PEfile, p) - ResourceVirtualPointer + ResourceRawPointer;
uint ResourceValueSize = ByteOperations.ReadUInt32(PEfile, p + 4);
byte[] ResourceValue = new byte[ResourceValueSize];
Array.Copy(PEfile, ResourceValuePointer, ResourceValue, 0, ResourceValueSize);
return ResourceValue;
}
internal static Version GetFileVersion(byte[] PEfile)
{
byte[] version = GetResource(PEfile, [(int)ResourceType.RT_VERSION, 1, 1033]);
// RT_VERSION format:
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms647001(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms646997(v=vs.85).aspx
const uint FixedFileInfoPointer = 0x28;
ushort Major = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x0A);
ushort Minor = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x08);
ushort Build = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x0E);
ushort Revision = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x0C);
return new Version(Major, Minor, Build, Revision);
}
internal static Version GetProductVersion(byte[] PEfile)
{
byte[] version = GetResource(PEfile, [(int)ResourceType.RT_VERSION, 1, 1033]);
// RT_VERSION format:
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms647001(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms646997(v=vs.85).aspx
const uint FixedFileInfoPointer = 0x28;
ushort Major = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x12);
ushort Minor = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x10);
ushort Build = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x16);
ushort Revision = ByteOperations.ReadUInt16(version, FixedFileInfoPointer + 0x14);
return new Version(Major, Minor, Build, Revision);
}
}
}
+52
View File
@@ -0,0 +1,52 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Linq;
using System.Windows.Documents;
namespace WPinternals.HelperClasses
{
// Overloaded Paragraph class to remove empty Run-elements, caused by auto-formatting new-lines in the XAML
// Use helpers:Paragraph in a FlowDocument
// This correction only works at run-time
public class Paragraph : System.Windows.Documents.Paragraph
{
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
int inlinesCount = Inlines.Count;
for (int i = 0; i < inlinesCount; i++)
{
Inline inline = Inlines.ElementAt(i);
if (inline is Run run)
{
if (run.Text == Convert.ToChar(32).ToString()) //ACSII 32 is the white space
{
run.Text = string.Empty;
}
}
}
}
}
}
@@ -0,0 +1,88 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
namespace WPinternals.HelperClasses
{
internal class ProgressUpdater
{
private readonly DateTime InitTime;
private DateTime LastUpdateTime;
private readonly ulong MaxValue;
private readonly Action<int, TimeSpan?> ProgressUpdateCallback;
internal int ProgressPercentage;
internal ProgressUpdater(ulong MaxValue, Action<int, TimeSpan?> ProgressUpdateCallback)
{
InitTime = DateTime.Now;
LastUpdateTime = DateTime.Now;
this.MaxValue = MaxValue;
this.ProgressUpdateCallback = ProgressUpdateCallback;
SetProgress(0);
}
private ulong _Progress;
internal ulong Progress
{
get
{
return _Progress;
}
}
internal void SetProgress(ulong NewValue)
{
if (_Progress != NewValue)
{
int PreviousProgressPercentage = (int)((double)_Progress / MaxValue * 100);
ProgressPercentage = (int)((double)NewValue / MaxValue * 100);
_Progress = NewValue;
if (DateTime.Now - LastUpdateTime > TimeSpan.FromSeconds(0.5) || ProgressPercentage == 100)
{
#if DEBUG
Console.WriteLine("Init time: " + InitTime.ToShortTimeString() + " / Now: " + DateTime.Now.ToString() + " / NewValue: " + NewValue.ToString() + " / MaxValue: " + MaxValue.ToString() + " ->> Percentage: " + ProgressPercentage.ToString() + " / Remaining: " + TimeSpan.FromTicks((long)((DateTime.Now - InitTime).Ticks / ((double)NewValue / MaxValue) * (1 - (double)NewValue / MaxValue))).ToString());
#endif
if (DateTime.Now - InitTime < TimeSpan.FromSeconds(30) && ProgressPercentage < 15)
{
ProgressUpdateCallback(ProgressPercentage, null);
}
else
{
ProgressUpdateCallback(ProgressPercentage, TimeSpan.FromTicks((long)((DateTime.Now - InitTime).Ticks / ((double)NewValue / MaxValue) * (1 - (double)NewValue / MaxValue))));
}
LastUpdateTime = DateTime.Now;
}
}
}
internal void IncreaseProgress(ulong Progress)
{
SetProgress(_Progress + Progress);
}
}
}
@@ -0,0 +1,342 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.IO;
namespace WPinternals.HelperClasses
{
// This class is written by: Eugene Beresovsky
// https://stackoverflow.com/questions/13035925/stream-wrapper-to-make-stream-seekable/28036366#28036366
internal class ReadSeekableStream : Stream
{
private long _underlyingPosition;
private readonly byte[] _seekBackBuffer;
private int _seekBackBufferCount;
private int _seekBackBufferIndex;
private readonly Stream _underlyingStream;
public ReadSeekableStream(Stream underlyingStream, int seekBackBufferSize)
{
if (!underlyingStream.CanRead)
{
throw new Exception("Provided stream " + underlyingStream + " is not readable");
}
_underlyingStream = underlyingStream;
_seekBackBuffer = new byte[seekBackBufferSize];
}
public override bool CanRead
{
get
{
return true;
}
}
public override bool CanSeek
{
get
{
return true;
}
}
public override int Read(byte[] buffer, int offset, int count)
{
int copiedFromBackBufferCount = 0;
if (_seekBackBufferIndex < _seekBackBufferCount)
{
copiedFromBackBufferCount = Math.Min(count, _seekBackBufferCount - _seekBackBufferIndex);
Buffer.BlockCopy(_seekBackBuffer, _seekBackBufferIndex, buffer, offset, copiedFromBackBufferCount);
offset += copiedFromBackBufferCount;
count -= copiedFromBackBufferCount;
_seekBackBufferIndex += copiedFromBackBufferCount;
}
int bytesReadFromUnderlying = 0;
if (count > 0)
{
bytesReadFromUnderlying = _underlyingStream.Read(buffer, offset, count);
if (bytesReadFromUnderlying > 0)
{
_underlyingPosition += bytesReadFromUnderlying;
int copyToBufferCount = Math.Min(bytesReadFromUnderlying, _seekBackBuffer.Length);
int copyToBufferOffset = Math.Min(_seekBackBufferCount, _seekBackBuffer.Length - copyToBufferCount);
int bufferBytesToMove = Math.Min(_seekBackBufferCount - 1, copyToBufferOffset);
if (bufferBytesToMove > 0)
{
Buffer.BlockCopy(_seekBackBuffer, _seekBackBufferCount - bufferBytesToMove, _seekBackBuffer, 0, bufferBytesToMove);
}
Buffer.BlockCopy(buffer, offset, _seekBackBuffer, copyToBufferOffset, copyToBufferCount);
_seekBackBufferCount = Math.Min(_seekBackBuffer.Length, _seekBackBufferCount + copyToBufferCount);
_seekBackBufferIndex = _seekBackBufferCount;
}
}
return copiedFromBackBufferCount + bytesReadFromUnderlying;
}
public override long Seek(long offset, SeekOrigin origin)
{
if (origin == SeekOrigin.End)
{
return SeekFromEnd((int)Math.Max(0, -offset));
}
long relativeOffset = origin == SeekOrigin.Current
? offset
: offset - Position;
if (relativeOffset == 0)
{
return Position;
}
else if (relativeOffset > 0)
{
return SeekForward(relativeOffset);
}
else
{
return SeekBackwards(-relativeOffset);
}
}
private long SeekForward(long origOffset)
{
long offset = origOffset;
int seekBackBufferLength = _seekBackBuffer.Length;
int backwardSoughtBytes = _seekBackBufferCount - _seekBackBufferIndex;
int seekForwardInBackBuffer = (int)Math.Min(offset, backwardSoughtBytes);
offset -= seekForwardInBackBuffer;
_seekBackBufferIndex += seekForwardInBackBuffer;
if (offset > 0)
{
// first completely fill seekBackBuffer to remove special cases from while loop below
if (_seekBackBufferCount < seekBackBufferLength)
{
int maxRead = seekBackBufferLength - _seekBackBufferCount;
if (offset < maxRead)
{
maxRead = (int)offset;
}
int bytesRead = _underlyingStream.Read(_seekBackBuffer, _seekBackBufferCount, maxRead);
_underlyingPosition += bytesRead;
_seekBackBufferCount += bytesRead;
_seekBackBufferIndex = _seekBackBufferCount;
if (bytesRead < maxRead)
{
if (_seekBackBufferCount < offset)
{
throw new NotSupportedException("Reached end of stream seeking forward " + origOffset + " bytes");
}
return Position;
}
offset -= bytesRead;
}
// now alternate between filling tempBuffer and seekBackBuffer
bool fillTempBuffer = true;
byte[] tempBuffer = new byte[seekBackBufferLength];
while (offset > 0)
{
int maxRead = offset < seekBackBufferLength ? (int)offset : seekBackBufferLength;
int bytesRead = _underlyingStream.Read(fillTempBuffer ? tempBuffer : _seekBackBuffer, 0, maxRead);
_underlyingPosition += bytesRead;
int bytesReadDiff = maxRead - bytesRead;
offset -= bytesRead;
if (bytesReadDiff > 0 /* reached end-of-stream */ || offset == 0)
{
if (fillTempBuffer)
{
if (bytesRead > 0)
{
Buffer.BlockCopy(_seekBackBuffer, bytesRead, _seekBackBuffer, 0, bytesReadDiff);
Buffer.BlockCopy(tempBuffer, 0, _seekBackBuffer, bytesReadDiff, bytesRead);
}
}
else
{
if (bytesRead > 0)
{
Buffer.BlockCopy(_seekBackBuffer, 0, _seekBackBuffer, bytesReadDiff, bytesRead);
}
Buffer.BlockCopy(tempBuffer, bytesRead, _seekBackBuffer, 0, bytesReadDiff);
}
if (offset > 0)
{
throw new NotSupportedException("Reached end of stream seeking forward " + origOffset + " bytes");
}
}
fillTempBuffer = !fillTempBuffer;
}
}
return Position;
}
private long SeekBackwards(long offset)
{
int intOffset = (int)offset;
if (offset > int.MaxValue || intOffset > _seekBackBufferIndex)
{
throw new NotSupportedException("Cannot currently seek backwards more than " + _seekBackBufferIndex + " bytes");
}
_seekBackBufferIndex -= intOffset;
return Position;
}
private long SeekFromEnd(long offset)
{
int intOffset = (int)offset;
int seekBackBufferLength = _seekBackBuffer.Length;
if (offset > int.MaxValue || intOffset > seekBackBufferLength)
{
throw new NotSupportedException("Cannot seek backwards from end more than " + seekBackBufferLength + " bytes");
}
// first completely fill seekBackBuffer to remove special cases from while loop below
if (_seekBackBufferCount < seekBackBufferLength)
{
int maxRead = seekBackBufferLength - _seekBackBufferCount;
int bytesRead = _underlyingStream.Read(_seekBackBuffer, _seekBackBufferCount, maxRead);
_underlyingPosition += bytesRead;
_seekBackBufferCount += bytesRead;
_seekBackBufferIndex = Math.Max(0, _seekBackBufferCount - intOffset);
if (bytesRead < maxRead)
{
if (_seekBackBufferCount < intOffset)
{
throw new NotSupportedException("Could not seek backwards from end " + intOffset + " bytes");
}
return Position;
}
}
else
{
_seekBackBufferIndex = _seekBackBufferCount;
}
// now alternate between filling tempBuffer and seekBackBuffer
bool fillTempBuffer = true;
byte[] tempBuffer = new byte[seekBackBufferLength];
while (true)
{
int bytesRead = _underlyingStream.Read(fillTempBuffer ? tempBuffer : _seekBackBuffer, 0, seekBackBufferLength);
_underlyingPosition += bytesRead;
int bytesReadDiff = seekBackBufferLength - bytesRead;
if (bytesReadDiff > 0) // reached end-of-stream
{
if (fillTempBuffer)
{
if (bytesRead > 0)
{
Buffer.BlockCopy(_seekBackBuffer, bytesRead, _seekBackBuffer, 0, bytesReadDiff);
Buffer.BlockCopy(tempBuffer, 0, _seekBackBuffer, bytesReadDiff, bytesRead);
}
}
else
{
if (bytesRead > 0)
{
Buffer.BlockCopy(_seekBackBuffer, 0, _seekBackBuffer, bytesReadDiff, bytesRead);
}
Buffer.BlockCopy(tempBuffer, bytesRead, _seekBackBuffer, 0, bytesReadDiff);
}
_seekBackBufferIndex -= intOffset;
return Position;
}
fillTempBuffer = !fillTempBuffer;
}
}
public override long Position
{
get
{
return _underlyingPosition - (_seekBackBufferCount - _seekBackBufferIndex);
}
set
{
Seek(value, SeekOrigin.Begin);
}
}
public override bool CanTimeout
{
get
{
return _underlyingStream.CanTimeout;
}
}
public override bool CanWrite
{
get
{
return _underlyingStream.CanWrite;
}
}
public override long Length
{
get
{
return _underlyingStream.Length;
}
}
public override void SetLength(long value)
{
_underlyingStream.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
_underlyingStream.Write(buffer, offset, count);
}
public override void Flush()
{
_underlyingStream.Flush();
}
public override void Close()
{
_underlyingStream.Close();
}
public new void Dispose()
{
_underlyingStream.Dispose();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_underlyingStream.Dispose();
}
}
}
}
+52
View File
@@ -0,0 +1,52 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
namespace WPinternals.HelperClasses
{
internal enum ResourceType
{
RT_CURSOR = 1,
RT_BITMAP = 2,
RT_ICON = 3,
RT_MENU = 4,
RT_DIALOG = 5,
RT_STRING = 6,
RT_FONTDIR = 7,
RT_FONT = 8,
RT_ACCELERATOR = 9,
RT_RCDATA = 10,
RT_MESSAGETABLE = 11,
RT_GROUP_CURSOR = RT_CURSOR + 11,
RT_GROUP_ICON = RT_ICON + 11,
RT_VERSION = 16,
RT_DLGINCLUDE = 17,
RT_PLUGPLAY = 19,
RT_VXD = 20,
RT_ANICURSOR = 21,
RT_ANIICON = 22,
RT_HTML = 23,
RT_MANIFEST = 24,
RT_DLGINIT = 240,
RT_TOOLBAR = 241
};
}
+183
View File
@@ -0,0 +1,183 @@
// 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
{
throw new ArgumentException("Unknown stream length");
}
}
}
public override bool CanRead
{
get
{
return true;
}
}
public override bool CanSeek
{
get
{
return true;
}
}
public override int Read(byte[] buffer, int offset, int count)
{
int RealCount = UnderlyingStream.Read(buffer, offset, count);
ReadPosition += RealCount;
return RealCount;
}
public override long Seek(long offset, SeekOrigin origin)
{
if (UnderlyingStream.CanSeek)
{
ReadPosition = UnderlyingStream.Seek(offset, origin);
return ReadPosition;
}
else
{
long NewPosition = 0;
switch (origin)
{
case SeekOrigin.Begin:
NewPosition = offset;
break;
case SeekOrigin.Current:
NewPosition = ReadPosition + offset;
break;
case SeekOrigin.End:
NewPosition = UnderlyingStreamLength - offset;
break;
}
if (NewPosition < 0 || NewPosition > UnderlyingStreamLength)
{
throw new ArgumentOutOfRangeException(nameof(offset));
}
if (NewPosition < ReadPosition)
{
UnderlyingStream.Close();
UnderlyingStream = StreamInitializer();
ReadPosition = 0;
}
ulong Remaining;
byte[] Buffer = new byte[16384];
while (ReadPosition < NewPosition)
{
Remaining = (ulong)(NewPosition - ReadPosition);
if (Remaining > (ulong)Buffer.Length)
{
Remaining = (ulong)Buffer.Length;
}
UnderlyingStream.Read(Buffer, 0, (int)Remaining);
ReadPosition += (long)Remaining;
}
return ReadPosition;
}
}
public override long Position
{
get
{
return ReadPosition;
}
set
{
Seek(value, SeekOrigin.Begin);
}
}
public override bool CanTimeout
{
get
{
return UnderlyingStream.CanTimeout;
}
}
public override bool CanWrite
{
get
{
return false;
}
}
public override long Length
{
get
{
return UnderlyingStreamLength;
}
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
public override void Flush()
{
throw new NotSupportedException();
}
public override void Close()
{
UnderlyingStream.Close();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
UnderlyingStream.Dispose();
}
}
}
}
+81
View File
@@ -0,0 +1,81 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace WPinternals.HelperClasses
{
#if PREVIEW
internal static class Uploader
{
internal static List<Task> Uploads = [];
internal static void Upload(string FileName, string Text)
{
byte[] byteArray = Encoding.UTF8.GetBytes(Text);
MemoryStream FileStream = new(byteArray);
Upload(FileName, FileStream);
}
internal static void Upload(string FileName, byte[] Data)
{
Upload(FileName, new MemoryStream(Data));
}
internal static void Upload(string FileName, Stream FileStream)
{
//TODO: Fix
//Upload(new Uri(@"https://www.wpinternals.net/upload.php", UriKind.Absolute), "uploadedfile", FileName, FileStream);
}
private static void Upload(Uri Address, string InputName, string FileName, Stream FileStream)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
System.Net.Http.HttpClient httpClient = new();
System.Net.Http.MultipartFormDataContent form = [];
System.Net.Http.StreamContent Content = new(FileStream);
Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("text/plain");
form.Add(Content, InputName, FileName);
Task<System.Net.Http.HttpResponseMessage> UploadTask = httpClient.PostAsync(Address, form);
Uploads.Add(
UploadTask.ContinueWith((t) =>
{
Uploads.Remove(t);
httpClient.Dispose();
})
);
}
internal static void WaitForUploads()
{
Task.WaitAll([.. Uploads]);
}
}
#endif
}
@@ -0,0 +1,43 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
namespace WPinternals.HelperClasses
{
internal class WPinternalsException : Exception
{
// Message and SubMessaage are always printable
internal string SubMessage = null;
internal WPinternalsException() : base() { }
internal WPinternalsException(string Message) : base(Message) { }
internal WPinternalsException(string Message, Exception InnerException) : base(Message, InnerException) { }
internal WPinternalsException(string Message, string SubMessage) : base(Message) { this.SubMessage = SubMessage; }
internal WPinternalsException(string Message, string SubMessage, Exception InnerException) : base(Message, InnerException) { this.SubMessage = SubMessage; }
}
}
@@ -0,0 +1,36 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
namespace WPinternals.HelperClasses
{
internal enum WPinternalsStatus
{
Undefined,
Scanning,
Flashing,
Patching,
WaitingForManualReset,
SwitchingMode,
Initializing
};
}
@@ -0,0 +1,132 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Some of the classes and functions in this file were found online.
// Where possible the original authors are referenced.
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Threading;
namespace WPinternals.HelperClasses
{
// This class is taken from the Prism library by Microsoft Patterns & Practices
// License: http://compositewpf.codeplex.com/license
internal static class WeakEventHandlerManager
{
public static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler, int defaultListSize)
{
(handlers ??= defaultListSize > 0 ? new List<WeakReference>(defaultListSize) : []).Add(new WeakReference(handler));
}
private static void CallHandler(object sender, EventHandler eventHandler)
{
DispatcherProxy proxy = DispatcherProxy.CreateDispatcher();
if (eventHandler != null)
{
if (proxy?.CheckAccess() == false)
{
proxy.BeginInvoke(new Action<object, EventHandler>(CallHandler), [sender, eventHandler]);
}
else
{
eventHandler(sender, EventArgs.Empty);
}
}
}
public static void CallWeakReferenceHandlers(object sender, List<WeakReference> handlers)
{
if (handlers != null)
{
EventHandler[] callees = new EventHandler[handlers.Count];
int count = 0;
count = CleanupOldHandlers(handlers, callees, count);
for (int i = 0; i < count; i++)
{
CallHandler(sender, callees[i]);
}
}
}
private static int CleanupOldHandlers(List<WeakReference> handlers, EventHandler[] callees, int count)
{
for (int i = handlers.Count - 1; i >= 0; i--)
{
WeakReference reference = handlers[i];
if (reference.Target is not EventHandler target)
{
handlers.RemoveAt(i);
}
else
{
callees[count] = target;
count++;
}
}
return count;
}
public static void RemoveWeakReferenceHandler(List<WeakReference> handlers, EventHandler handler)
{
if (handlers != null)
{
for (int i = handlers.Count - 1; i >= 0; i--)
{
WeakReference reference = handlers[i];
if (reference.Target is not EventHandler target || target == handler)
{
handlers.RemoveAt(i);
}
}
}
}
private class DispatcherProxy
{
private readonly Dispatcher innerDispatcher;
private DispatcherProxy(Dispatcher dispatcher)
{
innerDispatcher = dispatcher;
}
public DispatcherOperation BeginInvoke(Delegate method, params object[] args)
{
return innerDispatcher.BeginInvoke(method, DispatcherPriority.Normal, args);
}
public bool CheckAccess()
{
return innerDispatcher.CheckAccess();
}
public static DispatcherProxy CreateDispatcher()
{
if (Application.Current == null)
{
return null;
}
return new DispatcherProxy(Application.Current.Dispatcher);
}
}
}
}
+1 -1
View File
@@ -388,7 +388,7 @@ namespace WPinternals
unchecked
{
uint crc = (uint)(((uint)0) ^ (-1));
for (var i = Offset; i < (Offset + Length); i++)
for (uint i = Offset; i < (Offset + Length); i++)
{
crc = (crc >> 8) ^ CRC32Table[(crc ^ Input[i]) & 0xFF];
}
+3 -2
View File
@@ -20,6 +20,7 @@
using System;
using System.IO;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -288,7 +289,7 @@ namespace WPinternals
Partition Target = GPT.Partitions.Find(p => string.Equals(p.Name, Name, StringComparison.CurrentCultureIgnoreCase));
if (Target == null)
{
throw new ArgumentOutOfRangeException();
throw new ArgumentOutOfRangeException(nameof(Name));
}
return GetSectors((int)Target.FirstSector, (int)(Target.LastSector - Target.FirstSector + 1));
@@ -314,7 +315,7 @@ namespace WPinternals
Partition Target = GPT.Partitions.Find(p => string.Equals(p.Name, Name, StringComparison.CurrentCultureIgnoreCase));
if (Target == null)
{
throw new ArgumentOutOfRangeException();
throw new ArgumentOutOfRangeException(nameof(Name));
}
int FirstChunk = GetChunkIndexFromSectorIndex((int)Target.FirstSector);
+1
View File
@@ -24,6 +24,7 @@ using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Xml.Serialization;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -31,8 +31,9 @@ using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
using WPinternals.HelperClasses;
namespace WPinternals
namespace WPinternals.Models.Lumia.MSR
{
internal static class LumiaDownloadModel
{
@@ -301,12 +302,12 @@ namespace WPinternals
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);
Version version = new Version(PhoneFirmwareRevision);
Version version1 = new Version(Limit1);
Version version2 = new Version(Limit2);
var result = version.CompareTo(version1);
var result2 = version.CompareTo(version2);
int result = version.CompareTo(version1);
int result2 = version.CompareTo(version2);
return result >= 0 && result2 <= 0;
}
@@ -321,7 +322,7 @@ namespace WPinternals
LogFile.Log("Getting Emergency files for: " + ProductType, LogType.FileAndConsole);
if ((ProductType == "RM-1072") || (ProductType == "RM-1073"))
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";
@@ -486,20 +487,20 @@ namespace WPinternals
public DiscoveryParameters(DiscoveryCondition Condition)
{
this.apiVersion = "1";
this.query = new DiscoveryQueryParameters();
this.condition = [];
apiVersion = "1";
query = new DiscoveryQueryParameters();
condition = [];
if (Condition == DiscoveryCondition.All)
{
this.condition.Add("all");
condition.Add("all");
return;
}
if (Condition == DiscoveryCondition.Latest)
{
this.condition.Add("latest");
condition.Add("latest");
return;
}
this.condition.Add("default");
condition.Add("default");
}
}
@@ -517,18 +518,18 @@ namespace WPinternals
public ExtendedAttributes()
{
this.Dictionary = [];
Dictionary = [];
}
protected ExtendedAttributes(SerializationInfo info, StreamingContext context)
{
if (info != null)
{
this.Dictionary = [];
Dictionary = [];
SerializationInfoEnumerator Enumerator = info.GetEnumerator();
while (Enumerator.MoveNext())
{
this.Dictionary.Add(Enumerator.Current.Name, (string)Enumerator.Current.Value);
Dictionary.Add(Enumerator.Current.Name, (string)Enumerator.Current.Value);
}
}
}
@@ -537,9 +538,9 @@ namespace WPinternals
{
if (info != null)
{
foreach (string Current in this.Dictionary.Keys)
foreach (string Current in Dictionary.Keys)
{
info.AddValue(Current, this.Dictionary[Current]);
info.AddValue(Current, Dictionary[Current]);
}
}
}
@@ -651,209 +652,350 @@ namespace WPinternals
public class BasicProductCodes
{
[XmlElement(ElementName = "BasicProductCode")]
public List<string> BasicProductCode { get; set; }
public List<string> BasicProductCode
{
get; set;
}
}
[XmlRoot(ElementName = "Identification")]
public class Identification
{
[XmlElement(ElementName = "TypeDesignator")]
public string TypeDesignator { get; set; }
public string TypeDesignator
{
get; set;
}
[XmlElement(ElementName = "BasicProductCodes")]
public BasicProductCodes BasicProductCodes { get; set; }
public BasicProductCodes BasicProductCodes
{
get; set;
}
[XmlElement(ElementName = "Purpose")]
public string Purpose { get; set; }
public string Purpose
{
get; set;
}
}
[XmlRoot(ElementName = "Extensions")]
public class Extensions
{
[XmlElement(ElementName = "PackageType")]
public string PackageType { get; set; }
public string PackageType
{
get; set;
}
[XmlElement(ElementName = "Identification")]
public Identification Identification { get; set; }
public Identification Identification
{
get; set;
}
[XmlElement(ElementName = "FileType")]
public string FileType { get; set; }
public string FileType
{
get; set;
}
[XmlElement(ElementName = "MmosWimFile")]
public MmosWimFile MmosWimFile { get; set; }
public MmosWimFile MmosWimFile
{
get; set;
}
}
[XmlRoot(ElementName = "PackageDescription")]
public class PackageDescription
{
[XmlElement(ElementName = "Identifier")]
public string Identifier { get; set; }
public string Identifier
{
get; set;
}
[XmlElement(ElementName = "Revision")]
public string Revision { get; set; }
public string Revision
{
get; set;
}
[XmlElement(ElementName = "Extensions")]
public Extensions Extensions { get; set; }
public Extensions Extensions
{
get; set;
}
}
[XmlRoot(ElementName = "Digest")]
public class Digest
{
[XmlAttribute(AttributeName = "method")]
public string Method { get; set; }
public string Method
{
get; set;
}
[XmlAttribute(AttributeName = "encoding")]
public string Encoding { get; set; }
public string Encoding
{
get; set;
}
[XmlText]
public string Text { get; set; }
public string Text
{
get; set;
}
}
[XmlRoot(ElementName = "Digests")]
public class Digests
{
[XmlElement(ElementName = "Digest")]
public List<Digest> Digest { get; set; }
public List<Digest> Digest
{
get; set;
}
}
[XmlRoot(ElementName = "Range")]
public class Range
{
[XmlAttribute(AttributeName = "from")]
public string From { get; set; }
public string From
{
get; set;
}
[XmlAttribute(AttributeName = "to")]
public string To { get; set; }
public string To
{
get; set;
}
}
[XmlRoot(ElementName = "Compatibility")]
public class Compatibility
{
[XmlElement(ElementName = "Range")]
public Range Range { get; set; }
public Range Range
{
get; set;
}
[XmlAttribute(AttributeName = "useCase")]
public string UseCase { get; set; }
public string UseCase
{
get; set;
}
}
[XmlRoot(ElementName = "UseCaseCompatibilities")]
public class UseCaseCompatibilities
{
[XmlElement(ElementName = "Compatibility")]
public List<Compatibility> Compatibility { get; set; }
public List<Compatibility> Compatibility
{
get; set;
}
}
[XmlRoot(ElementName = "MmosWimFile")]
public class MmosWimFile
{
[XmlElement(ElementName = "UseCaseCompatibilities")]
public UseCaseCompatibilities UseCaseCompatibilities { get; set; }
public UseCaseCompatibilities UseCaseCompatibilities
{
get; set;
}
}
[XmlRoot(ElementName = "File")]
public class File
{
[XmlElement(ElementName = "Name")]
public string Name { get; set; }
public string Name
{
get; set;
}
[XmlElement(ElementName = "Digests")]
public Digests Digests { get; set; }
public Digests Digests
{
get; set;
}
[XmlElement(ElementName = "Revision")]
public string Revision { get; set; }
public string Revision
{
get; set;
}
[XmlElement(ElementName = "Extensions")]
public Extensions Extensions { get; set; }
public Extensions Extensions
{
get; set;
}
}
[XmlRoot(ElementName = "Files")]
public class Files
{
[XmlElement(ElementName = "File")]
public List<File> File { get; set; }
public List<File> File
{
get; set;
}
}
[XmlRoot(ElementName = "Content")]
public class Content
{
[XmlElement(ElementName = "PackageDescription")]
public PackageDescription PackageDescription { get; set; }
public PackageDescription PackageDescription
{
get; set;
}
[XmlElement(ElementName = "Files")]
public Files Files { get; set; }
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; }
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; }
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; }
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; }
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; }
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; }
public Transforms Transforms
{
get; set;
}
[XmlElement(ElementName = "DigestMethod", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public DigestMethod DigestMethod { get; set; }
public DigestMethod DigestMethod
{
get; set;
}
[XmlElement(ElementName = "DigestValue", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public string DigestValue { get; set; }
public string DigestValue
{
get; set;
}
[XmlAttribute(AttributeName = "URI")]
public string URI { get; set; }
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; }
public CanonicalizationMethod CanonicalizationMethod
{
get; set;
}
[XmlElement(ElementName = "SignatureMethod", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public SignatureMethod SignatureMethod { get; set; }
public SignatureMethod SignatureMethod
{
get; set;
}
[XmlElement(ElementName = "Reference", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public Reference Reference { get; set; }
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; }
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; }
public SignedInfo SignedInfo
{
get; set;
}
[XmlElement(ElementName = "SignatureValue", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public string SignatureValue { get; set; }
public string SignatureValue
{
get; set;
}
[XmlElement(ElementName = "KeyInfo", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public KeyInfo KeyInfo { get; set; }
public KeyInfo KeyInfo
{
get; set;
}
[XmlAttribute(AttributeName = "xmlns")]
public string Xmlns { get; set; }
public string Xmlns
{
get; set;
}
}
[XmlRoot(ElementName = "Package")]
public class Package
{
[XmlElement(ElementName = "Content")]
public Content Content { get; set; }
public Content Content
{
get; set;
}
[XmlElement(ElementName = "Signature", Namespace = "http://www.w3.org/2000/09/xmldsig#")]
public Signature Signature { get; set; }
public Signature Signature
{
get; set;
}
}
}
}
@@ -18,32 +18,20 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using MadWizard.WinUSBNet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
namespace WPinternals
namespace WPinternals.Models.Lumia.NCSd
{
internal class NokiaPhoneModel : IDisposable
internal class NokiaCareSuiteModel : NokiaPhoneModel
{
protected bool Disposed = false;
private readonly USBDevice Device = null;
private int MessageId = 0;
private readonly object UsbLock = new();
public NokiaPhoneModel(string DevicePath)
public NokiaCareSuiteModel(string DevicePath) : base(DevicePath)
{
// Mass Storage device is not WinUSB
try
{
Device = new USBDevice(DevicePath);
}
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
}
private JsonElement? ExecuteJsonMethodAsJsonToken(string JsonMethod, Dictionary<string, object> Params, string ResultElement)
@@ -72,7 +60,13 @@ namespace WPinternals
}
}
@params.Add("MessageVersion", 0);
string Request = JsonSerializer.Serialize(new { jsonrpc, id, method, @params });
string Request = JsonSerializer.Serialize(new
{
jsonrpc,
id,
method,
@params
});
Device.OutputPipe.Write(System.Text.Encoding.ASCII.GetBytes(Request));
Buffer = new byte[0x10000];
@@ -84,7 +78,7 @@ namespace WPinternals
try
{
JsonElement? ResultToken = ResultMessage.RootElement.GetProperty("result");
if ((ResultToken == null) || (ResultElement == null))
if (ResultToken == null || ResultElement == null)
{
return null;
}
@@ -207,7 +201,13 @@ namespace WPinternals
}
}
@params.Add("MessageVersion", 0);
string Request = JsonSerializer.Serialize(new { jsonrpc, id, method, @params });
string Request = JsonSerializer.Serialize(new
{
jsonrpc,
id,
method,
@params
});
byte[] OutBuffer = System.Text.Encoding.ASCII.GetBytes(Request);
Device.OutputPipe.BeginWrite(OutBuffer, 0, OutBuffer.Length, (AsyncResultWrite) => Device.OutputPipe.EndWrite(AsyncResultWrite), null);
@@ -295,7 +295,13 @@ namespace WPinternals
}
}
@params.Add("MessageVersion", 0);
string Request = JsonSerializer.Serialize(new { jsonrpc, id, method, @params });
string Request = JsonSerializer.Serialize(new
{
jsonrpc,
id,
method,
@params
});
byte[] OutBuffer = System.Text.Encoding.ASCII.GetBytes(Request);
Device.OutputPipe.BeginWrite(OutBuffer, 0, OutBuffer.Length, (AsyncResultWrite) =>
@@ -309,7 +315,7 @@ namespace WPinternals
JsonDocument ResultMessage = JsonDocument.Parse(System.Text.Encoding.ASCII.GetString(Buffer, 0, Length));
JsonElement? ResultToken = ResultMessage.RootElement.GetProperty("result");
if ((ResultToken == null) || (ResultElement == null))
if (ResultToken == null || ResultElement == null)
{
Callback(AsyncResultRead.AsyncState, null);
}
@@ -324,103 +330,5 @@ namespace WPinternals
{
ExecuteJsonMethodAsTokenAsync(JsonMethod, null, ResultElement, State, Callback);
}
public byte[] ExecuteRawMethod(byte[] RawMethod)
{
return ExecuteRawMethod(RawMethod, RawMethod.Length);
}
public byte[] ExecuteRawMethod(byte[] RawMethod, int Length)
{
byte[] Buffer = new byte[0x8000]; // Should be at least 0x4408 for receiving the GPT packet.
byte[] Result = null;
lock (UsbLock)
{
Device.OutputPipe.Write(RawMethod, 0, Length);
try
{
int OutputLength = Device.InputPipe.Read(Buffer);
Result = new byte[OutputLength];
System.Buffer.BlockCopy(Buffer, 0, Result, 0, OutputLength);
}
catch (Exception ex) // Reboot command looses connection
{
LogFile.LogException(ex, LogType.FileOnly);
}
}
return Result;
}
public void ExecuteRawVoidMethod(byte[] RawMethod)
{
ExecuteRawVoidMethod(RawMethod, RawMethod.Length);
}
public void ExecuteRawVoidMethod(byte[] RawMethod, int Length)
{
lock (UsbLock)
{
Device.OutputPipe.Write(RawMethod, 0, Length);
}
}
public void ResetDevice()
{
try
{
foreach (var pipe in Device.Pipes)
{
pipe.Abort();
pipe.Reset();
}
}
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
}
/// <summary>
/// Disposes the UsbDevice including all unmanaged WinUSB handles. This function
/// should be called when the UsbDevice object is no longer in use, otherwise
/// unmanaged handles will remain open until the garbage collector finalizes the
/// object.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Finalizer for the UsbDevice. Disposes all unmanaged handles.
/// </summary>
~NokiaPhoneModel()
{
Dispose(false);
}
/// <summary>
/// Disposes the object
/// </summary>
/// <param name="disposing">Indicates wether Dispose was called manually (true) or by
/// the garbage collector (false) via the destructor.</param>
protected virtual void Dispose(bool disposing)
{
if (Disposed)
{
return;
}
if (disposing)
{
Device?.Dispose();
}
// Clean unmanaged resources here.
// (none currently)
Disposed = true;
}
}
}
+105
View File
@@ -0,0 +1,105 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using MadWizard.WinUSBNet;
using System;
using WPinternals.HelperClasses;
namespace WPinternals.Models.Lumia
{
internal class NokiaPhoneModel : IDisposable
{
protected bool Disposed = false;
internal readonly USBDevice Device = null;
internal readonly object UsbLock = new();
public NokiaPhoneModel(string DevicePath)
{
// Mass Storage device is not WinUSB
try
{
Device = new USBDevice(DevicePath);
}
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
}
public void ResetDevice()
{
try
{
foreach (USBPipe pipe in Device.Pipes)
{
pipe.Abort();
pipe.Reset();
}
}
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
}
/// <summary>
/// Disposes the UsbDevice including all unmanaged WinUSB handles. This function
/// should be called when the UsbDevice object is no longer in use, otherwise
/// unmanaged handles will remain open until the garbage collector finalizes the
/// object.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Finalizer for the UsbDevice. Disposes all unmanaged handles.
/// </summary>
~NokiaPhoneModel()
{
Dispose(false);
}
/// <summary>
/// Disposes the object
/// </summary>
/// <param name="disposing">Indicates wether Dispose was called manually (true) or by
/// the garbage collector (false) via the destructor.</param>
protected virtual void Dispose(bool disposing)
{
if (Disposed)
{
return;
}
if (disposing)
{
Device?.Dispose();
}
// Clean unmanaged resources here.
// (none currently)
Disposed = true;
}
}
}
@@ -19,8 +19,10 @@
// DEALINGS IN THE SOFTWARE.
using System;
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia.UEFI;
namespace WPinternals
namespace WPinternals.Models.UEFIApps.BootMgr
{
internal class LumiaBootManagerAppModel : NokiaUEFIModel
{
@@ -94,6 +96,26 @@ namespace WPinternals
{
}
internal void ResetToMassStorageMode()
{
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, RebootToMassStorageSignature);
byte[] Response = ExecuteRawMethod(Request);
if (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU")
{
throw new NotSupportedException();
}
UInt16 Error = (UInt16)((Response[6] << 8) + Response[7]);
if (Error > 0)
{
throw new NotSupportedException("SendCommonExtendedSwitchToCommand: Error 0x" + Error.ToString("X4"));
}
}
internal void ContinueBoot()
{
LogFile.Log("Continue boot...");
@@ -132,7 +154,7 @@ namespace WPinternals
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, InfoQuerySignature);
byte[] Response = ExecuteRawMethod(Request);
if ((Response != null) && (ByteOperations.ReadAsciiString(Response, 0, 4) != "NOKU"))
if (Response != null && ByteOperations.ReadAsciiString(Response, 0, 4) != "NOKU")
{
Result.App = (FlashAppType)Response[5];
@@ -155,9 +177,8 @@ namespace WPinternals
LogFile.Log($"{Result.App} SubblockID: 0x{SubblockID:X}");
UInt16 SubblockLength = BigEndian.ToUInt16(Response, SubblockOffset + 0x01);
ushort SubblockLength = BigEndian.ToUInt16(Response, SubblockOffset + 0x01);
int SubblockPayloadOffset = SubblockOffset + 3;
byte SubblockVersion;
switch (SubblockID)
{
case 0x01:
@@ -200,12 +221,12 @@ namespace WPinternals
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
byte[] Buffer = ExecuteRawMethod(Request);
if ((Buffer == null) || (Buffer.Length < 0x4408))
if (Buffer == null || Buffer.Length < 0x4408)
{
throw new InvalidOperationException("Unable to read GPT!");
}
UInt16 Error = (UInt16)((Buffer[6] << 8) + Buffer[7]);
ushort Error = (ushort)((Buffer[6] << 8) + Buffer[7]);
if (Error > 0)
{
throw new NotSupportedException("ReadGPT: Error 0x" + Error.ToString("X4"));
@@ -217,7 +238,7 @@ namespace WPinternals
return new GPT(GPTBuffer); // NOKT message header and MBR are ignored
}
internal byte[] GetGptChunk(UInt32 Size) // TODO!
internal byte[] GetGptChunk(uint Size) // TODO!
{
// This function is also used to generate a dummy chunk to flash for testing.
// The dummy chunk will contain the GPT, so it can be flashed to the first sectors for testing.
@@ -229,12 +250,12 @@ namespace WPinternals
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
byte[] Buffer = ExecuteRawMethod(Request);
if ((Buffer == null) || (Buffer.Length < 0x4408))
if (Buffer == null || Buffer.Length < 0x4408)
{
throw new InvalidOperationException("Unable to read GPT!");
}
UInt16 Error = (UInt16)((Buffer[6] << 8) + Buffer[7]);
ushort Error = (ushort)((Buffer[6] << 8) + Buffer[7]);
if (Error > 0)
{
throw new NotSupportedException("ReadGPT: Error 0x" + Error.ToString("X4"));
@@ -252,7 +273,7 @@ namespace WPinternals
Request[6] = 0; // Options
Request[7] = (byte)KeyType;
byte[] Response = ExecuteRawMethod(Request);
UInt32 Status = ByteOperations.ReadUInt32(Response, 6);
uint Status = ByteOperations.ReadUInt32(Response, 6);
if (Status != 0)
{
ThrowFlashError((int)Status);
@@ -19,8 +19,10 @@
// DEALINGS IN THE SOFTWARE.
using System;
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia.UEFI;
namespace WPinternals
namespace WPinternals.Models.UEFIApps.BootMgr
{
internal class LumiaBootManagerPhoneInfo
{
@@ -38,7 +40,7 @@ namespace WPinternals
public byte BootManagerProtocolVersionMajor;
public byte BootManagerProtocolVersionMinor;
public UInt32 TransferSize;
public uint TransferSize;
public bool MmosOverUsbSupported;
internal void Log(LogType Type)
@@ -0,0 +1,63 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using WPinternals.HelperClasses;
namespace WPinternals.Models.Lumia.UEFI
{
internal class CommonPhoneInfo
{
public PhoneInfoState State = PhoneInfoState.Empty;
public FlashAppType App;
public byte VersionMajor;
public byte VersionMinor;
public byte ProtocolVersionMajor;
public byte ProtocolVersionMinor;
internal void Log(LogType Type)
{
LogFile.Log($"App: {VersionMajor}.{VersionMinor}", Type);
LogFile.Log($"Protocol: {ProtocolVersionMajor}.{ProtocolVersionMinor}", Type);
}
}
}
@@ -0,0 +1,31 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
namespace WPinternals.Models.UEFIApps.Flash
{
internal enum FfuProtocol
{
ProtocolSyncV1 = 1,
ProtocolAsyncV1 = 2,
ProtocolSyncV2 = 4,
ProtocolAsyncV2 = 8,
ProtocolAsyncV3 = 16
}
}
@@ -0,0 +1,33 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace WPinternals.Models.UEFIApps.Flash
{
[Flags]
internal enum FlashOptions : byte
{
SkipWrite = 1,
SkipHashCheck = 2,
SkipIdCheck = 4,
SkipSignatureCheck = 8
}
}
@@ -18,7 +18,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
namespace WPinternals
namespace WPinternals.Models.Lumia.UEFI.Flash
{
internal class FlashVersion
{
@@ -0,0 +1,44 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace WPinternals.Models.UEFIApps.Flash
{
[Flags]
internal enum Fuse
{
SecureBoot = 1,
FfuVerify = 2,
Jtag = 4,
Shk = 8,
Simlock = 16,
ProductionDone = 32,
Rkh = 64,
PublicId = 128,
Dak = 256,
SecGen = 512,
OemId = 1024,
FastBoot = 2048,
SpdmSecMode = 4096,
RpmWdog = 8192,
Ssm = 16384
}
}
@@ -21,53 +21,14 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia.UEFI;
using WPinternals.Models.Lumia.UEFI.Flash;
using WPinternals.Terminal;
namespace WPinternals
namespace WPinternals.Models.UEFIApps.Flash
{
internal enum SecureBootKeyType : byte
{
Retail = 0,
Engineering = 1
}
[Flags]
internal enum Fuse
{
SecureBoot = 1,
FfuVerify = 2,
Jtag = 4,
Shk = 8,
Simlock = 16,
ProductionDone = 32,
Rkh = 64,
PublicId = 128,
Dak = 256,
SecGen = 512,
OemId = 1024,
FastBoot = 2048,
SpdmSecMode = 4096,
RpmWdog = 8192,
Ssm = 16384
}
internal enum FfuProtocol
{
ProtocolSyncV1 = 1,
ProtocolAsyncV1 = 2,
ProtocolSyncV2 = 4,
ProtocolAsyncV2 = 8,
ProtocolAsyncV3 = 16
}
[Flags]
internal enum FlashOptions : byte
{
SkipWrite = 1,
SkipHashCheck = 2,
SkipIdCheck = 4,
SkipSignatureCheck = 8
}
internal class LumiaFlashAppModel : NokiaUEFIModel
{
internal readonly LumiaFlashAppPhoneInfo FlashAppInfo = new();
@@ -157,6 +118,62 @@ namespace WPinternals
{
}
public void WriteParam(string Param, byte[] Value)
{
// Command: NOKXFW
// Padding (one byte)
// Parameter (4 bytes)
// Length (4 bytes)
// Data
if (Param.Length > 4)
{
throw new ArgumentOutOfRangeException(nameof(Param));
}
byte[] Request = new byte[15 + Param.Length];
const string Header = WriteParamSignature;
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Param), 0, Request, 7, Param.Length);
Buffer.BlockCopy(BigEndian.GetBytes(Value.Length, 4), 0, Request, 11, 4);
Buffer.BlockCopy(Value, 0, Request, 15, Value.Length);
byte[] Response = ExecuteRawMethod(Request);
if (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU")
{
throw new NotSupportedException();
}
UInt16 Error = (UInt16)((Response[6] << 8) + Response[7]);
if (Error > 0)
{
throw new NotSupportedException("WriteParam: Error 0x" + Error.ToString("X4"));
}
}
internal void ResetToMassStorageMode()
{
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, RebootToMassStorageSignature);
byte[] Response = ExecuteRawMethod(Request);
if (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU")
{
throw new NotSupportedException();
}
UInt16 Error = (UInt16)((Response[6] << 8) + Response[7]);
if (Error > 0)
{
throw new NotSupportedException("SendCommonExtendedSwitchToCommand: Error 0x" + Error.ToString("X4"));
}
}
internal LumiaFlashAppPhoneInfo ReadPhoneInfo(bool ExtendedInfo = true)
{
// NOKH = Get Phone Info (IMEI and info from Product.dat) - Not available on some phones, like Lumia 640.
@@ -167,7 +184,7 @@ namespace WPinternals
LumiaFlashAppPhoneInfo Result = FlashAppInfo;
if (ExtendedInfo && (Result.State == PhoneInfoState.Basic))
if (ExtendedInfo && Result.State == PhoneInfoState.Basic)
{
if (Result.App == FlashAppType.FlashApp)
{
@@ -198,7 +215,7 @@ namespace WPinternals
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, InfoQuerySignature);
byte[] Response = ExecuteRawMethod(Request);
if ((Response != null) && (ByteOperations.ReadAsciiString(Response, 0, 4) != "NOKU"))
if (Response != null && ByteOperations.ReadAsciiString(Response, 0, 4) != "NOKU")
{
Result.App = (FlashAppType)Response[5];
@@ -221,7 +238,7 @@ namespace WPinternals
LogFile.Log($"{Result.App} SubblockID: 0x{SubblockID:X}");
UInt16 SubblockLength = BigEndian.ToUInt16(Response, SubblockOffset + 0x01);
ushort SubblockLength = BigEndian.ToUInt16(Response, SubblockOffset + 0x01);
int SubblockPayloadOffset = SubblockOffset + 3;
byte SubblockVersion;
switch (SubblockID)
@@ -250,7 +267,7 @@ namespace WPinternals
Result.SecureFfuEnabled = Response[SubblockPayloadOffset + 0x02] == 0x01;
Result.JtagDisabled = Response[SubblockPayloadOffset + 0x03] == 0x01;
Result.RdcPresent = Response[SubblockPayloadOffset + 0x04] == 0x01;
Result.Authenticated = (Response[SubblockPayloadOffset + 0x05] == 0x01) || (Response[SubblockPayloadOffset + 0x05] == 0x02);
Result.Authenticated = Response[SubblockPayloadOffset + 0x05] == 0x01 || Response[SubblockPayloadOffset + 0x05] == 0x02;
Result.UefiSecureBootEnabled = Response[SubblockPayloadOffset + 0x06] == 0x01;
Result.SecondaryHardwareKeyPresent = Response[SubblockPayloadOffset + 0x07] == 0x01;
break;
@@ -299,12 +316,12 @@ namespace WPinternals
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
byte[] Buffer = ExecuteRawMethod(Request);
if ((Buffer == null) || (Buffer.Length < 0x4408))
if (Buffer == null || Buffer.Length < 0x4408)
{
throw new InvalidOperationException("Unable to read GPT!");
}
UInt16 Error = (UInt16)((Buffer[6] << 8) + Buffer[7]);
ushort Error = (ushort)((Buffer[6] << 8) + Buffer[7]);
if (Error > 0)
{
throw new NotSupportedException("ReadGPT: Error 0x" + Error.ToString("X4"));
@@ -316,7 +333,7 @@ namespace WPinternals
return new GPT(GPTBuffer); // NOKT message header and MBR are ignored
}
internal byte[] GetGptChunk(UInt32 Size) // TODO!
internal byte[] GetGptChunk(uint Size) // TODO!
{
// This function is also used to generate a dummy chunk to flash for testing.
// The dummy chunk will contain the GPT, so it can be flashed to the first sectors for testing.
@@ -336,12 +353,12 @@ namespace WPinternals
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
byte[] Buffer = ExecuteRawMethod(Request);
if ((Buffer == null) || (Buffer.Length < 0x4408))
if (Buffer == null || Buffer.Length < 0x4408)
{
throw new InvalidOperationException("Unable to read GPT!");
}
UInt16 Error = (UInt16)((Buffer[6] << 8) + Buffer[7]);
ushort Error = (ushort)((Buffer[6] << 8) + Buffer[7]);
if (Error > 0)
{
ThrowFlashError(Error);
@@ -362,7 +379,7 @@ namespace WPinternals
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Param), 0, Request, 7, Param.Length);
byte[] Response = ExecuteRawMethod(Request);
if ((Response == null) || (Response.Length < 0x10))
if (Response == null || Response.Length < 0x10)
{
return null;
}
@@ -386,37 +403,37 @@ namespace WPinternals
public uint? ReadSecurityFlags()
{
byte[] Response = ReadParam("FCS");
if ((Response == null) || (Response.Length != 4))
if (Response == null || Response.Length != 4)
{
return null;
}
// This value is in big endian
return (UInt32)((Response[0] << 24) | (Response[1] << 16) | (Response[2] << 8) | Response[3]);
return (uint)(Response[0] << 24 | Response[1] << 16 | Response[2] << 8 | Response[3]);
}
public uint? ReadCurrentChargeLevel()
{
byte[] Response = ReadParam("CS");
if ((Response == null) || (Response.Length != 8))
if (Response == null || Response.Length != 8)
{
return null;
}
// This value is in big endian
return (UInt32)((Response[0] << 24) | (Response[1] << 16) | (Response[2] << 8) | Response[3]) + 1;
return (uint)(Response[0] << 24 | Response[1] << 16 | Response[2] << 8 | Response[3]) + 1;
}
public int? ReadCurrentChargeCurrent()
{
byte[] Response = ReadParam("CS");
if ((Response == null) || (Response.Length != 8))
if (Response == null || Response.Length != 8)
{
return null;
}
// This value is in big endian and needs to be XOR'd with 0xFFFFFFFF
return (Int32)(((Response[4] << 24) | (Response[5] << 16) | (Response[6] << 8) | Response[7]) ^ 0xFFFFFFFF) + 1;
return (int)((Response[4] << 24 | Response[5] << 16 | Response[6] << 8 | Response[7]) ^ 0xFFFFFFFF) + 1;
}
public UefiSecurityStatusResponse ReadSecurityStatus()
@@ -451,7 +468,7 @@ namespace WPinternals
public FlashVersion GetFlashVersion()
{
byte[] Response = ReadParam("FAI");
if ((Response == null) || (Response.Length < 6))
if (Response == null || Response.Length < 6)
{
return null;
}
@@ -466,7 +483,7 @@ namespace WPinternals
return Result;
}
internal UInt16 ReadSecureFfuSupportedProtocolMask()
internal ushort ReadSecureFfuSupportedProtocolMask()
{
return BigEndian.ToUInt16(ReadParam("SFPI"), 0);
}
@@ -483,10 +500,10 @@ namespace WPinternals
Buffer.BlockCopy(BigEndian.GetBytes(0x00, 4), 0, Request, 0x10, 4); // AsicIndex = 0x00
Buffer.BlockCopy(AsskMask, 0, Request, 0x14, 0x10);
byte[] TerminalResponse = ExecuteRawMethod(Request);
if ((TerminalResponse?.Length > 0x20) && (BigEndian.ToUInt32(TerminalResponse, 0x14) == (TerminalResponse.Length - 0x18)) && (BitConverter.ToUInt32(TerminalResponse, 0x1C) == (TerminalResponse.Length - 0x20)))
if (TerminalResponse?.Length > 0x20 && BigEndian.ToUInt32(TerminalResponse, 0x14) == TerminalResponse.Length - 0x18 && BitConverter.ToUInt32(TerminalResponse, 0x1C) == TerminalResponse.Length - 0x20)
{
// Parse Terminal Response from offset 0x18
return Terminal.Parse(TerminalResponse, 0x18);
return Terminal.Terminal.Parse(TerminalResponse, 0x18);
}
else
{
@@ -524,7 +541,7 @@ namespace WPinternals
}
}
public void SendFfuHeaderV2(UInt32 TotalHeaderLength, UInt32 OffsetForThisPart, byte[] FfuHeader, byte Options = 0)
public void SendFfuHeaderV2(uint TotalHeaderLength, uint OffsetForThisPart, byte[] FfuHeader, byte Options = 0)
{
byte[] Request = new byte[FfuHeader.Length + 0x3C];
@@ -627,7 +644,7 @@ namespace WPinternals
}
}
public void SendFfuPayloadV3(byte[] FfuChunk, UInt32 WriteDescriptorIndex, UInt32 CRC, int Progress = 0, byte Options = 0)
public void SendFfuPayloadV3(byte[] FfuChunk, uint WriteDescriptorIndex, uint CRC, int Progress = 0, byte Options = 0)
{
byte[] Request = new byte[FfuChunk.Length + 0x20];
@@ -691,7 +708,7 @@ namespace WPinternals
}
}
public void LoadMmosBinary(UInt32 TotalLength, UInt32 Offset, bool SkipMmosSupportCheck, byte[] MmosPart)
public void LoadMmosBinary(uint TotalLength, uint Offset, bool SkipMmosSupportCheck, byte[] MmosPart)
{
byte[] Request = new byte[MmosPart.Length + 0x20];
const string Header = LoadSignature;
@@ -763,7 +780,7 @@ namespace WPinternals
Request[6] = 0; // Options
Request[7] = (byte)KeyType;
byte[] Response = ExecuteRawMethod(Request);
UInt32 Status = ByteOperations.ReadUInt32(Response, 6);
uint Status = ByteOperations.ReadUInt32(Response, 6);
if (Status != 0)
{
ThrowFlashError((int)Status);
@@ -827,7 +844,7 @@ namespace WPinternals
return null;
}
var finalconfig = (Fuse)flags.Value;
Fuse finalconfig = (Fuse)flags.Value;
return finalconfig.HasFlag(fuse);
}
@@ -842,7 +859,7 @@ namespace WPinternals
return null;
}
public void FlashSectors(UInt32 StartSector, byte[] Data, int Progress = 0)
public void FlashSectors(uint StartSector, byte[] Data, int Progress = 0)
{
// Start sector is in UInt32, so max size of eMMC is 2 TB.
@@ -903,7 +920,7 @@ namespace WPinternals
byte[] Buffer = NewGPT.Rebuild();
UInt32? HeaderOffset = ByteOperations.FindAscii(Buffer, "EFI PART");
uint? HeaderOffset = ByteOperations.FindAscii(Buffer, "EFI PART");
if (HeaderOffset != 0)
{
throw new BadImageFormatException();
@@ -984,14 +1001,14 @@ namespace WPinternals
throw new WPinternalsException("Flash failed!", "Protocols not supported. The device reports that both Protocol Sync v1 and Protocol Sync v2 are not supported for FFU flashing. Is this an old device?");
}
UInt64 CombinedFFUHeaderSize = FFU.HeaderSize;
ulong CombinedFFUHeaderSize = FFU.HeaderSize;
byte[] FfuHeader = new byte[CombinedFFUHeaderSize];
using (FileStream FfuFile = new(FFU.Path, FileMode.Open, FileAccess.Read))
{
FfuFile.Read(FfuHeader, 0, (int)CombinedFFUHeaderSize);
SendFfuHeaderV1(FfuHeader, Options);
UInt64 Position = CombinedFFUHeaderSize;
ulong Position = CombinedFFUHeaderSize;
byte[] Payload;
int ChunkCount = 0;
@@ -1000,7 +1017,7 @@ namespace WPinternals
// Protocol v1
Payload = new byte[FFU.ChunkSize];
while (Position < (UInt64)FfuFile.Length)
while (Position < (ulong)FfuFile.Length)
{
FfuFile.Read(Payload, 0, Payload.Length);
ChunkCount++;
@@ -1015,12 +1032,12 @@ namespace WPinternals
// Protocol v2
Payload = new byte[Info.WriteBufferSize];
while (Position < (UInt64)FfuFile.Length)
while (Position < (ulong)FfuFile.Length)
{
UInt32 PayloadSize = Info.WriteBufferSize;
if (((UInt64)FfuFile.Length - Position) < PayloadSize)
uint PayloadSize = Info.WriteBufferSize;
if ((ulong)FfuFile.Length - Position < PayloadSize)
{
PayloadSize = (UInt32)((UInt64)FfuFile.Length - Position);
PayloadSize = (uint)((ulong)FfuFile.Length - Position);
Payload = new byte[PayloadSize];
}
@@ -1124,25 +1141,25 @@ namespace WPinternals
{
using (InputStream)
{
UInt64? InputStreamLength = null;
ulong? InputStreamLength = null;
try
{
InputStreamLength = (UInt64)InputStream.Length;
InputStreamLength = (ulong)InputStream.Length;
}
catch (Exception ex)
{
LogFile.LogException(ex, LogType.FileOnly);
}
if ((InputStreamLength != null) && ((UInt64)InputStream.Length > PartitionSize))
if (InputStreamLength != null && (ulong)InputStream.Length > PartitionSize)
{
throw new InvalidOperationException("Partition can not be flashed, because its size is too big!");
}
ProgressUpdater Progress = UpdaterPerSector;
if ((Progress == null) && (ProgressUpdateCallback != null) && (InputStreamLength != null))
if (Progress == null && ProgressUpdateCallback != null && InputStreamLength != null)
{
Progress = new ProgressUpdater((UInt64)(InputStreamLength / 0x200), ProgressUpdateCallback);
Progress = new ProgressUpdater((ulong)(InputStreamLength / 0x200), ProgressUpdateCallback);
}
int ProgressPercentage = 0;
@@ -1150,7 +1167,7 @@ namespace WPinternals
const int FlashBufferSize = 0x200000; // Flash 8 GB phone -> buffersize 0x200000 = 11:45 min, buffersize 0x20000 = 12:30 min
byte[] FlashBuffer = new byte[FlashBufferSize];
int BytesRead;
UInt64 i = 0;
ulong i = 0;
do
{
BytesRead = InputStream.Read(FlashBuffer, 0, FlashBufferSize);
@@ -1168,12 +1185,12 @@ namespace WPinternals
Buffer.BlockCopy(FlashBuffer, 0, FlashBufferFinalSize, 0, BytesRead);
}
FlashSectors((UInt32)(Partition.FirstSector + (i / 0x200)), FlashBufferFinalSize, ProgressPercentage);
FlashSectors((uint)(Partition.FirstSector + i / 0x200), FlashBufferFinalSize, ProgressPercentage);
}
if (Progress != null)
{
Progress.IncreaseProgress((UInt64)FlashBuffer.Length / 0x200);
Progress.IncreaseProgress((ulong)FlashBuffer.Length / 0x200);
ProgressPercentage = Progress.ProgressPercentage;
}
@@ -19,8 +19,10 @@
// DEALINGS IN THE SOFTWARE.
using System;
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia.UEFI;
namespace WPinternals
namespace WPinternals.Models.UEFIApps.Flash
{
internal class LumiaFlashAppPhoneInfo
{
@@ -36,13 +38,13 @@ namespace WPinternals
public byte FlashAppProtocolVersionMajor;
public byte FlashAppProtocolVersionMinor;
public UInt32 TransferSize;
public uint TransferSize;
public bool MmosOverUsbSupported;
public UInt32 SdCardSizeInSectors;
public UInt32 WriteBufferSize;
public UInt32 EmmcSizeInSectors;
public uint SdCardSizeInSectors;
public uint WriteBufferSize;
public uint EmmcSizeInSectors;
public string PlatformID;
public UInt16 SecureFfuSupportedProtocolMask;
public ushort SecureFfuSupportedProtocolMask;
public bool AsyncSupport;
public bool PlatformSecureBootEnabled;
@@ -78,14 +80,14 @@ namespace WPinternals
break;
}
LogFile.Log($"SecureBoot: {((!PlatformSecureBootEnabled || !UefiSecureBootEnabled) ? "Disabled" : "Enabled")} (Platform Secure Boot: {(PlatformSecureBootEnabled ? "Enabled" : "Disabled")}, UEFI Secure Boot: {(UefiSecureBootEnabled ? "Enabled" : "Disabled")})", Type);
LogFile.Log($"SecureBoot: {(!PlatformSecureBootEnabled || !UefiSecureBootEnabled ? "Disabled" : "Enabled")} (Platform Secure Boot: {(PlatformSecureBootEnabled ? "Enabled" : "Disabled")}, UEFI Secure Boot: {(UefiSecureBootEnabled ? "Enabled" : "Disabled")})", Type);
if ((Type == LogType.ConsoleOnly) || (Type == LogType.FileAndConsole))
if (Type == LogType.ConsoleOnly || Type == LogType.FileAndConsole)
{
LogFile.Log($"Flash app security: {(!IsBootloaderSecure ? "Disabled" : "Enabled")}", LogType.ConsoleOnly);
}
if ((Type == LogType.FileOnly) || (Type == LogType.FileAndConsole))
if (Type == LogType.FileOnly || Type == LogType.FileAndConsole)
{
LogFile.Log($"Flash app security: {(!IsBootloaderSecure ? "Disabled" : "Enabled")} (FFU security: {(SecureFfuEnabled ? "Enabled" : "Disabled")}, RDC: {(RdcPresent ? "Present" : "Not found")}, Authenticated: {(Authenticated ? "True" : "False")})", LogType.FileOnly);
}
@@ -0,0 +1,28 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
namespace WPinternals.Models.UEFIApps.Flash
{
internal enum SecureBootKeyType : byte
{
Retail = 0,
Engineering = 1
}
}
@@ -18,7 +18,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
namespace WPinternals
namespace WPinternals.Models.Lumia.UEFI.Flash
{
internal class UefiSecurityStatusResponse
{
@@ -18,7 +18,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
namespace WPinternals
namespace WPinternals.Models.Lumia.UEFI
{
internal enum FlashAppType
{
@@ -0,0 +1,122 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace WPinternals.Models.Lumia.UEFI
{
internal partial class NokiaUEFIModel : NokiaPhoneModel
{
internal void SwitchToFlashAppContext()
{
CommonPhoneInfo info = ReadPhoneInfoCommon();
bool ModernFlashApp = info.VersionMajor >= 2;
SendCommonExtendedSwitchToCommand('F');
if (ModernFlashApp)
{
DisableRebootTimeOut();
InterfaceChanged(PhoneInterfaces.Lumia_Flash, _devicePath);
}
}
internal void SwitchToPhoneInfoAppContext()
{
CommonPhoneInfo info = ReadPhoneInfoCommon();
bool ModernFlashApp = info.VersionMajor >= 2;
SendCommonExtendedSwitchToCommand('P');
if (ModernFlashApp)
{
DisableRebootTimeOut();
CommonInfo.App = FlashAppType.PhoneInfoApp;
InterfaceChanged(PhoneInterfaces.Lumia_PhoneInfo, _devicePath);
}
}
internal void SwitchToBootManagerContext(bool DisableTimeOut = true)
{
CommonPhoneInfo info = ReadPhoneInfoCommon();
bool ModernFlashApp = info.VersionMajor >= 2;
SendCommonExtendedSwitchToCommand('B');
if (ModernFlashApp)
{
DisableRebootTimeOut();
InterfaceChanged(PhoneInterfaces.Lumia_Bootloader, _devicePath);
}
}
internal void SwitchToMmosContext()
{
SendCommonExtendedSwitchToCommand('A');
}
internal void SwitchToNormalModeContext()
{
SendCommonExtendedSwitchToCommand('W');
}
internal void SwitchToMassStorageModeContext()
{
SendCommonExtendedSwitchToCommand('M');
}
internal void SwitchToResetContext()
{
SendCommonExtendedSwitchToCommand('R');
}
internal void SwitchToEmergencyMode()
{
SendCommonExtendedSwitchToCommand('E');
}
internal void SendCommonExtendedSwitchToCommand(char Mode)
{
byte[] Request = new byte[7];
ByteOperations.WriteAsciiString(Request, 0, $"{SwitchModeSignature}{Mode}");
byte[] Response = ExecuteRawMethod(Request);
if (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU")
{
throw new NotSupportedException();
}
UInt16 Error = (UInt16)((Response[6] << 8) + Response[7]);
if (Error > 0)
{
throw new NotSupportedException("SendCommonExtendedSwitchToCommand: Error 0x" + Error.ToString("X4"));
}
}
}
}
@@ -19,12 +19,13 @@
// DEALINGS IN THE SOFTWARE.
using System;
using WPinternals.HelperClasses;
namespace WPinternals
namespace WPinternals.Models.Lumia.UEFI
{
internal delegate void InterfaceChangedHandler(PhoneInterfaces NewInterface, string DevicePath);
internal class NokiaUEFIModel : NokiaPhoneModel
internal partial class NokiaUEFIModel : NokiaPhoneModel
{
private string _devicePath;
@@ -55,110 +56,6 @@ namespace WPinternals
_devicePath = DevicePath;
}
internal void SwitchToBootManagerContext(bool DisableTimeOut = true)
{
CommonPhoneInfo info = ReadPhoneInfoCommon();
bool ModernFlashApp = info.VersionMajor >= 2;
byte[] Request = new byte[7];
ByteOperations.WriteAsciiString(Request, 0, $"{SwitchModeSignature}B");
byte[] Response = ExecuteRawMethod(Request);
if (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU")
{
throw new NotSupportedException();
}
UInt16 Error = (UInt16)((Response[6] << 8) + Response[7]);
if (Error > 0)
{
throw new NotSupportedException("SwitchToBootManagerContext: Error 0x" + Error.ToString("X4"));
}
if (ModernFlashApp)
{
DisableRebootTimeOut();
InterfaceChanged(PhoneInterfaces.Lumia_Bootloader, _devicePath);
}
}
internal void SwitchToPhoneInfoAppContext()
{
CommonPhoneInfo info = ReadPhoneInfoCommon();
bool ModernFlashApp = info.VersionMajor >= 2;
byte[] Request = new byte[7];
ByteOperations.WriteAsciiString(Request, 0, SwitchModeSignature + "P");
byte[] Response = ExecuteRawMethod(Request);
if (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU")
{
throw new NotSupportedException();
}
UInt16 Error = (UInt16)((Response[6] << 8) + Response[7]);
if (Error > 0)
{
throw new NotSupportedException("SwitchToPhoneInfoAppContext: Error 0x" + Error.ToString("X4"));
}
if (ModernFlashApp)
{
DisableRebootTimeOut();
CommonInfo.App = FlashAppType.PhoneInfoApp;
InterfaceChanged(PhoneInterfaces.Lumia_PhoneInfo, _devicePath);
}
}
internal void SwitchToMmosContext()
{
byte[] Request = new byte[7];
ByteOperations.WriteAsciiString(Request, 0, $"{SwitchModeSignature}A");
byte[] Response = ExecuteRawMethod(Request);
if (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU")
{
throw new NotSupportedException();
}
UInt16 Error = (UInt16)((Response[6] << 8) + Response[7]);
if (Error > 0)
{
throw new NotSupportedException("SwitchToPhoneInfoAppContext: Error 0x" + Error.ToString("X4"));
}
}
internal void SwitchToFlashAppContext()
{
CommonPhoneInfo info = ReadPhoneInfoCommon();
bool ModernFlashApp = info.VersionMajor >= 2;
byte[] Request = new byte[7];
ByteOperations.WriteAsciiString(Request, 0, $"{SwitchModeSignature}F"); // This will stop charging the phone
byte[] Response = ExecuteRawMethod(Request);
if (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU")
{
throw new NotSupportedException();
}
UInt16 Error = (UInt16)((Response[6] << 8) + Response[7]);
if (Error > 0)
{
throw new NotSupportedException("SwitchToFlashAppContext: Error 0x" + Error.ToString("X4"));
}
if (ModernFlashApp)
{
DisableRebootTimeOut();
InterfaceChanged(PhoneInterfaces.Lumia_Flash, _devicePath);
}
}
//
// Normal commands
//
@@ -237,5 +134,46 @@ namespace WPinternals
{
InterfaceChanged(NewInterface, _devicePath);
}
// Raw USB Interfaces
protected byte[] ExecuteRawMethod(byte[] RawMethod)
{
return ExecuteRawMethod(RawMethod, RawMethod.Length);
}
protected byte[] ExecuteRawMethod(byte[] RawMethod, int Length)
{
byte[] Buffer = new byte[0x8000]; // Should be at least 0x4408 for receiving the GPT packet.
byte[] Result = null;
lock (UsbLock)
{
Device.OutputPipe.Write(RawMethod, 0, Length);
try
{
int OutputLength = Device.InputPipe.Read(Buffer);
Result = new byte[OutputLength];
System.Buffer.BlockCopy(Buffer, 0, Result, 0, OutputLength);
}
catch (Exception ex) // Reboot command looses connection
{
LogFile.LogException(ex, LogType.FileOnly);
}
}
return Result;
}
protected void ExecuteRawVoidMethod(byte[] RawMethod)
{
ExecuteRawVoidMethod(RawMethod, RawMethod.Length);
}
protected void ExecuteRawVoidMethod(byte[] RawMethod, int Length)
{
lock (UsbLock)
{
Device.OutputPipe.Write(RawMethod, 0, Length);
}
}
}
}
@@ -20,8 +20,10 @@
using System;
using System.Collections.Generic;
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia.UEFI;
namespace WPinternals
namespace WPinternals.Models.UEFIApps.PhoneInfo
{
internal class LumiaPhoneInfoAppModel : NokiaUEFIModel
{
@@ -82,12 +84,12 @@ namespace WPinternals
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, GetPhoneInfoSignature);
byte[] Response = ExecuteRawMethod(Request);
if ((Response == null) || (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU"))
if (Response == null || ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU")
{
throw new NotSupportedException();
}
UInt16 Length = BigEndian.ToUInt16(Response, 0x04);
ushort Length = BigEndian.ToUInt16(Response, 0x04);
string PhoneInfoData = ByteOperations.ReadAsciiString(Response, 0x8, Length);
@@ -104,7 +106,7 @@ namespace WPinternals
LumiaPhoneInfoAppPhoneInfo Result = PhoneInfoAppInfo;
if (ExtendedInfo && (Result.State == PhoneInfoState.Basic))
if (ExtendedInfo && Result.State == PhoneInfoState.Basic)
{
try
{
@@ -175,7 +177,7 @@ namespace WPinternals
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, InfoQuerySignature);
byte[] Response = ExecuteRawMethod(Request);
if ((Response != null) && (ByteOperations.ReadAsciiString(Response, 0, 4) != "NOKU"))
if (Response != null && ByteOperations.ReadAsciiString(Response, 0, 4) != "NOKU")
{
Result.App = (FlashAppType)Response[5];
@@ -198,9 +200,8 @@ namespace WPinternals
LogFile.Log($"{Result.App} SubblockID: 0x{SubblockID:X}");
UInt16 SubblockLength = BigEndian.ToUInt16(Response, SubblockOffset + 0x01);
ushort SubblockLength = BigEndian.ToUInt16(Response, SubblockOffset + 0x01);
int SubblockPayloadOffset = SubblockOffset + 3;
byte SubblockVersion;
switch (SubblockID)
{
case 0x20:
@@ -224,7 +225,7 @@ namespace WPinternals
byte[] Request = new byte[16];
ByteOperations.WriteAsciiString(Request, 0, GetVariableSignature + VariableName + "\0"); // BTR or CTR, CTR is public ProductCode
byte[] Response = ExecuteRawMethod(Request);
UInt16 Length = BigEndian.ToUInt16(Response, 6);
ushort Length = BigEndian.ToUInt16(Response, 6);
return ByteOperations.ReadAsciiString(Response, 8, Length).Trim([' ', '\0']);
}
@@ -18,7 +18,31 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
namespace WPinternals
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia.UEFI;
namespace WPinternals.Models.UEFIApps.PhoneInfo
{
internal class LumiaPhoneInfoAppPhoneInfo
{
@@ -49,7 +73,7 @@ namespace WPinternals
LogFile.Log($"Product code: {ProductCode}", Type);
}
if (Type != LogType.ConsoleOnly && (Imei != null))
if (Type != LogType.ConsoleOnly && Imei != null)
{
LogFile.Log($"IMEI: {Imei}", LogType.FileOnly);
}
@@ -18,7 +18,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
namespace WPinternals
namespace WPinternals.Models.Lumia.UEFI
{
internal enum PhoneInfoState
{
+5 -3
View File
@@ -23,6 +23,8 @@ using System.IO;
using System.Linq;
using System.Management;
using System.Runtime.InteropServices;
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia;
namespace WPinternals
{
@@ -41,14 +43,14 @@ namespace WPinternals
{
try
{
foreach (ManagementObject logical in new ManagementObjectSearcher("select * from Win32_LogicalDisk").Get())
foreach (ManagementObject logical in new ManagementObjectSearcher("select * from Win32_LogicalDisk").Get().Cast<ManagementObject>())
{
System.Diagnostics.Debug.Print(logical["Name"].ToString());
string Label = "";
foreach (ManagementObject partition in logical.GetRelated("Win32_DiskPartition"))
foreach (ManagementObject partition in logical.GetRelated("Win32_DiskPartition").Cast<ManagementObject>())
{
foreach (ManagementObject drive in partition.GetRelated("Win32_DiskDrive"))
foreach (ManagementObject drive in partition.GetRelated("Win32_DiskDrive").Cast<ManagementObject>())
{
if (drive["PNPDeviceID"].ToString().Contains("VEN_QUALCOMM&PROD_MMC_STORAGE", StringComparison.CurrentCulture) ||
drive["PNPDeviceID"].ToString().Contains("VEN_MSFT&PROD_PHONE_MMC_STOR", StringComparison.CurrentCulture))
+1
View File
@@ -28,6 +28,7 @@ using System.Security.Cryptography;
using System.Security.Principal;
using System.Xml;
using System.Xml.Serialization;
using WPinternals.HelperClasses;
namespace WPinternals
{
+1
View File
@@ -25,6 +25,7 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WPinternals.HelperClasses;
namespace WPinternals
{
+1
View File
@@ -20,6 +20,7 @@
using System;
using System.IO;
using WPinternals.HelperClasses;
namespace WPinternals
{
+1
View File
@@ -22,6 +22,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using WPinternals.HelperClasses;
namespace WPinternals
{
+1
View File
@@ -22,6 +22,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using WPinternals.HelperClasses;
namespace WPinternals
{
+1
View File
@@ -22,6 +22,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using WPinternals.HelperClasses;
namespace WPinternals
{
+1
View File
@@ -21,6 +21,7 @@
using MadWizard.WinUSBNet;
using System;
using System.IO.Ports;
using WPinternals.HelperClasses;
namespace WPinternals
{
+1
View File
@@ -20,6 +20,7 @@
using System;
using System.IO;
using WPinternals.HelperClasses;
namespace WPinternals
{
+1 -1
View File
@@ -316,7 +316,7 @@ namespace WPinternals
EFI File = EFIs.Find(f => string.Equals(Name, f.Name, StringComparison.CurrentCultureIgnoreCase) || string.Equals(Name, f.Guid.ToString(), StringComparison.CurrentCultureIgnoreCase));
if (File == null)
{
throw new ArgumentOutOfRangeException();
throw new ArgumentOutOfRangeException(nameof(Name));
}
UInt32 OldBinarySize = File.Size;
@@ -19,9 +19,8 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace WPinternals
namespace WPinternals.Terminal
{
internal static class Terminal
{
@@ -30,13 +29,13 @@ namespace WPinternals
TerminalResponse Response = new();
// Get root node
if (Buffer.Length >= (Offset + 8))
if (Buffer.Length >= Offset + 8)
{
int NodeNumber = BitConverter.ToInt32(Buffer, Offset);
int NodeSize = BitConverter.ToInt32(Buffer, Offset + 4);
int End = NodeSize + Offset + 8;
int Index = Offset + 8;
if ((NodeNumber == 0x10000) && (End <= Buffer.Length))
if (NodeNumber == 0x10000 && End <= Buffer.Length)
{
// Get subnodes
while (Index < End)
@@ -58,11 +57,4 @@ namespace WPinternals
return Response;
}
}
internal class TerminalResponse
{
public Dictionary<int, byte[]> RawEntries = [];
public byte[] PublicId = null;
public byte[] RootKeyHash = null;
}
}
+31
View File
@@ -0,0 +1,31 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
namespace WPinternals.Terminal
{
internal class TerminalResponse
{
public Dictionary<int, byte[]> RawEntries = [];
public byte[] PublicId = null;
public byte[] RootKeyHash = null;
}
}
+5 -3
View File
@@ -23,6 +23,8 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using WPinternals.HelperClasses;
using WPinternals.Models.UEFIApps.Flash;
namespace WPinternals
{
@@ -181,9 +183,9 @@ namespace WPinternals
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage);
MassStorage MassStorage = (MassStorage)Notifier.CurrentModel;
foreach (var part in Directory.EnumerateFiles(PartPath))
foreach (string part in Directory.EnumerateFiles(PartPath))
{
var partname = part.Split('\\').Last().Replace(".img", "");
string partname = part.Split('\\').Last().Replace(".img", "");
try
{
LogFile.Log($"Writing {partname} to the device.", LogType.ConsoleOnly);
@@ -203,7 +205,7 @@ namespace WPinternals
internal static void PatchImg(string dump)
{
using var fil = File.Open(dump, FileMode.Open);
using FileStream fil = File.Open(dump, FileMode.Open);
byte[] gptbuffer = new byte[0x4200];
fil.Seek(0x200, SeekOrigin.Begin);
@@ -20,6 +20,7 @@
using System;
using System.Threading;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -23,6 +23,7 @@ using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Threading;
using WPinternals.HelperClasses;
namespace WPinternals
{
+1
View File
@@ -20,6 +20,7 @@
using System;
using System.Threading;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -21,6 +21,7 @@
using System;
using System.ComponentModel;
using System.Threading;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -21,6 +21,7 @@
using Microsoft.Win32;
using System;
using System.Windows;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -21,6 +21,7 @@
using Microsoft.Win32;
using System;
using System.Windows;
using WPinternals.HelperClasses;
namespace WPinternals
{
+14 -12
View File
@@ -30,6 +30,11 @@ using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Data;
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia.MSR;
using WPinternals.Models.Lumia.NCSd;
using WPinternals.Models.UEFIApps.Flash;
using WPinternals.Models.UEFIApps.PhoneInfo;
namespace WPinternals
{
@@ -663,7 +668,7 @@ namespace WPinternals
}
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
{
NokiaPhoneModel LumiaNormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
NokiaCareSuiteModel LumiaNormalModel = (NokiaCareSuiteModel)Notifier.CurrentModel;
OperatorCode = LumiaNormalModel.ExecuteJsonMethodAsString("ReadOperatorName", "OperatorName"); // Example: 000-NL
string TempProductType = LumiaNormalModel.ExecuteJsonMethodAsString("ReadManufacturerModelName", "ManufacturerModelName"); // RM-821_eu_denmark_251
if (TempProductType.Contains('_'))
@@ -1082,7 +1087,7 @@ namespace WPinternals
public static class HttpClientProgressExtensions
{
public static async Task DownloadFileAsync(this HttpClient client, Uri address, string fileName, Action<HttpClientDownloadProgress> progress = null, Action<bool> completed = null, CancellationToken cancellationToken = default(CancellationToken))
public static async Task DownloadFileAsync(this HttpClient client, Uri address, string fileName, Action<HttpClientDownloadProgress> progress = null, Action<bool> completed = null, CancellationToken cancellationToken = default)
{
try
{
@@ -1094,25 +1099,22 @@ namespace WPinternals
if (progress is null || !contentLength.HasValue)
{
await download.CopyToAsync(destination);
if (completed != null)
completed(true);
completed?.Invoke(true);
return;
}
Progress<long> progressWrapper = new Progress<long>(totalBytes => progress(new HttpClientDownloadProgress(totalBytes, contentLength.Value)));
Progress<long> progressWrapper = new(totalBytes => progress(new HttpClientDownloadProgress(totalBytes, contentLength.Value)));
await download.CopyToAsync(destination, 81920, progressWrapper, cancellationToken);
if (completed != null)
completed(true);
completed?.Invoke(true);
}
catch
{
if (completed != null)
completed(false);
completed?.Invoke(false);
}
}
private static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress<long> progress = null, CancellationToken cancellationToken = default(CancellationToken))
private static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress<long> progress = null, CancellationToken cancellationToken = default)
{
if (bufferSize < 0)
throw new ArgumentOutOfRangeException(nameof(bufferSize));
@@ -1128,9 +1130,9 @@ namespace WPinternals
byte[] buffer = new byte[bufferSize];
long totalBytesRead = 0;
int bytesRead;
while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
while ((bytesRead = await source.ReadAsync(buffer, cancellationToken).ConfigureAwait(false)) != 0)
{
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
await destination.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken).ConfigureAwait(false);
totalBytesRead += bytesRead;
progress?.Report(totalBytesRead);
}
@@ -20,6 +20,7 @@
using System;
using System.Threading;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -21,6 +21,7 @@
using System;
using System.Linq;
using System.Threading;
using WPinternals.HelperClasses;
namespace WPinternals
{
+4 -4
View File
@@ -438,12 +438,12 @@ namespace WPinternals
//read the content
//TODO: it may throw an exception (stream closed because file expired?)
//In that case we would wrap into another try catch and try to read the reason behind this
while ((bytesRead = await streamToReadFrom.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) > 0)
while ((bytesRead = await streamToReadFrom.ReadAsync(buffer, cancellationToken)) > 0)
{
totalBytesRead += bytesRead;
//simply write to the file
await streamToWriteTo.WriteAsync(buffer, 0, bytesRead, cancellationToken);
await streamToWriteTo.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken);
//report progress
downloadProgress?.Report(new FileDownloadStatus(downloadFile)
@@ -593,9 +593,9 @@ namespace WPinternals
byte[] buffer = new byte[bufSizeEffective];
using MemoryStream ms = new(buffer);
using CryptoStream cs = new(ms, hashAlgorithm, CryptoStreamMode.Write);
while ((readBytes = await fileStream.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) > 0)
while ((readBytes = await fileStream.ReadAsync(buffer, cancellationToken)) > 0)
{
await cs.WriteAsync(buffer, 0, readBytes, cancellationToken);
await cs.WriteAsync(buffer.AsMemory(0, readBytes), cancellationToken);
ms.Position = 0;
totalBytesRead += readBytes;
progress?.Report(totalBytesRead);
@@ -20,6 +20,7 @@
using System;
using System.Threading;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -25,6 +25,9 @@ using System.IO.Compression;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using WPinternals.HelperClasses;
using WPinternals.Models.UEFIApps.BootMgr;
using WPinternals.Models.UEFIApps.Flash;
namespace WPinternals
{
+7 -2
View File
@@ -19,6 +19,11 @@
// DEALINGS IN THE SOFTWARE.
using System;
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia.NCSd;
using WPinternals.Models.UEFIApps.BootMgr;
using WPinternals.Models.UEFIApps.Flash;
using WPinternals.Models.UEFIApps.PhoneInfo;
namespace WPinternals
{
@@ -75,13 +80,13 @@ namespace WPinternals
ActivateSubContext(new NokiaPhoneInfoViewModel((LumiaPhoneInfoAppModel)CurrentModel, ModeSwitchRequestCallback, SwitchToGettingStarted));
break;
case PhoneInterfaces.Lumia_Normal:
ActivateSubContext(new NokiaNormalViewModel((NokiaPhoneModel)CurrentModel, ModeSwitchRequestCallback));
ActivateSubContext(new NokiaNormalViewModel((NokiaCareSuiteModel)CurrentModel, ModeSwitchRequestCallback));
break;
case PhoneInterfaces.Lumia_Flash:
ActivateSubContext(new NokiaFlashViewModel((LumiaFlashAppModel)CurrentModel, ModeSwitchRequestCallback, SwitchToGettingStarted));
break;
case PhoneInterfaces.Lumia_Label:
ActivateSubContext(new NokiaLabelViewModel((NokiaPhoneModel)CurrentModel, ModeSwitchRequestCallback));
ActivateSubContext(new NokiaLabelViewModel((NokiaCareSuiteModel)CurrentModel, ModeSwitchRequestCallback));
break;
case PhoneInterfaces.Lumia_MassStorage:
ActivateSubContext(new NokiaMassStorageViewModel((MassStorage)CurrentModel));
+7 -2
View File
@@ -19,6 +19,11 @@
// DEALINGS IN THE SOFTWARE.
using System;
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia.NCSd;
using WPinternals.Models.UEFIApps.BootMgr;
using WPinternals.Models.UEFIApps.Flash;
using WPinternals.Models.UEFIApps.PhoneInfo;
namespace WPinternals
{
@@ -93,13 +98,13 @@ namespace WPinternals
ActivateSubContext(new NokiaModePhoneInfoViewModel((LumiaPhoneInfoAppModel)CurrentModel, OnModeSwitchRequested));
break;
case PhoneInterfaces.Lumia_Normal:
ActivateSubContext(new NokiaModeNormalViewModel((NokiaPhoneModel)CurrentModel, OnModeSwitchRequested));
ActivateSubContext(new NokiaModeNormalViewModel((NokiaCareSuiteModel)CurrentModel, OnModeSwitchRequested));
break;
case PhoneInterfaces.Lumia_Flash:
ActivateSubContext(new NokiaModeFlashViewModel((LumiaFlashAppModel)CurrentModel, OnModeSwitchRequested));
break;
case PhoneInterfaces.Lumia_Label:
ActivateSubContext(new NokiaModeLabelViewModel((NokiaPhoneModel)CurrentModel, OnModeSwitchRequested));
ActivateSubContext(new NokiaModeLabelViewModel((NokiaCareSuiteModel)CurrentModel, OnModeSwitchRequested));
break;
case PhoneInterfaces.Lumia_MassStorage:
ActivateSubContext(new NokiaModeMassStorageViewModel((MassStorage)CurrentModel, OnModeSwitchRequested));
@@ -24,6 +24,11 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WPinternals.Config;
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia.UEFI.Flash;
using WPinternals.Models.UEFIApps.Flash;
using WPinternals.Models.UEFIApps.PhoneInfo;
namespace WPinternals
{
@@ -26,6 +26,10 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia.UEFI.Flash;
using WPinternals.Models.UEFIApps.BootMgr;
using WPinternals.Models.UEFIApps.Flash;
namespace WPinternals
{
@@ -51,8 +55,7 @@ namespace WPinternals
FlashModel.SendFfuPayloadV1(EmptyChunk);
// Reboot to Qualcomm Emergency mode
byte[] RebootCommand = [0x4E, 0x4F, 0x4B, 0x52]; // NOKR
FlashModel.ExecuteRawVoidMethod(RebootCommand);
FlashModel.ResetPhone();
}
private static void SendLoader(PhoneNotifierViewModel PhoneNotifier, List<QualcommPartition> PossibleLoaders)
@@ -1960,7 +1963,7 @@ namespace WPinternals
string SBRes = IsSpecB ? "WPinternals.SB" : "WPinternals.SBA";
Part.Stream = new SeekableStream(() =>
{
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
// Magic!
// The SB(A) resource is a compressed version of a raw NV-variable-partition.
@@ -1968,7 +1971,7 @@ namespace WPinternals
// 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.
var stream = assembly.GetManifestResourceStream(SBRes);
Stream stream = assembly.GetManifestResourceStream(SBRes);
return new DecompressedStream(stream);
});
@@ -20,6 +20,7 @@
using System;
using System.Threading;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -21,6 +21,7 @@
using System;
using System.Linq;
using System.Threading;
using WPinternals.HelperClasses;
namespace WPinternals
{
@@ -25,6 +25,13 @@ using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Threading.Tasks;
using WPinternals.Config;
using WPinternals.HelperClasses;
using WPinternals.Models.Lumia.UEFI;
using WPinternals.Models.UEFIApps;
using WPinternals.Models.UEFIApps.BootMgr;
using WPinternals.Models.UEFIApps.Flash;
using WPinternals.Models.UEFIApps.PhoneInfo;
namespace WPinternals
{
@@ -183,7 +190,7 @@ namespace WPinternals
Part.StartSector = (UInt32)TargetPartition.FirstSector; // GPT is prepared for 64-bit sector-offset, but flash app isn't.
Part.Stream = new SeekableStream(() =>
{
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
// Magic!
// The SB resource is a compressed version of a raw NV-variable-partition.
@@ -191,7 +198,7 @@ namespace WPinternals
// 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.
var stream = assembly.GetManifestResourceStream("WPinternals.SB");
Stream stream = assembly.GetManifestResourceStream("WPinternals.SB");
return new DecompressedStream(stream);
});
@@ -500,7 +507,7 @@ namespace WPinternals
}
else
{
foreach (var part in FlashParts)
foreach (FlashPart part in FlashParts)
{
if (part.StartSector >= UefiBSNV.FirstSector && part.StartSector <= UefiBSNV.LastSector)
{
@@ -1877,7 +1884,7 @@ namespace WPinternals
ulong CurrentProcess1 = 0;
SetWorkingStatus("Hashing resources...", "Initializing flash...", (UInt64)TotalProcess1, Status: WPinternalsStatus.Initializing);
var crypto = System.Security.Cryptography.SHA256.Create();
System.Security.Cryptography.SHA256 crypto = System.Security.Cryptography.SHA256.Create();
List<FlashingPayload> flashingPayloads = [];
if (flashParts == null)
{
@@ -1888,7 +1895,7 @@ namespace WPinternals
{
FlashPart flashPart = flashParts[(Int32)j];
flashPart.Stream.Seek(0, SeekOrigin.Begin);
var totalChunkCount = flashPart.Stream.Length / chunkSize;
long totalChunkCount = flashPart.Stream.Length / chunkSize;
for (UInt32 i = 0; i < totalChunkCount; i++)
{
UpdateWorkingStatus("Hashing resources...", "Initializing flash...", CurrentProcess1, WPinternalsStatus.Initializing);
@@ -1931,19 +1938,19 @@ namespace WPinternals
{
FlashPart flashPart = flashParts[(Int32)j];
flashPart.Stream.Seek(0, SeekOrigin.Begin);
var totalChunkCount = flashPart.Stream.Length / chunkSize;
long totalChunkCount = flashPart.Stream.Length / chunkSize;
for (UInt32 i = 0; i < totalChunkCount; i++)
{
UpdateWorkingStatus("Hashing resources...", "Initializing flash...", CurrentProcess1, WPinternalsStatus.Initializing);
byte[] buffer = new byte[chunkSize];
Int64 position = flashPart.Stream.Position;
flashPart.Stream.Read(buffer, 0, chunkSize);
var hash = crypto.ComputeHash(buffer);
byte[] hash = crypto.ComputeHash(buffer);
if (flashingPayloads.Any(x => ByteOperations.Compare(x.ChunkHashes[0], hash)))
{
var payloadIndex = flashingPayloads.FindIndex(x => ByteOperations.Compare(x.ChunkHashes[0], hash));
var locationList = flashingPayloads[payloadIndex].TargetLocations.ToList();
int payloadIndex = flashingPayloads.FindIndex(x => ByteOperations.Compare(x.ChunkHashes[0], hash));
List<uint> locationList = flashingPayloads[payloadIndex].TargetLocations.ToList();
locationList.Add((flashPart.StartSector * 0x200 / (UInt32)chunkSize) + i);
flashingPayloads[payloadIndex].TargetLocations = [.. locationList];
}
@@ -2255,7 +2262,7 @@ namespace WPinternals
Part.StartSector = (UInt32)Target.FirstSector; // GPT is prepared for 64-bit sector-offset, but flash app isn't.
Part.Stream = new SeekableStream(() =>
{
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
// Magic!
// The SB resource is a compressed version of a raw NV-variable-partition.
@@ -2263,7 +2270,7 @@ namespace WPinternals
// 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.
var stream = assembly.GetManifestResourceStream("WPinternals.SB");
Stream stream = assembly.GetManifestResourceStream("WPinternals.SB");
return new DecompressedStream(stream);
});
@@ -2614,7 +2621,7 @@ namespace WPinternals
Part.StartSector = (UInt32)Target.FirstSector; // GPT is prepared for 64-bit sector-offset, but flash app isn't.
Part.Stream = new SeekableStream(() =>
{
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
// Magic!
// The SB resource is a compressed version of a raw NV-variable-partition.
@@ -2622,7 +2629,7 @@ namespace WPinternals
// 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.
var stream = assembly.GetManifestResourceStream("WPinternals.SB");
Stream stream = assembly.GetManifestResourceStream("WPinternals.SB");
return new DecompressedStream(stream);
});

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