33 Commits
Author SHA1 Message Date
Gustave Monce 8981fd02e9 Enable Preview Build 2023-11-26 18:50:46 +01:00
Gustave Monce 16d3f95971 WPinternals v3.0 2023-11-26 18:39:49 +01:00
Gustave Monce 293c649edb Refactor Qualcomm Sahara and Qualcomm Firehose code 2023-11-26 18:37:14 +01:00
Gustave Monce 88efc77887 Cleanup Sahara Implementation 2023-11-26 18:08:50 +01:00
Gustave Monce dc6085f185 Sahara: Implement getting the RKH 2023-11-26 16:51:29 +01:00
Gustave Monce e2cbb9c6fc Alter the list of OS partitions 2023-11-26 14:19:05 +01:00
Gustave Monce 4b7b9621b4 Rebuild the Backup to Custom ROM zip functionality to handle more partitions and be more flexible 2023-11-26 14:04:13 +01:00
Gustave Monce 96c42a29b5 Adopt new C# syntax for array init 2023-11-26 14:03:46 +01:00
Gustave Monce 742c89b9bf CI: Use .NET 8 SDK 2023-11-26 13:09:49 +01:00
Gustave Monce dbd303fd07 Add new feature to generate a GPT xml file from a binary or backup 2023-11-26 13:08:33 +01:00
Gustave Monce 8d35be447a Project: Update to .NET 8 2023-11-26 12:25:14 +01:00
Gustave Monce 83c09bdc81 Improve RKH Reading from Qualcomm Images 2023-03-09 21:40:23 +01:00
Gustave MonceandGitHub 93a5064751 Merge pull request #47 from ungeskriptet/fix-typo 2022-12-23 09:31:24 +01:00
David Wronek ef6a962a01 Fix typo in MassStorageView 2022-12-19 20:35:47 +01:00
Gustave Monce d32788198d Project: Migrate to .NET 7 2022-11-11 02:26:45 -08:00
Gustave Monce 7798dd1c34 RKH: Fix an issue retrieving modern day RKH 2022-11-11 02:22:17 -08:00
Gustave Monce 57cd052d61 About: Show Build and Revision in the version field 2021-11-15 15:06:13 +01:00
Gustave Monce 5eb523530c Remove the Lumia 535 from the supported phone list 2021-11-15 14:53:34 +01:00
Gustave Monce 8a17b05398 Project: Update to .NET 6 2021-11-15 14:47:29 +01:00
Gustave Monce dc5ac1e7d4 CI: Make CI always fetch latest .NET 5 SDK 2021-08-26 09:09:47 +02:00
Gustave Monce 1d14d79fab Flash: Custom ROM: Fix incorrect unlocked check for EFIESP 2021-08-16 11:40:58 +02:00
Gustave Monce 846ea41883 Project: Add SDK 2021-08-14 11:24:02 +02:00
Gustave Monce 452393aaa7 Project: Add RootAccessTestUWP 2021-08-14 11:14:56 +02:00
Gustave Monce 17bc763761 Project: Move WPinternals code to a WPinternals folder 2021-08-14 11:04:37 +02:00
Gustave Monce 668a9b7fe2 Fix an issue with incorrect logging of secure boot state 2021-08-13 13:21:15 +02:00
Gustave Monce 8293c18406 Merge branch 'master' of https://github.com/ReneLergner/WPinternals 2021-08-12 17:43:45 +02:00
Gustave Monce 48fbfa77df Project: remove references to hijacked website/domain to prevent potential malicious activity due to us not controlling the domain anymore. 2021-08-12 17:43:38 +02:00
Gustave MonceandGitHub 709c91cec5 Create bug_report.yml 2021-08-12 08:59:16 +02:00
Gustave MonceandGitHub 611ad122f9 Create README.md 2021-08-12 08:52:54 +02:00
Gustave Monce d8fd0aa516 Fix more hyperlink issues 2021-08-12 08:37:20 +02:00
Gustave Monce 7f3c8b1777 Merge branch 'master' of https://github.com/ReneLergner/WPinternals 2021-08-12 08:32:27 +02:00
Gustave Monce 087457fa0d FIx an issue with hyperlinks 2021-08-12 08:31:36 +02:00
Gustave MonceandGitHub bb9f614e82 CI: Use .NET 5.0.9 SDK 2021-08-11 18:43:57 +02:00
267 changed files with 53320 additions and 48253 deletions
+60
View File
@@ -0,0 +1,60 @@
name: Bug Report
description: Create a bug report to help improve WPinternals
labels: [bug]
body:
- type: textarea
attributes:
label: Description
description: A clear and concise description of what the bug is.
validations:
required: true
- type: textarea
attributes:
label: Steps To Reproduce
description: Steps to reproduce the behavior.
placeholder: |
1. Go to '....'
2. Click on '....'
3. Scroll down to '....'
4. See the error
validations:
required: false
- type: textarea
attributes:
label: Expected behavior
description: A clear and concise description of what you expected to happen.
validations:
required: true
- type: input
id: wpi-version
attributes:
label: WPinternals Version
description: What version of WPinternals are you using?
placeholder: v2.9.2
validations:
required: true
- type: input
attributes:
label: Windows Version
description: What version of Windows are you using? Press <kbd>Win</kbd> + <kbd>Pause/Break</kbd> and copy.
placeholder: e.g. Windows 11 21H2 22000.132
validations:
required: true
- type: input
attributes:
label: Phone model
description: What phone model did you reproduce the bug on (if applicable)
placeholder: e.g. Lumia 950 XL (RM-1085)
validations:
required: false
- type: textarea
attributes:
label: Relevant Assets
description: |
A list of assets (logs, screenshots) relevant to this bug.
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
placeholder: |
To upload the log
- Copy the `WPinternals.log` files from `%ALLUSERSPROFILE%\WPinternals`
- Drag and drop them into this text area.
+2 -2
View File
@@ -11,7 +11,7 @@ jobs:
runs-on: windows-latest runs-on: windows-latest
strategy: strategy:
matrix: matrix:
architecture: [x86, x64] architecture: [x86, x64, arm64]
platform: [win] platform: [win]
steps: steps:
- name: Checkout - name: Checkout
@@ -20,7 +20,7 @@ jobs:
- name: Install .NET SDK - name: Install .NET SDK
uses: actions/setup-dotnet@v1 uses: actions/setup-dotnet@v1
with: with:
dotnet-version: "5.0.101" dotnet-version: "8.0.x"
- name: Add MSBuild to PATH - name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@v1.0.2 uses: microsoft/setup-msbuild@v1.0.2
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
+24
View File
@@ -0,0 +1,24 @@
# Windows Phone Internals
Windows Phone Internals (WPinternals or WPI for short) is a tool designed to unlock the bootloader and/or secure boot of select Lumia devices made by Nokia and Microsoft.
Thanks to specifically crafted exploits/techniques the tool is able to disable Bootloader Security/SecureBoot on select Lumia models.
After unlocking your bootloader you will be able to notably perform the following actions:
- Boot other Operating Systems
- Enable Root Access (on select OS versions)
- Flash Custom ROMs
- Backup your current Windows Phone ROM
- Access your phone internal storage over USB
## Root Access
Root Access is a set of patches/hacks disabling security inside Windows Phone at its root. Kernel Security, Permission checks, application container security, deployment capability security and much gets disabled as part of enabling root access.
## How to get started?
The tool contains all the documentation you need to know more about the tool, we invite you to read the getting started section of the tool to know more.
## Where do I download the tool?
Here: https://github.com/ReneLergner/WPinternals/releases/latest
+8
View File
@@ -0,0 +1,8 @@
<Application
x:Class="RootAccessTestUWP.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:RootAccessTestUWP"
RequestedTheme="Dark">
</Application>
+100
View File
@@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace RootAccessTestUWP
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
sealed partial class App : Application
{
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
}
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.
/// </summary>
/// <param name="e">Details about the launch request and process.</param>
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
if (e.PrelaunchActivated == false)
{
if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
rootFrame.Navigate(typeof(MainPage), e.Arguments);
}
// Ensure the current window is active
Window.Current.Activate();
}
}
/// <summary>
/// Invoked when Navigation to a certain page fails
/// </summary>
/// <param name="sender">The Frame which failed navigation</param>
/// <param name="e">Details about the navigation failure</param>
void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}
/// <summary>
/// Invoked when application execution is being suspended. Application state is saved
/// without knowing whether the application will be terminated or resumed with the contents
/// of memory still intact.
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
deferral.Complete();
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

+89
View File
@@ -0,0 +1,89 @@
using System;
using System.Runtime.InteropServices;
namespace RootAccessTestUWP
{
public static class Core
{
[DllImport("KERNELBASE.DLL", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int RegQueryValueEx(UIntPtr hKey, string lpValueName, int lpReserved, out Core.RegistryValueKind lpType, IntPtr lpData, ref int lpcbData);
[DllImport("KERNELBASE.DLL", CharSet = CharSet.Unicode)]
private static extern int RegOpenKeyEx(UIntPtr hKey, string subKey, int ulOptions, int samDesired, out UIntPtr hkResult);
[DllImport("KERNELBASE.DLL", SetLastError = true)]
private static extern int RegCloseKey(UIntPtr hKey);
internal static string RegReadStringValue(UIntPtr rootKey, string keyPath, string valueName)
{
UIntPtr hKey;
int num = Core.RegOpenKeyEx(rootKey, keyPath, 0, Core.KEY_READ, out hKey);
if (num != 0)
{
throw new COMException("Failed to open registry key", num);
}
int cb = 1024;
IntPtr intPtr = Marshal.AllocHGlobal(cb);
Core.RegistryValueKind registryValueKind;
num = Core.RegQueryValueEx(hKey, valueName, 0, out registryValueKind, intPtr, ref cb);
if (num != 0)
{
throw new COMException("Failed to read registry value", num);
}
if (registryValueKind != Core.RegistryValueKind.String)
{
throw new Exception("Wrong registry value type");
}
string result = Marshal.PtrToStringUni(intPtr);
Core.RegCloseKey(hKey);
return result;
}
internal static uint RegReadDwordValue(UIntPtr rootKey, string keyPath, string valueName)
{
UIntPtr hKey;
int num = Core.RegOpenKeyEx(rootKey, keyPath, 0, Core.KEY_READ, out hKey);
if (num != 0)
{
throw new COMException("Failed to open registry key", num);
}
int cb = 1024;
IntPtr intPtr = Marshal.AllocHGlobal(cb);
Core.RegistryValueKind registryValueKind;
num = Core.RegQueryValueEx(hKey, valueName, 0, out registryValueKind, intPtr, ref cb);
if (num != 0)
{
throw new COMException("Failed to read registry value", num);
}
if (registryValueKind != Core.RegistryValueKind.DWord)
{
throw new Exception("Wrong registry value type");
}
uint result = (uint)Marshal.ReadInt32(intPtr);
Core.RegCloseKey(hKey);
return result;
}
public static UIntPtr HKEY_CLASSES_ROOT = (UIntPtr)2147483648U;
public static UIntPtr HKEY_CURRENT_USER = (UIntPtr)2147483649U;
public static UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)2147483650U;
public static UIntPtr HKEY_USERS = (UIntPtr)2147483651U;
private static int KEY_READ = 131097;
public enum RegistryValueKind
{
Unknown,
String,
ExpandString,
Binary,
DWord,
MultiString = 7,
QWord = 11,
None = -1
}
}
}
+19
View File
@@ -0,0 +1,19 @@
<Page
x:Class="RootAccessTestUWP.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:RootAccessTestUWP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock x:Name="TextBlock"
Margin="10"
HorizontalAlignment="Stretch"
TextWrapping="Wrap"
Text=""
VerticalAlignment="Stretch"
FontFamily="Courier New" />
</Grid>
</Page>
+65
View File
@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
namespace RootAccessTestUWP
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
TextBlock.Text = "Reading: HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\PhoneProvisioner\\ColdBootDone" + Environment.NewLine + Environment.NewLine;
bool flag = false;
try
{
Core.RegReadDwordValue(Core.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\PhoneProvisioner", "ColdBootDone");
flag = true;
}
catch
{
}
if (flag)
{
TextBlock.Text = string.Concat(new string[]
{
TextBlock.Text,
"Success!",
Environment.NewLine,
Environment.NewLine,
"Root Access: Enabled"
});
}
else
{
TextBlock.Text = string.Concat(new string[]
{
TextBlock.Text,
"Failed!",
Environment.NewLine,
Environment.NewLine,
"Root Access: Disabled"
});
}
}
}
}
+49
View File
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
IgnorableNamespaces="uap mp">
<Identity
Name="66bf96f4-f5ba-41f1-8ceb-ac4e9065ac52"
Publisher="CN=Rene"
Version="1.0.0.0" />
<mp:PhoneIdentity PhoneProductId="66bf96f4-f5ba-41f1-8ceb-ac4e9065ac52" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
<Properties>
<DisplayName>RootAccessTestUWP</DisplayName>
<PublisherDisplayName>Rene</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="RootAccessTestUWP.App">
<uap:VisualElements
DisplayName="RootAccessTestUWP"
Square150x150Logo="Assets\Square150x150Logo.png"
Square44x44Logo="Assets\Square44x44Logo.png"
Description="RootAccessTestUWP"
BackgroundColor="transparent">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
</Capabilities>
</Package>
@@ -0,0 +1,29 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("RootAccessTestUWP")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RootAccessTestUWP")]
[assembly: AssemblyCopyright("Copyright © 2021")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ComVisible(false)]
@@ -0,0 +1,31 @@
<!--
This file contains Runtime Directives used by .NET Native. The defaults here are suitable for most
developers. However, you can modify these parameters to modify the behavior of the .NET Native
optimizer.
Runtime Directives are documented at https://go.microsoft.com/fwlink/?LinkID=391919
To fully enable reflection for App1.MyClass and all of its public/private members
<Type Name="App1.MyClass" Dynamic="Required All"/>
To enable dynamic creation of the specific instantiation of AppClass<T> over System.Int32
<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32" Activate="Required Public" />
Using the Namespace directive to apply reflection policy to all the types in a particular namespace
<Namespace Name="DataClasses.ViewModels" Serialize="All" />
-->
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<!--
An Assembly element with Name="*Application*" applies to all assemblies in
the application package. The asterisks are not wildcards.
-->
<Assembly Name="*Application*" Dynamic="Required All" />
<!-- Add your application specific runtime directives here. -->
</Application>
</Directives>
+169
View File
@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{8B6AADBB-C750-492E-AF60-82F6323401CC}</ProjectGuid>
<OutputType>AppContainerExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>RootAccessTestUWP</RootNamespace>
<AssemblyName>RootAccessTestUWP</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.22000.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WindowsXamlEnableOverview>true</WindowsXamlEnableOverview>
<AppxPackageSigningEnabled>false</AppxPackageSigningEnabled>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM64'">
<OutputPath>bin\ARM64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>
<ItemGroup>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="Core.cs" />
<Compile Include="MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
</ItemGroup>
<ItemGroup>
<Content Include="Properties\Default.rd.xml" />
<Content Include="Assets\LockScreenLogo.scale-200.png" />
<Content Include="Assets\SplashScreen.scale-200.png" />
<Content Include="Assets\Square150x150Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
<Content Include="Assets\StoreLogo.png" />
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
<Version>6.2.13</Version>
</PackageReference>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
+1818 -5
View File
File diff suppressed because it is too large Load Diff
@@ -1,64 +1,64 @@
// Common/CRC.cs // Common/CRC.cs
namespace SevenZip namespace SevenZip
{ {
internal class CRC internal class CRC
{ {
public static readonly uint[] Table; public static readonly uint[] Table;
static CRC() static CRC()
{ {
Table = new uint[256]; Table = new uint[256];
const uint kPoly = 0xEDB88320; const uint kPoly = 0xEDB88320;
for (uint i = 0; i < 256; i++) for (uint i = 0; i < 256; i++)
{ {
uint r = i; uint r = i;
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++)
{ {
if ((r & 1) != 0) if ((r & 1) != 0)
{ {
r = (r >> 1) ^ kPoly; r = (r >> 1) ^ kPoly;
} }
else else
{ {
r >>= 1; r >>= 1;
} }
} }
Table[i] = r; Table[i] = r;
} }
} }
private uint _value = 0xFFFFFFFF; private uint _value = 0xFFFFFFFF;
public void Init() { _value = 0xFFFFFFFF; } public void Init() { _value = 0xFFFFFFFF; }
public void UpdateByte(byte b) public void UpdateByte(byte b)
{ {
_value = Table[((byte)_value) ^ b] ^ (_value >> 8); _value = Table[((byte)_value) ^ b] ^ (_value >> 8);
} }
public void Update(byte[] data, uint offset, uint size) public void Update(byte[] data, uint offset, uint size)
{ {
for (uint i = 0; i < size; i++) for (uint i = 0; i < size; i++)
{ {
_value = Table[((byte)_value) ^ data[offset + i]] ^ (_value >> 8); _value = Table[((byte)_value) ^ data[offset + i]] ^ (_value >> 8);
} }
} }
public uint GetDigest() { return _value ^ 0xFFFFFFFF; } public uint GetDigest() { return _value ^ 0xFFFFFFFF; }
private static uint CalculateDigest(byte[] data, uint offset, uint size) private static uint CalculateDigest(byte[] data, uint offset, uint size)
{ {
CRC crc = new(); CRC crc = new();
// crc.Init(); // crc.Init();
crc.Update(data, offset, size); crc.Update(data, offset, size);
return crc.GetDigest(); return crc.GetDigest();
} }
private static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) private static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size)
{ {
return CalculateDigest(data, offset, size) == digest; return CalculateDigest(data, offset, size) == digest;
} }
} }
} }
@@ -1,325 +1,325 @@
// CommandLineParser.cs // CommandLineParser.cs
using System; using System;
using System.Collections; using System.Collections;
namespace SevenZip.CommandLineParser namespace SevenZip.CommandLineParser
{ {
public enum SwitchType public enum SwitchType
{ {
Simple, Simple,
PostMinus, PostMinus,
LimitedPostString, LimitedPostString,
UnLimitedPostString, UnLimitedPostString,
PostChar PostChar
} }
public class SwitchForm public class SwitchForm
{ {
public string IDString; public string IDString;
public SwitchType Type; public SwitchType Type;
public bool Multi; public bool Multi;
public int MinLen; public int MinLen;
public int MaxLen; public int MaxLen;
public string PostCharSet; public string PostCharSet;
public SwitchForm(string idString, SwitchType type, bool multi, public SwitchForm(string idString, SwitchType type, bool multi,
int minLen, int maxLen, string postCharSet) int minLen, int maxLen, string postCharSet)
{ {
IDString = idString; IDString = idString;
Type = type; Type = type;
Multi = multi; Multi = multi;
MinLen = minLen; MinLen = minLen;
MaxLen = maxLen; MaxLen = maxLen;
PostCharSet = postCharSet; PostCharSet = postCharSet;
} }
public SwitchForm(string idString, SwitchType type, bool multi, int minLen) : public SwitchForm(string idString, SwitchType type, bool multi, int minLen) :
this(idString, type, multi, minLen, 0, "") this(idString, type, multi, minLen, 0, "")
{ {
} }
public SwitchForm(string idString, SwitchType type, bool multi) : public SwitchForm(string idString, SwitchType type, bool multi) :
this(idString, type, multi, 0) this(idString, type, multi, 0)
{ {
} }
} }
public class SwitchResult public class SwitchResult
{ {
public bool ThereIs; public bool ThereIs;
public bool WithMinus; public bool WithMinus;
public ArrayList PostStrings = new(); public ArrayList PostStrings = new();
public int PostCharIndex; public int PostCharIndex;
public SwitchResult() public SwitchResult()
{ {
ThereIs = false; ThereIs = false;
} }
} }
public class Parser public class Parser
{ {
public ArrayList NonSwitchStrings = new(); public ArrayList NonSwitchStrings = new();
private readonly SwitchResult[] _switches; private readonly SwitchResult[] _switches;
public Parser(int numSwitches) public Parser(int numSwitches)
{ {
_switches = new SwitchResult[numSwitches]; _switches = new SwitchResult[numSwitches];
for (int i = 0; i < numSwitches; i++) for (int i = 0; i < numSwitches; i++)
{ {
_switches[i] = new SwitchResult(); _switches[i] = new SwitchResult();
} }
} }
private bool ParseString(string srcString, SwitchForm[] switchForms) private bool ParseString(string srcString, SwitchForm[] switchForms)
{ {
int len = srcString.Length; int len = srcString.Length;
if (len == 0) if (len == 0)
{ {
return false; return false;
} }
int pos = 0; int pos = 0;
if (!IsItSwitchChar(srcString[pos])) if (!IsItSwitchChar(srcString[pos]))
{ {
return false; return false;
} }
while (pos < len) while (pos < len)
{ {
if (IsItSwitchChar(srcString[pos])) if (IsItSwitchChar(srcString[pos]))
{ {
pos++; pos++;
} }
const int kNoLen = -1; const int kNoLen = -1;
int matchedSwitchIndex = 0; int matchedSwitchIndex = 0;
int maxLen = kNoLen; int maxLen = kNoLen;
for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++) for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++)
{ {
int switchLen = switchForms[switchIndex].IDString.Length; int switchLen = switchForms[switchIndex].IDString.Length;
if (switchLen <= maxLen || pos + switchLen > len) if (switchLen <= maxLen || pos + switchLen > len)
{ {
continue; continue;
} }
if (String.Compare(switchForms[switchIndex].IDString, 0, if (String.Compare(switchForms[switchIndex].IDString, 0,
srcString, pos, switchLen, true) == 0) srcString, pos, switchLen, true) == 0)
{ {
matchedSwitchIndex = switchIndex; matchedSwitchIndex = switchIndex;
maxLen = switchLen; maxLen = switchLen;
} }
} }
if (maxLen == kNoLen) if (maxLen == kNoLen)
{ {
throw new Exception("maxLen == kNoLen"); throw new Exception("maxLen == kNoLen");
} }
SwitchResult matchedSwitch = _switches[matchedSwitchIndex]; SwitchResult matchedSwitch = _switches[matchedSwitchIndex];
SwitchForm switchForm = switchForms[matchedSwitchIndex]; SwitchForm switchForm = switchForms[matchedSwitchIndex];
if ((!switchForm.Multi) && matchedSwitch.ThereIs) if ((!switchForm.Multi) && matchedSwitch.ThereIs)
{ {
throw new Exception("switch must be single"); throw new Exception("switch must be single");
} }
matchedSwitch.ThereIs = true; matchedSwitch.ThereIs = true;
pos += maxLen; pos += maxLen;
int tailSize = len - pos; int tailSize = len - pos;
SwitchType type = switchForm.Type; SwitchType type = switchForm.Type;
switch (type) switch (type)
{ {
case SwitchType.PostMinus: case SwitchType.PostMinus:
{ {
if (tailSize == 0) if (tailSize == 0)
{ {
matchedSwitch.WithMinus = false; matchedSwitch.WithMinus = false;
} }
else else
{ {
matchedSwitch.WithMinus = srcString[pos] == kSwitchMinus; matchedSwitch.WithMinus = srcString[pos] == kSwitchMinus;
if (matchedSwitch.WithMinus) if (matchedSwitch.WithMinus)
{ {
pos++; pos++;
} }
} }
break; break;
} }
case SwitchType.PostChar: case SwitchType.PostChar:
{ {
if (tailSize < switchForm.MinLen) if (tailSize < switchForm.MinLen)
{ {
throw new Exception("switch is not full"); throw new Exception("switch is not full");
} }
string charSet = switchForm.PostCharSet; string charSet = switchForm.PostCharSet;
const int kEmptyCharValue = -1; const int kEmptyCharValue = -1;
if (tailSize == 0) if (tailSize == 0)
{ {
matchedSwitch.PostCharIndex = kEmptyCharValue; matchedSwitch.PostCharIndex = kEmptyCharValue;
} }
else else
{ {
int index = charSet.IndexOf(srcString[pos]); int index = charSet.IndexOf(srcString[pos]);
if (index < 0) if (index < 0)
{ {
matchedSwitch.PostCharIndex = kEmptyCharValue; matchedSwitch.PostCharIndex = kEmptyCharValue;
} }
else else
{ {
matchedSwitch.PostCharIndex = index; matchedSwitch.PostCharIndex = index;
pos++; pos++;
} }
} }
break; break;
} }
case SwitchType.LimitedPostString: case SwitchType.LimitedPostString:
case SwitchType.UnLimitedPostString: case SwitchType.UnLimitedPostString:
{ {
int minLen = switchForm.MinLen; int minLen = switchForm.MinLen;
if (tailSize < minLen) if (tailSize < minLen)
{ {
throw new Exception("switch is not full"); throw new Exception("switch is not full");
} }
if (type == SwitchType.UnLimitedPostString) if (type == SwitchType.UnLimitedPostString)
{ {
matchedSwitch.PostStrings.Add(srcString[pos..]); matchedSwitch.PostStrings.Add(srcString[pos..]);
return true; return true;
} }
String stringSwitch = srcString.Substring(pos, minLen); String stringSwitch = srcString.Substring(pos, minLen);
pos += minLen; pos += minLen;
for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++) for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++)
{ {
char c = srcString[pos]; char c = srcString[pos];
if (IsItSwitchChar(c)) if (IsItSwitchChar(c))
{ {
break; break;
} }
stringSwitch += c; stringSwitch += c;
} }
matchedSwitch.PostStrings.Add(stringSwitch); matchedSwitch.PostStrings.Add(stringSwitch);
break; break;
} }
} }
} }
return true; return true;
} }
public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings) public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings)
{ {
int numCommandStrings = commandStrings.Length; int numCommandStrings = commandStrings.Length;
bool stopSwitch = false; bool stopSwitch = false;
for (int i = 0; i < numCommandStrings; i++) for (int i = 0; i < numCommandStrings; i++)
{ {
string s = commandStrings[i]; string s = commandStrings[i];
if (stopSwitch) if (stopSwitch)
{ {
NonSwitchStrings.Add(s); NonSwitchStrings.Add(s);
} }
else else
if (s == kStopSwitchParsing) if (s == kStopSwitchParsing)
{ {
stopSwitch = true; stopSwitch = true;
} }
else else
if (!ParseString(s, switchForms)) if (!ParseString(s, switchForms))
{ {
NonSwitchStrings.Add(s); NonSwitchStrings.Add(s);
} }
} }
} }
public SwitchResult this[int index] { get { return _switches[index]; } } public SwitchResult this[int index] { get { return _switches[index]; } }
public static int ParseCommand(CommandForm[] commandForms, string commandString, public static int ParseCommand(CommandForm[] commandForms, string commandString,
out string postString) out string postString)
{ {
for (int i = 0; i < commandForms.Length; i++) for (int i = 0; i < commandForms.Length; i++)
{ {
string id = commandForms[i].IDString; string id = commandForms[i].IDString;
if (commandForms[i].PostStringMode) if (commandForms[i].PostStringMode)
{ {
if (commandString.IndexOf(id) == 0) if (commandString.IndexOf(id) == 0)
{ {
postString = commandString[id.Length..]; postString = commandString[id.Length..];
return i; return i;
} }
} }
else else
if (commandString == id) if (commandString == id)
{ {
postString = ""; postString = "";
return i; return i;
} }
} }
postString = ""; postString = "";
return -1; return -1;
} }
private static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms, private static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms,
string commandString, ArrayList indices) string commandString, ArrayList indices)
{ {
indices.Clear(); indices.Clear();
int numUsedChars = 0; int numUsedChars = 0;
for (int i = 0; i < numForms; i++) for (int i = 0; i < numForms; i++)
{ {
CommandSubCharsSet charsSet = forms[i]; CommandSubCharsSet charsSet = forms[i];
int currentIndex = -1; int currentIndex = -1;
int len = charsSet.Chars.Length; int len = charsSet.Chars.Length;
for (int j = 0; j < len; j++) for (int j = 0; j < len; j++)
{ {
char c = charsSet.Chars[j]; char c = charsSet.Chars[j];
int newIndex = commandString.IndexOf(c); int newIndex = commandString.IndexOf(c);
if (newIndex >= 0) if (newIndex >= 0)
{ {
if (currentIndex >= 0) if (currentIndex >= 0)
{ {
return false; return false;
} }
if (commandString.IndexOf(c, newIndex + 1) >= 0) if (commandString.IndexOf(c, newIndex + 1) >= 0)
{ {
return false; return false;
} }
currentIndex = j; currentIndex = j;
numUsedChars++; numUsedChars++;
} }
} }
if (currentIndex == -1 && !charsSet.EmptyAllowed) if (currentIndex == -1 && !charsSet.EmptyAllowed)
{ {
return false; return false;
} }
indices.Add(currentIndex); indices.Add(currentIndex);
} }
return numUsedChars == commandString.Length; return numUsedChars == commandString.Length;
} }
private const char kSwitchID1 = '-'; private const char kSwitchID1 = '-';
private const char kSwitchID2 = '/'; private const char kSwitchID2 = '/';
private const char kSwitchMinus = '-'; private const char kSwitchMinus = '-';
private const string kStopSwitchParsing = "--"; private const string kStopSwitchParsing = "--";
private static bool IsItSwitchChar(char c) private static bool IsItSwitchChar(char c)
{ {
return c == kSwitchID1 || c == kSwitchID2; return c == kSwitchID1 || c == kSwitchID2;
} }
} }
public class CommandForm public class CommandForm
{ {
public string IDString = ""; public string IDString = "";
public bool PostStringMode = false; public bool PostStringMode = false;
public CommandForm(string idString, bool postStringMode) public CommandForm(string idString, bool postStringMode)
{ {
IDString = idString; IDString = idString;
PostStringMode = postStringMode; PostStringMode = postStringMode;
} }
} }
internal class CommandSubCharsSet internal class CommandSubCharsSet
{ {
public string Chars = ""; public string Chars = "";
public bool EmptyAllowed = false; public bool EmptyAllowed = false;
} }
} }
@@ -1,78 +1,78 @@
// InBuffer.cs // InBuffer.cs
namespace SevenZip.Buffer namespace SevenZip.Buffer
{ {
public class InBuffer public class InBuffer
{ {
private readonly byte[] m_Buffer; private readonly byte[] m_Buffer;
private uint m_Pos; private uint m_Pos;
private uint m_Limit; private uint m_Limit;
private readonly uint m_BufferSize; private readonly uint m_BufferSize;
private System.IO.Stream m_Stream; private System.IO.Stream m_Stream;
private bool m_StreamWasExhausted; private bool m_StreamWasExhausted;
private ulong m_ProcessedSize; private ulong m_ProcessedSize;
public InBuffer(uint bufferSize) public InBuffer(uint bufferSize)
{ {
m_Buffer = new byte[bufferSize]; m_Buffer = new byte[bufferSize];
m_BufferSize = bufferSize; m_BufferSize = bufferSize;
} }
public void Init(System.IO.Stream stream) public void Init(System.IO.Stream stream)
{ {
m_Stream = stream; m_Stream = stream;
m_ProcessedSize = 0; m_ProcessedSize = 0;
m_Limit = 0; m_Limit = 0;
m_Pos = 0; m_Pos = 0;
m_StreamWasExhausted = false; m_StreamWasExhausted = false;
} }
public bool ReadBlock() public bool ReadBlock()
{ {
if (m_StreamWasExhausted) if (m_StreamWasExhausted)
{ {
return false; return false;
} }
m_ProcessedSize += m_Pos; m_ProcessedSize += m_Pos;
int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize); int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize);
m_Pos = 0; m_Pos = 0;
m_Limit = (uint)aNumProcessedBytes; m_Limit = (uint)aNumProcessedBytes;
m_StreamWasExhausted = aNumProcessedBytes == 0; m_StreamWasExhausted = aNumProcessedBytes == 0;
return !m_StreamWasExhausted; return !m_StreamWasExhausted;
} }
public void ReleaseStream() public void ReleaseStream()
{ {
// m_Stream.Close(); // m_Stream.Close();
m_Stream = null; m_Stream = null;
} }
public bool ReadByte(byte b) // check it public bool ReadByte(byte b) // check it
{ {
if (m_Pos >= m_Limit && !ReadBlock()) if (m_Pos >= m_Limit && !ReadBlock())
{ {
return false; return false;
} }
b = m_Buffer[m_Pos++]; b = m_Buffer[m_Pos++];
return true; return true;
} }
public byte ReadByte() public byte ReadByte()
{ {
// return (byte)m_Stream.ReadByte(); // return (byte)m_Stream.ReadByte();
if (m_Pos >= m_Limit && !ReadBlock()) if (m_Pos >= m_Limit && !ReadBlock())
{ {
return 0xFF; return 0xFF;
} }
return m_Buffer[m_Pos++]; return m_Buffer[m_Pos++];
} }
public ulong GetProcessedSize() public ulong GetProcessedSize()
{ {
return m_ProcessedSize + m_Pos; return m_ProcessedSize + m_Pos;
} }
} }
} }
@@ -1,52 +1,52 @@
// OutBuffer.cs // OutBuffer.cs
namespace SevenZip.Buffer namespace SevenZip.Buffer
{ {
public class OutBuffer public class OutBuffer
{ {
private readonly byte[] m_Buffer; private readonly byte[] m_Buffer;
private uint m_Pos; private uint m_Pos;
private readonly uint m_BufferSize; private readonly uint m_BufferSize;
private System.IO.Stream m_Stream; private System.IO.Stream m_Stream;
private ulong m_ProcessedSize; private ulong m_ProcessedSize;
public OutBuffer(uint bufferSize) public OutBuffer(uint bufferSize)
{ {
m_Buffer = new byte[bufferSize]; m_Buffer = new byte[bufferSize];
m_BufferSize = bufferSize; m_BufferSize = bufferSize;
} }
public void SetStream(System.IO.Stream stream) { m_Stream = stream; } public void SetStream(System.IO.Stream stream) { m_Stream = stream; }
public void FlushStream() { m_Stream.Flush(); } public void FlushStream() { m_Stream.Flush(); }
public void CloseStream() { m_Stream.Close(); } public void CloseStream() { m_Stream.Close(); }
public void ReleaseStream() { m_Stream = null; } public void ReleaseStream() { m_Stream = null; }
public void Init() public void Init()
{ {
m_ProcessedSize = 0; m_ProcessedSize = 0;
m_Pos = 0; m_Pos = 0;
} }
public void WriteByte(byte b) public void WriteByte(byte b)
{ {
m_Buffer[m_Pos++] = b; m_Buffer[m_Pos++] = b;
if (m_Pos >= m_BufferSize) if (m_Pos >= m_BufferSize)
{ {
FlushData(); FlushData();
} }
} }
public void FlushData() public void FlushData()
{ {
if (m_Pos == 0) if (m_Pos == 0)
{ {
return; return;
} }
m_Stream.Write(m_Buffer, 0, (int)m_Pos); m_Stream.Write(m_Buffer, 0, (int)m_Pos);
m_Pos = 0; m_Pos = 0;
} }
public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; }
} }
} }
@@ -1,24 +1,24 @@
// IMatchFinder.cs // IMatchFinder.cs
using System; using System;
namespace SevenZip.Compression.LZ namespace SevenZip.Compression.LZ
{ {
internal interface IInWindowStream internal interface IInWindowStream
{ {
void SetStream(System.IO.Stream inStream); void SetStream(System.IO.Stream inStream);
void Init(); void Init();
void ReleaseStream(); void ReleaseStream();
Byte GetIndexByte(Int32 index); Byte GetIndexByte(Int32 index);
UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit);
UInt32 GetNumAvailableBytes(); UInt32 GetNumAvailableBytes();
} }
internal interface IMatchFinder : IInWindowStream internal interface IMatchFinder : IInWindowStream
{ {
void Create(UInt32 historySize, UInt32 keepAddBufferBefore, void Create(UInt32 historySize, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter); UInt32 matchMaxLen, UInt32 keepAddBufferAfter);
UInt32 GetMatches(UInt32[] distances); UInt32 GetMatches(UInt32[] distances);
void Skip(UInt32 num); void Skip(UInt32 num);
} }
} }
@@ -1,408 +1,408 @@
// LzBinTree.cs // LzBinTree.cs
using System; using System;
namespace SevenZip.Compression.LZ namespace SevenZip.Compression.LZ
{ {
public class BinTree : InWindow, IMatchFinder public class BinTree : InWindow, IMatchFinder
{ {
private UInt32 _cyclicBufferPos; private UInt32 _cyclicBufferPos;
private UInt32 _cyclicBufferSize = 0; private UInt32 _cyclicBufferSize = 0;
private UInt32 _matchMaxLen; private UInt32 _matchMaxLen;
private UInt32[] _son; private UInt32[] _son;
private UInt32[] _hash; private UInt32[] _hash;
private UInt32 _cutValue = 0xFF; private UInt32 _cutValue = 0xFF;
private UInt32 _hashMask; private UInt32 _hashMask;
private UInt32 _hashSizeSum = 0; private UInt32 _hashSizeSum = 0;
private bool HASH_ARRAY = true; private bool HASH_ARRAY = true;
private const UInt32 kHash2Size = 1 << 10; private const UInt32 kHash2Size = 1 << 10;
private const UInt32 kHash3Size = 1 << 16; private const UInt32 kHash3Size = 1 << 16;
private const UInt32 kBT2HashSize = 1 << 16; private const UInt32 kBT2HashSize = 1 << 16;
private const UInt32 kStartMaxLen = 1; private const UInt32 kStartMaxLen = 1;
private const UInt32 kHash3Offset = kHash2Size; private const UInt32 kHash3Offset = kHash2Size;
private const UInt32 kEmptyHashValue = 0; private const UInt32 kEmptyHashValue = 0;
private const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1; private const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1;
private UInt32 kNumHashDirectBytes = 0; private UInt32 kNumHashDirectBytes = 0;
private UInt32 kMinMatchCheck = 4; private UInt32 kMinMatchCheck = 4;
private UInt32 kFixHashSize = kHash2Size + kHash3Size; private UInt32 kFixHashSize = kHash2Size + kHash3Size;
public void SetType(int numHashBytes) public void SetType(int numHashBytes)
{ {
HASH_ARRAY = numHashBytes > 2; HASH_ARRAY = numHashBytes > 2;
if (HASH_ARRAY) if (HASH_ARRAY)
{ {
kNumHashDirectBytes = 0; kNumHashDirectBytes = 0;
kMinMatchCheck = 4; kMinMatchCheck = 4;
kFixHashSize = kHash2Size + kHash3Size; kFixHashSize = kHash2Size + kHash3Size;
} }
else else
{ {
kNumHashDirectBytes = 2; kNumHashDirectBytes = 2;
kMinMatchCheck = 2 + 1; kMinMatchCheck = 2 + 1;
kFixHashSize = 0; kFixHashSize = 0;
} }
} }
public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); } public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); }
public new void ReleaseStream() { base.ReleaseStream(); } public new void ReleaseStream() { base.ReleaseStream(); }
public new void Init() public new void Init()
{ {
base.Init(); base.Init();
for (UInt32 i = 0; i < _hashSizeSum; i++) for (UInt32 i = 0; i < _hashSizeSum; i++)
{ {
_hash[i] = kEmptyHashValue; _hash[i] = kEmptyHashValue;
} }
_cyclicBufferPos = 0; _cyclicBufferPos = 0;
ReduceOffsets(-1); ReduceOffsets(-1);
} }
public new void MovePos() public new void MovePos()
{ {
if (++_cyclicBufferPos >= _cyclicBufferSize) if (++_cyclicBufferPos >= _cyclicBufferSize)
{ {
_cyclicBufferPos = 0; _cyclicBufferPos = 0;
} }
base.MovePos(); base.MovePos();
if (_pos == kMaxValForNormalize) if (_pos == kMaxValForNormalize)
{ {
Normalize(); Normalize();
} }
} }
public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); } public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); }
public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
{ return base.GetMatchLen(index, distance, limit); } { return base.GetMatchLen(index, distance, limit); }
public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); } public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); }
public void Create(UInt32 historySize, UInt32 keepAddBufferBefore, public void Create(UInt32 historySize, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter) UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
{ {
if (historySize > kMaxValForNormalize - 256) if (historySize > kMaxValForNormalize - 256)
{ {
throw new Exception(); throw new Exception();
} }
_cutValue = 16 + (matchMaxLen >> 1); _cutValue = 16 + (matchMaxLen >> 1);
UInt32 windowReservSize = ((historySize + keepAddBufferBefore + UInt32 windowReservSize = ((historySize + keepAddBufferBefore +
matchMaxLen + keepAddBufferAfter) / 2) + 256; matchMaxLen + keepAddBufferAfter) / 2) + 256;
Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize);
_matchMaxLen = matchMaxLen; _matchMaxLen = matchMaxLen;
UInt32 cyclicBufferSize = historySize + 1; UInt32 cyclicBufferSize = historySize + 1;
if (_cyclicBufferSize != cyclicBufferSize) if (_cyclicBufferSize != cyclicBufferSize)
{ {
_son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2]; _son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2];
} }
UInt32 hs = kBT2HashSize; UInt32 hs = kBT2HashSize;
if (HASH_ARRAY) if (HASH_ARRAY)
{ {
hs = historySize - 1; hs = historySize - 1;
hs |= hs >> 1; hs |= hs >> 1;
hs |= hs >> 2; hs |= hs >> 2;
hs |= hs >> 4; hs |= hs >> 4;
hs |= hs >> 8; hs |= hs >> 8;
hs >>= 1; hs >>= 1;
hs |= 0xFFFF; hs |= 0xFFFF;
if (hs > (1 << 24)) if (hs > (1 << 24))
{ {
hs >>= 1; hs >>= 1;
} }
_hashMask = hs; _hashMask = hs;
hs++; hs++;
hs += kFixHashSize; hs += kFixHashSize;
} }
if (hs != _hashSizeSum) if (hs != _hashSizeSum)
{ {
_hash = new UInt32[_hashSizeSum = hs]; _hash = new UInt32[_hashSizeSum = hs];
} }
} }
public UInt32 GetMatches(UInt32[] distances) public UInt32 GetMatches(UInt32[] distances)
{ {
UInt32 lenLimit; UInt32 lenLimit;
if (_pos + _matchMaxLen <= _streamPos) if (_pos + _matchMaxLen <= _streamPos)
{ {
lenLimit = _matchMaxLen; lenLimit = _matchMaxLen;
} }
else else
{ {
lenLimit = _streamPos - _pos; lenLimit = _streamPos - _pos;
if (lenLimit < kMinMatchCheck) if (lenLimit < kMinMatchCheck)
{ {
MovePos(); MovePos();
return 0; return 0;
} }
} }
UInt32 offset = 0; UInt32 offset = 0;
UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
UInt32 cur = _bufferOffset + _pos; UInt32 cur = _bufferOffset + _pos;
UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize; UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize;
UInt32 hashValue, hash2Value = 0, hash3Value = 0; UInt32 hashValue, hash2Value = 0, hash3Value = 0;
if (HASH_ARRAY) if (HASH_ARRAY)
{ {
UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];
hash2Value = temp & (kHash2Size - 1); hash2Value = temp & (kHash2Size - 1);
temp ^= (UInt32)_bufferBase[cur + 2] << 8; temp ^= (UInt32)_bufferBase[cur + 2] << 8;
hash3Value = temp & (kHash3Size - 1); hash3Value = temp & (kHash3Size - 1);
hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;
} }
else else
{ {
hashValue = _bufferBase[cur] ^ ((UInt32)_bufferBase[cur + 1] << 8); hashValue = _bufferBase[cur] ^ ((UInt32)_bufferBase[cur + 1] << 8);
} }
UInt32 curMatch = _hash[kFixHashSize + hashValue]; UInt32 curMatch = _hash[kFixHashSize + hashValue];
if (HASH_ARRAY) if (HASH_ARRAY)
{ {
UInt32 curMatch2 = _hash[hash2Value]; UInt32 curMatch2 = _hash[hash2Value];
UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];
_hash[hash2Value] = _pos; _hash[hash2Value] = _pos;
_hash[kHash3Offset + hash3Value] = _pos; _hash[kHash3Offset + hash3Value] = _pos;
if (curMatch2 > matchMinPos && _bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) if (curMatch2 > matchMinPos && _bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur])
{ {
distances[offset++] = maxLen = 2; distances[offset++] = maxLen = 2;
distances[offset++] = _pos - curMatch2 - 1; distances[offset++] = _pos - curMatch2 - 1;
} }
if (curMatch3 > matchMinPos && _bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) if (curMatch3 > matchMinPos && _bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur])
{ {
if (curMatch3 == curMatch2) if (curMatch3 == curMatch2)
{ {
offset -= 2; offset -= 2;
} }
distances[offset++] = maxLen = 3; distances[offset++] = maxLen = 3;
distances[offset++] = _pos - curMatch3 - 1; distances[offset++] = _pos - curMatch3 - 1;
curMatch2 = curMatch3; curMatch2 = curMatch3;
} }
if (offset != 0 && curMatch2 == curMatch) if (offset != 0 && curMatch2 == curMatch)
{ {
offset -= 2; offset -= 2;
maxLen = kStartMaxLen; maxLen = kStartMaxLen;
} }
} }
_hash[kFixHashSize + hashValue] = _pos; _hash[kFixHashSize + hashValue] = _pos;
UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
UInt32 ptr1 = _cyclicBufferPos << 1; UInt32 ptr1 = _cyclicBufferPos << 1;
UInt32 len0, len1; UInt32 len0, len1;
len0 = len1 = kNumHashDirectBytes; len0 = len1 = kNumHashDirectBytes;
if (kNumHashDirectBytes != 0 && curMatch > matchMinPos) if (kNumHashDirectBytes != 0 && curMatch > matchMinPos)
{ {
if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] !=
_bufferBase[cur + kNumHashDirectBytes]) _bufferBase[cur + kNumHashDirectBytes])
{ {
distances[offset++] = maxLen = kNumHashDirectBytes; distances[offset++] = maxLen = kNumHashDirectBytes;
distances[offset++] = _pos - curMatch - 1; distances[offset++] = _pos - curMatch - 1;
} }
} }
UInt32 count = _cutValue; UInt32 count = _cutValue;
while (true) while (true)
{ {
if (curMatch <= matchMinPos || count-- == 0) if (curMatch <= matchMinPos || count-- == 0)
{ {
_son[ptr0] = _son[ptr1] = kEmptyHashValue; _son[ptr0] = _son[ptr1] = kEmptyHashValue;
break; break;
} }
UInt32 delta = _pos - curMatch; UInt32 delta = _pos - curMatch;
UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
(_cyclicBufferPos - delta) : (_cyclicBufferPos - delta) :
(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
UInt32 pby1 = _bufferOffset + curMatch; UInt32 pby1 = _bufferOffset + curMatch;
UInt32 len = Math.Min(len0, len1); UInt32 len = Math.Min(len0, len1);
if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
{ {
while (++len != lenLimit) while (++len != lenLimit)
{ {
if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
{ {
break; break;
} }
} }
if (maxLen < len) if (maxLen < len)
{ {
distances[offset++] = maxLen = len; distances[offset++] = maxLen = len;
distances[offset++] = delta - 1; distances[offset++] = delta - 1;
if (len == lenLimit) if (len == lenLimit)
{ {
_son[ptr1] = _son[cyclicPos]; _son[ptr1] = _son[cyclicPos];
_son[ptr0] = _son[cyclicPos + 1]; _son[ptr0] = _son[cyclicPos + 1];
break; break;
} }
} }
} }
if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
{ {
_son[ptr1] = curMatch; _son[ptr1] = curMatch;
ptr1 = cyclicPos + 1; ptr1 = cyclicPos + 1;
curMatch = _son[ptr1]; curMatch = _son[ptr1];
len1 = len; len1 = len;
} }
else else
{ {
_son[ptr0] = curMatch; _son[ptr0] = curMatch;
ptr0 = cyclicPos; ptr0 = cyclicPos;
curMatch = _son[ptr0]; curMatch = _son[ptr0];
len0 = len; len0 = len;
} }
} }
MovePos(); MovePos();
return offset; return offset;
} }
public void Skip(UInt32 num) public void Skip(UInt32 num)
{ {
do do
{ {
UInt32 lenLimit; UInt32 lenLimit;
if (_pos + _matchMaxLen <= _streamPos) if (_pos + _matchMaxLen <= _streamPos)
{ {
lenLimit = _matchMaxLen; lenLimit = _matchMaxLen;
} }
else else
{ {
lenLimit = _streamPos - _pos; lenLimit = _streamPos - _pos;
if (lenLimit < kMinMatchCheck) if (lenLimit < kMinMatchCheck)
{ {
MovePos(); MovePos();
continue; continue;
} }
} }
UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
UInt32 cur = _bufferOffset + _pos; UInt32 cur = _bufferOffset + _pos;
UInt32 hashValue; UInt32 hashValue;
if (HASH_ARRAY) if (HASH_ARRAY)
{ {
UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];
UInt32 hash2Value = temp & (kHash2Size - 1); UInt32 hash2Value = temp & (kHash2Size - 1);
_hash[hash2Value] = _pos; _hash[hash2Value] = _pos;
temp ^= (UInt32)_bufferBase[cur + 2] << 8; temp ^= (UInt32)_bufferBase[cur + 2] << 8;
UInt32 hash3Value = temp & (kHash3Size - 1); UInt32 hash3Value = temp & (kHash3Size - 1);
_hash[kHash3Offset + hash3Value] = _pos; _hash[kHash3Offset + hash3Value] = _pos;
hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;
} }
else else
{ {
hashValue = _bufferBase[cur] ^ ((UInt32)_bufferBase[cur + 1] << 8); hashValue = _bufferBase[cur] ^ ((UInt32)_bufferBase[cur + 1] << 8);
} }
UInt32 curMatch = _hash[kFixHashSize + hashValue]; UInt32 curMatch = _hash[kFixHashSize + hashValue];
_hash[kFixHashSize + hashValue] = _pos; _hash[kFixHashSize + hashValue] = _pos;
UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
UInt32 ptr1 = _cyclicBufferPos << 1; UInt32 ptr1 = _cyclicBufferPos << 1;
UInt32 len0, len1; UInt32 len0, len1;
len0 = len1 = kNumHashDirectBytes; len0 = len1 = kNumHashDirectBytes;
UInt32 count = _cutValue; UInt32 count = _cutValue;
while (true) while (true)
{ {
if (curMatch <= matchMinPos || count-- == 0) if (curMatch <= matchMinPos || count-- == 0)
{ {
_son[ptr0] = _son[ptr1] = kEmptyHashValue; _son[ptr0] = _son[ptr1] = kEmptyHashValue;
break; break;
} }
UInt32 delta = _pos - curMatch; UInt32 delta = _pos - curMatch;
UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
(_cyclicBufferPos - delta) : (_cyclicBufferPos - delta) :
(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
UInt32 pby1 = _bufferOffset + curMatch; UInt32 pby1 = _bufferOffset + curMatch;
UInt32 len = Math.Min(len0, len1); UInt32 len = Math.Min(len0, len1);
if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
{ {
while (++len != lenLimit) while (++len != lenLimit)
{ {
if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
{ {
break; break;
} }
} }
if (len == lenLimit) if (len == lenLimit)
{ {
_son[ptr1] = _son[cyclicPos]; _son[ptr1] = _son[cyclicPos];
_son[ptr0] = _son[cyclicPos + 1]; _son[ptr0] = _son[cyclicPos + 1];
break; break;
} }
} }
if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
{ {
_son[ptr1] = curMatch; _son[ptr1] = curMatch;
ptr1 = cyclicPos + 1; ptr1 = cyclicPos + 1;
curMatch = _son[ptr1]; curMatch = _son[ptr1];
len1 = len; len1 = len;
} }
else else
{ {
_son[ptr0] = curMatch; _son[ptr0] = curMatch;
ptr0 = cyclicPos; ptr0 = cyclicPos;
curMatch = _son[ptr0]; curMatch = _son[ptr0];
len0 = len; len0 = len;
} }
} }
MovePos(); MovePos();
} }
while (--num != 0); while (--num != 0);
} }
private void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue) private void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue)
{ {
for (UInt32 i = 0; i < numItems; i++) for (UInt32 i = 0; i < numItems; i++)
{ {
UInt32 value = items[i]; UInt32 value = items[i];
if (value <= subValue) if (value <= subValue)
{ {
value = kEmptyHashValue; value = kEmptyHashValue;
} }
else else
{ {
value -= subValue; value -= subValue;
} }
items[i] = value; items[i] = value;
} }
} }
private void Normalize() private void Normalize()
{ {
UInt32 subValue = _pos - _cyclicBufferSize; UInt32 subValue = _pos - _cyclicBufferSize;
NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_son, _cyclicBufferSize * 2, subValue);
NormalizeLinks(_hash, _hashSizeSum, subValue); NormalizeLinks(_hash, _hashSizeSum, subValue);
ReduceOffsets((Int32)subValue); ReduceOffsets((Int32)subValue);
} }
public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; }
} }
} }
@@ -1,155 +1,155 @@
// LzInWindow.cs // LzInWindow.cs
using System; using System;
namespace SevenZip.Compression.LZ namespace SevenZip.Compression.LZ
{ {
public class InWindow public class InWindow
{ {
public Byte[] _bufferBase = null; // pointer to buffer with data public Byte[] _bufferBase = null; // pointer to buffer with data
private System.IO.Stream _stream; private System.IO.Stream _stream;
private UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done private UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done
private bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream private bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream
private UInt32 _pointerToLastSafePosition; private UInt32 _pointerToLastSafePosition;
public UInt32 _bufferOffset; public UInt32 _bufferOffset;
public UInt32 _blockSize; // Size of Allocated memory block public UInt32 _blockSize; // Size of Allocated memory block
public UInt32 _pos; // offset (from _buffer) of curent byte public UInt32 _pos; // offset (from _buffer) of curent byte
private UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos private UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos
private UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos private UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos
public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream
public void MoveBlock() public void MoveBlock()
{ {
UInt32 offset = _bufferOffset + _pos - _keepSizeBefore; UInt32 offset = _bufferOffset + _pos - _keepSizeBefore;
// we need one additional byte, since MovePos moves on 1 byte. // we need one additional byte, since MovePos moves on 1 byte.
if (offset > 0) if (offset > 0)
{ {
offset--; offset--;
} }
UInt32 numBytes = _bufferOffset + _streamPos - offset; UInt32 numBytes = _bufferOffset + _streamPos - offset;
// check negative offset ???? // check negative offset ????
for (UInt32 i = 0; i < numBytes; i++) for (UInt32 i = 0; i < numBytes; i++)
{ {
_bufferBase[i] = _bufferBase[offset + i]; _bufferBase[i] = _bufferBase[offset + i];
} }
_bufferOffset -= offset; _bufferOffset -= offset;
} }
public virtual void ReadBlock() public virtual void ReadBlock()
{ {
if (_streamEndWasReached) if (_streamEndWasReached)
{ {
return; return;
} }
while (true) while (true)
{ {
int size = (int)(0 - _bufferOffset + _blockSize - _streamPos); int size = (int)(0 - _bufferOffset + _blockSize - _streamPos);
if (size == 0) if (size == 0)
{ {
return; return;
} }
int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size); int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size);
if (numReadBytes == 0) if (numReadBytes == 0)
{ {
_posLimit = _streamPos; _posLimit = _streamPos;
UInt32 pointerToPostion = _bufferOffset + _posLimit; UInt32 pointerToPostion = _bufferOffset + _posLimit;
if (pointerToPostion > _pointerToLastSafePosition) if (pointerToPostion > _pointerToLastSafePosition)
{ {
_posLimit = _pointerToLastSafePosition - _bufferOffset; _posLimit = _pointerToLastSafePosition - _bufferOffset;
} }
_streamEndWasReached = true; _streamEndWasReached = true;
return; return;
} }
_streamPos += (UInt32)numReadBytes; _streamPos += (UInt32)numReadBytes;
if (_streamPos >= _pos + _keepSizeAfter) if (_streamPos >= _pos + _keepSizeAfter)
{ {
_posLimit = _streamPos - _keepSizeAfter; _posLimit = _streamPos - _keepSizeAfter;
} }
} }
} }
private void Free() { _bufferBase = null; } private void Free() { _bufferBase = null; }
public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv)
{ {
_keepSizeBefore = keepSizeBefore; _keepSizeBefore = keepSizeBefore;
_keepSizeAfter = keepSizeAfter; _keepSizeAfter = keepSizeAfter;
UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;
if (_bufferBase == null || _blockSize != blockSize) if (_bufferBase == null || _blockSize != blockSize)
{ {
Free(); Free();
_blockSize = blockSize; _blockSize = blockSize;
_bufferBase = new Byte[_blockSize]; _bufferBase = new Byte[_blockSize];
} }
_pointerToLastSafePosition = _blockSize - keepSizeAfter; _pointerToLastSafePosition = _blockSize - keepSizeAfter;
} }
public void SetStream(System.IO.Stream stream) { _stream = stream; } public void SetStream(System.IO.Stream stream) { _stream = stream; }
public void ReleaseStream() { _stream = null; } public void ReleaseStream() { _stream = null; }
public void Init() public void Init()
{ {
_bufferOffset = 0; _bufferOffset = 0;
_pos = 0; _pos = 0;
_streamPos = 0; _streamPos = 0;
_streamEndWasReached = false; _streamEndWasReached = false;
ReadBlock(); ReadBlock();
} }
public void MovePos() public void MovePos()
{ {
_pos++; _pos++;
if (_pos > _posLimit) if (_pos > _posLimit)
{ {
UInt32 pointerToPostion = _bufferOffset + _pos; UInt32 pointerToPostion = _bufferOffset + _pos;
if (pointerToPostion > _pointerToLastSafePosition) if (pointerToPostion > _pointerToLastSafePosition)
{ {
MoveBlock(); MoveBlock();
} }
ReadBlock(); ReadBlock();
} }
} }
public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; } public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; }
// index + limit have not to exceed _keepSizeAfter; // index + limit have not to exceed _keepSizeAfter;
public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
{ {
if (_streamEndWasReached && _pos + index + limit > _streamPos) if (_streamEndWasReached && _pos + index + limit > _streamPos)
{ {
limit = _streamPos - (UInt32)(_pos + index); limit = _streamPos - (UInt32)(_pos + index);
} }
distance++; distance++;
// Byte *pby = _buffer + (size_t)_pos + index; // Byte *pby = _buffer + (size_t)_pos + index;
UInt32 pby = _bufferOffset + _pos + (UInt32)index; UInt32 pby = _bufferOffset + _pos + (UInt32)index;
UInt32 i; UInt32 i;
for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++) for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++)
{ {
} }
return i; return i;
} }
public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; } public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; }
public void ReduceOffsets(Int32 subValue) public void ReduceOffsets(Int32 subValue)
{ {
_bufferOffset += (UInt32)subValue; _bufferOffset += (UInt32)subValue;
_posLimit -= (UInt32)subValue; _posLimit -= (UInt32)subValue;
_pos -= (UInt32)subValue; _pos -= (UInt32)subValue;
_streamPos -= (UInt32)subValue; _streamPos -= (UInt32)subValue;
} }
} }
} }
@@ -1,137 +1,137 @@
// LzOutWindow.cs // LzOutWindow.cs
namespace SevenZip.Compression.LZ namespace SevenZip.Compression.LZ
{ {
public class OutWindow public class OutWindow
{ {
private byte[] _buffer = null; private byte[] _buffer = null;
private uint _pos; private uint _pos;
private uint _windowSize = 0; private uint _windowSize = 0;
private uint _streamPos; private uint _streamPos;
private System.IO.Stream _stream; private System.IO.Stream _stream;
public uint TrainSize = 0; public uint TrainSize = 0;
public void Create(uint windowSize) public void Create(uint windowSize)
{ {
if (_windowSize != windowSize) if (_windowSize != windowSize)
{ {
// System.GC.Collect(); // System.GC.Collect();
_buffer = new byte[windowSize]; _buffer = new byte[windowSize];
} }
_windowSize = windowSize; _windowSize = windowSize;
_pos = 0; _pos = 0;
_streamPos = 0; _streamPos = 0;
} }
public void Init(System.IO.Stream stream, bool solid) public void Init(System.IO.Stream stream, bool solid)
{ {
ReleaseStream(); ReleaseStream();
_stream = stream; _stream = stream;
if (!solid) if (!solid)
{ {
_streamPos = 0; _streamPos = 0;
_pos = 0; _pos = 0;
TrainSize = 0; TrainSize = 0;
} }
} }
public bool Train(System.IO.Stream stream) public bool Train(System.IO.Stream stream)
{ {
long len = stream.Length; long len = stream.Length;
uint size = (len < _windowSize) ? (uint)len : _windowSize; uint size = (len < _windowSize) ? (uint)len : _windowSize;
TrainSize = size; TrainSize = size;
stream.Position = len - size; stream.Position = len - size;
_streamPos = _pos = 0; _streamPos = _pos = 0;
while (size > 0) while (size > 0)
{ {
uint curSize = _windowSize - _pos; uint curSize = _windowSize - _pos;
if (size < curSize) if (size < curSize)
{ {
curSize = size; curSize = size;
} }
int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize); int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize);
if (numReadBytes == 0) if (numReadBytes == 0)
{ {
return false; return false;
} }
size -= (uint)numReadBytes; size -= (uint)numReadBytes;
_pos += (uint)numReadBytes; _pos += (uint)numReadBytes;
_streamPos += (uint)numReadBytes; _streamPos += (uint)numReadBytes;
if (_pos == _windowSize) if (_pos == _windowSize)
{ {
_streamPos = _pos = 0; _streamPos = _pos = 0;
} }
} }
return true; return true;
} }
public void ReleaseStream() public void ReleaseStream()
{ {
Flush(); Flush();
_stream = null; _stream = null;
} }
public void Flush() public void Flush()
{ {
uint size = _pos - _streamPos; uint size = _pos - _streamPos;
if (size == 0) if (size == 0)
{ {
return; return;
} }
_stream.Write(_buffer, (int)_streamPos, (int)size); _stream.Write(_buffer, (int)_streamPos, (int)size);
if (_pos >= _windowSize) if (_pos >= _windowSize)
{ {
_pos = 0; _pos = 0;
} }
_streamPos = _pos; _streamPos = _pos;
} }
public void CopyBlock(uint distance, uint len) public void CopyBlock(uint distance, uint len)
{ {
uint pos = _pos - distance - 1; uint pos = _pos - distance - 1;
if (pos >= _windowSize) if (pos >= _windowSize)
{ {
pos += _windowSize; pos += _windowSize;
} }
for (; len > 0; len--) for (; len > 0; len--)
{ {
if (pos >= _windowSize) if (pos >= _windowSize)
{ {
pos = 0; pos = 0;
} }
_buffer[_pos++] = _buffer[pos++]; _buffer[_pos++] = _buffer[pos++];
if (_pos >= _windowSize) if (_pos >= _windowSize)
{ {
Flush(); Flush();
} }
} }
} }
public void PutByte(byte b) public void PutByte(byte b)
{ {
_buffer[_pos++] = b; _buffer[_pos++] = b;
if (_pos >= _windowSize) if (_pos >= _windowSize)
{ {
Flush(); Flush();
} }
} }
public byte GetByte(uint distance) public byte GetByte(uint distance)
{ {
uint pos = _pos - distance - 1; uint pos = _pos - distance - 1;
if (pos >= _windowSize) if (pos >= _windowSize)
{ {
pos += _windowSize; pos += _windowSize;
} }
return _buffer[pos]; return _buffer[pos];
} }
} }
} }
@@ -1,88 +1,88 @@
// LzmaBase.cs // LzmaBase.cs
namespace SevenZip.Compression.LZMA namespace SevenZip.Compression.LZMA
{ {
internal abstract class Base internal abstract class Base
{ {
public const uint kNumRepDistances = 4; public const uint kNumRepDistances = 4;
public const uint kNumStates = 12; public const uint kNumStates = 12;
// static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; // static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
// static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; // static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
// static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; // static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
// static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; // static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
public struct State public struct State
{ {
public uint Index; public uint Index;
public void Init() { Index = 0; } public void Init() { Index = 0; }
public void UpdateChar() public void UpdateChar()
{ {
if (Index < 4) if (Index < 4)
{ {
Index = 0; Index = 0;
} }
else if (Index < 10) else if (Index < 10)
{ {
Index -= 3; Index -= 3;
} }
else else
{ {
Index -= 6; Index -= 6;
} }
} }
public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); } public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); }
public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); } public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); }
public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); } public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); }
public bool IsCharState() { return Index < 7; } public bool IsCharState() { return Index < 7; }
} }
public const int kNumPosSlotBits = 6; public const int kNumPosSlotBits = 6;
public const int kDicLogSizeMin = 0; public const int kDicLogSizeMin = 0;
// public const int kDicLogSizeMax = 30; // public const int kDicLogSizeMax = 30;
// public const uint kDistTableSizeMax = kDicLogSizeMax * 2; // public const uint kDistTableSizeMax = kDicLogSizeMax * 2;
public const int kNumLenToPosStatesBits = 2; // it's for speed optimization public const int kNumLenToPosStatesBits = 2; // it's for speed optimization
public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits;
public const uint kMatchMinLen = 2; public const uint kMatchMinLen = 2;
public static uint GetLenToPosState(uint len) public static uint GetLenToPosState(uint len)
{ {
len -= kMatchMinLen; len -= kMatchMinLen;
if (len < kNumLenToPosStates) if (len < kNumLenToPosStates)
{ {
return len; return len;
} }
return kNumLenToPosStates - 1; return kNumLenToPosStates - 1;
} }
public const int kNumAlignBits = 4; public const int kNumAlignBits = 4;
public const uint kAlignTableSize = 1 << kNumAlignBits; public const uint kAlignTableSize = 1 << kNumAlignBits;
public const uint kAlignMask = kAlignTableSize - 1; public const uint kAlignMask = kAlignTableSize - 1;
public const uint kStartPosModelIndex = 4; public const uint kStartPosModelIndex = 4;
public const uint kEndPosModelIndex = 14; public const uint kEndPosModelIndex = 14;
public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;
public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2); public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2);
public const uint kNumLitPosStatesBitsEncodingMax = 4; public const uint kNumLitPosStatesBitsEncodingMax = 4;
public const uint kNumLitContextBitsMax = 8; public const uint kNumLitContextBitsMax = 8;
public const int kNumPosStatesBitsMax = 4; public const int kNumPosStatesBitsMax = 4;
public const uint kNumPosStatesMax = 1 << kNumPosStatesBitsMax; public const uint kNumPosStatesMax = 1 << kNumPosStatesBitsMax;
public const int kNumPosStatesBitsEncodingMax = 4; public const int kNumPosStatesBitsEncodingMax = 4;
public const uint kNumPosStatesEncodingMax = 1 << kNumPosStatesBitsEncodingMax; public const uint kNumPosStatesEncodingMax = 1 << kNumPosStatesBitsEncodingMax;
public const int kNumLowLenBits = 3; public const int kNumLowLenBits = 3;
public const int kNumMidLenBits = 3; public const int kNumMidLenBits = 3;
public const int kNumHighLenBits = 8; public const int kNumHighLenBits = 8;
public const uint kNumLowLenSymbols = 1 << kNumLowLenBits; public const uint kNumLowLenSymbols = 1 << kNumLowLenBits;
public const uint kNumMidLenSymbols = 1 << kNumMidLenBits; public const uint kNumMidLenSymbols = 1 << kNumMidLenBits;
public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols +
(1 << kNumHighLenBits); (1 << kNumHighLenBits);
public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1;
} }
} }
@@ -1,465 +1,465 @@
// LzmaDecoder.cs // LzmaDecoder.cs
using System; using System;
namespace SevenZip.Compression.LZMA namespace SevenZip.Compression.LZMA
{ {
using RangeCoder; using RangeCoder;
using System.Threading; using System.Threading;
public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream
{ {
private class LenDecoder private class LenDecoder
{ {
private BitDecoder m_Choice = new(); private BitDecoder m_Choice = new();
private BitDecoder m_Choice2 = new(); private BitDecoder m_Choice2 = new();
private readonly BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; private readonly BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
private readonly BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; private readonly BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
private readonly BitTreeDecoder m_HighCoder = new(Base.kNumHighLenBits); private readonly BitTreeDecoder m_HighCoder = new(Base.kNumHighLenBits);
private uint m_NumPosStates = 0; private uint m_NumPosStates = 0;
public void Create(uint numPosStates) public void Create(uint numPosStates)
{ {
for (uint posState = m_NumPosStates; posState < numPosStates; posState++) for (uint posState = m_NumPosStates; posState < numPosStates; posState++)
{ {
m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits); m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits);
m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits); m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits);
} }
m_NumPosStates = numPosStates; m_NumPosStates = numPosStates;
} }
public void Init() public void Init()
{ {
m_Choice.Init(); m_Choice.Init();
for (uint posState = 0; posState < m_NumPosStates; posState++) for (uint posState = 0; posState < m_NumPosStates; posState++)
{ {
m_LowCoder[posState].Init(); m_LowCoder[posState].Init();
m_MidCoder[posState].Init(); m_MidCoder[posState].Init();
} }
m_Choice2.Init(); m_Choice2.Init();
m_HighCoder.Init(); m_HighCoder.Init();
} }
public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState) public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState)
{ {
if (m_Choice.Decode(rangeDecoder) == 0) if (m_Choice.Decode(rangeDecoder) == 0)
{ {
return m_LowCoder[posState].Decode(rangeDecoder); return m_LowCoder[posState].Decode(rangeDecoder);
} }
else else
{ {
uint symbol = Base.kNumLowLenSymbols; uint symbol = Base.kNumLowLenSymbols;
if (m_Choice2.Decode(rangeDecoder) == 0) if (m_Choice2.Decode(rangeDecoder) == 0)
{ {
symbol += m_MidCoder[posState].Decode(rangeDecoder); symbol += m_MidCoder[posState].Decode(rangeDecoder);
} }
else else
{ {
symbol += Base.kNumMidLenSymbols; symbol += Base.kNumMidLenSymbols;
symbol += m_HighCoder.Decode(rangeDecoder); symbol += m_HighCoder.Decode(rangeDecoder);
} }
return symbol; return symbol;
} }
} }
} }
private class LiteralDecoder private class LiteralDecoder
{ {
private struct Decoder2 private struct Decoder2
{ {
private BitDecoder[] m_Decoders; private BitDecoder[] m_Decoders;
public void Create() { m_Decoders = new BitDecoder[0x300]; } public void Create() { m_Decoders = new BitDecoder[0x300]; }
public void Init() { for (int i = 0; i < 0x300; i++) public void Init() { for (int i = 0; i < 0x300; i++)
{ {
m_Decoders[i].Init(); m_Decoders[i].Init();
} }
} }
public byte DecodeNormal(RangeCoder.Decoder rangeDecoder) public byte DecodeNormal(RangeCoder.Decoder rangeDecoder)
{ {
uint symbol = 1; uint symbol = 1;
do do
{ {
symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
} }
while (symbol < 0x100); while (symbol < 0x100);
return (byte)symbol; return (byte)symbol;
} }
public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte) public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte)
{ {
uint symbol = 1; uint symbol = 1;
do do
{ {
uint matchBit = (uint)(matchByte >> 7) & 1; uint matchBit = (uint)(matchByte >> 7) & 1;
matchByte <<= 1; matchByte <<= 1;
uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder); uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder);
symbol = (symbol << 1) | bit; symbol = (symbol << 1) | bit;
if (matchBit != bit) if (matchBit != bit)
{ {
while (symbol < 0x100) while (symbol < 0x100)
{ {
symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
} }
break; break;
} }
} }
while (symbol < 0x100); while (symbol < 0x100);
return (byte)symbol; return (byte)symbol;
} }
} }
private Decoder2[] m_Coders; private Decoder2[] m_Coders;
private int m_NumPrevBits; private int m_NumPrevBits;
private int m_NumPosBits; private int m_NumPosBits;
private uint m_PosMask; private uint m_PosMask;
public void Create(int numPosBits, int numPrevBits) public void Create(int numPosBits, int numPrevBits)
{ {
if (m_Coders != null && m_NumPrevBits == numPrevBits && if (m_Coders != null && m_NumPrevBits == numPrevBits &&
m_NumPosBits == numPosBits) m_NumPosBits == numPosBits)
{ {
return; return;
} }
m_NumPosBits = numPosBits; m_NumPosBits = numPosBits;
m_PosMask = ((uint)1 << numPosBits) - 1; m_PosMask = ((uint)1 << numPosBits) - 1;
m_NumPrevBits = numPrevBits; m_NumPrevBits = numPrevBits;
uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
m_Coders = new Decoder2[numStates]; m_Coders = new Decoder2[numStates];
for (uint i = 0; i < numStates; i++) for (uint i = 0; i < numStates; i++)
{ {
m_Coders[i].Create(); m_Coders[i].Create();
} }
} }
public void Init() public void Init()
{ {
uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
for (uint i = 0; i < numStates; i++) for (uint i = 0; i < numStates; i++)
{ {
m_Coders[i].Init(); m_Coders[i].Init();
} }
} }
private uint GetState(uint pos, byte prevByte) private uint GetState(uint pos, byte prevByte)
{ return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); } { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); }
public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte) public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte)
{ return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); }
public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte) public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte)
{ return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); }
}; };
private readonly LZ.OutWindow m_OutWindow = new(); private readonly LZ.OutWindow m_OutWindow = new();
private readonly RangeCoder.Decoder m_RangeDecoder = new(); private readonly RangeCoder.Decoder m_RangeDecoder = new();
private readonly BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; private readonly BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
private readonly BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates]; private readonly BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates];
private readonly BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates]; private readonly BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates];
private readonly BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates]; private readonly BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates];
private readonly BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates]; private readonly BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates];
private readonly BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; private readonly BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
private readonly BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; private readonly BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates];
private readonly BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; private readonly BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex];
private readonly BitTreeDecoder m_PosAlignDecoder = new(Base.kNumAlignBits); private readonly BitTreeDecoder m_PosAlignDecoder = new(Base.kNumAlignBits);
private readonly LenDecoder m_LenDecoder = new(); private readonly LenDecoder m_LenDecoder = new();
private readonly LenDecoder m_RepLenDecoder = new(); private readonly LenDecoder m_RepLenDecoder = new();
private readonly LiteralDecoder m_LiteralDecoder = new(); private readonly LiteralDecoder m_LiteralDecoder = new();
private uint m_DictionarySize; private uint m_DictionarySize;
private uint m_DictionarySizeCheck; private uint m_DictionarySizeCheck;
private uint m_PosStateMask; private uint m_PosStateMask;
public Decoder() public Decoder()
{ {
m_DictionarySize = 0xFFFFFFFF; m_DictionarySize = 0xFFFFFFFF;
for (int i = 0; i < Base.kNumLenToPosStates; i++) for (int i = 0; i < Base.kNumLenToPosStates; i++)
{ {
m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits);
} }
} }
private void SetDictionarySize(uint dictionarySize) private void SetDictionarySize(uint dictionarySize)
{ {
if (m_DictionarySize != dictionarySize) if (m_DictionarySize != dictionarySize)
{ {
m_DictionarySize = dictionarySize; m_DictionarySize = dictionarySize;
m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1); m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1);
uint blockSize = Math.Max(m_DictionarySizeCheck, 1 << 12); uint blockSize = Math.Max(m_DictionarySizeCheck, 1 << 12);
m_OutWindow.Create(blockSize); m_OutWindow.Create(blockSize);
} }
} }
private void SetLiteralProperties(int lp, int lc) private void SetLiteralProperties(int lp, int lc)
{ {
if (lp > 8) if (lp > 8)
{ {
throw new InvalidParamException(); throw new InvalidParamException();
} }
if (lc > 8) if (lc > 8)
{ {
throw new InvalidParamException(); throw new InvalidParamException();
} }
m_LiteralDecoder.Create(lp, lc); m_LiteralDecoder.Create(lp, lc);
} }
private void SetPosBitsProperties(int pb) private void SetPosBitsProperties(int pb)
{ {
if (pb > Base.kNumPosStatesBitsMax) if (pb > Base.kNumPosStatesBitsMax)
{ {
throw new InvalidParamException(); throw new InvalidParamException();
} }
uint numPosStates = (uint)1 << pb; uint numPosStates = (uint)1 << pb;
m_LenDecoder.Create(numPosStates); m_LenDecoder.Create(numPosStates);
m_RepLenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates);
m_PosStateMask = numPosStates - 1; m_PosStateMask = numPosStates - 1;
} }
private bool _solid = false; private bool _solid = false;
private void Init(System.IO.Stream inStream, System.IO.Stream outStream) private void Init(System.IO.Stream inStream, System.IO.Stream outStream)
{ {
m_RangeDecoder.Init(inStream); m_RangeDecoder.Init(inStream);
m_OutWindow.Init(outStream, _solid); m_OutWindow.Init(outStream, _solid);
uint i; uint i;
for (i = 0; i < Base.kNumStates; i++) for (i = 0; i < Base.kNumStates; i++)
{ {
for (uint j = 0; j <= m_PosStateMask; j++) for (uint j = 0; j <= m_PosStateMask; j++)
{ {
uint index = (i << Base.kNumPosStatesBitsMax) + j; uint index = (i << Base.kNumPosStatesBitsMax) + j;
m_IsMatchDecoders[index].Init(); m_IsMatchDecoders[index].Init();
m_IsRep0LongDecoders[index].Init(); m_IsRep0LongDecoders[index].Init();
} }
m_IsRepDecoders[i].Init(); m_IsRepDecoders[i].Init();
m_IsRepG0Decoders[i].Init(); m_IsRepG0Decoders[i].Init();
m_IsRepG1Decoders[i].Init(); m_IsRepG1Decoders[i].Init();
m_IsRepG2Decoders[i].Init(); m_IsRepG2Decoders[i].Init();
} }
m_LiteralDecoder.Init(); m_LiteralDecoder.Init();
for (i = 0; i < Base.kNumLenToPosStates; i++) for (i = 0; i < Base.kNumLenToPosStates; i++)
{ {
m_PosSlotDecoder[i].Init(); m_PosSlotDecoder[i].Init();
} }
// m_PosSpecDecoder.Init(); // m_PosSpecDecoder.Init();
for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)
{ {
m_PosDecoders[i].Init(); m_PosDecoders[i].Init();
} }
m_LenDecoder.Init(); m_LenDecoder.Init();
m_RepLenDecoder.Init(); m_RepLenDecoder.Init();
m_PosAlignDecoder.Init(); m_PosAlignDecoder.Init();
} }
public void Code(System.IO.Stream inStream, System.IO.Stream outStream, public void Code(System.IO.Stream inStream, System.IO.Stream outStream,
Int64 inSize, Int64 outSize, ICodeProgress progress, CancellationToken? token = null) Int64 inSize, Int64 outSize, ICodeProgress progress, CancellationToken? token = null)
{ {
Init(inStream, outStream); Init(inStream, outStream);
Base.State state = new(); Base.State state = new();
state.Init(); state.Init();
uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
UInt64 nowPos64 = 0; UInt64 nowPos64 = 0;
UInt64 outSize64 = (UInt64)outSize; UInt64 outSize64 = (UInt64)outSize;
if (nowPos64 < outSize64) if (nowPos64 < outSize64)
{ {
if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0) if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0)
{ {
throw new DataErrorException(); throw new DataErrorException();
} }
state.UpdateChar(); state.UpdateChar();
byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0); byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0);
m_OutWindow.PutByte(b); m_OutWindow.PutByte(b);
nowPos64++; nowPos64++;
} }
try try
{ {
while (nowPos64 < outSize64) while (nowPos64 < outSize64)
{ {
token?.ThrowIfCancellationRequested(); token?.ThrowIfCancellationRequested();
// UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64); // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64);
// while(nowPos64 < next) // while(nowPos64 < next)
{ {
uint posState = (uint)nowPos64 & m_PosStateMask; uint posState = (uint)nowPos64 & m_PosStateMask;
if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
{ {
byte b; byte b;
byte prevByte = m_OutWindow.GetByte(0); byte prevByte = m_OutWindow.GetByte(0);
b = !state.IsCharState() b = !state.IsCharState()
? m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder, ? m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder,
(uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0)) (uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0))
: m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte); : m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte);
m_OutWindow.PutByte(b); m_OutWindow.PutByte(b);
state.UpdateChar(); state.UpdateChar();
nowPos64++; nowPos64++;
} }
else else
{ {
uint len; uint len;
if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1) if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1)
{ {
if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0) if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0)
{ {
if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
{ {
state.UpdateShortRep(); state.UpdateShortRep();
m_OutWindow.PutByte(m_OutWindow.GetByte(rep0)); m_OutWindow.PutByte(m_OutWindow.GetByte(rep0));
nowPos64++; nowPos64++;
continue; continue;
} }
} }
else else
{ {
UInt32 distance; UInt32 distance;
if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0) if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0)
{ {
distance = rep1; distance = rep1;
} }
else else
{ {
if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0) if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0)
{ {
distance = rep2; distance = rep2;
} }
else else
{ {
distance = rep3; distance = rep3;
rep3 = rep2; rep3 = rep2;
} }
rep2 = rep1; rep2 = rep1;
} }
rep1 = rep0; rep1 = rep0;
rep0 = distance; rep0 = distance;
} }
len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen;
state.UpdateRep(); state.UpdateRep();
} }
else else
{ {
rep3 = rep2; rep3 = rep2;
rep2 = rep1; rep2 = rep1;
rep1 = rep0; rep1 = rep0;
len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState);
state.UpdateMatch(); state.UpdateMatch();
uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder);
if (posSlot >= Base.kStartPosModelIndex) if (posSlot >= Base.kStartPosModelIndex)
{ {
int numDirectBits = (int)((posSlot >> 1) - 1); int numDirectBits = (int)((posSlot >> 1) - 1);
rep0 = (2 | (posSlot & 1)) << numDirectBits; rep0 = (2 | (posSlot & 1)) << numDirectBits;
if (posSlot < Base.kEndPosModelIndex) if (posSlot < Base.kEndPosModelIndex)
{ {
rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders,
rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); rep0 - posSlot - 1, m_RangeDecoder, numDirectBits);
} }
else else
{ {
rep0 += m_RangeDecoder.DecodeDirectBits( rep0 += m_RangeDecoder.DecodeDirectBits(
numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits; numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits;
rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);
} }
} }
else else
{ {
rep0 = posSlot; rep0 = posSlot;
} }
} }
if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck) if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck)
{ {
if (rep0 == 0xFFFFFFFF) if (rep0 == 0xFFFFFFFF)
{ {
break; break;
} }
throw new DataErrorException(); throw new DataErrorException();
} }
m_OutWindow.CopyBlock(rep0, len); m_OutWindow.CopyBlock(rep0, len);
nowPos64 += len; nowPos64 += len;
} }
} }
} }
} }
catch (OperationCanceledException) catch (OperationCanceledException)
{ {
} }
m_OutWindow.Flush(); m_OutWindow.Flush();
m_OutWindow.ReleaseStream(); m_OutWindow.ReleaseStream();
m_RangeDecoder.ReleaseStream(); m_RangeDecoder.ReleaseStream();
} }
public void SetDecoderProperties(byte[] properties) public void SetDecoderProperties(byte[] properties)
{ {
if (properties.Length < 5) if (properties.Length < 5)
{ {
throw new InvalidParamException(); throw new InvalidParamException();
} }
int lc = properties[0] % 9; int lc = properties[0] % 9;
int remainder = properties[0] / 9; int remainder = properties[0] / 9;
int lp = remainder % 5; int lp = remainder % 5;
int pb = remainder / 5; int pb = remainder / 5;
if (pb > Base.kNumPosStatesBitsMax) if (pb > Base.kNumPosStatesBitsMax)
{ {
throw new InvalidParamException(); throw new InvalidParamException();
} }
UInt32 dictionarySize = 0; UInt32 dictionarySize = 0;
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
dictionarySize += ((UInt32)properties[1 + i]) << (i * 8); dictionarySize += ((UInt32)properties[1 + i]) << (i * 8);
} }
SetDictionarySize(dictionarySize); SetDictionarySize(dictionarySize);
SetLiteralProperties(lp, lc); SetLiteralProperties(lp, lc);
SetPosBitsProperties(pb); SetPosBitsProperties(pb);
} }
public bool Train(System.IO.Stream stream) public bool Train(System.IO.Stream stream)
{ {
_solid = true; _solid = true;
return m_OutWindow.Train(stream); return m_OutWindow.Train(stream);
} }
/* /*
public override bool CanRead { get { return true; }} public override bool CanRead { get { return true; }}
public override bool CanWrite { get { return true; }} public override bool CanWrite { get { return true; }}
public override bool CanSeek { get { return true; }} public override bool CanSeek { get { return true; }}
public override long Length { get { return 0; }} public override long Length { get { return 0; }}
public override long Position public override long Position
{ {
get { return 0; } get { return 0; }
set { } set { }
} }
public override void Flush() { } public override void Flush() { }
public override int Read(byte[] buffer, int offset, int count) public override int Read(byte[] buffer, int offset, int count)
{ {
return 0; return 0;
} }
public override void Write(byte[] buffer, int offset, int count) public override void Write(byte[] buffer, int offset, int count)
{ {
} }
public override long Seek(long offset, System.IO.SeekOrigin origin) public override long Seek(long offset, System.IO.SeekOrigin origin)
{ {
return 0; return 0;
} }
public override void SetLength(long value) {} public override void SetLength(long value) {}
*/ */
} }
} }
File diff suppressed because it is too large Load Diff
@@ -1,243 +1,243 @@
using System; using System;
namespace SevenZip.Compression.RangeCoder namespace SevenZip.Compression.RangeCoder
{ {
internal class Encoder internal class Encoder
{ {
public const uint kTopValue = 1 << 24; public const uint kTopValue = 1 << 24;
private System.IO.Stream Stream; private System.IO.Stream Stream;
public UInt64 Low; public UInt64 Low;
public uint Range; public uint Range;
private uint _cacheSize; private uint _cacheSize;
private byte _cache; private byte _cache;
private long StartPosition; private long StartPosition;
public void SetStream(System.IO.Stream stream) public void SetStream(System.IO.Stream stream)
{ {
Stream = stream; Stream = stream;
} }
public void ReleaseStream() public void ReleaseStream()
{ {
Stream = null; Stream = null;
} }
public void Init() public void Init()
{ {
StartPosition = Stream.Position; StartPosition = Stream.Position;
Low = 0; Low = 0;
Range = 0xFFFFFFFF; Range = 0xFFFFFFFF;
_cacheSize = 1; _cacheSize = 1;
_cache = 0; _cache = 0;
} }
public void FlushData() public void FlushData()
{ {
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ {
ShiftLow(); ShiftLow();
} }
} }
public void FlushStream() public void FlushStream()
{ {
Stream.Flush(); Stream.Flush();
} }
public void CloseStream() public void CloseStream()
{ {
Stream.Close(); Stream.Close();
} }
public void Encode(uint start, uint size, uint total) public void Encode(uint start, uint size, uint total)
{ {
Low += start * (Range /= total); Low += start * (Range /= total);
Range *= size; Range *= size;
while (Range < kTopValue) while (Range < kTopValue)
{ {
Range <<= 8; Range <<= 8;
ShiftLow(); ShiftLow();
} }
} }
public void ShiftLow() public void ShiftLow()
{ {
if ((uint)Low < 0xFF000000 || (uint)(Low >> 32) == 1) if ((uint)Low < 0xFF000000 || (uint)(Low >> 32) == 1)
{ {
byte temp = _cache; byte temp = _cache;
do do
{ {
Stream.WriteByte((byte)(temp + (Low >> 32))); Stream.WriteByte((byte)(temp + (Low >> 32)));
temp = 0xFF; temp = 0xFF;
} }
while (--_cacheSize != 0); while (--_cacheSize != 0);
_cache = (byte)(((uint)Low) >> 24); _cache = (byte)(((uint)Low) >> 24);
} }
_cacheSize++; _cacheSize++;
Low = ((uint)Low) << 8; Low = ((uint)Low) << 8;
} }
public void EncodeDirectBits(uint v, int numTotalBits) public void EncodeDirectBits(uint v, int numTotalBits)
{ {
for (int i = numTotalBits - 1; i >= 0; i--) for (int i = numTotalBits - 1; i >= 0; i--)
{ {
Range >>= 1; Range >>= 1;
if (((v >> i) & 1) == 1) if (((v >> i) & 1) == 1)
{ {
Low += Range; Low += Range;
} }
if (Range < kTopValue) if (Range < kTopValue)
{ {
Range <<= 8; Range <<= 8;
ShiftLow(); ShiftLow();
} }
} }
} }
public void EncodeBit(uint size0, int numTotalBits, uint symbol) public void EncodeBit(uint size0, int numTotalBits, uint symbol)
{ {
uint newBound = (Range >> numTotalBits) * size0; uint newBound = (Range >> numTotalBits) * size0;
if (symbol == 0) if (symbol == 0)
{ {
Range = newBound; Range = newBound;
} }
else else
{ {
Low += newBound; Low += newBound;
Range -= newBound; Range -= newBound;
} }
while (Range < kTopValue) while (Range < kTopValue)
{ {
Range <<= 8; Range <<= 8;
ShiftLow(); ShiftLow();
} }
} }
public long GetProcessedSizeAdd() public long GetProcessedSizeAdd()
{ {
return _cacheSize + return _cacheSize +
Stream.Position - StartPosition + 4; Stream.Position - StartPosition + 4;
// (long)Stream.GetProcessedSize(); // (long)Stream.GetProcessedSize();
} }
} }
internal class Decoder internal class Decoder
{ {
public const uint kTopValue = 1 << 24; public const uint kTopValue = 1 << 24;
public uint Range; public uint Range;
public uint Code; public uint Code;
// public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16); // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16);
public System.IO.Stream Stream; public System.IO.Stream Stream;
public void Init(System.IO.Stream stream) public void Init(System.IO.Stream stream)
{ {
// Stream.Init(stream); // Stream.Init(stream);
Stream = stream; Stream = stream;
Code = 0; Code = 0;
Range = 0xFFFFFFFF; Range = 0xFFFFFFFF;
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ {
Code = (Code << 8) | (byte)Stream.ReadByte(); Code = (Code << 8) | (byte)Stream.ReadByte();
} }
} }
public void ReleaseStream() public void ReleaseStream()
{ {
// Stream.ReleaseStream(); // Stream.ReleaseStream();
Stream = null; Stream = null;
} }
public void CloseStream() public void CloseStream()
{ {
Stream.Close(); Stream.Close();
} }
public void Normalize() public void Normalize()
{ {
while (Range < kTopValue) while (Range < kTopValue)
{ {
Code = (Code << 8) | (byte)Stream.ReadByte(); Code = (Code << 8) | (byte)Stream.ReadByte();
Range <<= 8; Range <<= 8;
} }
} }
public void Normalize2() public void Normalize2()
{ {
if (Range < kTopValue) if (Range < kTopValue)
{ {
Code = (Code << 8) | (byte)Stream.ReadByte(); Code = (Code << 8) | (byte)Stream.ReadByte();
Range <<= 8; Range <<= 8;
} }
} }
public uint GetThreshold(uint total) public uint GetThreshold(uint total)
{ {
return Code / (Range /= total); return Code / (Range /= total);
} }
public void Decode(uint start, uint size, uint total) public void Decode(uint start, uint size, uint total)
{ {
Code -= start * Range; Code -= start * Range;
Range *= size; Range *= size;
Normalize(); Normalize();
} }
public uint DecodeDirectBits(int numTotalBits) public uint DecodeDirectBits(int numTotalBits)
{ {
uint range = Range; uint range = Range;
uint code = Code; uint code = Code;
uint result = 0; uint result = 0;
for (int i = numTotalBits; i > 0; i--) for (int i = numTotalBits; i > 0; i--)
{ {
range >>= 1; range >>= 1;
/* /*
result <<= 1; result <<= 1;
if (code >= range) if (code >= range)
{ {
code -= range; code -= range;
result |= 1; result |= 1;
} }
*/ */
uint t = (code - range) >> 31; uint t = (code - range) >> 31;
code -= range & (t - 1); code -= range & (t - 1);
result = (result << 1) | (1 - t); result = (result << 1) | (1 - t);
if (range < kTopValue) if (range < kTopValue)
{ {
code = (code << 8) | (byte)Stream.ReadByte(); code = (code << 8) | (byte)Stream.ReadByte();
range <<= 8; range <<= 8;
} }
} }
Range = range; Range = range;
Code = code; Code = code;
return result; return result;
} }
public uint DecodeBit(uint size0, int numTotalBits) public uint DecodeBit(uint size0, int numTotalBits)
{ {
uint newBound = (Range >> numTotalBits) * size0; uint newBound = (Range >> numTotalBits) * size0;
uint symbol; uint symbol;
if (Code < newBound) if (Code < newBound)
{ {
symbol = 0; symbol = 0;
Range = newBound; Range = newBound;
} }
else else
{ {
symbol = 1; symbol = 1;
Code -= newBound; Code -= newBound;
Range -= newBound; Range -= newBound;
} }
Normalize(); Normalize();
return symbol; return symbol;
} }
// ulong GetProcessedSize() {return Stream.GetProcessedSize(); } // ulong GetProcessedSize() {return Stream.GetProcessedSize(); }
} }
} }
@@ -1,127 +1,127 @@
using System; using System;
namespace SevenZip.Compression.RangeCoder namespace SevenZip.Compression.RangeCoder
{ {
internal struct BitEncoder internal struct BitEncoder
{ {
public const int kNumBitModelTotalBits = 11; public const int kNumBitModelTotalBits = 11;
public const uint kBitModelTotal = 1 << kNumBitModelTotalBits; public const uint kBitModelTotal = 1 << kNumBitModelTotalBits;
private const int kNumMoveBits = 5; private const int kNumMoveBits = 5;
private const int kNumMoveReducingBits = 2; private const int kNumMoveReducingBits = 2;
public const int kNumBitPriceShiftBits = 6; public const int kNumBitPriceShiftBits = 6;
private uint Prob; private uint Prob;
public void Init() { Prob = kBitModelTotal >> 1; } public void Init() { Prob = kBitModelTotal >> 1; }
public void UpdateModel(uint symbol) public void UpdateModel(uint symbol)
{ {
if (symbol == 0) if (symbol == 0)
{ {
Prob += (kBitModelTotal - Prob) >> kNumMoveBits; Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
} }
else else
{ {
Prob -= Prob >> kNumMoveBits; Prob -= Prob >> kNumMoveBits;
} }
} }
public void Encode(Encoder encoder, uint symbol) public void Encode(Encoder encoder, uint symbol)
{ {
// encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol); // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol);
// UpdateModel(symbol); // UpdateModel(symbol);
uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob; uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob;
if (symbol == 0) if (symbol == 0)
{ {
encoder.Range = newBound; encoder.Range = newBound;
Prob += (kBitModelTotal - Prob) >> kNumMoveBits; Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
} }
else else
{ {
encoder.Low += newBound; encoder.Low += newBound;
encoder.Range -= newBound; encoder.Range -= newBound;
Prob -= Prob >> kNumMoveBits; Prob -= Prob >> kNumMoveBits;
} }
if (encoder.Range < Encoder.kTopValue) if (encoder.Range < Encoder.kTopValue)
{ {
encoder.Range <<= 8; encoder.Range <<= 8;
encoder.ShiftLow(); encoder.ShiftLow();
} }
} }
private static readonly UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits]; private static readonly UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits];
static BitEncoder() static BitEncoder()
{ {
const int kNumBits = kNumBitModelTotalBits - kNumMoveReducingBits; const int kNumBits = kNumBitModelTotalBits - kNumMoveReducingBits;
for (int i = kNumBits - 1; i >= 0; i--) for (int i = kNumBits - 1; i >= 0; i--)
{ {
UInt32 start = (UInt32)1 << (kNumBits - i - 1); UInt32 start = (UInt32)1 << (kNumBits - i - 1);
UInt32 end = (UInt32)1 << (kNumBits - i); UInt32 end = (UInt32)1 << (kNumBits - i);
for (UInt32 j = start; j < end; j++) for (UInt32 j = start; j < end; j++)
{ {
ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) + ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) +
(((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1));
} }
} }
} }
public uint GetPrice(uint symbol) public uint GetPrice(uint symbol)
{ {
return ProbPrices[(((Prob - symbol) ^ (-(int)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; return ProbPrices[(((Prob - symbol) ^ (-(int)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];
} }
public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; } public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; }
public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; } public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; }
} }
internal struct BitDecoder internal struct BitDecoder
{ {
public const int kNumBitModelTotalBits = 11; public const int kNumBitModelTotalBits = 11;
public const uint kBitModelTotal = 1 << kNumBitModelTotalBits; public const uint kBitModelTotal = 1 << kNumBitModelTotalBits;
private const int kNumMoveBits = 5; private const int kNumMoveBits = 5;
private uint Prob; private uint Prob;
public void UpdateModel(int numMoveBits, uint symbol) public void UpdateModel(int numMoveBits, uint symbol)
{ {
if (symbol == 0) if (symbol == 0)
{ {
Prob += (kBitModelTotal - Prob) >> numMoveBits; Prob += (kBitModelTotal - Prob) >> numMoveBits;
} }
else else
{ {
Prob -= Prob >> numMoveBits; Prob -= Prob >> numMoveBits;
} }
} }
public void Init() { Prob = kBitModelTotal >> 1; } public void Init() { Prob = kBitModelTotal >> 1; }
public uint Decode(Decoder rangeDecoder) public uint Decode(Decoder rangeDecoder)
{ {
uint newBound = (rangeDecoder.Range >> kNumBitModelTotalBits) * Prob; uint newBound = (rangeDecoder.Range >> kNumBitModelTotalBits) * Prob;
if (rangeDecoder.Code < newBound) if (rangeDecoder.Code < newBound)
{ {
rangeDecoder.Range = newBound; rangeDecoder.Range = newBound;
Prob += (kBitModelTotal - Prob) >> kNumMoveBits; Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
if (rangeDecoder.Range < Decoder.kTopValue) if (rangeDecoder.Range < Decoder.kTopValue)
{ {
rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
rangeDecoder.Range <<= 8; rangeDecoder.Range <<= 8;
} }
return 0; return 0;
} }
else else
{ {
rangeDecoder.Range -= newBound; rangeDecoder.Range -= newBound;
rangeDecoder.Code -= newBound; rangeDecoder.Code -= newBound;
Prob -= Prob >> kNumMoveBits; Prob -= Prob >> kNumMoveBits;
if (rangeDecoder.Range < Decoder.kTopValue) if (rangeDecoder.Range < Decoder.kTopValue)
{ {
rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
rangeDecoder.Range <<= 8; rangeDecoder.Range <<= 8;
} }
return 1; return 1;
} }
} }
} }
} }
@@ -1,164 +1,164 @@
using System; using System;
namespace SevenZip.Compression.RangeCoder namespace SevenZip.Compression.RangeCoder
{ {
internal struct BitTreeEncoder internal struct BitTreeEncoder
{ {
private readonly BitEncoder[] Models; private readonly BitEncoder[] Models;
private readonly int NumBitLevels; private readonly int NumBitLevels;
public BitTreeEncoder(int numBitLevels) public BitTreeEncoder(int numBitLevels)
{ {
NumBitLevels = numBitLevels; NumBitLevels = numBitLevels;
Models = new BitEncoder[1 << numBitLevels]; Models = new BitEncoder[1 << numBitLevels];
} }
public void Init() public void Init()
{ {
for (uint i = 1; i < (1 << NumBitLevels); i++) for (uint i = 1; i < (1 << NumBitLevels); i++)
{ {
Models[i].Init(); Models[i].Init();
} }
} }
public void Encode(Encoder rangeEncoder, UInt32 symbol) public void Encode(Encoder rangeEncoder, UInt32 symbol)
{ {
UInt32 m = 1; UInt32 m = 1;
for (int bitIndex = NumBitLevels; bitIndex > 0;) for (int bitIndex = NumBitLevels; bitIndex > 0;)
{ {
bitIndex--; bitIndex--;
UInt32 bit = (symbol >> bitIndex) & 1; UInt32 bit = (symbol >> bitIndex) & 1;
Models[m].Encode(rangeEncoder, bit); Models[m].Encode(rangeEncoder, bit);
m = (m << 1) | bit; m = (m << 1) | bit;
} }
} }
public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol) public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol)
{ {
UInt32 m = 1; UInt32 m = 1;
for (UInt32 i = 0; i < NumBitLevels; i++) for (UInt32 i = 0; i < NumBitLevels; i++)
{ {
UInt32 bit = symbol & 1; UInt32 bit = symbol & 1;
Models[m].Encode(rangeEncoder, bit); Models[m].Encode(rangeEncoder, bit);
m = (m << 1) | bit; m = (m << 1) | bit;
symbol >>= 1; symbol >>= 1;
} }
} }
public UInt32 GetPrice(UInt32 symbol) public UInt32 GetPrice(UInt32 symbol)
{ {
UInt32 price = 0; UInt32 price = 0;
UInt32 m = 1; UInt32 m = 1;
for (int bitIndex = NumBitLevels; bitIndex > 0;) for (int bitIndex = NumBitLevels; bitIndex > 0;)
{ {
bitIndex--; bitIndex--;
UInt32 bit = (symbol >> bitIndex) & 1; UInt32 bit = (symbol >> bitIndex) & 1;
price += Models[m].GetPrice(bit); price += Models[m].GetPrice(bit);
m = (m << 1) + bit; m = (m << 1) + bit;
} }
return price; return price;
} }
public UInt32 ReverseGetPrice(UInt32 symbol) public UInt32 ReverseGetPrice(UInt32 symbol)
{ {
UInt32 price = 0; UInt32 price = 0;
UInt32 m = 1; UInt32 m = 1;
for (int i = NumBitLevels; i > 0; i--) for (int i = NumBitLevels; i > 0; i--)
{ {
UInt32 bit = symbol & 1; UInt32 bit = symbol & 1;
symbol >>= 1; symbol >>= 1;
price += Models[m].GetPrice(bit); price += Models[m].GetPrice(bit);
m = (m << 1) | bit; m = (m << 1) | bit;
} }
return price; return price;
} }
public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex, public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex,
int NumBitLevels, UInt32 symbol) int NumBitLevels, UInt32 symbol)
{ {
UInt32 price = 0; UInt32 price = 0;
UInt32 m = 1; UInt32 m = 1;
for (int i = NumBitLevels; i > 0; i--) for (int i = NumBitLevels; i > 0; i--)
{ {
UInt32 bit = symbol & 1; UInt32 bit = symbol & 1;
symbol >>= 1; symbol >>= 1;
price += Models[startIndex + m].GetPrice(bit); price += Models[startIndex + m].GetPrice(bit);
m = (m << 1) | bit; m = (m << 1) | bit;
} }
return price; return price;
} }
public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex, public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex,
Encoder rangeEncoder, int NumBitLevels, UInt32 symbol) Encoder rangeEncoder, int NumBitLevels, UInt32 symbol)
{ {
UInt32 m = 1; UInt32 m = 1;
for (int i = 0; i < NumBitLevels; i++) for (int i = 0; i < NumBitLevels; i++)
{ {
UInt32 bit = symbol & 1; UInt32 bit = symbol & 1;
Models[startIndex + m].Encode(rangeEncoder, bit); Models[startIndex + m].Encode(rangeEncoder, bit);
m = (m << 1) | bit; m = (m << 1) | bit;
symbol >>= 1; symbol >>= 1;
} }
} }
} }
internal struct BitTreeDecoder internal struct BitTreeDecoder
{ {
private readonly BitDecoder[] Models; private readonly BitDecoder[] Models;
private readonly int NumBitLevels; private readonly int NumBitLevels;
public BitTreeDecoder(int numBitLevels) public BitTreeDecoder(int numBitLevels)
{ {
NumBitLevels = numBitLevels; NumBitLevels = numBitLevels;
Models = new BitDecoder[1 << numBitLevels]; Models = new BitDecoder[1 << numBitLevels];
} }
public void Init() public void Init()
{ {
for (uint i = 1; i < (1 << NumBitLevels); i++) for (uint i = 1; i < (1 << NumBitLevels); i++)
{ {
Models[i].Init(); Models[i].Init();
} }
} }
public uint Decode(Decoder rangeDecoder) public uint Decode(Decoder rangeDecoder)
{ {
uint m = 1; uint m = 1;
for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--)
{ {
m = (m << 1) + Models[m].Decode(rangeDecoder); m = (m << 1) + Models[m].Decode(rangeDecoder);
} }
return m - ((uint)1 << NumBitLevels); return m - ((uint)1 << NumBitLevels);
} }
public uint ReverseDecode(Decoder rangeDecoder) public uint ReverseDecode(Decoder rangeDecoder)
{ {
uint m = 1; uint m = 1;
uint symbol = 0; uint symbol = 0;
for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
{ {
uint bit = Models[m].Decode(rangeDecoder); uint bit = Models[m].Decode(rangeDecoder);
m <<= 1; m <<= 1;
m += bit; m += bit;
symbol |= bit << bitIndex; symbol |= bit << bitIndex;
} }
return symbol; return symbol;
} }
public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex, public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex,
Decoder rangeDecoder, int NumBitLevels) Decoder rangeDecoder, int NumBitLevels)
{ {
uint m = 1; uint m = 1;
uint symbol = 0; uint symbol = 0;
for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
{ {
uint bit = Models[startIndex + m].Decode(rangeDecoder); uint bit = Models[startIndex + m].Decode(rangeDecoder);
m <<= 1; m <<= 1;
m += bit; m += bit;
symbol |= bit << bitIndex; symbol |= bit << bitIndex;
} }
return symbol; return symbol;
} }
} }
} }
+173 -173
View File
@@ -1,173 +1,173 @@
// ICoder.h // ICoder.h
using System; using System;
using System.Threading; using System.Threading;
namespace SevenZip namespace SevenZip
{ {
/// <summary> /// <summary>
/// The exception that is thrown when an error in input stream occurs during decoding. /// The exception that is thrown when an error in input stream occurs during decoding.
/// </summary> /// </summary>
internal class DataErrorException : ApplicationException internal class DataErrorException : ApplicationException
{ {
public DataErrorException() : base("Data Error") { } public DataErrorException() : base("Data Error") { }
public DataErrorException(string message) : base(message) public DataErrorException(string message) : base(message)
{ {
} }
public DataErrorException(string message, Exception innerException) : base(message, innerException) public DataErrorException(string message, Exception innerException) : base(message, innerException)
{ {
} }
} }
/// <summary> /// <summary>
/// The exception that is thrown when the value of an argument is outside the allowable range. /// The exception that is thrown when the value of an argument is outside the allowable range.
/// </summary> /// </summary>
internal class InvalidParamException : ApplicationException internal class InvalidParamException : ApplicationException
{ {
public InvalidParamException() : base("Invalid Parameter") { } public InvalidParamException() : base("Invalid Parameter") { }
public InvalidParamException(string message) : base(message) public InvalidParamException(string message) : base(message)
{ {
} }
public InvalidParamException(string message, Exception innerException) : base(message, innerException) public InvalidParamException(string message, Exception innerException) : base(message, innerException)
{ {
} }
} }
public interface ICodeProgress public interface ICodeProgress
{ {
/// <summary> /// <summary>
/// Callback progress. /// Callback progress.
/// </summary> /// </summary>
/// <param name="inSize"> /// <param name="inSize">
/// input size. -1 if unknown. /// input size. -1 if unknown.
/// </param> /// </param>
/// <param name="outSize"> /// <param name="outSize">
/// output size. -1 if unknown. /// output size. -1 if unknown.
/// </param> /// </param>
void SetProgress(Int64 inSize, Int64 outSize); void SetProgress(Int64 inSize, Int64 outSize);
}; };
public interface ICoder public interface ICoder
{ {
/// <summary> /// <summary>
/// Codes streams. /// Codes streams.
/// </summary> /// </summary>
/// <param name="inStream"> /// <param name="inStream">
/// input Stream. /// input Stream.
/// </param> /// </param>
/// <param name="outStream"> /// <param name="outStream">
/// output Stream. /// output Stream.
/// </param> /// </param>
/// <param name="inSize"> /// <param name="inSize">
/// input Size. -1 if unknown. /// input Size. -1 if unknown.
/// </param> /// </param>
/// <param name="outSize"> /// <param name="outSize">
/// output Size. -1 if unknown. /// output Size. -1 if unknown.
/// </param> /// </param>
/// <param name="progress"> /// <param name="progress">
/// callback progress reference. /// callback progress reference.
/// </param> /// </param>
/// <exception cref="DataErrorException"> /// <exception cref="DataErrorException">
/// if input stream is not valid /// if input stream is not valid
/// </exception> /// </exception>
void Code(System.IO.Stream inStream, System.IO.Stream outStream, void Code(System.IO.Stream inStream, System.IO.Stream outStream,
Int64 inSize, Int64 outSize, ICodeProgress progress, CancellationToken? token = null); Int64 inSize, Int64 outSize, ICodeProgress progress, CancellationToken? token = null);
}; };
/* /*
public interface ICoder2 public interface ICoder2
{ {
void Code(ISequentialInStream []inStreams, void Code(ISequentialInStream []inStreams,
const UInt64 []inSizes, const UInt64 []inSizes,
ISequentialOutStream []outStreams, ISequentialOutStream []outStreams,
UInt64 []outSizes, UInt64 []outSizes,
ICodeProgress progress); ICodeProgress progress);
}; };
*/ */
/// <summary> /// <summary>
/// Provides the fields that represent properties idenitifiers for compressing. /// Provides the fields that represent properties idenitifiers for compressing.
/// </summary> /// </summary>
public enum CoderPropID public enum CoderPropID
{ {
/// <summary> /// <summary>
/// Specifies default property. /// Specifies default property.
/// </summary> /// </summary>
DefaultProp = 0, DefaultProp = 0,
/// <summary> /// <summary>
/// Specifies size of dictionary. /// Specifies size of dictionary.
/// </summary> /// </summary>
DictionarySize, DictionarySize,
/// <summary> /// <summary>
/// Specifies size of memory for PPM*. /// Specifies size of memory for PPM*.
/// </summary> /// </summary>
UsedMemorySize, UsedMemorySize,
/// <summary> /// <summary>
/// Specifies order for PPM methods. /// Specifies order for PPM methods.
/// </summary> /// </summary>
Order, Order,
/// <summary> /// <summary>
/// Specifies Block Size. /// Specifies Block Size.
/// </summary> /// </summary>
BlockSize, BlockSize,
/// <summary> /// <summary>
/// Specifies number of postion state bits for LZMA (0 <= x <= 4). /// Specifies number of postion state bits for LZMA (0 <= x <= 4).
/// </summary> /// </summary>
PosStateBits, PosStateBits,
/// <summary> /// <summary>
/// Specifies number of literal context bits for LZMA (0 <= x <= 8). /// Specifies number of literal context bits for LZMA (0 <= x <= 8).
/// </summary> /// </summary>
LitContextBits, LitContextBits,
/// <summary> /// <summary>
/// Specifies number of literal position bits for LZMA (0 <= x <= 4). /// Specifies number of literal position bits for LZMA (0 <= x <= 4).
/// </summary> /// </summary>
LitPosBits, LitPosBits,
/// <summary> /// <summary>
/// Specifies number of fast bytes for LZ*. /// Specifies number of fast bytes for LZ*.
/// </summary> /// </summary>
NumFastBytes, NumFastBytes,
/// <summary> /// <summary>
/// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B". /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B".
/// </summary> /// </summary>
MatchFinder, MatchFinder,
/// <summary> /// <summary>
/// Specifies the number of match finder cyckes. /// Specifies the number of match finder cyckes.
/// </summary> /// </summary>
MatchFinderCycles, MatchFinderCycles,
/// <summary> /// <summary>
/// Specifies number of passes. /// Specifies number of passes.
/// </summary> /// </summary>
NumPasses, NumPasses,
/// <summary> /// <summary>
/// Specifies number of algorithm. /// Specifies number of algorithm.
/// </summary> /// </summary>
Algorithm, Algorithm,
/// <summary> /// <summary>
/// Specifies the number of threads. /// Specifies the number of threads.
/// </summary> /// </summary>
NumThreads, NumThreads,
/// <summary> /// <summary>
/// Specifies mode with end marker. /// Specifies mode with end marker.
/// </summary> /// </summary>
EndMarker EndMarker
}; };
public interface ISetCoderProperties public interface ISetCoderProperties
{ {
void SetCoderProperties(CoderPropID[] propIDs, object[] properties); void SetCoderProperties(CoderPropID[] propIDs, object[] properties);
}; };
public interface IWriteCoderProperties public interface IWriteCoderProperties
{ {
void WriteCoderProperties(System.IO.Stream outStream); void WriteCoderProperties(System.IO.Stream outStream);
} }
public interface ISetDecoderProperties public interface ISetDecoderProperties
{ {
void SetDecoderProperties(byte[] properties); void SetDecoderProperties(byte[] properties);
} }
} }
+112 -112
View File
@@ -1,112 +1,112 @@
<!-- <!--
Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions: Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
--> -->
<Application x:Class="WPinternals.App" <Application x:Class="WPinternals.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Views\StartupWindow.xaml" StartupUri="Views\StartupWindow.xaml"
xmlns:ComponentModel="clr-namespace:System.ComponentModel;assembly=PresentationFramework" xmlns:ComponentModel="clr-namespace:System.ComponentModel;assembly=PresentationFramework"
> >
<Application.Resources> <Application.Resources>
<Style TargetType="{x:Type UserControl}"> <Style TargetType="{x:Type UserControl}">
<Style.Triggers> <Style.Triggers>
<Trigger Property="ComponentModel:DesignerProperties.IsInDesignMode" <Trigger Property="ComponentModel:DesignerProperties.IsInDesignMode"
Value="true"> Value="true">
<Setter Property="Background" <Setter Property="Background"
Value="White" /> Value="White" />
</Trigger> </Trigger>
</Style.Triggers> </Style.Triggers>
</Style> </Style>
<ControlTemplate x:Key="TopicExpanderTemplate" TargetType="{x:Type Expander}"> <ControlTemplate x:Key="TopicExpanderTemplate" TargetType="{x:Type Expander}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="3" SnapsToDevicePixels="True"> <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="3" SnapsToDevicePixels="True">
<DockPanel> <DockPanel>
<ToggleButton x:Name="HeaderSite" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" DockPanel.Dock="Top" Foreground="{TemplateBinding Foreground}" FontWeight="{TemplateBinding FontWeight}" FontStyle="{TemplateBinding FontStyle}" FontStretch="{TemplateBinding FontStretch}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" MinWidth="0" MinHeight="0" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"> <ToggleButton x:Name="HeaderSite" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" DockPanel.Dock="Top" Foreground="{TemplateBinding Foreground}" FontWeight="{TemplateBinding FontWeight}" FontStyle="{TemplateBinding FontStyle}" FontStretch="{TemplateBinding FontStretch}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" MinWidth="0" MinHeight="0" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}">
<ToggleButton.FocusVisualStyle> <ToggleButton.FocusVisualStyle>
<Style> <Style>
<Setter Property="Control.Template"> <Setter Property="Control.Template">
<Setter.Value> <Setter.Value>
<ControlTemplate> <ControlTemplate>
<Border> <Border>
<Rectangle Margin="0" SnapsToDevicePixels="True" Stroke="Black" StrokeThickness="1" StrokeDashArray="1 2"/> <Rectangle Margin="0" SnapsToDevicePixels="True" Stroke="Black" StrokeThickness="1" StrokeDashArray="1 2"/>
</Border> </Border>
</ControlTemplate> </ControlTemplate>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Style> </Style>
</ToggleButton.FocusVisualStyle> </ToggleButton.FocusVisualStyle>
<ToggleButton.Style> <ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}"> <Style TargetType="{x:Type ToggleButton}">
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}"> <ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Padding="{TemplateBinding Padding}"> <Border Padding="{TemplateBinding Padding}">
<Grid Background="Transparent" SnapsToDevicePixels="False"> <Grid Background="Transparent" SnapsToDevicePixels="False">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
<ColumnDefinition Width="19"/> <ColumnDefinition Width="19"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Ellipse x:Name="circle" Fill="White" HorizontalAlignment="Center" Height="19" Stroke="#FF333333" VerticalAlignment="Center" Width="19" Grid.Column="1" /> <Ellipse x:Name="circle" Fill="White" HorizontalAlignment="Center" Height="19" Stroke="#FF333333" VerticalAlignment="Center" Width="19" Grid.Column="1" />
<Path x:Name="arrow" Data="M1,1.5L4.5,5 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="False" Stroke="#FF333333" StrokeThickness="2" VerticalAlignment="Center" Grid.Column="1" /> <Path x:Name="arrow" Data="M1,1.5L4.5,5 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="False" Stroke="#FF333333" StrokeThickness="2" VerticalAlignment="Center" Grid.Column="1" />
<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="0" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="Left" Margin="0,0,0,0" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Center" TextBlock.FontSize="18" TextBlock.FontWeight="Bold" TextBlock.Foreground="#FF3753A6"/> <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="0" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="Left" Margin="0,0,0,0" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Center" TextBlock.FontSize="18" TextBlock.FontWeight="Bold" TextBlock.Foreground="#FF3753A6"/>
</Grid> </Grid>
</Border> </Border>
<ControlTemplate.Triggers> <ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True"> <Trigger Property="IsChecked" Value="True">
<Setter Property="Data" TargetName="arrow" Value="M1,4.5L4.5,1 8,4.5"/> <Setter Property="Data" TargetName="arrow" Value="M1,4.5L4.5,1 8,4.5"/>
</Trigger> </Trigger>
<Trigger Property="IsMouseOver" Value="True"> <Trigger Property="IsMouseOver" Value="True">
<Setter Property="Stroke" TargetName="circle" Value="#FF5593FF"/> <Setter Property="Stroke" TargetName="circle" Value="#FF5593FF"/>
<Setter Property="Fill" TargetName="circle" Value="#FFF3F9FF"/> <Setter Property="Fill" TargetName="circle" Value="#FFF3F9FF"/>
<Setter Property="Stroke" TargetName="arrow" Value="Black"/> <Setter Property="Stroke" TargetName="arrow" Value="Black"/>
</Trigger> </Trigger>
<Trigger Property="IsPressed" Value="True"> <Trigger Property="IsPressed" Value="True">
<Setter Property="Stroke" TargetName="circle" Value="#FF3C77DD"/> <Setter Property="Stroke" TargetName="circle" Value="#FF3C77DD"/>
<Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/> <Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
<Setter Property="Fill" TargetName="circle" Value="#FFD9ECFF"/> <Setter Property="Fill" TargetName="circle" Value="#FFD9ECFF"/>
<Setter Property="Stroke" TargetName="arrow" Value="Black"/> <Setter Property="Stroke" TargetName="arrow" Value="Black"/>
</Trigger> </Trigger>
<Trigger Property="IsEnabled" Value="False"> <Trigger Property="IsEnabled" Value="False">
<Setter Property="Stroke" TargetName="circle" Value="#FFBCBCBC"/> <Setter Property="Stroke" TargetName="circle" Value="#FFBCBCBC"/>
<Setter Property="Fill" TargetName="circle" Value="#FFE6E6E6"/> <Setter Property="Fill" TargetName="circle" Value="#FFE6E6E6"/>
<Setter Property="Stroke" TargetName="arrow" Value="#FF707070"/> <Setter Property="Stroke" TargetName="arrow" Value="#FF707070"/>
</Trigger> </Trigger>
</ControlTemplate.Triggers> </ControlTemplate.Triggers>
</ControlTemplate> </ControlTemplate>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Style> </Style>
</ToggleButton.Style> </ToggleButton.Style>
</ToggleButton> </ToggleButton>
<ContentPresenter x:Name="ExpandSite" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" DockPanel.Dock="Bottom" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" Visibility="Collapsed" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> <ContentPresenter x:Name="ExpandSite" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" DockPanel.Dock="Bottom" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" Visibility="Collapsed" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</DockPanel> </DockPanel>
</Border> </Border>
<ControlTemplate.Triggers> <ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="True"> <Trigger Property="IsExpanded" Value="True">
<Setter Property="Visibility" TargetName="ExpandSite" Value="Visible"/> <Setter Property="Visibility" TargetName="ExpandSite" Value="Visible"/>
</Trigger> </Trigger>
<Trigger Property="IsEnabled" Value="False"> <Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger> </Trigger>
</ControlTemplate.Triggers> </ControlTemplate.Triggers>
</ControlTemplate> </ControlTemplate>
</Application.Resources> </Application.Resources>
</Application> </Application>
+103 -103
View File
@@ -1,103 +1,103 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Windows; using System.Windows;
namespace WPinternals namespace WPinternals
{ {
/// <summary> /// <summary>
/// Interaction logic for App.xaml /// Interaction logic for App.xaml
/// </summary> /// </summary>
public partial class App : Application public partial class App : Application
{ {
internal static Action NavigateToGettingStarted; internal static Action NavigateToGettingStarted;
internal static Action NavigateToUnlockBoot; internal static Action NavigateToUnlockBoot;
internal static PatchEngine PatchEngine; internal static PatchEngine PatchEngine;
internal static WPinternalsConfig Config; internal static WPinternalsConfig Config;
internal static Mutex mutex = new(false, "Global\\WPinternalsRunning"); internal static Mutex mutex = new(false, "Global\\WPinternalsRunning");
internal static DownloadsViewModel DownloadManager; internal static DownloadsViewModel DownloadManager;
internal static bool InterruptBoot = false; internal static bool InterruptBoot = false;
internal static bool IsPnPEventLogMissing = true; internal static bool IsPnPEventLogMissing = true;
public App() public App()
: base() : base()
{ {
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
#if NETCORE #if NETCORE
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance); System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
#endif #endif
if (Environment.GetCommandLineArgs().Length > 1) if (Environment.GetCommandLineArgs().Length > 1)
{ {
CommandLine.OpenConsole(); CommandLine.OpenConsole();
} }
try try
{ {
if (!mutex.WaitOne(0, false)) if (!mutex.WaitOne(0, false))
{ {
if (Environment.GetCommandLineArgs().Length > 1) if (Environment.GetCommandLineArgs().Length > 1)
{ {
Console.WriteLine("Windows Phone Internals is already running"); Console.WriteLine("Windows Phone Internals is already running");
CommandLine.CloseConsole(); CommandLine.CloseConsole();
} }
else else
{ {
MessageBox.Show("Windows Phone Internals is already running.", "Windows Phone Internals", MessageBoxButton.OK, MessageBoxImage.Exclamation); MessageBox.Show("Windows Phone Internals is already running.", "Windows Phone Internals", MessageBoxButton.OK, MessageBoxImage.Exclamation);
} }
Environment.Exit(0); Environment.Exit(0);
} }
} }
catch (AbandonedMutexException) { } catch (AbandonedMutexException) { }
Registration.CheckExpiration(); Registration.CheckExpiration();
string PatchDefintionsXml; string PatchDefintionsXml;
string PatchDefintionsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PatchDefintions.xml"); string PatchDefintionsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PatchDefintions.xml");
if (File.Exists(PatchDefintionsPath)) if (File.Exists(PatchDefintionsPath))
{ {
PatchDefintionsXml = File.ReadAllText(PatchDefintionsPath); PatchDefintionsXml = File.ReadAllText(PatchDefintionsPath);
} }
else else
{ {
using Stream stream = System.Reflection.Assembly.GetEntryAssembly().GetManifestResourceStream("WPinternals.PatchDefinitions.xml"); using Stream stream = System.Reflection.Assembly.GetEntryAssembly().GetManifestResourceStream("WPinternals.PatchDefinitions.xml");
using StreamReader sr = new(stream); using StreamReader sr = new(stream);
PatchDefintionsXml = sr.ReadToEnd(); PatchDefintionsXml = sr.ReadToEnd();
} }
PatchEngine = new PatchEngine(PatchDefintionsXml); PatchEngine = new PatchEngine(PatchDefintionsXml);
Config = WPinternalsConfig.ReadConfig(); Config = WPinternalsConfig.ReadConfig();
} }
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{ {
if (e.ExceptionObject is Exception) if (e.ExceptionObject is Exception)
{ {
LogFile.LogException(e.ExceptionObject as Exception); LogFile.LogException(e.ExceptionObject as Exception);
} }
} }
} }
} }
File diff suppressed because it is too large Load Diff
@@ -68,7 +68,7 @@ namespace DiscUtils.Internal
result.Add(func(sVal)); result.Add(func(sVal));
} }
return result.ToArray(); return [.. result];
} }
/// <summary> /// <summary>
@@ -31,15 +31,15 @@ namespace DiscUtils.Fat
private const byte SpaceByte = 0x20; private const byte SpaceByte = 0x20;
public static readonly FileName SelfEntryName = public static readonly FileName SelfEntryName =
new(new byte[] { 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }, 0); new([0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20], 0);
public static readonly FileName ParentEntryName = public static readonly FileName ParentEntryName =
new(new byte[] { 0x2E, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }, 0); new([0x2E, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20], 0);
public static readonly FileName Null = public static readonly FileName Null =
new(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0); new([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], 0);
private static readonly byte[] InvalidBytes = { 0x22, 0x2A, 0x2B, 0x2C, 0x2E, 0x2F, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x5B, 0x5C, 0x5D, 0x7C }; private static readonly byte[] InvalidBytes = [0x22, 0x2A, 0x2B, 0x2C, 0x2E, 0x2F, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x5B, 0x5C, 0x5D, 0x7C];
private readonly byte[] _raw; private readonly byte[] _raw;
@@ -33,10 +33,10 @@ namespace DiscUtils.Fat
{ {
if (FatFileSystem.Detect(stream)) if (FatFileSystem.Detect(stream))
{ {
return new FileSystemInfo[] { new VfsFileSystemInfo("FAT", "Microsoft FAT", Open) }; return [new VfsFileSystemInfo("FAT", "Microsoft FAT", Open)];
} }
return System.Array.Empty<FileSystemInfo>(); return [];
} }
private DiscFileSystem Open(Stream stream, VolumeInfo volumeInfo, FileSystemParameters parameters) private DiscFileSystem Open(Stream stream, VolumeInfo volumeInfo, FileSystemParameters parameters)
@@ -80,22 +80,22 @@ namespace DiscUtils.Fat
{ {
// see http://home.teleport.com/~brainy/lfn.htm // see http://home.teleport.com/~brainy/lfn.htm
// NOTE: we assume ordinals are ok here. // NOTE: we assume ordinals are ok here.
char[] chars = new char[13]; char[] chars =
chars[0] = (char)((256 * buffer[2]) + buffer[1]); [
chars[1] = (char)((256 * buffer[4]) + buffer[3]); (char)((256 * buffer[2]) + buffer[1]),
chars[2] = (char)((256 * buffer[6]) + buffer[5]); (char)((256 * buffer[4]) + buffer[3]),
chars[3] = (char)((256 * buffer[8]) + buffer[7]); (char)((256 * buffer[6]) + buffer[5]),
chars[4] = (char)((256 * buffer[10]) + buffer[9]); (char)((256 * buffer[8]) + buffer[7]),
(char)((256 * buffer[10]) + buffer[9]),
chars[5] = (char)((256 * buffer[15]) + buffer[14]); (char)((256 * buffer[15]) + buffer[14]),
chars[6] = (char)((256 * buffer[17]) + buffer[16]); (char)((256 * buffer[17]) + buffer[16]),
chars[7] = (char)((256 * buffer[19]) + buffer[18]); (char)((256 * buffer[19]) + buffer[18]),
chars[8] = (char)((256 * buffer[21]) + buffer[20]); (char)((256 * buffer[21]) + buffer[20]),
chars[9] = (char)((256 * buffer[23]) + buffer[22]); (char)((256 * buffer[23]) + buffer[22]),
chars[10] = (char)((256 * buffer[25]) + buffer[24]); (char)((256 * buffer[25]) + buffer[24]),
(char)((256 * buffer[29]) + buffer[28]),
chars[11] = (char)((256 * buffer[29]) + buffer[28]); (char)((256 * buffer[31]) + buffer[30]),
chars[12] = (char)((256 * buffer[31]) + buffer[30]); ];
string chunk = new(chars); string chunk = new(chars);
int zero = chunk.IndexOf('\0'); int zero = chunk.IndexOf('\0');
return zero >= 0 ? chunk.Substring(0, zero) : chunk; return zero >= 0 ? chunk.Substring(0, zero) : chunk;
@@ -201,7 +201,7 @@ namespace DiscUtils.Fat
} }
} }
return dirs.ToArray(); return [.. dirs];
} }
public DirectoryEntry[] GetFiles() public DirectoryEntry[] GetFiles()
@@ -215,7 +215,7 @@ namespace DiscUtils.Fat
} }
} }
return files.ToArray(); return [.. files];
} }
public DirectoryEntry GetEntry(long id) public DirectoryEntry GetEntry(long id)
@@ -1258,7 +1258,7 @@ namespace DiscUtils.Fat
dirs.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding))); dirs.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding)));
} }
return dirs.ToArray(); return [.. dirs];
} }
/// <summary> /// <summary>
@@ -1275,7 +1275,7 @@ namespace DiscUtils.Fat
List<string> dirs = new(); List<string> dirs = new();
DoSearch(dirs, path, re, searchOption == SearchOption.AllDirectories, true, false); DoSearch(dirs, path, re, searchOption == SearchOption.AllDirectories, true, false);
return dirs.ToArray(); return [.. dirs];
} }
/// <summary> /// <summary>
@@ -1294,7 +1294,7 @@ namespace DiscUtils.Fat
files.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding))); files.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding)));
} }
return files.ToArray(); return [.. files];
} }
/// <summary> /// <summary>
@@ -1311,7 +1311,7 @@ namespace DiscUtils.Fat
List<string> results = new(); List<string> results = new();
DoSearch(results, path, re, searchOption == SearchOption.AllDirectories, false, true); DoSearch(results, path, re, searchOption == SearchOption.AllDirectories, false, true);
return results.ToArray(); return [.. results];
} }
/// <summary> /// <summary>
@@ -1330,7 +1330,7 @@ namespace DiscUtils.Fat
result.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding))); result.Add(Utilities.CombinePaths(path, dirEntry.Name.GetDisplayName(FatOptions.FileNameEncoding)));
} }
return result.ToArray(); return [.. result];
} }
/// <summary> /// <summary>
@@ -1356,7 +1356,7 @@ namespace DiscUtils.Fat
} }
} }
return result.ToArray(); return [.. result];
} }
/// <summary> /// <summary>
@@ -1915,9 +1915,7 @@ namespace DiscUtils.Fat
throw new DirectoryNotFoundException(string.Format(CultureInfo.InvariantCulture, "The directory '{0}' was not found", path)); throw new DirectoryNotFoundException(string.Format(CultureInfo.InvariantCulture, "The directory '{0}' was not found", path));
} }
DirectoryEntry[] entries = dir.Entries; foreach (DirectoryEntry de in dir.Entries)
foreach (DirectoryEntry de in entries)
{ {
bool isDir = (de.Attributes & FatAttributes.Directory) != 0; bool isDir = (de.Attributes & FatAttributes.Directory) != 0;
@@ -1,41 +1,41 @@
<!-- <!--
Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions: Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
--> -->
<UserControl <UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPinternals" x:Class="WPinternals.FilePickerBase" xmlns:local="clr-namespace:WPinternals" x:Class="WPinternals.FilePickerBase"
mc:Ignorable="d" mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="300" d:DesignHeight="100" d:DesignWidth="300"
x:Name="FilePickerControlName" x:Name="FilePickerControlName"
SizeChanged="SizeChangedHandler" Loaded="LoadedHandler" SizeChanged="SizeChangedHandler" Loaded="LoadedHandler"
> >
<Grid> <Grid>
<TextBlock x:Name="CaptionTextBlock" HorizontalAlignment="Left" Text=""/> <TextBlock x:Name="CaptionTextBlock" HorizontalAlignment="Left" Text=""/>
<TextBlock x:Name="PathTextBlock" FontWeight="Bold" HorizontalAlignment="Left" Text="Path here"/> <TextBlock x:Name="PathTextBlock" FontWeight="Bold" HorizontalAlignment="Left" Text="Path here"/>
<TextBlock x:Name="SelectLink" Margin="150,0,0,0" HorizontalAlignment="Left"><Hyperlink NavigateUri="Select" Click="SelectLink_Click"><TextBlock Text="{Binding Path=SelectionText, ElementName=FilePickerControlName}"/></Hyperlink></TextBlock> <TextBlock x:Name="SelectLink" Margin="150,0,0,0" HorizontalAlignment="Left"><Hyperlink NavigateUri="Select" Click="SelectLink_Click"><TextBlock Text="{Binding Path=SelectionText, ElementName=FilePickerControlName}"/></Hyperlink></TextBlock>
<TextBlock x:Name="ChangeLink" Margin="210,0,0,0" HorizontalAlignment="Left"><Hyperlink NavigateUri="Change" Click="ChangeLink_Click">Change</Hyperlink></TextBlock> <TextBlock x:Name="ChangeLink" Margin="210,0,0,0" HorizontalAlignment="Left"><Hyperlink NavigateUri="Change" Click="ChangeLink_Click">Change</Hyperlink></TextBlock>
<TextBlock x:Name="ClearLink" Margin="260,0,0,0" HorizontalAlignment="Left"><Hyperlink NavigateUri="Clear" Click="ClearLink_Click">Clear</Hyperlink></TextBlock> <TextBlock x:Name="ClearLink" Margin="260,0,0,0" HorizontalAlignment="Left"><Hyperlink NavigateUri="Clear" Click="ClearLink_Click">Clear</Hyperlink></TextBlock>
</Grid> </Grid>
</UserControl> </UserControl>
File diff suppressed because it is too large Load Diff
@@ -1,120 +1,120 @@
// This class was found online. // This class was found online.
// Original author is probably: Swizzy // Original author is probably: Swizzy
// https://github.com/ttgxdinger/Random/blob/master/CPUKey%20Checker/CPUKey%20Checker/FolderSelectDialog.cs // https://github.com/ttgxdinger/Random/blob/master/CPUKey%20Checker/CPUKey%20Checker/FolderSelectDialog.cs
using System; using System;
using System.Windows.Forms; using System.Windows.Forms;
namespace WPinternals namespace WPinternals
{ {
/// <summary> /// <summary>
/// Wraps System.Windows.Forms.OpenFileDialog to make it present /// Wraps System.Windows.Forms.OpenFileDialog to make it present
/// a vista-style dialog. /// a vista-style dialog.
/// </summary> /// </summary>
public class FolderSelectDialog public class FolderSelectDialog
{ {
// Wrapped dialog // Wrapped dialog
private readonly OpenFileDialog ofd = null; private readonly OpenFileDialog ofd = null;
/// <summary> /// <summary>
/// Default constructor /// Default constructor
/// </summary> /// </summary>
public FolderSelectDialog() public FolderSelectDialog()
{ {
ofd = new OpenFileDialog ofd = new OpenFileDialog
{ {
Filter = "Folders|\n", Filter = "Folders|\n",
AddExtension = false, AddExtension = false,
CheckFileExists = false, CheckFileExists = false,
DereferenceLinks = true, DereferenceLinks = true,
Multiselect = false Multiselect = false
}; };
} }
#region Properties #region Properties
/// <summary> /// <summary>
/// Gets/Sets the initial folder to be selected. A null value selects the current directory. /// Gets/Sets the initial folder to be selected. A null value selects the current directory.
/// </summary> /// </summary>
public string InitialDirectory public string InitialDirectory
{ {
get { return ofd.InitialDirectory; } get { return ofd.InitialDirectory; }
set { ofd.InitialDirectory = string.IsNullOrEmpty(value) ? Environment.CurrentDirectory : value; } set { ofd.InitialDirectory = string.IsNullOrEmpty(value) ? Environment.CurrentDirectory : value; }
} }
/// <summary> /// <summary>
/// Gets/Sets the title to show in the dialog /// Gets/Sets the title to show in the dialog
/// </summary> /// </summary>
public string Title public string Title
{ {
get { return ofd.Title; } get { return ofd.Title; }
set { ofd.Title = value ?? "Select a folder"; } set { ofd.Title = value ?? "Select a folder"; }
} }
/// <summary> /// <summary>
/// Gets the selected folder /// Gets the selected folder
/// </summary> /// </summary>
public string FileName public string FileName
{ {
get { return ofd.FileName; } get { return ofd.FileName; }
} }
#endregion #endregion
#region Methods #region Methods
/// <summary> /// <summary>
/// Shows the dialog /// Shows the dialog
/// </summary> /// </summary>
/// <returns>True if the user presses OK else false</returns> /// <returns>True if the user presses OK else false</returns>
public bool ShowDialog() public bool ShowDialog()
{ {
return ShowDialog(IntPtr.Zero); return ShowDialog(IntPtr.Zero);
} }
/// <summary> /// <summary>
/// Shows the dialog /// Shows the dialog
/// </summary> /// </summary>
/// <param name="hWndOwner">Handle of the control to be parent</param> /// <param name="hWndOwner">Handle of the control to be parent</param>
/// <returns>True if the user presses OK else false</returns> /// <returns>True if the user presses OK else false</returns>
public bool ShowDialog(IntPtr hWndOwner) public bool ShowDialog(IntPtr hWndOwner)
{ {
var fbd = new FolderBrowserDialog var fbd = new FolderBrowserDialog
{ {
Description = this.Title, Description = this.Title,
SelectedPath = this.InitialDirectory, SelectedPath = this.InitialDirectory,
ShowNewFolderButton = false ShowNewFolderButton = false
}; };
if (fbd.ShowDialog(new WindowWrapper(hWndOwner)) != DialogResult.OK) if (fbd.ShowDialog(new WindowWrapper(hWndOwner)) != DialogResult.OK)
{ {
return false; return false;
} }
ofd.FileName = fbd.SelectedPath; ofd.FileName = fbd.SelectedPath;
return true; return true;
} }
#endregion #endregion
} }
/// <summary> /// <summary>
/// Creates IWin32Window around an IntPtr /// Creates IWin32Window around an IntPtr
/// </summary> /// </summary>
public class WindowWrapper : IWin32Window public class WindowWrapper : IWin32Window
{ {
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
/// <param name="handle">Handle to wrap</param> /// <param name="handle">Handle to wrap</param>
public WindowWrapper(IntPtr handle) public WindowWrapper(IntPtr handle)
{ {
Handle = handle; Handle = handle;
} }
/// <summary> /// <summary>
/// Original ptr /// Original ptr
/// </summary> /// </summary>
public IntPtr Handle { get; } public IntPtr Handle { get; }
} }
} }
File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

@@ -1,401 +1,401 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
// These functions assume same endianness for the CPU architecture and the raw data it reads from or writes to. // These functions assume same endianness for the CPU architecture and the raw data it reads from or writes to.
using System; using System;
using System.IO; using System.IO;
namespace WPinternals namespace WPinternals
{ {
internal static class ByteOperations internal static class ByteOperations
{ {
internal static string ReadAsciiString(byte[] ByteArray, UInt32 Offset, UInt32 Length) internal static string ReadAsciiString(byte[] ByteArray, UInt32 Offset, UInt32 Length)
{ {
byte[] Bytes = new byte[Length]; byte[] Bytes = new byte[Length];
Buffer.BlockCopy(ByteArray, (int)Offset, Bytes, 0, (int)Length); Buffer.BlockCopy(ByteArray, (int)Offset, Bytes, 0, (int)Length);
return System.Text.Encoding.ASCII.GetString(Bytes); return System.Text.Encoding.ASCII.GetString(Bytes);
} }
internal static string ReadUnicodeString(byte[] ByteArray, UInt32 Offset, UInt32 Length) internal static string ReadUnicodeString(byte[] ByteArray, UInt32 Offset, UInt32 Length)
{ {
byte[] Bytes = new byte[Length]; byte[] Bytes = new byte[Length];
Buffer.BlockCopy(ByteArray, (int)Offset, Bytes, 0, (int)Length); Buffer.BlockCopy(ByteArray, (int)Offset, Bytes, 0, (int)Length);
return System.Text.Encoding.Unicode.GetString(Bytes); return System.Text.Encoding.Unicode.GetString(Bytes);
} }
internal static void WriteAsciiString(byte[] ByteArray, UInt32 Offset, string Text, UInt32? MaxBufferLength = null) internal static void WriteAsciiString(byte[] ByteArray, UInt32 Offset, string Text, UInt32? MaxBufferLength = null)
{ {
if (MaxBufferLength != null) if (MaxBufferLength != null)
{ {
Array.Clear(ByteArray, (int)Offset, (int)MaxBufferLength); Array.Clear(ByteArray, (int)Offset, (int)MaxBufferLength);
} }
byte[] TextBytes = System.Text.Encoding.ASCII.GetBytes(Text); byte[] TextBytes = System.Text.Encoding.ASCII.GetBytes(Text);
int WriteLength = TextBytes.Length; int WriteLength = TextBytes.Length;
if (WriteLength > MaxBufferLength) if (WriteLength > MaxBufferLength)
{ {
WriteLength = (int)MaxBufferLength; WriteLength = (int)MaxBufferLength;
} }
Buffer.BlockCopy(TextBytes, 0, ByteArray, (int)Offset, WriteLength); Buffer.BlockCopy(TextBytes, 0, ByteArray, (int)Offset, WriteLength);
} }
internal static void WriteUnicodeString(byte[] ByteArray, UInt32 Offset, string Text, UInt32? MaxBufferLength = null) internal static void WriteUnicodeString(byte[] ByteArray, UInt32 Offset, string Text, UInt32? MaxBufferLength = null)
{ {
if (MaxBufferLength != null) if (MaxBufferLength != null)
{ {
Array.Clear(ByteArray, (int)Offset, (int)MaxBufferLength); Array.Clear(ByteArray, (int)Offset, (int)MaxBufferLength);
} }
byte[] TextBytes = System.Text.Encoding.Unicode.GetBytes(Text); byte[] TextBytes = System.Text.Encoding.Unicode.GetBytes(Text);
int WriteLength = TextBytes.Length; int WriteLength = TextBytes.Length;
if (WriteLength > MaxBufferLength) if (WriteLength > MaxBufferLength)
{ {
WriteLength = (int)MaxBufferLength; WriteLength = (int)MaxBufferLength;
} }
Buffer.BlockCopy(TextBytes, 0, ByteArray, (int)Offset, WriteLength); Buffer.BlockCopy(TextBytes, 0, ByteArray, (int)Offset, WriteLength);
} }
internal static UInt32 ReadUInt32(byte[] ByteArray, UInt32 Offset) internal static UInt32 ReadUInt32(byte[] ByteArray, UInt32 Offset)
{ {
return BitConverter.ToUInt32(ByteArray, (int)Offset); return BitConverter.ToUInt32(ByteArray, (int)Offset);
} }
internal static void WriteUInt32(byte[] ByteArray, UInt32 Offset, UInt32 Value) internal static void WriteUInt32(byte[] ByteArray, UInt32 Offset, UInt32 Value)
{ {
Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 4); Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 4);
} }
internal static Int32 ReadInt32(byte[] ByteArray, UInt32 Offset) internal static Int32 ReadInt32(byte[] ByteArray, UInt32 Offset)
{ {
return BitConverter.ToInt32(ByteArray, (int)Offset); return BitConverter.ToInt32(ByteArray, (int)Offset);
} }
internal static void WriteInt32(byte[] ByteArray, UInt32 Offset, Int32 Value) internal static void WriteInt32(byte[] ByteArray, UInt32 Offset, Int32 Value)
{ {
Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 4); Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 4);
} }
internal static UInt16 ReadUInt16(byte[] ByteArray, UInt32 Offset) internal static UInt16 ReadUInt16(byte[] ByteArray, UInt32 Offset)
{ {
return BitConverter.ToUInt16(ByteArray, (int)Offset); return BitConverter.ToUInt16(ByteArray, (int)Offset);
} }
internal static void WriteUInt16(byte[] ByteArray, UInt32 Offset, UInt16 Value) internal static void WriteUInt16(byte[] ByteArray, UInt32 Offset, UInt16 Value)
{ {
Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 2); Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 2);
} }
internal static Int16 ReadInt16(byte[] ByteArray, UInt32 Offset) internal static Int16 ReadInt16(byte[] ByteArray, UInt32 Offset)
{ {
return BitConverter.ToInt16(ByteArray, (int)Offset); return BitConverter.ToInt16(ByteArray, (int)Offset);
} }
internal static void WriteInt16(byte[] ByteArray, UInt32 Offset, Int16 Value) internal static void WriteInt16(byte[] ByteArray, UInt32 Offset, Int16 Value)
{ {
Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 2); Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 2);
} }
internal static byte ReadUInt8(byte[] ByteArray, UInt32 Offset) internal static byte ReadUInt8(byte[] ByteArray, UInt32 Offset)
{ {
return ByteArray[Offset]; return ByteArray[Offset];
} }
internal static void WriteUInt8(byte[] ByteArray, UInt32 Offset, byte Value) internal static void WriteUInt8(byte[] ByteArray, UInt32 Offset, byte Value)
{ {
ByteArray[Offset] = Value; ByteArray[Offset] = Value;
} }
internal static UInt32 ReadUInt24(byte[] ByteArray, UInt32 Offset) internal static UInt32 ReadUInt24(byte[] ByteArray, UInt32 Offset)
{ {
return (UInt32)(ByteArray[Offset] + (ByteArray[Offset + 1] << 8) + (ByteArray[Offset + 2] << 16)); return (UInt32)(ByteArray[Offset] + (ByteArray[Offset + 1] << 8) + (ByteArray[Offset + 2] << 16));
} }
internal static void WriteUInt24(byte[] ByteArray, UInt32 Offset, UInt32 Value) internal static void WriteUInt24(byte[] ByteArray, UInt32 Offset, UInt32 Value)
{ {
Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 3); Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 3);
} }
internal static UInt64 ReadUInt64(byte[] ByteArray, UInt32 Offset) internal static UInt64 ReadUInt64(byte[] ByteArray, UInt32 Offset)
{ {
return BitConverter.ToUInt64(ByteArray, (int)Offset); return BitConverter.ToUInt64(ByteArray, (int)Offset);
} }
internal static void WriteUInt64(byte[] ByteArray, UInt32 Offset, UInt64 Value) internal static void WriteUInt64(byte[] ByteArray, UInt32 Offset, UInt64 Value)
{ {
Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 8); Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 8);
} }
internal static Guid ReadGuid(byte[] ByteArray, UInt32 Offset) internal static Guid ReadGuid(byte[] ByteArray, UInt32 Offset)
{ {
byte[] GuidBuffer = new byte[0x10]; byte[] GuidBuffer = new byte[0x10];
Buffer.BlockCopy(ByteArray, (int)Offset, GuidBuffer, 0, 0x10); Buffer.BlockCopy(ByteArray, (int)Offset, GuidBuffer, 0, 0x10);
return new Guid(GuidBuffer); return new Guid(GuidBuffer);
} }
internal static void WriteGuid(byte[] ByteArray, UInt32 Offset, Guid Value) internal static void WriteGuid(byte[] ByteArray, UInt32 Offset, Guid Value)
{ {
Buffer.BlockCopy(Value.ToByteArray(), 0, ByteArray, (int)Offset, 0x10); Buffer.BlockCopy(Value.ToByteArray(), 0, ByteArray, (int)Offset, 0x10);
} }
internal static UInt32 Align(UInt32 Base, UInt32 Offset, UInt32 Alignment) internal static UInt32 Align(UInt32 Base, UInt32 Offset, UInt32 Alignment)
{ {
if (((Offset - Base) % Alignment) == 0) if (((Offset - Base) % Alignment) == 0)
{ {
return Offset; return Offset;
} }
else else
{ {
return ((((Offset - Base) / Alignment) + 1) * Alignment) + Base; return ((((Offset - Base) / Alignment) + 1) * Alignment) + Base;
} }
} }
internal static UInt32? FindPatternInFile(string FileName, byte[] Pattern, byte[] Mask, out byte[] OutPattern) internal static UInt32? FindPatternInFile(string FileName, byte[] Pattern, byte[] Mask, out byte[] OutPattern)
{ {
// The mask is optional. // The mask is optional.
// In the mask 0x00 means the value must match, and 0xFF means that this position is a wildcard. // In the mask 0x00 means the value must match, and 0xFF means that this position is a wildcard.
UInt32? Result = null; UInt32? Result = null;
FileStream Stream = new(FileName, FileMode.Open, FileAccess.Read); FileStream Stream = new(FileName, FileMode.Open, FileAccess.Read);
byte[] Buffer = new byte[0x10000 + Pattern.Length - 1]; byte[] Buffer = new byte[0x10000 + Pattern.Length - 1];
UInt32 BufferReadPosition = 0; // Position in buffer where file-chunk is being read. UInt32 BufferReadPosition = 0; // Position in buffer where file-chunk is being read.
UInt32 BytesInBuffer = 0; UInt32 BytesInBuffer = 0;
UInt32 BytesRead; UInt32 BytesRead;
UInt32 SearchPositionFile = 0; UInt32 SearchPositionFile = 0;
UInt32 SearchPositionBuffer = 0; UInt32 SearchPositionBuffer = 0;
UInt32 BufferFileOffset = 0; // Offset in file where data from buffer is located. UInt32 BufferFileOffset = 0; // Offset in file where data from buffer is located.
bool Match = false; bool Match = false;
int i; int i;
OutPattern = null; OutPattern = null;
while (SearchPositionFile <= (Stream.Length - Pattern.Length)) while (SearchPositionFile <= (Stream.Length - Pattern.Length))
{ {
if ((SearchPositionBuffer + Pattern.Length) > BytesInBuffer) if ((SearchPositionBuffer + Pattern.Length) > BytesInBuffer)
{ {
// Need to read next chunk // Need to read next chunk
if ((BytesInBuffer - SearchPositionBuffer) > 0) if ((BytesInBuffer - SearchPositionBuffer) > 0)
{ {
System.Buffer.BlockCopy(Buffer, (int)SearchPositionBuffer, Buffer, 0, (int)(BytesInBuffer - SearchPositionBuffer)); System.Buffer.BlockCopy(Buffer, (int)SearchPositionBuffer, Buffer, 0, (int)(BytesInBuffer - SearchPositionBuffer));
} }
BufferReadPosition = BytesInBuffer - SearchPositionBuffer; BufferReadPosition = BytesInBuffer - SearchPositionBuffer;
BytesInBuffer -= SearchPositionBuffer; BytesInBuffer -= SearchPositionBuffer;
BufferFileOffset += SearchPositionBuffer; BufferFileOffset += SearchPositionBuffer;
SearchPositionBuffer = 0; SearchPositionBuffer = 0;
BytesRead = (UInt32)Stream.Read(Buffer, (int)BufferReadPosition, Buffer.Length - (int)BufferReadPosition); BytesRead = (UInt32)Stream.Read(Buffer, (int)BufferReadPosition, Buffer.Length - (int)BufferReadPosition);
BytesInBuffer += BytesRead; BytesInBuffer += BytesRead;
} }
Match = true; Match = true;
for (i = 0; i < Pattern.Length; i++) for (i = 0; i < Pattern.Length; i++)
{ {
if (Buffer[SearchPositionBuffer + i] != Pattern[i]) if (Buffer[SearchPositionBuffer + i] != Pattern[i])
{ {
if ((Mask == null) || (Mask[i] == 0)) if ((Mask == null) || (Mask[i] == 0))
{ {
Match = false; Match = false;
break; break;
} }
} }
} }
if (Match) if (Match)
{ {
Result = SearchPositionFile; Result = SearchPositionFile;
OutPattern = new byte[Pattern.Length]; OutPattern = new byte[Pattern.Length];
System.Buffer.BlockCopy(Buffer, (int)SearchPositionBuffer, OutPattern, 0, Pattern.Length); System.Buffer.BlockCopy(Buffer, (int)SearchPositionBuffer, OutPattern, 0, Pattern.Length);
break; break;
} }
SearchPositionBuffer++; SearchPositionBuffer++;
SearchPositionFile++; SearchPositionFile++;
} }
Stream.Close(); Stream.Close();
return Result; return Result;
} }
internal static UInt32? FindAscii(byte[] SourceBuffer, string Pattern) internal static UInt32? FindAscii(byte[] SourceBuffer, string Pattern)
{ {
return FindPattern(SourceBuffer, System.Text.Encoding.ASCII.GetBytes(Pattern), null, null); return FindPattern(SourceBuffer, System.Text.Encoding.ASCII.GetBytes(Pattern), null, null);
} }
internal static UInt32? FindUnicode(byte[] SourceBuffer, string Pattern) internal static UInt32? FindUnicode(byte[] SourceBuffer, string Pattern)
{ {
return FindPattern(SourceBuffer, System.Text.Encoding.Unicode.GetBytes(Pattern), null, null); return FindPattern(SourceBuffer, System.Text.Encoding.Unicode.GetBytes(Pattern), null, null);
} }
internal static UInt32? FindUint(byte[] SourceBuffer, UInt32 Pattern) internal static UInt32? FindUint(byte[] SourceBuffer, UInt32 Pattern)
{ {
return FindPattern(SourceBuffer, BitConverter.GetBytes(Pattern), null, null); return FindPattern(SourceBuffer, BitConverter.GetBytes(Pattern), null, null);
} }
internal static UInt32? FindPattern(byte[] SourceBuffer, byte[] Pattern, byte[] Mask, byte[] OutPattern) internal static UInt32? FindPattern(byte[] SourceBuffer, byte[] Pattern, byte[] Mask, byte[] OutPattern)
{ {
return FindPattern(SourceBuffer, 0, null, Pattern, Mask, OutPattern); return FindPattern(SourceBuffer, 0, null, Pattern, Mask, OutPattern);
} }
internal static bool Compare(byte[] Array1, byte[] Array2) internal static bool Compare(byte[] Array1, byte[] Array2)
{ {
return System.Collections.StructuralComparisons.StructuralEqualityComparer.Equals(Array1, Array2); return System.Collections.StructuralComparisons.StructuralEqualityComparer.Equals(Array1, Array2);
} }
internal static UInt32? FindPattern(byte[] SourceBuffer, uint SourceOffset, uint? SourceSize, byte[] Pattern, byte[] Mask, byte[] OutPattern) internal static UInt32? FindPattern(byte[] SourceBuffer, uint SourceOffset, uint? SourceSize, byte[] Pattern, byte[] Mask, byte[] OutPattern)
{ {
// The mask is optional. // The mask is optional.
// In the mask 0x00 means the value must match, and 0xFF means that this position is a wildcard. // In the mask 0x00 means the value must match, and 0xFF means that this position is a wildcard.
UInt32? Result = null; UInt32? Result = null;
UInt32 SearchPosition = SourceOffset; UInt32 SearchPosition = SourceOffset;
bool Match = false; bool Match = false;
int i; int i;
while ((SearchPosition <= (SourceBuffer.Length - Pattern.Length)) && ((SourceSize == null) || (SearchPosition <= (SourceOffset + SourceSize - Pattern.Length)))) while ((SearchPosition <= (SourceBuffer.Length - Pattern.Length)) && ((SourceSize == null) || (SearchPosition <= (SourceOffset + SourceSize - Pattern.Length))))
{ {
Match = true; Match = true;
for (i = 0; i < Pattern.Length; i++) for (i = 0; i < Pattern.Length; i++)
{ {
if (SourceBuffer[SearchPosition + i] != Pattern[i]) if (SourceBuffer[SearchPosition + i] != Pattern[i])
{ {
if ((Mask == null) || (Mask[i] == 0)) if ((Mask == null) || (Mask[i] == 0))
{ {
Match = false; Match = false;
break; break;
} }
} }
} }
if (Match) if (Match)
{ {
Result = SearchPosition; Result = SearchPosition;
if (OutPattern != null) if (OutPattern != null)
{ {
Buffer.BlockCopy(SourceBuffer, (int)SearchPosition, OutPattern, 0, Pattern.Length); Buffer.BlockCopy(SourceBuffer, (int)SearchPosition, OutPattern, 0, Pattern.Length);
} }
break; break;
} }
SearchPosition++; SearchPosition++;
} }
return Result; return Result;
} }
internal static byte CalculateChecksum8(byte[] Buffer, UInt32 Offset, UInt32 Size) internal static byte CalculateChecksum8(byte[] Buffer, UInt32 Offset, UInt32 Size)
{ {
byte Checksum = 0; byte Checksum = 0;
for (UInt32 i = Offset; i < (Offset + Size); i++) for (UInt32 i = Offset; i < (Offset + Size); i++)
{ {
Checksum += Buffer[i]; Checksum += Buffer[i];
} }
return (byte)(0x100 - Checksum); return (byte)(0x100 - Checksum);
} }
internal static UInt16 CalculateChecksum16(byte[] Buffer, UInt32 Offset, UInt32 Size) internal static UInt16 CalculateChecksum16(byte[] Buffer, UInt32 Offset, UInt32 Size)
{ {
UInt16 Checksum = 0; UInt16 Checksum = 0;
for (UInt32 i = Offset; i < (Offset + Size - 1); i += 2) for (UInt32 i = Offset; i < (Offset + Size - 1); i += 2)
{ {
Checksum += BitConverter.ToUInt16(Buffer, (int)i); Checksum += BitConverter.ToUInt16(Buffer, (int)i);
} }
return (UInt16)(0x10000 - Checksum); return (UInt16)(0x10000 - Checksum);
} }
private static readonly UInt32[] CRC32Table = new UInt32[] { private static readonly UInt32[] CRC32Table = [
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
}; ];
internal static UInt32 CRC32(byte[] Input, UInt32 Offset, UInt32 Length) internal static UInt32 CRC32(byte[] Input, UInt32 Offset, UInt32 Length)
{ {
if ((Input == null) || ((Offset + Length) > Input.Length)) if ((Input == null) || ((Offset + Length) > Input.Length))
{ {
throw new ArgumentException(); throw new ArgumentException();
} }
unchecked unchecked
{ {
uint crc = (uint)(((uint)0) ^ (-1)); uint crc = (uint)(((uint)0) ^ (-1));
for (var i = Offset; i < (Offset + Length); i++) for (var i = Offset; i < (Offset + Length); i++)
{ {
crc = (crc >> 8) ^ CRC32Table[(crc ^ Input[i]) & 0xFF]; crc = (crc >> 8) ^ CRC32Table[(crc ^ Input[i]) & 0xFF];
} }
crc = (uint)(crc ^ (-1)); crc = (uint)(crc ^ (-1));
return crc; return crc;
} }
} }
} }
} }
+487 -487
View File
@@ -1,487 +1,487 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
namespace WPinternals namespace WPinternals
{ {
internal class FFU internal class FFU
{ {
internal int ChunkSize; internal int ChunkSize;
internal string Path; internal string Path;
internal byte[] SecurityHeader; internal byte[] SecurityHeader;
internal byte[] ImageHeader; internal byte[] ImageHeader;
internal byte[] StoreHeader; internal byte[] StoreHeader;
private readonly int?[] ChunkIndexes; private readonly int?[] ChunkIndexes;
private FileStream FFUFile = null; private FileStream FFUFile = null;
private int FileOpenCount = 0; private int FileOpenCount = 0;
internal string PlatformID; internal string PlatformID;
internal GPT GPT; internal GPT GPT;
internal UInt64 TotalSize; internal UInt64 TotalSize;
internal UInt64 HeaderSize; internal UInt64 HeaderSize;
internal UInt64 PayloadSize; internal UInt64 PayloadSize;
internal UInt64 TotalChunkCount; internal UInt64 TotalChunkCount;
internal FFU(string Path) internal FFU(string Path)
{ {
this.Path = Path; this.Path = Path;
try try
{ {
OpenFile(); OpenFile();
// Read Security Header // Read Security Header
byte[] ShortSecurityHeader = new byte[0x20]; byte[] ShortSecurityHeader = new byte[0x20];
FFUFile.Read(ShortSecurityHeader, 0, 0x20); FFUFile.Read(ShortSecurityHeader, 0, 0x20);
if (ByteOperations.ReadAsciiString(ShortSecurityHeader, 0x04, 0x0C) != "SignedImage ") if (ByteOperations.ReadAsciiString(ShortSecurityHeader, 0x04, 0x0C) != "SignedImage ")
{ {
throw new BadImageFormatException(); throw new BadImageFormatException();
} }
ChunkSize = ByteOperations.ReadInt32(ShortSecurityHeader, 0x10) * 1024; ChunkSize = ByteOperations.ReadInt32(ShortSecurityHeader, 0x10) * 1024;
UInt32 SecurityHeaderSize = ByteOperations.ReadUInt32(ShortSecurityHeader, 0x00); UInt32 SecurityHeaderSize = ByteOperations.ReadUInt32(ShortSecurityHeader, 0x00);
UInt32 CatalogSize = ByteOperations.ReadUInt32(ShortSecurityHeader, 0x18); UInt32 CatalogSize = ByteOperations.ReadUInt32(ShortSecurityHeader, 0x18);
UInt32 HashTableSize = ByteOperations.ReadUInt32(ShortSecurityHeader, 0x1C); UInt32 HashTableSize = ByteOperations.ReadUInt32(ShortSecurityHeader, 0x1C);
SecurityHeader = new byte[RoundUpToChunks(SecurityHeaderSize + CatalogSize + HashTableSize)]; SecurityHeader = new byte[RoundUpToChunks(SecurityHeaderSize + CatalogSize + HashTableSize)];
FFUFile.Seek(0, SeekOrigin.Begin); FFUFile.Seek(0, SeekOrigin.Begin);
FFUFile.Read(SecurityHeader, 0, SecurityHeader.Length); FFUFile.Read(SecurityHeader, 0, SecurityHeader.Length);
// Read Image Header // Read Image Header
byte[] ShortImageHeader = new byte[0x1C]; byte[] ShortImageHeader = new byte[0x1C];
FFUFile.Read(ShortImageHeader, 0, 0x1C); FFUFile.Read(ShortImageHeader, 0, 0x1C);
if (ByteOperations.ReadAsciiString(ShortImageHeader, 0x04, 0x0C) != "ImageFlash ") if (ByteOperations.ReadAsciiString(ShortImageHeader, 0x04, 0x0C) != "ImageFlash ")
{ {
throw new BadImageFormatException(); throw new BadImageFormatException();
} }
UInt32 ImageHeaderSize = ByteOperations.ReadUInt32(ShortImageHeader, 0x00); UInt32 ImageHeaderSize = ByteOperations.ReadUInt32(ShortImageHeader, 0x00);
UInt32 ManifestSize = ByteOperations.ReadUInt32(ShortImageHeader, 0x10); UInt32 ManifestSize = ByteOperations.ReadUInt32(ShortImageHeader, 0x10);
ImageHeader = new byte[RoundUpToChunks(ImageHeaderSize + ManifestSize)]; ImageHeader = new byte[RoundUpToChunks(ImageHeaderSize + ManifestSize)];
FFUFile.Seek(SecurityHeader.Length, SeekOrigin.Begin); FFUFile.Seek(SecurityHeader.Length, SeekOrigin.Begin);
FFUFile.Read(ImageHeader, 0, ImageHeader.Length); FFUFile.Read(ImageHeader, 0, ImageHeader.Length);
// Read Store Header // Read Store Header
byte[] ShortStoreHeader = new byte[248]; byte[] ShortStoreHeader = new byte[248];
FFUFile.Read(ShortStoreHeader, 0, 248); FFUFile.Read(ShortStoreHeader, 0, 248);
PlatformID = ByteOperations.ReadAsciiString(ShortStoreHeader, 0x0C, 192).TrimEnd(new char[] { (char)0, ' ' }); PlatformID = ByteOperations.ReadAsciiString(ShortStoreHeader, 0x0C, 192).TrimEnd([(char)0, ' ']);
int WriteDescriptorCount = ByteOperations.ReadInt32(ShortStoreHeader, 208); int WriteDescriptorCount = ByteOperations.ReadInt32(ShortStoreHeader, 208);
UInt32 WriteDescriptorLength = ByteOperations.ReadUInt32(ShortStoreHeader, 212); UInt32 WriteDescriptorLength = ByteOperations.ReadUInt32(ShortStoreHeader, 212);
UInt32 ValidateDescriptorLength = ByteOperations.ReadUInt32(ShortStoreHeader, 220); UInt32 ValidateDescriptorLength = ByteOperations.ReadUInt32(ShortStoreHeader, 220);
StoreHeader = new byte[RoundUpToChunks(248 + WriteDescriptorLength + ValidateDescriptorLength)]; StoreHeader = new byte[RoundUpToChunks(248 + WriteDescriptorLength + ValidateDescriptorLength)];
FFUFile.Seek(SecurityHeader.Length + ImageHeader.Length, SeekOrigin.Begin); FFUFile.Seek(SecurityHeader.Length + ImageHeader.Length, SeekOrigin.Begin);
FFUFile.Read(StoreHeader, 0, StoreHeader.Length); FFUFile.Read(StoreHeader, 0, StoreHeader.Length);
// Parse Chunk Indexes // Parse Chunk Indexes
int HighestChunkIndex = 0; int HighestChunkIndex = 0;
UInt32 LocationCount; UInt32 LocationCount;
int ChunkIndex; int ChunkIndex;
int ChunkCount; int ChunkCount;
int DiskAccessMethod; int DiskAccessMethod;
UInt32 WriteDescriptorEntryOffset = 248 + ValidateDescriptorLength; UInt32 WriteDescriptorEntryOffset = 248 + ValidateDescriptorLength;
int FFUChunkIndex = 0; int FFUChunkIndex = 0;
for (int i = 0; i < WriteDescriptorCount; i++) for (int i = 0; i < WriteDescriptorCount; i++)
{ {
LocationCount = ByteOperations.ReadUInt32(StoreHeader, WriteDescriptorEntryOffset + 0x00); LocationCount = ByteOperations.ReadUInt32(StoreHeader, WriteDescriptorEntryOffset + 0x00);
ChunkCount = ByteOperations.ReadInt32(StoreHeader, WriteDescriptorEntryOffset + 0x04); ChunkCount = ByteOperations.ReadInt32(StoreHeader, WriteDescriptorEntryOffset + 0x04);
for (int j = 0; j < LocationCount; j++) for (int j = 0; j < LocationCount; j++)
{ {
DiskAccessMethod = ByteOperations.ReadInt32(StoreHeader, (UInt32)(WriteDescriptorEntryOffset + 0x08 + (j * 0x08))); DiskAccessMethod = ByteOperations.ReadInt32(StoreHeader, (UInt32)(WriteDescriptorEntryOffset + 0x08 + (j * 0x08)));
ChunkIndex = ByteOperations.ReadInt32(StoreHeader, (UInt32)(WriteDescriptorEntryOffset + 0x0C + (j * 0x08))); ChunkIndex = ByteOperations.ReadInt32(StoreHeader, (UInt32)(WriteDescriptorEntryOffset + 0x0C + (j * 0x08)));
if (DiskAccessMethod == 0 && (ChunkIndex + ChunkCount - 1) > HighestChunkIndex) // 0 = From begin, 2 = From end. We ignore chunks at end of disk. These contain secondairy GPT. if (DiskAccessMethod == 0 && (ChunkIndex + ChunkCount - 1) > HighestChunkIndex) // 0 = From begin, 2 = From end. We ignore chunks at end of disk. These contain secondairy GPT.
{ {
HighestChunkIndex = ChunkIndex + ChunkCount - 1; HighestChunkIndex = ChunkIndex + ChunkCount - 1;
} }
} }
WriteDescriptorEntryOffset += 8 + (LocationCount * 0x08); WriteDescriptorEntryOffset += 8 + (LocationCount * 0x08);
FFUChunkIndex += ChunkCount; FFUChunkIndex += ChunkCount;
} }
ChunkIndexes = new int?[HighestChunkIndex + 1]; ChunkIndexes = new int?[HighestChunkIndex + 1];
WriteDescriptorEntryOffset = 248 + ValidateDescriptorLength; WriteDescriptorEntryOffset = 248 + ValidateDescriptorLength;
FFUChunkIndex = 0; FFUChunkIndex = 0;
for (int i = 0; i < WriteDescriptorCount; i++) for (int i = 0; i < WriteDescriptorCount; i++)
{ {
LocationCount = ByteOperations.ReadUInt32(StoreHeader, WriteDescriptorEntryOffset + 0x00); LocationCount = ByteOperations.ReadUInt32(StoreHeader, WriteDescriptorEntryOffset + 0x00);
ChunkCount = ByteOperations.ReadInt32(StoreHeader, WriteDescriptorEntryOffset + 0x04); ChunkCount = ByteOperations.ReadInt32(StoreHeader, WriteDescriptorEntryOffset + 0x04);
for (int j = 0; j < LocationCount; j++) for (int j = 0; j < LocationCount; j++)
{ {
DiskAccessMethod = ByteOperations.ReadInt32(StoreHeader, (UInt32)(WriteDescriptorEntryOffset + 0x08 + (j * 0x08))); DiskAccessMethod = ByteOperations.ReadInt32(StoreHeader, (UInt32)(WriteDescriptorEntryOffset + 0x08 + (j * 0x08)));
ChunkIndex = ByteOperations.ReadInt32(StoreHeader, (UInt32)(WriteDescriptorEntryOffset + 0x0C + (j * 0x08))); ChunkIndex = ByteOperations.ReadInt32(StoreHeader, (UInt32)(WriteDescriptorEntryOffset + 0x0C + (j * 0x08)));
if (DiskAccessMethod == 0) // 0 = From begin, 2 = From end. We ignore chunks at end of disk. These contain secondairy GPT. if (DiskAccessMethod == 0) // 0 = From begin, 2 = From end. We ignore chunks at end of disk. These contain secondairy GPT.
{ {
for (int k = 0; k < ChunkCount; k++) for (int k = 0; k < ChunkCount; k++)
{ {
ChunkIndexes[ChunkIndex + k] = FFUChunkIndex + k; ChunkIndexes[ChunkIndex + k] = FFUChunkIndex + k;
} }
} }
} }
WriteDescriptorEntryOffset += 8 + (LocationCount * 0x08); WriteDescriptorEntryOffset += 8 + (LocationCount * 0x08);
FFUChunkIndex += ChunkCount; FFUChunkIndex += ChunkCount;
} }
byte[] GPTBuffer = GetSectors(0x01, 0x21); byte[] GPTBuffer = GetSectors(0x01, 0x21);
GPT = new GPT(GPTBuffer); GPT = new GPT(GPTBuffer);
HeaderSize = (UInt64)(SecurityHeader.Length + ImageHeader.Length + StoreHeader.Length); HeaderSize = (UInt64)(SecurityHeader.Length + ImageHeader.Length + StoreHeader.Length);
TotalChunkCount = (UInt64)FFUChunkIndex; TotalChunkCount = (UInt64)FFUChunkIndex;
PayloadSize = TotalChunkCount * (UInt64)ChunkSize; PayloadSize = TotalChunkCount * (UInt64)ChunkSize;
TotalSize = HeaderSize + PayloadSize; TotalSize = HeaderSize + PayloadSize;
if (TotalSize != (UInt64)FFUFile.Length) if (TotalSize != (UInt64)FFUFile.Length)
{ {
throw new WPinternalsException("Bad FFU file", "Bad FFU file: " + Path + "." + Environment.NewLine + "Expected size: " + TotalSize.ToString() + ". Actual size: " + FFUFile.Length + "."); throw new WPinternalsException("Bad FFU file", "Bad FFU file: " + Path + "." + Environment.NewLine + "Expected size: " + TotalSize.ToString() + ". Actual size: " + FFUFile.Length + ".");
} }
} }
catch (WPinternalsException) catch (WPinternalsException)
{ {
throw; throw;
} }
catch (Exception Ex) catch (Exception Ex)
{ {
throw new WPinternalsException("Bad FFU file", "Bad FFU file: " + Path + "." + Environment.NewLine + Ex.Message, Ex); throw new WPinternalsException("Bad FFU file", "Bad FFU file: " + Path + "." + Environment.NewLine + Ex.Message, Ex);
} }
finally finally
{ {
CloseFile(); CloseFile();
} }
} }
internal static bool IsFFU(string FileName) internal static bool IsFFU(string FileName)
{ {
bool Result = false; bool Result = false;
FileStream FFUFile = new(FileName, FileMode.Open, FileAccess.Read); FileStream FFUFile = new(FileName, FileMode.Open, FileAccess.Read);
byte[] Signature = new byte[0x10]; byte[] Signature = new byte[0x10];
FFUFile.Read(Signature, 0, 0x10); FFUFile.Read(Signature, 0, 0x10);
Result = ByteOperations.ReadAsciiString(Signature, 0x04, 0x0C) == "SignedImage "; Result = ByteOperations.ReadAsciiString(Signature, 0x04, 0x0C) == "SignedImage ";
FFUFile.Close(); FFUFile.Close();
return Result; return Result;
} }
private void OpenFile() private void OpenFile()
{ {
if (FFUFile == null) if (FFUFile == null)
{ {
FFUFile = new FileStream(Path, FileMode.Open, FileAccess.Read); FFUFile = new FileStream(Path, FileMode.Open, FileAccess.Read);
FileOpenCount = 0; FileOpenCount = 0;
} }
FileOpenCount++; FileOpenCount++;
} }
private void CloseFile() private void CloseFile()
{ {
FileOpenCount--; FileOpenCount--;
if (FileOpenCount == 0) if (FileOpenCount == 0)
{ {
FFUFile.Close(); FFUFile.Close();
FFUFile = null; FFUFile = null;
} }
} }
private void FileSeek(long Position) private void FileSeek(long Position)
{ {
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/2e67ca57-3556-4275-accd-58b7df30d424/unnecessary-filestreamseek-and-setting-filestreamposition-has-huge-effect-on-performance?forum=csharpgeneral // https://social.msdn.microsoft.com/Forums/vstudio/en-US/2e67ca57-3556-4275-accd-58b7df30d424/unnecessary-filestreamseek-and-setting-filestreamposition-has-huge-effect-on-performance?forum=csharpgeneral
if (FFUFile != null && FFUFile.Position != Position) if (FFUFile != null && FFUFile.Position != Position)
{ {
FFUFile.Seek(Position, SeekOrigin.Begin); FFUFile.Seek(Position, SeekOrigin.Begin);
} }
} }
internal UInt32 RoundUpToChunks(UInt32 Size) internal UInt32 RoundUpToChunks(UInt32 Size)
{ {
if ((Size % ChunkSize) > 0) if ((Size % ChunkSize) > 0)
{ {
return (UInt32)(((Size / ChunkSize) + 1) * ChunkSize); return (UInt32)(((Size / ChunkSize) + 1) * ChunkSize);
} }
else else
{ {
return Size; return Size;
} }
} }
internal UInt32 RoundDownToChunks(UInt32 Size) internal UInt32 RoundDownToChunks(UInt32 Size)
{ {
if ((Size % ChunkSize) > 0) if ((Size % ChunkSize) > 0)
{ {
return (UInt32)(Size / ChunkSize * ChunkSize); return (UInt32)(Size / ChunkSize * ChunkSize);
} }
else else
{ {
return Size; return Size;
} }
} }
internal byte[] GetSectors(int StartSector, int SectorCount) internal byte[] GetSectors(int StartSector, int SectorCount)
{ {
int FirstChunk = GetChunkIndexFromSectorIndex(StartSector); int FirstChunk = GetChunkIndexFromSectorIndex(StartSector);
int LastChunk = GetChunkIndexFromSectorIndex(StartSector + SectorCount - 1); int LastChunk = GetChunkIndexFromSectorIndex(StartSector + SectorCount - 1);
byte[] Buffer = new byte[ChunkSize]; byte[] Buffer = new byte[ChunkSize];
OpenFile(); OpenFile();
byte[] Result = new byte[SectorCount * 0x200]; byte[] Result = new byte[SectorCount * 0x200];
int ResultOffset = 0; int ResultOffset = 0;
for (int j = FirstChunk; j <= LastChunk; j++) for (int j = FirstChunk; j <= LastChunk; j++)
{ {
GetChunk(Buffer, j); GetChunk(Buffer, j);
int FirstSector = 0; int FirstSector = 0;
int LastSector = (ChunkSize / 0x200) - 1; int LastSector = (ChunkSize / 0x200) - 1;
if (j == FirstChunk) if (j == FirstChunk)
{ {
FirstSector = GetSectorNumberInChunkFromSectorIndex(StartSector); FirstSector = GetSectorNumberInChunkFromSectorIndex(StartSector);
} }
if (j == LastChunk) if (j == LastChunk)
{ {
LastSector = GetSectorNumberInChunkFromSectorIndex(StartSector + SectorCount - 1); LastSector = GetSectorNumberInChunkFromSectorIndex(StartSector + SectorCount - 1);
} }
int Offset = FirstSector * 0x200; int Offset = FirstSector * 0x200;
int Size = (LastSector - FirstSector + 1) * 0x200; int Size = (LastSector - FirstSector + 1) * 0x200;
System.Buffer.BlockCopy(Buffer, Offset, Result, ResultOffset, Size); System.Buffer.BlockCopy(Buffer, Offset, Result, ResultOffset, Size);
ResultOffset += Size; ResultOffset += Size;
} }
CloseFile(); CloseFile();
return Result; return Result;
} }
internal byte[] GetPartition(string Name) internal byte[] GetPartition(string Name)
{ {
Partition Target = GPT.Partitions.Find(p => string.Equals(p.Name, Name, StringComparison.CurrentCultureIgnoreCase)); Partition Target = GPT.Partitions.Find(p => string.Equals(p.Name, Name, StringComparison.CurrentCultureIgnoreCase));
if (Target == null) if (Target == null)
{ {
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
} }
return GetSectors((int)Target.FirstSector, (int)(Target.LastSector - Target.FirstSector + 1)); return GetSectors((int)Target.FirstSector, (int)(Target.LastSector - Target.FirstSector + 1));
} }
internal void WritePartition(string Name, string FilePath, bool Compress = false) internal void WritePartition(string Name, string FilePath, bool Compress = false)
{ {
WritePartition(Name, FilePath, null, null, Compress); WritePartition(Name, FilePath, null, null, Compress);
} }
internal void WritePartition(string Name, string FilePath, Action<int, TimeSpan?> ProgressUpdateCallback, bool Compress = false) internal void WritePartition(string Name, string FilePath, Action<int, TimeSpan?> ProgressUpdateCallback, bool Compress = false)
{ {
WritePartition(Name, FilePath, ProgressUpdateCallback, null, Compress); WritePartition(Name, FilePath, ProgressUpdateCallback, null, Compress);
} }
internal void WritePartition(string Name, string FilePath, ProgressUpdater UpdaterPerSector, bool Compress = false) internal void WritePartition(string Name, string FilePath, ProgressUpdater UpdaterPerSector, bool Compress = false)
{ {
WritePartition(Name, FilePath, null, UpdaterPerSector, Compress); WritePartition(Name, FilePath, null, UpdaterPerSector, Compress);
} }
private void WritePartition(string Name, string FilePath, Action<int, TimeSpan?> ProgressUpdateCallback, ProgressUpdater UpdaterPerSector, bool Compress = false) private void WritePartition(string Name, string FilePath, Action<int, TimeSpan?> ProgressUpdateCallback, ProgressUpdater UpdaterPerSector, bool Compress = false)
{ {
Partition Target = GPT.Partitions.Find(p => string.Equals(p.Name, Name, StringComparison.CurrentCultureIgnoreCase)); Partition Target = GPT.Partitions.Find(p => string.Equals(p.Name, Name, StringComparison.CurrentCultureIgnoreCase));
if (Target == null) if (Target == null)
{ {
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
} }
int FirstChunk = GetChunkIndexFromSectorIndex((int)Target.FirstSector); int FirstChunk = GetChunkIndexFromSectorIndex((int)Target.FirstSector);
int LastChunk = GetChunkIndexFromSectorIndex((int)Target.LastSector); int LastChunk = GetChunkIndexFromSectorIndex((int)Target.LastSector);
ProgressUpdater Updater = UpdaterPerSector; ProgressUpdater Updater = UpdaterPerSector;
if ((Updater == null) && (ProgressUpdateCallback != null)) if ((Updater == null) && (ProgressUpdateCallback != null))
{ {
Updater = new ProgressUpdater(Target.LastSector - Target.FirstSector + 1, ProgressUpdateCallback); Updater = new ProgressUpdater(Target.LastSector - Target.FirstSector + 1, ProgressUpdateCallback);
} }
byte[] Buffer = new byte[ChunkSize]; byte[] Buffer = new byte[ChunkSize];
OpenFile(); OpenFile();
FileStream OutputFile = new(FilePath, FileMode.Create, FileAccess.Write); FileStream OutputFile = new(FilePath, FileMode.Create, FileAccess.Write);
Stream OutStream = OutputFile; Stream OutStream = OutputFile;
// We use gzip compression // We use gzip compression
// //
// LZMA is about 60 times slower (compression is twice as good, but compressed size is already really small, so it doesnt matter much) // LZMA is about 60 times slower (compression is twice as good, but compressed size is already really small, so it doesnt matter much)
// OutStream = new LZMACompressionStream(OutputFile, System.IO.Compression.CompressionMode.Compress, false); // OutStream = new LZMACompressionStream(OutputFile, System.IO.Compression.CompressionMode.Compress, false);
// //
// DeflateStream is a raw compression stream without recognizable header // DeflateStream is a raw compression stream without recognizable header
// Deflate has almost no performance penalty // Deflate has almost no performance penalty
// OutStream = new DeflateStream(OutputFile, CompressionLevel.Optimal, false); // OutStream = new DeflateStream(OutputFile, CompressionLevel.Optimal, false);
// //
// GZip can be recognized. It always starts with 1F 8B 08 (1F 8B is the magic value, 08 is the Deflate compression method) // GZip can be recognized. It always starts with 1F 8B 08 (1F 8B is the magic value, 08 is the Deflate compression method)
// With GZip compression, dump time goes from 1m to 1m37s. So that doesnt matter much. // With GZip compression, dump time goes from 1m to 1m37s. So that doesnt matter much.
if (Compress) if (Compress)
{ {
OutStream = new CompressedStream(OutputFile, (Target.LastSector - Target.FirstSector + 1) * 0x200); OutStream = new CompressedStream(OutputFile, (Target.LastSector - Target.FirstSector + 1) * 0x200);
} }
for (int j = FirstChunk; j <= LastChunk; j++) for (int j = FirstChunk; j <= LastChunk; j++)
{ {
GetChunk(Buffer, j); GetChunk(Buffer, j);
int FirstSector = 0; int FirstSector = 0;
int LastSector = (ChunkSize / 0x200) - 1; int LastSector = (ChunkSize / 0x200) - 1;
if (j == FirstChunk) if (j == FirstChunk)
{ {
FirstSector = GetSectorNumberInChunkFromSectorIndex((int)Target.FirstSector); FirstSector = GetSectorNumberInChunkFromSectorIndex((int)Target.FirstSector);
} }
if (j == LastChunk) if (j == LastChunk)
{ {
LastSector = GetSectorNumberInChunkFromSectorIndex((int)Target.LastSector); LastSector = GetSectorNumberInChunkFromSectorIndex((int)Target.LastSector);
} }
int Offset = FirstSector * 0x200; int Offset = FirstSector * 0x200;
int Size = (LastSector - FirstSector + 1) * 0x200; int Size = (LastSector - FirstSector + 1) * 0x200;
OutStream.Write(Buffer, Offset, Size); OutStream.Write(Buffer, Offset, Size);
Updater?.IncreaseProgress((UInt64)(ChunkSize / 0x200)); Updater?.IncreaseProgress((UInt64)(ChunkSize / 0x200));
} }
OutStream.Close(); OutStream.Close();
CloseFile(); CloseFile();
} }
private byte[] GetChunk(int ChunkIndex) private byte[] GetChunk(int ChunkIndex)
{ {
long BaseOffset = (long)SecurityHeader.Length + ImageHeader.Length + StoreHeader.Length; long BaseOffset = (long)SecurityHeader.Length + ImageHeader.Length + StoreHeader.Length;
if (ChunkIndexes[ChunkIndex] == null) if (ChunkIndexes[ChunkIndex] == null)
{ {
return new byte[ChunkSize]; return new byte[ChunkSize];
} }
else else
{ {
OpenFile(); OpenFile();
FileSeek(BaseOffset + ((long)ChunkIndexes[ChunkIndex] * ChunkSize)); FileSeek(BaseOffset + ((long)ChunkIndexes[ChunkIndex] * ChunkSize));
byte[] Chunk = new byte[ChunkSize]; byte[] Chunk = new byte[ChunkSize];
FFUFile.Read(Chunk, 0, ChunkSize); FFUFile.Read(Chunk, 0, ChunkSize);
CloseFile(); CloseFile();
return Chunk; return Chunk;
} }
} }
private void GetChunk(byte[] Chunk, int ChunkIndex) private void GetChunk(byte[] Chunk, int ChunkIndex)
{ {
long BaseOffset = SecurityHeader.Length + ImageHeader.Length + StoreHeader.Length; long BaseOffset = SecurityHeader.Length + ImageHeader.Length + StoreHeader.Length;
if (ChunkIndexes[ChunkIndex] == null) if (ChunkIndexes[ChunkIndex] == null)
{ {
Array.Clear(Chunk, 0, ChunkSize); Array.Clear(Chunk, 0, ChunkSize);
} }
else else
{ {
OpenFile(); OpenFile();
FileSeek(BaseOffset + ((long)ChunkIndexes[ChunkIndex] * ChunkSize)); FileSeek(BaseOffset + ((long)ChunkIndexes[ChunkIndex] * ChunkSize));
FFUFile.Read(Chunk, 0, ChunkSize); FFUFile.Read(Chunk, 0, ChunkSize);
CloseFile(); CloseFile();
} }
} }
private int GetChunkIndexFromSectorIndex(int SectorIndex) private int GetChunkIndexFromSectorIndex(int SectorIndex)
{ {
int SectorsPerChunk = ChunkSize / 0x200; int SectorsPerChunk = ChunkSize / 0x200;
return SectorIndex / SectorsPerChunk; return SectorIndex / SectorsPerChunk;
} }
private int GetSectorNumberInChunkFromSectorIndex(int SectorIndex) private int GetSectorNumberInChunkFromSectorIndex(int SectorIndex)
{ {
int SectorsPerChunk = ChunkSize / 0x200; int SectorsPerChunk = ChunkSize / 0x200;
return SectorIndex % SectorsPerChunk; return SectorIndex % SectorsPerChunk;
} }
internal bool IsPartitionPresentInFFU(string PartitionName) internal bool IsPartitionPresentInFFU(string PartitionName)
{ {
Partition Target = GPT.GetPartition(PartitionName); Partition Target = GPT.GetPartition(PartitionName);
if (Target == null) if (Target == null)
{ {
throw new InvalidOperationException("Partitionname is not found!"); throw new InvalidOperationException("Partitionname is not found!");
} }
int ChunkIndex = GetChunkIndexFromSectorIndex((int)Target.FirstSector); int ChunkIndex = GetChunkIndexFromSectorIndex((int)Target.FirstSector);
return ChunkIndexes[ChunkIndex] != null; return ChunkIndexes[ChunkIndex] != null;
} }
private int GetChunkIndexFromSectorIndex(ulong p) private int GetChunkIndexFromSectorIndex(ulong p)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
internal string GetFirmwareVersion() internal string GetFirmwareVersion()
{ {
string Result = null; string Result = null;
Partition Plat = GPT.GetPartition("PLAT"); Partition Plat = GPT.GetPartition("PLAT");
if (Plat != null) if (Plat != null)
{ {
byte[] Data = GetPartition("PLAT"); byte[] Data = GetPartition("PLAT");
uint? Offset = ByteOperations.FindAscii(Data, "SWVERSION="); uint? Offset = ByteOperations.FindAscii(Data, "SWVERSION=");
if (Offset != null) if (Offset != null)
{ {
uint Start = (uint)Offset + 10; uint Start = (uint)Offset + 10;
uint Length = (uint)ByteOperations.FindPattern(Data, Start, 0x100, new byte[] { 0x00 }, null, null) - Start; uint Length = (uint)ByteOperations.FindPattern(Data, Start, 0x100, [0x00], null, null) - Start;
uint? Offset0D = ByteOperations.FindPattern(Data, Start, 0x100, new byte[] { 0x0D }, null, null); uint? Offset0D = ByteOperations.FindPattern(Data, Start, 0x100, [0x0D], null, null);
if ((Offset0D != null) && (Offset0D < (Start + Length))) if ((Offset0D != null) && (Offset0D < (Start + Length)))
{ {
Length = (uint)Offset0D - Start; Length = (uint)Offset0D - Start;
} }
Result = ByteOperations.ReadAsciiString(Data, Start, Length); Result = ByteOperations.ReadAsciiString(Data, Start, Length);
} }
} }
return Result; return Result;
} }
internal string GetOSVersion() internal string GetOSVersion()
{ {
byte[] efiesp = GetPartition("EFIESP"); byte[] efiesp = GetPartition("EFIESP");
MemoryStream s = new(efiesp); MemoryStream s = new(efiesp);
DiscUtils.Fat.FatFileSystem fs = new(s); DiscUtils.Fat.FatFileSystem fs = new(s);
Stream mss = fs.OpenFile(@"\Windows\System32\Boot\mobilestartup.efi", FileMode.Open, FileAccess.Read); Stream mss = fs.OpenFile(@"\Windows\System32\Boot\mobilestartup.efi", FileMode.Open, FileAccess.Read);
MemoryStream msms = new(); MemoryStream msms = new();
mss.CopyTo(msms); mss.CopyTo(msms);
byte[] mobilestartup = msms.ToArray(); byte[] mobilestartup = msms.ToArray();
Version OSVersion = PE.GetProductVersion(mobilestartup); Version OSVersion = PE.GetProductVersion(mobilestartup);
s.Close(); s.Close();
return OSVersion.ToString(); return OSVersion.ToString();
} }
} }
} }
File diff suppressed because it is too large Load Diff
+312 -312
View File
@@ -1,312 +1,312 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
// SevenZip LZMA SDK: http://www.7-zip.org/download.html // SevenZip LZMA SDK: http://www.7-zip.org/download.html
// Usage: http://stackoverflow.com/questions/7646328/how-to-use-the-7z-sdk-to-compress-and-decompress-a-file // Usage: http://stackoverflow.com/questions/7646328/how-to-use-the-7z-sdk-to-compress-and-decompress-a-file
using SevenZip; using SevenZip;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
namespace WPinternals namespace WPinternals
{ {
internal static class LZMA internal static class LZMA
{ {
internal static byte[] Decompress(byte[] Input, UInt32 Offset, UInt32 InputSize) internal static byte[] Decompress(byte[] Input, UInt32 Offset, UInt32 InputSize)
{ {
byte[] Properties = new byte[5]; byte[] Properties = new byte[5];
Buffer.BlockCopy(Input, (int)Offset, Properties, 0, 5); Buffer.BlockCopy(Input, (int)Offset, Properties, 0, 5);
UInt64 OutputSize = ByteOperations.ReadUInt64(Input, Offset + 5); UInt64 OutputSize = ByteOperations.ReadUInt64(Input, Offset + 5);
SevenZip.Compression.LZMA.Decoder Coder = new(); SevenZip.Compression.LZMA.Decoder Coder = new();
Coder.SetDecoderProperties(Properties); Coder.SetDecoderProperties(Properties);
MemoryStream InStream = new(Input, (int)Offset + 0x0D, (int)InputSize - 0x0D); MemoryStream InStream = new(Input, (int)Offset + 0x0D, (int)InputSize - 0x0D);
byte[] Output = new byte[OutputSize]; byte[] Output = new byte[OutputSize];
MemoryStream OutStream = new(Output, true); MemoryStream OutStream = new(Output, true);
Coder.Code(InStream, OutStream, (Int64)InputSize - 0x0D, (Int64)OutputSize, null); Coder.Code(InStream, OutStream, (Int64)InputSize - 0x0D, (Int64)OutputSize, null);
OutStream.Flush(); OutStream.Flush();
OutStream.Close(); OutStream.Close();
InStream.Close(); InStream.Close();
return Output; return Output;
} }
internal static byte[] Compress(byte[] Input, UInt32 Offset, UInt32 InputSize) internal static byte[] Compress(byte[] Input, UInt32 Offset, UInt32 InputSize)
{ {
SevenZip.Compression.LZMA.Encoder Coder = new(); SevenZip.Compression.LZMA.Encoder Coder = new();
MemoryStream InStream = new(Input, (int)Offset, (int)InputSize); MemoryStream InStream = new(Input, (int)Offset, (int)InputSize);
MemoryStream OutStream = new(); MemoryStream OutStream = new();
// Write the encoder properties // Write the encoder properties
Coder.WriteCoderProperties(OutStream); Coder.WriteCoderProperties(OutStream);
// Write the decompressed file size // Write the decompressed file size
OutStream.Write(BitConverter.GetBytes(InStream.Length), 0, 8); OutStream.Write(BitConverter.GetBytes(InStream.Length), 0, 8);
// Encode the file // Encode the file
Coder.Code(InStream, OutStream, InputSize, -1, null); Coder.Code(InStream, OutStream, InputSize, -1, null);
byte[] Output = new byte[OutStream.Length]; byte[] Output = new byte[OutStream.Length];
Buffer.BlockCopy(OutStream.GetBuffer(), 0, Output, 0, (int)OutStream.Length); Buffer.BlockCopy(OutStream.GetBuffer(), 0, Output, 0, (int)OutStream.Length);
OutStream.Flush(); OutStream.Flush();
OutStream.Close(); OutStream.Close();
InStream.Close(); InStream.Close();
return Output; return Output;
} }
} }
public class LZMACompressionStream : Stream public class LZMACompressionStream : Stream
{ {
private readonly SevenZip.Compression.LZMA.Encoder Encoder = null; private readonly SevenZip.Compression.LZMA.Encoder Encoder = null;
private readonly SevenZip.Compression.LZMA.Decoder Decoder = null; private readonly SevenZip.Compression.LZMA.Decoder Decoder = null;
private readonly PumpStream BufferStream; private readonly PumpStream BufferStream;
private readonly Stream stream; private readonly Stream stream;
private readonly bool LeaveOpen; private readonly bool LeaveOpen;
private readonly Thread WorkThread; private readonly Thread WorkThread;
private readonly CancellationTokenSource source; private readonly CancellationTokenSource source;
private readonly CancellationToken token; private readonly CancellationToken token;
public LZMACompressionStream(Stream stream, CompressionMode mode, bool LeaveOpen, int DictionarySize, int PosStateBits, public LZMACompressionStream(Stream stream, CompressionMode mode, bool LeaveOpen, int DictionarySize, int PosStateBits,
int LitContextBits, int LitPosBits, int Algorithm, int NumFastBytes, string MatchFinder, bool EndMarker) int LitContextBits, int LitPosBits, int Algorithm, int NumFastBytes, string MatchFinder, bool EndMarker)
{ {
this.stream = stream; this.stream = stream;
this.LeaveOpen = LeaveOpen; this.LeaveOpen = LeaveOpen;
BufferStream = new PumpStream(); BufferStream = new PumpStream();
source = new CancellationTokenSource(); source = new CancellationTokenSource();
token = source.Token; token = source.Token;
if (mode == CompressionMode.Compress) if (mode == CompressionMode.Compress)
{ {
Encoder = new SevenZip.Compression.LZMA.Encoder(); Encoder = new SevenZip.Compression.LZMA.Encoder();
if (DictionarySize != 0) if (DictionarySize != 0)
{ {
Encoder.SetCoderProperties( Encoder.SetCoderProperties(
new CoderPropID[8] {CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits, [CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits,
CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker}, CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker],
new object[8] { DictionarySize, PosStateBits, LitContextBits, LitPosBits, Algorithm, NumFastBytes, MatchFinder, EndMarker }); [DictionarySize, PosStateBits, LitContextBits, LitPosBits, Algorithm, NumFastBytes, MatchFinder, EndMarker]);
} }
Encoder.WriteCoderProperties(stream); Encoder.WriteCoderProperties(stream);
WorkThread = new Thread(new ThreadStart(Encode)); WorkThread = new Thread(new ThreadStart(Encode));
} }
else else
{ {
byte[] DecoderProperties = new byte[5]; byte[] DecoderProperties = new byte[5];
stream.Read(DecoderProperties, 0, 5); stream.Read(DecoderProperties, 0, 5);
Decoder = new SevenZip.Compression.LZMA.Decoder(); Decoder = new SevenZip.Compression.LZMA.Decoder();
Decoder.SetDecoderProperties(DecoderProperties); Decoder.SetDecoderProperties(DecoderProperties);
WorkThread = new Thread(new ThreadStart(Decode)); WorkThread = new Thread(new ThreadStart(Decode));
} }
WorkThread.Start(); WorkThread.Start();
} }
public LZMACompressionStream(Stream stream, CompressionMode mode, bool LeaveOpen) public LZMACompressionStream(Stream stream, CompressionMode mode, bool LeaveOpen)
: this(stream, mode, LeaveOpen, 0, 0, 0, 0, 0, 0, null, false) : this(stream, mode, LeaveOpen, 0, 0, 0, 0, 0, 0, null, false)
{ {
} }
private void Encode() private void Encode()
{ {
Encoder.Code(BufferStream, stream, -1, -1, null, token); Encoder.Code(BufferStream, stream, -1, -1, null, token);
if (!LeaveOpen) if (!LeaveOpen)
{ {
stream.Close(); stream.Close();
} }
} }
private void Decode() private void Decode()
{ {
Decoder.Code(stream, BufferStream, -1, -1, null, token); Decoder.Code(stream, BufferStream, -1, -1, null, token);
BufferStream.Close(); BufferStream.Close();
if (!LeaveOpen) if (!LeaveOpen)
{ {
stream.Close(); stream.Close();
} }
} }
public override void Close() public override void Close()
{ {
if (Encoder != null) if (Encoder != null)
{ {
BufferStream.Close(); BufferStream.Close();
} }
else if (WorkThread.IsAlive) else if (WorkThread.IsAlive)
{ {
source?.Cancel(); source?.Cancel();
WorkThread.Join(); WorkThread.Join();
} }
} }
public override int Read(byte[] buffer, int offset, int count) public override int Read(byte[] buffer, int offset, int count)
{ {
return BufferStream.Read(buffer, offset, count); return BufferStream.Read(buffer, offset, count);
} }
public override void Write(byte[] buffer, int offset, int count) public override void Write(byte[] buffer, int offset, int count)
{ {
BufferStream.Write(buffer, offset, count); BufferStream.Write(buffer, offset, count);
} }
public override bool CanRead { get { return Decoder != null; } } public override bool CanRead { get { return Decoder != null; } }
public override bool CanSeek { get { return false; } } public override bool CanSeek { get { return false; } }
public override bool CanWrite { get { return Encoder != null; } } public override bool CanWrite { get { return Encoder != null; } }
public override void Flush() { } public override void Flush() { }
public override long Length { get { return 0; } } public override long Length { get { return 0; } }
public override long Position { get { return 0; } set { } } public override long Position { get { return 0; } set { } }
public override long Seek(long offset, SeekOrigin origin) { return 0; } public override long Seek(long offset, SeekOrigin origin) { return 0; }
public override void SetLength(long value) { } public override void SetLength(long value) { }
} }
public class PumpStream : Stream public class PumpStream : Stream
{ {
private readonly Queue<byte[]> BufferQueue; private readonly Queue<byte[]> BufferQueue;
private int BufferOffset; private int BufferOffset;
private readonly long MaxBufferSize; private readonly long MaxBufferSize;
private long BufferSize; private long BufferSize;
private bool Closed; private bool Closed;
private bool EOF; private bool EOF;
public PumpStream(long MaxBufferSize, int ReadTimeout, int WriteTimeout) public PumpStream(long MaxBufferSize, int ReadTimeout, int WriteTimeout)
{ {
this.MaxBufferSize = MaxBufferSize; this.MaxBufferSize = MaxBufferSize;
this.ReadTimeout = ReadTimeout; this.ReadTimeout = ReadTimeout;
this.WriteTimeout = WriteTimeout; this.WriteTimeout = WriteTimeout;
BufferQueue = new Queue<byte[]>(); BufferQueue = new Queue<byte[]>();
BufferOffset = 0; BufferOffset = 0;
BufferSize = 0; BufferSize = 0;
Closed = false; Closed = false;
EOF = false; EOF = false;
} }
public PumpStream() public PumpStream()
: this(16777216, Timeout.Infinite, Timeout.Infinite) : this(16777216, Timeout.Infinite, Timeout.Infinite)
{ {
} }
public new void Dispose() public new void Dispose()
{ {
BufferQueue.Clear(); BufferQueue.Clear();
} }
public override void Close() public override void Close()
{ {
Closed = true; Closed = true;
lock (BufferQueue) lock (BufferQueue)
{ {
Monitor.Pulse(BufferQueue); Monitor.Pulse(BufferQueue);
} }
} }
public override int Read(byte[] buffer, int offset, int count) public override int Read(byte[] buffer, int offset, int count)
{ {
int BytesRead = 0; int BytesRead = 0;
lock (BufferQueue) lock (BufferQueue)
{ {
while (BytesRead < count && !EOF) while (BytesRead < count && !EOF)
{ {
if (BufferQueue.Count > 0) if (BufferQueue.Count > 0)
{ {
byte[] b = BufferQueue.Peek(); byte[] b = BufferQueue.Peek();
if ((b.Length - BufferOffset) <= (count - BytesRead)) if ((b.Length - BufferOffset) <= (count - BytesRead))
{ {
Array.Copy(b, BufferOffset, buffer, offset + BytesRead, b.Length - BufferOffset); Array.Copy(b, BufferOffset, buffer, offset + BytesRead, b.Length - BufferOffset);
BufferQueue.Dequeue(); BufferQueue.Dequeue();
BufferSize -= b.Length; BufferSize -= b.Length;
Monitor.Pulse(BufferQueue); Monitor.Pulse(BufferQueue);
BytesRead += b.Length - BufferOffset; BytesRead += b.Length - BufferOffset;
BufferOffset = 0; BufferOffset = 0;
} }
else else
{ {
Array.Copy(b, BufferOffset, buffer, offset + BytesRead, count - BytesRead); Array.Copy(b, BufferOffset, buffer, offset + BytesRead, count - BytesRead);
BufferOffset += count - BytesRead; BufferOffset += count - BytesRead;
BytesRead += count - BytesRead; BytesRead += count - BytesRead;
} }
} }
else else
{ {
if (!Closed) if (!Closed)
{ {
if (!Monitor.Wait(BufferQueue, ReadTimeout)) if (!Monitor.Wait(BufferQueue, ReadTimeout))
{ {
throw new IOException("Could not read from stream: Timeout expired waiting for data to be written."); throw new IOException("Could not read from stream: Timeout expired waiting for data to be written.");
} }
} }
else else
{ {
EOF = true; EOF = true;
} }
} }
} }
} }
return BytesRead; return BytesRead;
} }
public override void Write(byte[] buffer, int offset, int count) public override void Write(byte[] buffer, int offset, int count)
{ {
lock (BufferQueue) lock (BufferQueue)
{ {
while (BufferSize >= MaxBufferSize) while (BufferSize >= MaxBufferSize)
{ {
if (!Monitor.Wait(BufferQueue, WriteTimeout)) if (!Monitor.Wait(BufferQueue, WriteTimeout))
{ {
throw new IOException("Could not write to stream: Timeout expired waiting for data to be read."); throw new IOException("Could not write to stream: Timeout expired waiting for data to be read.");
} }
} }
byte[] b = new byte[count]; byte[] b = new byte[count];
Array.Copy(buffer, offset, b, 0, count); Array.Copy(buffer, offset, b, 0, count);
BufferQueue.Enqueue(b); BufferQueue.Enqueue(b);
BufferSize += b.Length; BufferSize += b.Length;
Monitor.Pulse(BufferQueue); Monitor.Pulse(BufferQueue);
} }
} }
public override int ReadTimeout { get; set; } public override int ReadTimeout { get; set; }
public override int WriteTimeout { get; set; } public override int WriteTimeout { get; set; }
public override bool CanRead { get { return true; } } public override bool CanRead { get { return true; } }
public override bool CanSeek { get { return false; } } public override bool CanSeek { get { return false; } }
public override bool CanWrite { get { return true; } } public override bool CanWrite { get { return true; } }
public override void Flush() { } public override void Flush() { }
public override long Length { get { return 0; } } public override long Length { get { return 0; } }
public override long Position { get { return 0; } set { } } public override long Position { get { return 0; } set { } }
public override long Seek(long offset, SeekOrigin origin) { return 0; } public override long Seek(long offset, SeekOrigin origin) { return 0; }
public override void SetLength(long value) { } public override void SetLength(long value) { }
} }
} }
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,302 +1,302 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using Microsoft.Win32.SafeHandles; using Microsoft.Win32.SafeHandles;
using System; using System;
using System.Runtime.ConstrainedExecution; using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security; using System.Security;
namespace WPinternals namespace WPinternals
{ {
[Flags] [Flags]
internal enum TokenAccessLevels internal enum TokenAccessLevels
{ {
AssignPrimary = 0x00000001, AssignPrimary = 0x00000001,
Duplicate = 0x00000002, Duplicate = 0x00000002,
Impersonate = 0x00000004, Impersonate = 0x00000004,
Query = 0x00000008, Query = 0x00000008,
QuerySource = 0x00000010, QuerySource = 0x00000010,
AdjustPrivileges = 0x00000020, AdjustPrivileges = 0x00000020,
AdjustGroups = 0x00000040, AdjustGroups = 0x00000040,
AdjustDefault = 0x00000080, AdjustDefault = 0x00000080,
AdjustSessionId = 0x00000100, AdjustSessionId = 0x00000100,
Read = 0x00020000 | Query, Read = 0x00020000 | Query,
Write = 0x00020000 | AdjustPrivileges | AdjustGroups | AdjustDefault, Write = 0x00020000 | AdjustPrivileges | AdjustGroups | AdjustDefault,
AllAccess = 0x000F0000 | AllAccess = 0x000F0000 |
AssignPrimary | AssignPrimary |
Duplicate | Duplicate |
Impersonate | Impersonate |
Query | Query |
QuerySource | QuerySource |
AdjustPrivileges | AdjustPrivileges |
AdjustGroups | AdjustGroups |
AdjustDefault | AdjustDefault |
AdjustSessionId, AdjustSessionId,
MaximumAllowed = 0x02000000 MaximumAllowed = 0x02000000
} }
internal enum SecurityImpersonationLevel internal enum SecurityImpersonationLevel
{ {
Anonymous = 0, Anonymous = 0,
Identification = 1, Identification = 1,
Impersonation = 2, Impersonation = 2,
Delegation = 3, Delegation = 3,
} }
internal enum TokenType internal enum TokenType
{ {
Primary = 1, Primary = 1,
Impersonation = 2, Impersonation = 2,
} }
internal enum EMoveMethod : uint internal enum EMoveMethod : uint
{ {
Begin = 0, Begin = 0,
Current = 1, Current = 1,
End = 2 End = 2
} }
internal sealed class NativeMethods internal sealed class NativeMethods
{ {
internal const uint SE_PRIVILEGE_DISABLED = 0x00000000; internal const uint SE_PRIVILEGE_DISABLED = 0x00000000;
internal const uint SE_PRIVILEGE_ENABLED = 0x00000002; internal const uint SE_PRIVILEGE_ENABLED = 0x00000002;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct LUID internal struct LUID
{ {
internal uint LowPart; internal uint LowPart;
internal uint HighPart; internal uint HighPart;
} }
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct LUID_AND_ATTRIBUTES internal struct LUID_AND_ATTRIBUTES
{ {
internal LUID Luid; internal LUID Luid;
internal uint Attributes; internal uint Attributes;
} }
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct TOKEN_PRIVILEGE internal struct TOKEN_PRIVILEGE
{ {
internal uint PrivilegeCount; internal uint PrivilegeCount;
internal LUID_AND_ATTRIBUTES Privilege; internal LUID_AND_ATTRIBUTES Privilege;
} }
internal const string ADVAPI32 = "advapi32.dll"; internal const string ADVAPI32 = "advapi32.dll";
internal const string KERNEL32 = "kernel32.dll"; internal const string KERNEL32 = "kernel32.dll";
internal const int ERROR_SUCCESS = 0x0; internal const int ERROR_SUCCESS = 0x0;
internal const int ERROR_ACCESS_DENIED = 0x5; internal const int ERROR_ACCESS_DENIED = 0x5;
internal const int ERROR_NOT_ENOUGH_MEMORY = 0x8; internal const int ERROR_NOT_ENOUGH_MEMORY = 0x8;
internal const int ERROR_NO_TOKEN = 0x3f0; internal const int ERROR_NO_TOKEN = 0x3f0;
internal const int ERROR_NOT_ALL_ASSIGNED = 0x514; internal const int ERROR_NOT_ALL_ASSIGNED = 0x514;
internal const int ERROR_NO_SUCH_PRIVILEGE = 0x521; internal const int ERROR_NO_SUCH_PRIVILEGE = 0x521;
internal const int ERROR_CANT_OPEN_ANONYMOUS = 0x543; internal const int ERROR_CANT_OPEN_ANONYMOUS = 0x543;
[DllImport( [DllImport(
KERNEL32, KERNEL32,
SetLastError = true)] SetLastError = true)]
internal static extern bool CloseHandle(IntPtr handle); internal static extern bool CloseHandle(IntPtr handle);
[DllImport( [DllImport(
ADVAPI32, ADVAPI32,
CharSet = CharSet.Unicode, CharSet = CharSet.Unicode,
SetLastError = true)] SetLastError = true)]
internal static extern bool AdjustTokenPrivileges( internal static extern bool AdjustTokenPrivileges(
[In] SafeTokenHandle TokenHandle, [In] SafeTokenHandle TokenHandle,
[In] bool DisableAllPrivileges, [In] bool DisableAllPrivileges,
[In] ref TOKEN_PRIVILEGE NewState, [In] ref TOKEN_PRIVILEGE NewState,
[In] uint BufferLength, [In] uint BufferLength,
[In, Out] ref TOKEN_PRIVILEGE PreviousState, [In, Out] ref TOKEN_PRIVILEGE PreviousState,
[In, Out] ref uint ReturnLength); [In, Out] ref uint ReturnLength);
[DllImport( [DllImport(
ADVAPI32, ADVAPI32,
CharSet = CharSet.Auto, CharSet = CharSet.Auto,
SetLastError = true)] SetLastError = true)]
internal static extern internal static extern
bool RevertToSelf(); bool RevertToSelf();
[DllImport( [DllImport(
ADVAPI32, ADVAPI32,
EntryPoint = "LookupPrivilegeValueW", EntryPoint = "LookupPrivilegeValueW",
CharSet = CharSet.Auto, CharSet = CharSet.Auto,
SetLastError = true)] SetLastError = true)]
internal static extern internal static extern
bool LookupPrivilegeValue( bool LookupPrivilegeValue(
[In] string lpSystemName, [In] string lpSystemName,
[In] string lpName, [In] string lpName,
[In, Out] ref LUID Luid); [In, Out] ref LUID Luid);
[DllImport( [DllImport(
KERNEL32, KERNEL32,
CharSet = CharSet.Auto, CharSet = CharSet.Auto,
SetLastError = true)] SetLastError = true)]
internal static extern internal static extern
IntPtr GetCurrentProcess(); IntPtr GetCurrentProcess();
[DllImport( [DllImport(
KERNEL32, KERNEL32,
CharSet = CharSet.Auto, CharSet = CharSet.Auto,
SetLastError = true)] SetLastError = true)]
internal static extern internal static extern
IntPtr GetCurrentThread(); IntPtr GetCurrentThread();
[DllImport( [DllImport(
ADVAPI32, ADVAPI32,
CharSet = CharSet.Unicode, CharSet = CharSet.Unicode,
SetLastError = true)] SetLastError = true)]
internal static extern internal static extern
bool OpenProcessToken( bool OpenProcessToken(
[In] IntPtr ProcessToken, [In] IntPtr ProcessToken,
[In] TokenAccessLevels DesiredAccess, [In] TokenAccessLevels DesiredAccess,
[In, Out] ref SafeTokenHandle TokenHandle); [In, Out] ref SafeTokenHandle TokenHandle);
[DllImport [DllImport
(ADVAPI32, (ADVAPI32,
CharSet = CharSet.Unicode, CharSet = CharSet.Unicode,
SetLastError = true)] SetLastError = true)]
internal static extern internal static extern
bool OpenThreadToken( bool OpenThreadToken(
[In] IntPtr ThreadToken, [In] IntPtr ThreadToken,
[In] TokenAccessLevels DesiredAccess, [In] TokenAccessLevels DesiredAccess,
[In] bool OpenAsSelf, [In] bool OpenAsSelf,
[In, Out] ref SafeTokenHandle TokenHandle); [In, Out] ref SafeTokenHandle TokenHandle);
[DllImport [DllImport
(ADVAPI32, (ADVAPI32,
CharSet = CharSet.Unicode, CharSet = CharSet.Unicode,
SetLastError = true)] SetLastError = true)]
internal static extern internal static extern
bool DuplicateTokenEx( bool DuplicateTokenEx(
[In] SafeTokenHandle ExistingToken, [In] SafeTokenHandle ExistingToken,
[In] TokenAccessLevels DesiredAccess, [In] TokenAccessLevels DesiredAccess,
[In] IntPtr TokenAttributes, [In] IntPtr TokenAttributes,
[In] SecurityImpersonationLevel ImpersonationLevel, [In] SecurityImpersonationLevel ImpersonationLevel,
[In] TokenType TokenType, [In] TokenType TokenType,
[In, Out] ref SafeTokenHandle NewToken); [In, Out] ref SafeTokenHandle NewToken);
[DllImport [DllImport
(ADVAPI32, (ADVAPI32,
CharSet = CharSet.Unicode, CharSet = CharSet.Unicode,
SetLastError = true)] SetLastError = true)]
internal static extern internal static extern
bool SetThreadToken( bool SetThreadToken(
[In] IntPtr Thread, [In] IntPtr Thread,
[In] SafeTokenHandle Token); [In] SafeTokenHandle Token);
internal const uint FILE_SHARE_READ = 0x00000001; internal const uint FILE_SHARE_READ = 0x00000001;
internal const uint FILE_SHARE_WRITE = 0x00000002; internal const uint FILE_SHARE_WRITE = 0x00000002;
internal const uint FILE_SHARE_DELETE = 0x00000004; internal const uint FILE_SHARE_DELETE = 0x00000004;
internal const uint OPEN_EXISTING = 3; internal const uint OPEN_EXISTING = 3;
internal const uint GENERIC_READ = 0x80000000; internal const uint GENERIC_READ = 0x80000000;
internal const uint GENERIC_WRITE = 0x40000000; internal const uint GENERIC_WRITE = 0x40000000;
internal const uint FILE_FLAG_WRITE_THROUGH = 0x80000000; internal const uint FILE_FLAG_WRITE_THROUGH = 0x80000000;
internal const uint FILE_FLAG_NO_BUFFERING = 0x20000000; internal const uint FILE_FLAG_NO_BUFFERING = 0x20000000;
internal const uint FILE_READ_ATTRIBUTES = 0x0080; internal const uint FILE_READ_ATTRIBUTES = 0x0080;
internal const uint FILE_WRITE_ATTRIBUTES = 0x0100; internal const uint FILE_WRITE_ATTRIBUTES = 0x0100;
internal const uint ERROR_INSUFFICIENT_BUFFER = 122; internal const uint ERROR_INSUFFICIENT_BUFFER = 122;
internal const uint FILE_BEGIN = 0; internal const uint FILE_BEGIN = 0;
internal const uint FSCTL_LOCK_VOLUME = 0x00090018; internal const uint FSCTL_LOCK_VOLUME = 0x00090018;
internal const uint FSCTL_DISMOUNT_VOLUME = 0x00090020; internal const uint FSCTL_DISMOUNT_VOLUME = 0x00090020;
internal const uint FSCTL_UNLOCK_VOLUME = 0x00090022; internal const uint FSCTL_UNLOCK_VOLUME = 0x00090022;
internal const uint IOCTL_STORAGE_EJECT_MEDIA = 0x2D4808; internal const uint IOCTL_STORAGE_EJECT_MEDIA = 0x2D4808;
internal const uint IOCTL_STORAGE_LOAD_MEDIA = 0x2D480C; internal const uint IOCTL_STORAGE_LOAD_MEDIA = 0x2D480C;
internal const Int32 INVALID_HANDLE_VALUE = -1; internal const Int32 INVALID_HANDLE_VALUE = -1;
internal const Int32 FILE_ATTRIBUTE_NORMAL = 1; internal const Int32 FILE_ATTRIBUTE_NORMAL = 1;
[DllImport("kernel32.dll", SetLastError = true)] [DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool WriteFile(IntPtr hFile, byte[] lpBuffer, uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten, IntPtr lpOverlapped); internal static extern bool WriteFile(IntPtr hFile, byte[] lpBuffer, uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten, IntPtr lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true)] [DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool ReadFile(IntPtr hFile, [Out] byte[] lpBuffer, uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped); internal static extern bool ReadFile(IntPtr hFile, [Out] byte[] lpBuffer, uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
internal static extern uint SetFilePointer( internal static extern uint SetFilePointer(
[In] IntPtr hFile, [In] IntPtr hFile,
[In] int lDistanceToMove, [In] int lDistanceToMove,
[In, Out] ref int lpDistanceToMoveHigh, [In, Out] ref int lpDistanceToMoveHigh,
[In] EMoveMethod dwMoveMethod); [In] EMoveMethod dwMoveMethod);
[DllImport("kernel32.dll", SetLastError = true)] [DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr CreateFile( internal static extern IntPtr CreateFile(
string lpFileName, string lpFileName,
uint dwDesiredAccess, uint dwDesiredAccess,
uint dwShareMode, uint dwShareMode,
IntPtr lpSecurityAttributes, IntPtr lpSecurityAttributes,
uint dwCreationDisposition, uint dwCreationDisposition,
uint dwFlagsAndAttributes, uint dwFlagsAndAttributes,
IntPtr hTemplateFile); IntPtr hTemplateFile);
[DllImport("Kernel32.dll", SetLastError = false, CharSet = CharSet.Auto)] [DllImport("Kernel32.dll", SetLastError = false, CharSet = CharSet.Auto)]
public static extern bool DeviceIoControl( public static extern bool DeviceIoControl(
IntPtr hDevice, IntPtr hDevice,
uint IoControlCode, uint IoControlCode,
[In] object InBuffer, [In] object InBuffer,
uint nInBufferSize, uint nInBufferSize,
[Out] object OutBuffer, [Out] object OutBuffer,
uint nOutBufferSize, uint nOutBufferSize,
ref uint pBytesReturned, ref uint pBytesReturned,
IntPtr Overlapped IntPtr Overlapped
); );
[DllImport("kernel32.dll", SetLastError = true)] [DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]
public static extern bool FlushFileBuffers(IntPtr hFile); public static extern bool FlushFileBuffers(IntPtr hFile);
static NativeMethods() static NativeMethods()
{ {
} }
} }
internal sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid internal sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
{ {
private SafeTokenHandle() : base(true) { } private SafeTokenHandle() : base(true) { }
// 0 is an Invalid Handle // 0 is an Invalid Handle
internal SafeTokenHandle(IntPtr handle) internal SafeTokenHandle(IntPtr handle)
: base(true) : base(true)
{ {
SetHandle(handle); SetHandle(handle);
} }
internal static SafeTokenHandle InvalidHandle internal static SafeTokenHandle InvalidHandle
{ {
get { return new SafeTokenHandle(IntPtr.Zero); } get { return new SafeTokenHandle(IntPtr.Zero); }
} }
[DllImport(NativeMethods.KERNEL32, SetLastError = true), [DllImport(NativeMethods.KERNEL32, SetLastError = true),
SuppressUnmanagedCodeSecurity] SuppressUnmanagedCodeSecurity]
private static extern bool CloseHandle(IntPtr handle); private static extern bool CloseHandle(IntPtr handle);
override protected bool ReleaseHandle() override protected bool ReleaseHandle()
{ {
return CloseHandle(handle); return CloseHandle(handle);
} }
} }
} }
File diff suppressed because it is too large Load Diff
@@ -1,412 +1,412 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using MadWizard.WinUSBNet; using MadWizard.WinUSBNet;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.Json; using System.Text.Json;
namespace WPinternals namespace WPinternals
{ {
internal class NokiaPhoneModel : IDisposable internal class NokiaPhoneModel : IDisposable
{ {
protected bool Disposed = false; protected bool Disposed = false;
private readonly USBDevice Device = null; private readonly USBDevice Device = null;
private int MessageId = 0; private int MessageId = 0;
private readonly object UsbLock = new(); private readonly object UsbLock = new();
public NokiaPhoneModel(string DevicePath) public NokiaPhoneModel(string DevicePath)
{ {
// Mass Storage device is not WinUSB // Mass Storage device is not WinUSB
try try
{ {
Device = new USBDevice(DevicePath); Device = new USBDevice(DevicePath);
} }
catch { } catch { }
} }
private JsonElement? ExecuteJsonMethodAsJsonToken(string JsonMethod, Dictionary<string, object> Params, string ResultElement) private JsonElement? ExecuteJsonMethodAsJsonToken(string JsonMethod, Dictionary<string, object> Params, string ResultElement)
{ {
byte[] Buffer; byte[] Buffer;
int Length; int Length;
lock (UsbLock) lock (UsbLock)
{ {
const string jsonrpc = "2.0"; const string jsonrpc = "2.0";
int id = MessageId++; int id = MessageId++;
string method = JsonMethod; string method = JsonMethod;
Dictionary<string, object> @params = new(); Dictionary<string, object> @params = new();
if (Params != null) if (Params != null)
{ {
foreach (KeyValuePair<string, object> Param in Params) foreach (KeyValuePair<string, object> Param in Params)
{ {
if (Param.Value is byte[] v) if (Param.Value is byte[] v)
{ {
@params.Add(Param.Key, v.Select(b => (int)b).ToArray()); // convert to int-array @params.Add(Param.Key, v.Select(b => (int)b).ToArray()); // convert to int-array
} }
else else
{ {
@params.Add(Param.Key, Param.Value); @params.Add(Param.Key, Param.Value);
} }
} }
} }
@params.Add("MessageVersion", 0); @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)); Device.OutputPipe.Write(System.Text.Encoding.ASCII.GetBytes(Request));
Buffer = new byte[0x10000]; Buffer = new byte[0x10000];
Length = Device.InputPipe.Read(Buffer); Length = Device.InputPipe.Read(Buffer);
} }
JsonDocument ResultMessage = JsonDocument.Parse(System.Text.Encoding.ASCII.GetString(Buffer, 0, Length)); JsonDocument ResultMessage = JsonDocument.Parse(System.Text.Encoding.ASCII.GetString(Buffer, 0, Length));
try try
{ {
JsonElement? ResultToken = ResultMessage.RootElement.GetProperty("result"); JsonElement? ResultToken = ResultMessage.RootElement.GetProperty("result");
if ((ResultToken == null) || (ResultElement == null)) if ((ResultToken == null) || (ResultElement == null))
{ {
return null; return null;
} }
return ResultToken.Value.GetProperty(ResultElement); return ResultToken.Value.GetProperty(ResultElement);
} }
catch catch
{ {
return null; return null;
} }
} }
public void ExecuteJsonMethod(string JsonMethod, Dictionary<string, object> Params) public void ExecuteJsonMethod(string JsonMethod, Dictionary<string, object> Params)
{ {
_ = ExecuteJsonMethodAsJsonToken(JsonMethod, Params, null); _ = ExecuteJsonMethodAsJsonToken(JsonMethod, Params, null);
} }
public string ExecuteJsonMethodAsString(string JsonMethod, Dictionary<string, object> Params, string ResultElement) public string ExecuteJsonMethodAsString(string JsonMethod, Dictionary<string, object> Params, string ResultElement)
{ {
JsonElement? Token = ExecuteJsonMethodAsJsonToken(JsonMethod, Params, ResultElement); JsonElement? Token = ExecuteJsonMethodAsJsonToken(JsonMethod, Params, ResultElement);
if (Token == null) if (Token == null)
{ {
return null; return null;
} }
return Token.Value.GetString(); return Token.Value.GetString();
} }
public string ExecuteJsonMethodAsString(string JsonMethod, string ResultElement) public string ExecuteJsonMethodAsString(string JsonMethod, string ResultElement)
{ {
JsonElement? Token = ExecuteJsonMethodAsJsonToken(JsonMethod, null, ResultElement); JsonElement? Token = ExecuteJsonMethodAsJsonToken(JsonMethod, null, ResultElement);
if (Token == null) if (Token == null)
{ {
return null; return null;
} }
return Token.Value.GetString(); return Token.Value.GetString();
} }
public int ExecuteJsonMethodAsInteger(string JsonMethod, Dictionary<string, object> Params, string ResultElement) public int ExecuteJsonMethodAsInteger(string JsonMethod, Dictionary<string, object> Params, string ResultElement)
{ {
JsonElement? Token = ExecuteJsonMethodAsJsonToken(JsonMethod, Params, ResultElement); JsonElement? Token = ExecuteJsonMethodAsJsonToken(JsonMethod, Params, ResultElement);
if (Token == null) if (Token == null)
{ {
return 0; return 0;
} }
return Token.Value.GetInt32(); return Token.Value.GetInt32();
} }
public int ExecuteJsonMethodAsInteger(string JsonMethod, string ResultElement) public int ExecuteJsonMethodAsInteger(string JsonMethod, string ResultElement)
{ {
JsonElement? Token = ExecuteJsonMethodAsJsonToken(JsonMethod, null, ResultElement); JsonElement? Token = ExecuteJsonMethodAsJsonToken(JsonMethod, null, ResultElement);
if (Token == null) if (Token == null)
{ {
return 0; return 0;
} }
return Token.Value.GetInt32(); return Token.Value.GetInt32();
} }
public byte[] ExecuteJsonMethodAsBytes(string JsonMethod, Dictionary<string, object> Params, string ResultElement) public byte[] ExecuteJsonMethodAsBytes(string JsonMethod, Dictionary<string, object> Params, string ResultElement)
{ {
JsonElement? Token = ExecuteJsonMethodAsJsonToken(JsonMethod, Params, ResultElement); JsonElement? Token = ExecuteJsonMethodAsJsonToken(JsonMethod, Params, ResultElement);
if (Token == null) if (Token == null)
{ {
return null; return null;
} }
return Token.Value.EnumerateArray().Select(x => x.GetByte()).ToArray(); return Token.Value.EnumerateArray().Select(x => x.GetByte()).ToArray();
} }
public byte[] ExecuteJsonMethodAsBytes(string JsonMethod, string ResultElement) public byte[] ExecuteJsonMethodAsBytes(string JsonMethod, string ResultElement)
{ {
JsonElement? Token = ExecuteJsonMethodAsJsonToken(JsonMethod, null, ResultElement); JsonElement? Token = ExecuteJsonMethodAsJsonToken(JsonMethod, null, ResultElement);
if (Token == null) if (Token == null)
{ {
return null; return null;
} }
return Token.Value.EnumerateArray().Select(x => x.GetByte()).ToArray(); return Token.Value.EnumerateArray().Select(x => x.GetByte()).ToArray();
} }
public bool? ExecuteJsonMethodAsBoolean(string JsonMethod, string ResultElement) public bool? ExecuteJsonMethodAsBoolean(string JsonMethod, string ResultElement)
{ {
JsonElement? Token = ExecuteJsonMethodAsJsonToken(JsonMethod, null, ResultElement); JsonElement? Token = ExecuteJsonMethodAsJsonToken(JsonMethod, null, ResultElement);
if (Token == null) if (Token == null)
{ {
return null; return null;
} }
return Token.Value.GetBoolean(); return Token.Value.GetBoolean();
} }
public void ExecuteJsonMethodAsync(string JsonMethod, Dictionary<string, object> Params) public void ExecuteJsonMethodAsync(string JsonMethod, Dictionary<string, object> Params)
{ {
lock (UsbLock) lock (UsbLock)
{ {
const string jsonrpc = "2.0"; const string jsonrpc = "2.0";
int id = MessageId++; int id = MessageId++;
string method = JsonMethod; string method = JsonMethod;
Dictionary<string, object> @params = new(); Dictionary<string, object> @params = new();
if (Params != null) if (Params != null)
{ {
foreach (KeyValuePair<string, object> Param in Params) foreach (KeyValuePair<string, object> Param in Params)
{ {
if (Param.Value is byte[] v) if (Param.Value is byte[] v)
{ {
@params.Add(Param.Key, v.Select(b => (int)b).ToArray()); // convert to int-array @params.Add(Param.Key, v.Select(b => (int)b).ToArray()); // convert to int-array
} }
else else
{ {
@params.Add(Param.Key, Param.Value); @params.Add(Param.Key, Param.Value);
} }
} }
} }
@params.Add("MessageVersion", 0); @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); byte[] OutBuffer = System.Text.Encoding.ASCII.GetBytes(Request);
Device.OutputPipe.BeginWrite(OutBuffer, 0, OutBuffer.Length, (AsyncResultWrite) => Device.OutputPipe.EndWrite(AsyncResultWrite), null); Device.OutputPipe.BeginWrite(OutBuffer, 0, OutBuffer.Length, (AsyncResultWrite) => Device.OutputPipe.EndWrite(AsyncResultWrite), null);
} }
} }
public void ExecuteJsonMethodAsync(string JsonMethod) public void ExecuteJsonMethodAsync(string JsonMethod)
{ {
ExecuteJsonMethod(JsonMethod, null); ExecuteJsonMethod(JsonMethod, null);
} }
public delegate void JsonMethodCallbackString(object State, string Result); public delegate void JsonMethodCallbackString(object State, string Result);
public void ExecuteJsonMethodAsStringAsync(string JsonMethod, Dictionary<string, object> Params, string ResultElement, object State, JsonMethodCallbackString Callback) public void ExecuteJsonMethodAsStringAsync(string JsonMethod, Dictionary<string, object> Params, string ResultElement, object State, JsonMethodCallbackString Callback)
{ {
ExecuteJsonMethodAsTokenAsync(JsonMethod, Params, ResultElement, State, (ReturnState, Token) => Callback(ReturnState, Token.Value.GetRawText())); ExecuteJsonMethodAsTokenAsync(JsonMethod, Params, ResultElement, State, (ReturnState, Token) => Callback(ReturnState, Token.Value.GetRawText()));
} }
public void ExecuteJsonMethodAsStringAsync(string JsonMethod, string ResultElement, object State, JsonMethodCallbackString Callback) public void ExecuteJsonMethodAsStringAsync(string JsonMethod, string ResultElement, object State, JsonMethodCallbackString Callback)
{ {
ExecuteJsonMethodAsTokenAsync(JsonMethod, null, ResultElement, State, (ReturnState, Token) => Callback(ReturnState, Token.Value.GetRawText())); ExecuteJsonMethodAsTokenAsync(JsonMethod, null, ResultElement, State, (ReturnState, Token) => Callback(ReturnState, Token.Value.GetRawText()));
} }
public delegate void JsonMethodCallbackBoolean(object State, bool Result); public delegate void JsonMethodCallbackBoolean(object State, bool Result);
public void ExecuteJsonMethodAsBooleanAsync(string JsonMethod, Dictionary<string, object> Params, string ResultElement, object State, JsonMethodCallbackBoolean Callback) public void ExecuteJsonMethodAsBooleanAsync(string JsonMethod, Dictionary<string, object> Params, string ResultElement, object State, JsonMethodCallbackBoolean Callback)
{ {
ExecuteJsonMethodAsTokenAsync(JsonMethod, Params, ResultElement, State, (ReturnState, Token) => Callback(ReturnState, Token.Value.GetBoolean())); ExecuteJsonMethodAsTokenAsync(JsonMethod, Params, ResultElement, State, (ReturnState, Token) => Callback(ReturnState, Token.Value.GetBoolean()));
} }
public void ExecuteJsonMethodAsBooleanAsync(string JsonMethod, string ResultElement, object State, JsonMethodCallbackBoolean Callback) public void ExecuteJsonMethodAsBooleanAsync(string JsonMethod, string ResultElement, object State, JsonMethodCallbackBoolean Callback)
{ {
ExecuteJsonMethodAsTokenAsync(JsonMethod, null, ResultElement, State, (ReturnState, Token) => Callback(ReturnState, Token.Value.GetBoolean())); ExecuteJsonMethodAsTokenAsync(JsonMethod, null, ResultElement, State, (ReturnState, Token) => Callback(ReturnState, Token.Value.GetBoolean()));
} }
public delegate void JsonMethodCallbackBytes(object State, byte[] Result); public delegate void JsonMethodCallbackBytes(object State, byte[] Result);
public void ExecuteJsonMethodAsBytesAsync(string JsonMethod, Dictionary<string, object> Params, string ResultElement, object State, JsonMethodCallbackBytes Callback) public void ExecuteJsonMethodAsBytesAsync(string JsonMethod, Dictionary<string, object> Params, string ResultElement, object State, JsonMethodCallbackBytes Callback)
{ {
ExecuteJsonMethodAsTokenAsync(JsonMethod, Params, ResultElement, State, (ReturnState, Token) => Callback(ReturnState, Token.Value.EnumerateArray().Select(x => x.GetByte()).ToArray())); ExecuteJsonMethodAsTokenAsync(JsonMethod, Params, ResultElement, State, (ReturnState, Token) => Callback(ReturnState, Token.Value.EnumerateArray().Select(x => x.GetByte()).ToArray()));
} }
public void ExecuteJsonMethodAsBytesAsync(string JsonMethod, string ResultElement, object State, JsonMethodCallbackBytes Callback) public void ExecuteJsonMethodAsBytesAsync(string JsonMethod, string ResultElement, object State, JsonMethodCallbackBytes Callback)
{ {
ExecuteJsonMethodAsTokenAsync(JsonMethod, null, ResultElement, State, (ReturnState, Token) => Callback(ReturnState, Token.Value.EnumerateArray().Select(x => x.GetByte()).ToArray())); ExecuteJsonMethodAsTokenAsync(JsonMethod, null, ResultElement, State, (ReturnState, Token) => Callback(ReturnState, Token.Value.EnumerateArray().Select(x => x.GetByte()).ToArray()));
} }
public delegate void JsonMethodCallbackInteger(object State, int Result); public delegate void JsonMethodCallbackInteger(object State, int Result);
public void ExecuteJsonMethodAsIntegerAsync(string JsonMethod, Dictionary<string, object> Params, string ResultElement, object State, JsonMethodCallbackInteger Callback) public void ExecuteJsonMethodAsIntegerAsync(string JsonMethod, Dictionary<string, object> Params, string ResultElement, object State, JsonMethodCallbackInteger Callback)
{ {
ExecuteJsonMethodAsTokenAsync(JsonMethod, Params, ResultElement, State, (ReturnState, Token) => Callback(ReturnState, Token.Value.GetInt32())); ExecuteJsonMethodAsTokenAsync(JsonMethod, Params, ResultElement, State, (ReturnState, Token) => Callback(ReturnState, Token.Value.GetInt32()));
} }
public void ExecuteJsonMethodAsIntegerAsync(string JsonMethod, string ResultElement, object State, JsonMethodCallbackInteger Callback) public void ExecuteJsonMethodAsIntegerAsync(string JsonMethod, string ResultElement, object State, JsonMethodCallbackInteger Callback)
{ {
ExecuteJsonMethodAsTokenAsync(JsonMethod, null, ResultElement, State, (ReturnState, Token) => Callback(ReturnState, Token.Value.GetInt32())); ExecuteJsonMethodAsTokenAsync(JsonMethod, null, ResultElement, State, (ReturnState, Token) => Callback(ReturnState, Token.Value.GetInt32()));
} }
public delegate void JsonMethodCallbackToken(object State, JsonElement? Result); public delegate void JsonMethodCallbackToken(object State, JsonElement? Result);
public void ExecuteJsonMethodAsTokenAsync(string JsonMethod, Dictionary<string, object> Params, string ResultElement, object State, JsonMethodCallbackToken Callback) public void ExecuteJsonMethodAsTokenAsync(string JsonMethod, Dictionary<string, object> Params, string ResultElement, object State, JsonMethodCallbackToken Callback)
{ {
byte[] Buffer; byte[] Buffer;
int Length; int Length;
lock (UsbLock) lock (UsbLock)
{ {
const string jsonrpc = "2.0"; const string jsonrpc = "2.0";
int id = MessageId++; int id = MessageId++;
string method = JsonMethod; string method = JsonMethod;
Dictionary<string, object> @params = new(); Dictionary<string, object> @params = new();
if (Params != null) if (Params != null)
{ {
foreach (KeyValuePair<string, object> Param in Params) foreach (KeyValuePair<string, object> Param in Params)
{ {
if (Param.Value is byte[] v) if (Param.Value is byte[] v)
{ {
@params.Add(Param.Key, v.Select(b => (int)b).ToArray()); // convert to int-array @params.Add(Param.Key, v.Select(b => (int)b).ToArray()); // convert to int-array
} }
else else
{ {
@params.Add(Param.Key, Param.Value); @params.Add(Param.Key, Param.Value);
} }
} }
} }
@params.Add("MessageVersion", 0); @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); byte[] OutBuffer = System.Text.Encoding.ASCII.GetBytes(Request);
Device.OutputPipe.BeginWrite(OutBuffer, 0, OutBuffer.Length, (AsyncResultWrite) => Device.OutputPipe.BeginWrite(OutBuffer, 0, OutBuffer.Length, (AsyncResultWrite) =>
{ {
Device.OutputPipe.EndWrite(AsyncResultWrite); Device.OutputPipe.EndWrite(AsyncResultWrite);
Buffer = new byte[0x10000]; Buffer = new byte[0x10000];
Device.InputPipe.BeginRead(Buffer, 0, 0x10000, (AsyncResultRead) => Device.InputPipe.BeginRead(Buffer, 0, 0x10000, (AsyncResultRead) =>
{ {
Length = Device.InputPipe.EndRead(AsyncResultRead); Length = Device.InputPipe.EndRead(AsyncResultRead);
JsonDocument ResultMessage = JsonDocument.Parse(System.Text.Encoding.ASCII.GetString(Buffer, 0, Length)); JsonDocument ResultMessage = JsonDocument.Parse(System.Text.Encoding.ASCII.GetString(Buffer, 0, Length));
JsonElement? ResultToken = ResultMessage.RootElement.GetProperty("result"); JsonElement? ResultToken = ResultMessage.RootElement.GetProperty("result");
if ((ResultToken == null) || (ResultElement == null)) if ((ResultToken == null) || (ResultElement == null))
{ {
Callback(AsyncResultRead.AsyncState, null); Callback(AsyncResultRead.AsyncState, null);
} }
Callback(AsyncResultRead.AsyncState, ResultToken.Value.GetProperty(ResultElement)); Callback(AsyncResultRead.AsyncState, ResultToken.Value.GetProperty(ResultElement));
}, AsyncResultWrite.AsyncState); }, AsyncResultWrite.AsyncState);
}, State); }, State);
} }
} }
public void ExecuteJsonMethodAsTokenAsync(string JsonMethod, string ResultElement, object State, JsonMethodCallbackToken Callback) public void ExecuteJsonMethodAsTokenAsync(string JsonMethod, string ResultElement, object State, JsonMethodCallbackToken Callback)
{ {
ExecuteJsonMethodAsTokenAsync(JsonMethod, null, ResultElement, State, Callback); ExecuteJsonMethodAsTokenAsync(JsonMethod, null, ResultElement, State, Callback);
} }
public byte[] ExecuteRawMethod(byte[] RawMethod) public byte[] ExecuteRawMethod(byte[] RawMethod)
{ {
return ExecuteRawMethod(RawMethod, RawMethod.Length); return ExecuteRawMethod(RawMethod, RawMethod.Length);
} }
public byte[] ExecuteRawMethod(byte[] RawMethod, int Length) public byte[] ExecuteRawMethod(byte[] RawMethod, int Length)
{ {
byte[] Buffer = new byte[0x8000]; // Should be at least 0x4408 for receiving the GPT packet. byte[] Buffer = new byte[0x8000]; // Should be at least 0x4408 for receiving the GPT packet.
byte[] Result = null; byte[] Result = null;
lock (UsbLock) lock (UsbLock)
{ {
Device.OutputPipe.Write(RawMethod, 0, Length); Device.OutputPipe.Write(RawMethod, 0, Length);
try try
{ {
int OutputLength = Device.InputPipe.Read(Buffer); int OutputLength = Device.InputPipe.Read(Buffer);
Result = new byte[OutputLength]; Result = new byte[OutputLength];
System.Buffer.BlockCopy(Buffer, 0, Result, 0, OutputLength); System.Buffer.BlockCopy(Buffer, 0, Result, 0, OutputLength);
} }
catch { } // Reboot command looses connection catch { } // Reboot command looses connection
} }
return Result; return Result;
} }
public void ExecuteRawVoidMethod(byte[] RawMethod) public void ExecuteRawVoidMethod(byte[] RawMethod)
{ {
ExecuteRawVoidMethod(RawMethod, RawMethod.Length); ExecuteRawVoidMethod(RawMethod, RawMethod.Length);
} }
public void ExecuteRawVoidMethod(byte[] RawMethod, int Length) public void ExecuteRawVoidMethod(byte[] RawMethod, int Length)
{ {
lock (UsbLock) lock (UsbLock)
{ {
Device.OutputPipe.Write(RawMethod, 0, Length); Device.OutputPipe.Write(RawMethod, 0, Length);
} }
} }
public void ResetDevice() public void ResetDevice()
{ {
try try
{ {
foreach (var pipe in Device.Pipes) foreach (var pipe in Device.Pipes)
{ {
pipe.Abort(); pipe.Abort();
pipe.Reset(); pipe.Reset();
} }
} }
catch { } catch { }
} }
/// <summary> /// <summary>
/// Disposes the UsbDevice including all unmanaged WinUSB handles. This function /// Disposes the UsbDevice including all unmanaged WinUSB handles. This function
/// should be called when the UsbDevice object is no longer in use, otherwise /// should be called when the UsbDevice object is no longer in use, otherwise
/// unmanaged handles will remain open until the garbage collector finalizes the /// unmanaged handles will remain open until the garbage collector finalizes the
/// object. /// object.
/// </summary> /// </summary>
public void Dispose() public void Dispose()
{ {
Dispose(true); Dispose(true);
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
/// <summary> /// <summary>
/// Finalizer for the UsbDevice. Disposes all unmanaged handles. /// Finalizer for the UsbDevice. Disposes all unmanaged handles.
/// </summary> /// </summary>
~NokiaPhoneModel() ~NokiaPhoneModel()
{ {
Dispose(false); Dispose(false);
} }
/// <summary> /// <summary>
/// Disposes the object /// Disposes the object
/// </summary> /// </summary>
/// <param name="disposing">Indicates wether Dispose was called manually (true) or by /// <param name="disposing">Indicates wether Dispose was called manually (true) or by
/// the garbage collector (false) via the destructor.</param> /// the garbage collector (false) via the destructor.</param>
protected virtual void Dispose(bool disposing) protected virtual void Dispose(bool disposing)
{ {
if (Disposed) if (Disposed)
{ {
return; return;
} }
if (disposing) if (disposing)
{ {
Device?.Dispose(); Device?.Dispose();
} }
// Clean unmanaged resources here. // Clean unmanaged resources here.
// (none currently) // (none currently)
Disposed = true; Disposed = true;
} }
} }
} }
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,145 +1,145 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
namespace WPinternals namespace WPinternals
{ {
internal class QualcommDownload internal class QualcommDownload
{ {
private readonly QualcommSerial Serial; private readonly QualcommSerial Serial;
public QualcommDownload(QualcommSerial Serial) public QualcommDownload(QualcommSerial Serial)
{ {
this.Serial = Serial; this.Serial = Serial;
} }
public bool IsAlive() public bool IsAlive()
{ {
try try
{ {
Serial.SendCommand(new byte[] { 0x06 }, new byte[] { 0x02 }); Serial.SendCommand([0x06], [0x02]);
return true; return true;
} }
catch catch
{ {
return false; return false;
} }
} }
public void SendToPhoneMemory(UInt32 Address, Stream Data, UInt32 Length = UInt32.MaxValue) public void SendToPhoneMemory(UInt32 Address, Stream Data, UInt32 Length = UInt32.MaxValue)
{ {
long Remaining = Length > (Data.Length - Data.Position) ? Data.Length - Data.Position : Length; long Remaining = Length > (Data.Length - Data.Position) ? Data.Length - Data.Position : Length;
UInt32 CurrentLength; UInt32 CurrentLength;
byte[] Buffer = new byte[0x107]; byte[] Buffer = new byte[0x107];
Buffer[0] = 0x0F; Buffer[0] = 0x0F;
System.Buffer.BlockCopy(BitConverter.GetBytes((UInt16)0x100).Reverse().ToArray(), 0, Buffer, 5, 2); // Length is in Big Endian System.Buffer.BlockCopy(BitConverter.GetBytes((UInt16)0x100).Reverse().ToArray(), 0, Buffer, 5, 2); // Length is in Big Endian
UInt32 CurrentAddress = Address; UInt32 CurrentAddress = Address;
while (Remaining > 0) while (Remaining > 0)
{ {
System.Buffer.BlockCopy(BitConverter.GetBytes(CurrentAddress).Reverse().ToArray(), 0, Buffer, 1, 4); // Address is in Big Endian System.Buffer.BlockCopy(BitConverter.GetBytes(CurrentAddress).Reverse().ToArray(), 0, Buffer, 1, 4); // Address is in Big Endian
CurrentLength = Remaining >= 0x100 ? 0x100 : (UInt32)Remaining; CurrentLength = Remaining >= 0x100 ? 0x100 : (UInt32)Remaining;
CurrentLength = (UInt32)Data.Read(Buffer, 7, (int)CurrentLength); CurrentLength = (UInt32)Data.Read(Buffer, 7, (int)CurrentLength);
Serial.SendCommand(Buffer, new byte[] { 0x02 }); Serial.SendCommand(Buffer, [0x02]);
CurrentAddress += CurrentLength; CurrentAddress += CurrentLength;
Remaining -= CurrentLength; Remaining -= CurrentLength;
} }
} }
public void SendToPhoneMemory(UInt32 Address, byte[] Data, UInt32 Offset = 0, UInt32 Length = UInt32.MaxValue) public void SendToPhoneMemory(UInt32 Address, byte[] Data, UInt32 Offset = 0, UInt32 Length = UInt32.MaxValue)
{ {
long Remaining; long Remaining;
if (Offset > (Data.Length - 1)) if (Offset > (Data.Length - 1))
{ {
throw new ArgumentException("Wrong offset"); throw new ArgumentException("Wrong offset");
} }
Remaining = Length > (Data.Length - Offset) ? Data.Length - Offset : Length; Remaining = Length > (Data.Length - Offset) ? Data.Length - Offset : Length;
UInt32 CurrentLength; UInt32 CurrentLength;
UInt32 CurrentOffset = Offset; UInt32 CurrentOffset = Offset;
byte[] Buffer = new byte[0x107]; byte[] Buffer = new byte[0x107];
UInt32 CurrentAddress = Address; UInt32 CurrentAddress = Address;
byte[] CurrentBytes; byte[] CurrentBytes;
while (Remaining > 0) while (Remaining > 0)
{ {
if (Remaining >= 0x100) if (Remaining >= 0x100)
{ {
CurrentLength = 0x100; CurrentLength = 0x100;
CurrentBytes = Buffer; CurrentBytes = Buffer;
} }
else else
{ {
CurrentLength = (UInt32)Remaining; CurrentLength = (UInt32)Remaining;
CurrentBytes = new byte[CurrentLength + 7]; CurrentBytes = new byte[CurrentLength + 7];
} }
CurrentBytes[0] = 0x0F; CurrentBytes[0] = 0x0F;
System.Buffer.BlockCopy(BitConverter.GetBytes(CurrentAddress).Reverse().ToArray(), 0, CurrentBytes, 1, 4); // Address is in Big Endian System.Buffer.BlockCopy(BitConverter.GetBytes(CurrentAddress).Reverse().ToArray(), 0, CurrentBytes, 1, 4); // Address is in Big Endian
System.Buffer.BlockCopy(BitConverter.GetBytes((UInt16)CurrentLength).Reverse().ToArray(), 0, CurrentBytes, 5, 2); // Length is in Big Endian System.Buffer.BlockCopy(BitConverter.GetBytes((UInt16)CurrentLength).Reverse().ToArray(), 0, CurrentBytes, 5, 2); // Length is in Big Endian
System.Buffer.BlockCopy(Data, (int)CurrentOffset, CurrentBytes, 7, (int)CurrentLength); System.Buffer.BlockCopy(Data, (int)CurrentOffset, CurrentBytes, 7, (int)CurrentLength);
Serial.SendCommand(CurrentBytes, new byte[] { 0x02 }); Serial.SendCommand(CurrentBytes, [0x02]);
CurrentAddress += CurrentLength; CurrentAddress += CurrentLength;
CurrentOffset += CurrentLength; CurrentOffset += CurrentLength;
Remaining -= CurrentLength; Remaining -= CurrentLength;
} }
} }
public void StartBootloader(UInt32 Address) public void StartBootloader(UInt32 Address)
{ {
byte[] Buffer = new byte[5]; byte[] Buffer = new byte[5];
Buffer[0] = 0x05; Buffer[0] = 0x05;
System.Buffer.BlockCopy(BitConverter.GetBytes(Address).Reverse().ToArray(), 0, Buffer, 1, 4); // Address is in Big Endian System.Buffer.BlockCopy(BitConverter.GetBytes(Address).Reverse().ToArray(), 0, Buffer, 1, 4); // Address is in Big Endian
Serial.SendCommand(Buffer, new byte[] { 0x02 }); Serial.SendCommand(Buffer, [0x02]);
} }
// Reset interface. Interface becomes unresponsive. // Reset interface. Interface becomes unresponsive.
public void Reset() public void Reset()
{ {
Serial.SendCommand(new byte[] { 0x0A }, new byte[] { 0x02 }); Serial.SendCommand([0x0A], [0x02]);
} }
// This also resets interface. This does not actually reboot the phone. The interface becomes unresponsive. // This also resets interface. This does not actually reboot the phone. The interface becomes unresponsive.
public void Shutdown() public void Shutdown()
{ {
Serial.SendCommand(new byte[] { 0x0E }, new byte[] { 0x02 }); Serial.SendCommand([0x0E], [0x02]);
} }
// This command only works on 9008 interface. // This command only works on 9008 interface.
public byte[] GetRKH() public byte[] GetRKH()
{ {
byte[] Response = Serial.SendCommand(new byte[] { 0x18 }, new byte[] { 0x18, 0x01, 0x00 }); byte[] Response = Serial.SendCommand([0x18], [0x18, 0x01, 0x00]);
byte[] Result = new byte[0x20]; byte[] Result = new byte[0x20];
Buffer.BlockCopy(Response, 3, Result, 0, 0x20); Buffer.BlockCopy(Response, 3, Result, 0, 0x20);
return Result; return Result;
} }
public void CloseSerial() public void CloseSerial()
{ {
Serial.Close(); Serial.Close();
} }
} }
} }
@@ -1,600 +1,384 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System.Collections;
using System.Collections; using System.IO;
using System.IO; using System.Linq;
using System.Linq; using System.Text;
using System.Text; using System.Threading;
using System.Threading; using System.Threading.Tasks;
using System.Threading.Tasks;
namespace WPinternals
namespace WPinternals {
{ internal class QualcommFirehose
internal enum SaharaMode : uint {
{ private readonly QualcommSerial Serial;
ImageTransferPending = 0x00,
ImagetransferComplete = 0x01, public QualcommFirehose(QualcommSerial Serial)
MemoryDebug = 0x02, {
Command = 0x03 this.Serial = Serial;
} }
internal delegate void ReadyHandler(); public bool ConnectToProgrammer(byte[] PacketFromPcToProgrammer)
{
internal class QualcommSahara // Behaviour of old firehose:
{ // Takes about 20 ms to be started.
private readonly QualcommSerial Serial; // Then PC has to start talking to the phone.
// Behaviour of new firehose:
public QualcommSahara(QualcommSerial Serial) // After 2000 ms the firehose starts talking to the PC
{ //
Serial.EncodeCommands = false; // For the duration of 2.5 seconds we will send Hello packages
Serial.DecodeResponses = false; // And also wait for incoming messages
this.Serial = Serial; // An incoming message can be a response to our outgoing Hello packet (read incoming until "response value")
} // Or it can be an incoming Hello-packet from the programmer (always 2 packets, starting with "Chip serial num")
// Sending the hello-packet can succeed immediately, or it can timeout.
public bool SendImage(string Path) // When sending succeeds, an answer should be incoming immediately to complete the handshake.
{ // When an incoming Hello was received, the phone still expects to receive another Hello.
bool Result = true;
int HelloSendCount = 0;
LogFile.Log("Sending programmer: " + Path, LogType.FileOnly); bool HandshakeCompleted = false;
string Incoming;
int Step = 0; do
UInt32 Offset = 0; {
UInt32 Length = 0; Serial.SetTimeOut(200);
HelloSendCount++;
byte[] ImageBuffer = null; try
try {
{ LogFile.Log("Send Hello to programmer (" + HelloSendCount.ToString() + ")", LogType.FileOnly);
Step = 1; Serial.SendData(PacketFromPcToProgrammer);
byte[] Hello = Serial.GetResponse(new byte[] { 0x01, 0x00, 0x00, 0x00 }); LogFile.Log("Hello packet accepted", LogType.FileOnly);
}
// Incoming Hello packet: catch
// 00000001 = Hello command id {
// xxxxxxxx = Length LogFile.Log("Hello packet not accepted", LogType.FileOnly);
// xxxxxxxx = Protocol version }
// xxxxxxxx = Supported version
// xxxxxxxx = Max packet length try
// xxxxxxxx = Expected mode {
// 6 dwords reserved space Serial.SetTimeOut(500);
LogFile.Log("Protocol: 0x" + ByteOperations.ReadUInt32(Hello, 0x08).ToString("X8"), LogType.FileOnly); Incoming = Encoding.ASCII.GetString(Serial.GetResponse(null));
LogFile.Log("Supported: 0x" + ByteOperations.ReadUInt32(Hello, 0x0C).ToString("X8"), LogType.FileOnly); LogFile.Log("In: " + Incoming, LogType.FileOnly);
LogFile.Log("MaxLength: 0x" + ByteOperations.ReadUInt32(Hello, 0x10).ToString("X8"), LogType.FileOnly); Serial.SetTimeOut(200);
LogFile.Log("Mode: 0x" + ByteOperations.ReadUInt32(Hello, 0x14).ToString("X8"), LogType.FileOnly); if (Incoming.Contains("Chip serial num"))
{
// Packet: Incoming = Encoding.ASCII.GetString(Serial.GetResponse(null));
// 00000002 = Hello response command id LogFile.Log("In: " + Incoming, LogType.FileOnly);
// 00000030 = Length LogFile.Log("Incoming Hello-packets received", LogType.FileOnly);
// 00000002 = Protocol version }
// 00000001 = Supported version
// 00000000 = Status OK while (Incoming.IndexOf("response value") < 0)
// 00000000 = Mode {
// rest is reserved space Incoming = Encoding.ASCII.GetString(Serial.GetResponse(null));
Step = 2; LogFile.Log("In: " + Incoming, LogType.FileOnly);
byte[] HelloResponse = new byte[] { }
0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, LogFile.Log("Incoming Hello-response received", LogType.FileOnly);
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}; if (!Incoming.Contains("Failed to authenticate Digital Signature."))
Serial.SendData(HelloResponse); {
HandshakeCompleted = true;
Step = 3; }
using FileStream FileStream = new(Path, FileMode.Open, FileAccess.Read); else
while (true) {
{ LogFile.Log("Programmer failed to authenticate Digital Signature", LogType.FileOnly);
Step = 4; }
byte[] ReadDataRequest = Serial.GetResponse(null); }
UInt32 ResponseID = ByteOperations.ReadUInt32(ReadDataRequest, 0); catch { }
if (ResponseID == 4) }
{ while (!HandshakeCompleted && (HelloSendCount < 6));
break;
} return HandshakeCompleted;
}
if (ResponseID != 3)
{ public bool ConnectToProgrammerInTestMode()
Step = 5; {
throw new BadConnectionException(); byte[] HelloPacketFromPcToProgrammer = new byte[0x20C];
} ByteOperations.WriteUInt32(HelloPacketFromPcToProgrammer, 0, 0x57503730);
ByteOperations.WriteUInt32(HelloPacketFromPcToProgrammer, 0x28, 0x57503730);
Offset = ByteOperations.ReadUInt32(ReadDataRequest, 0x0C); ByteOperations.WriteUInt32(HelloPacketFromPcToProgrammer, 0x208, 0x57503730);
Length = ByteOperations.ReadUInt32(ReadDataRequest, 0x10); ByteOperations.WriteUInt16(HelloPacketFromPcToProgrammer, 0x48, 0x4445);
if ((ImageBuffer == null) || (ImageBuffer.Length != Length))
{ bool HandshakeCompleted = ConnectToProgrammer(HelloPacketFromPcToProgrammer);
ImageBuffer = new byte[Length];
} if (HandshakeCompleted)
{
if (FileStream.Position != Offset) LogFile.Log("Handshake completed with programmer in testmode", LogType.FileOnly);
{ }
FileStream.Seek(Offset, SeekOrigin.Begin); else
} {
LogFile.Log("Handshake with programmer failed", LogType.FileOnly);
Step = 6; }
FileStream.Read(ImageBuffer, 0, (int)Length);
return HandshakeCompleted;
Step = 7; }
Serial.SendData(ImageBuffer);
} public async Task<bool> Reset()
} {
catch (Exception Ex) bool Connected = await Task.Run(() => ConnectToProgrammerInTestMode());
{ if (!Connected)
LogFile.LogException(Ex, LogType.FileAndConsole, Step.ToString() + " 0x" + Offset.ToString("X8") + " 0x" + Length.ToString("X8")); {
Result = false; return false;
} }
if (Result) LogFile.Log("Rebooting phone", LogType.FileAndConsole);
{ const string Command03 = "<?xml version=\"1.0\" ?><data><power value=\"reset\"/></data>";
LogFile.Log("Programmer loaded into phone memory", LogType.FileOnly); LogFile.Log("Out: " + Command03, LogType.FileOnly);
} Serial.SendData(Encoding.ASCII.GetBytes(Command03));
return Result; string Incoming;
} do
{
public bool Handshake() Incoming = Encoding.ASCII.GetString(Serial.GetResponse(null));
{ LogFile.Log("In: " + Incoming, LogType.FileOnly);
bool Result = true; }
while (Incoming.IndexOf("response value") < 0);
try
{ // Workaround for problem
byte[] Hello = Serial.GetResponse(new byte[] { 0x01, 0x00, 0x00, 0x00 }); // SerialPort is sometimes not disposed correctly when the device is already removed.
// So explicitly dispose here
// Incoming Hello packet: Serial.Close();
// 00000001 = Hello command id
// xxxxxxxx = Length return true;
// xxxxxxxx = Protocol version }
// xxxxxxxx = Supported version
// xxxxxxxx = Max packet length public bool SendEdPayload(string ProgrammerPath, string PayloadPath)
// xxxxxxxx = Expected mode {
// 6 dwords reserved space // First, let's read the Emergency Download payload header and verify its validity
LogFile.Log("Protocol: 0x" + ByteOperations.ReadUInt32(Hello, 0x08).ToString("X8"), LogType.FileOnly); FileStream PayloadStream = File.OpenRead(PayloadPath);
LogFile.Log("Supported: 0x" + ByteOperations.ReadUInt32(Hello, 0x0C).ToString("X8"), LogType.FileOnly);
LogFile.Log("MaxLength: 0x" + ByteOperations.ReadUInt32(Hello, 0x10).ToString("X8"), LogType.FileOnly); byte[] ValidReferencePayloadHeader = [0x45, 0x6D, 0x65, 0x72, 0x67, 0x65, 0x6E, 0x63, 0x79, 0x20, 0x50, 0x61, 0x79, 0x6C, 0x6F, 0x61, 0x64];
LogFile.Log("Mode: 0x" + ByteOperations.ReadUInt32(Hello, 0x14).ToString("X8"), LogType.FileOnly);
byte[] PayloadHeader = new byte[17];
byte[] HelloResponse = new byte[] { PayloadStream.Read(PayloadHeader, 0, 17);
0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, bool IsValidEdPayloadImage = StructuralComparisons.StructuralEqualityComparer.Equals(PayloadHeader, ValidReferencePayloadHeader);
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 if (!IsValidEdPayloadImage)
}; {
return false;
byte[] Ready = Serial.SendCommand(HelloResponse, new byte[] { 0x03, 0x00, 0x00, 0x00 }); }
}
catch // Now let's read the information block
{ PayloadStream.Seek(0x64, SeekOrigin.Begin);
Result = false; byte[] PayloadInformationBlock = new byte[0x64];
}
PayloadStream.Read(PayloadInformationBlock, 0, 0x64);
return Result; string buildtime = Encoding.ASCII.GetString(PayloadInformationBlock).Trim('\0');
}
PayloadStream.Read(PayloadInformationBlock, 0, 0x64);
public void ResetSahara() string builddate = Encoding.ASCII.GetString(PayloadInformationBlock).Trim('\0');
{
Serial.SendCommand(new byte[] { 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, new byte[] { 0x08, 0x00, 0x00, 0x00 }); PayloadStream.Read(PayloadInformationBlock, 0, 0x64);
} string version = Encoding.ASCII.GetString(PayloadInformationBlock).Trim('\0');
public bool ConnectToProgrammer(byte[] PacketFromPcToProgrammer) PayloadInformationBlock = new byte[0x670];
{ PayloadStream.Read(PayloadInformationBlock, 0, 0x670);
// Behaviour of old firehose: string Info = Encoding.ASCII.GetString(PayloadInformationBlock).Trim('\0');
// Takes about 20 ms to be started.
// Then PC has to start talking to the phone. // Print some information about the payload
// Behaviour of new firehose: LogFile.Log("Emerency flasher version 0.1", LogType.FileAndConsole);
// After 2000 ms the firehose starts talking to the PC LogFile.Log("Programmer information:", LogType.FileAndConsole);
// LogFile.Log("Build time: " + buildtime, LogType.FileAndConsole);
// For the duration of 2.5 seconds we will send Hello packages LogFile.Log("Build date: " + builddate, LogType.FileAndConsole);
// And also wait for incoming messages LogFile.Log("Version: " + version, LogType.FileAndConsole);
// An incoming message can be a response to our outgoing Hello packet (read incoming until "response value") LogFile.Log("Info: " + Info, LogType.FileAndConsole);
// Or it can be an incoming Hello-packet from the programmer (always 2 packets, starting with "Chip serial num")
// Sending the hello-packet can succeed immediately, or it can timeout. // Wait a few seconds before sending commands
// When sending succeeds, an answer should be incoming immediately to complete the handshake. LogFile.Log("Waiting...", LogType.FileAndConsole);
// When an incoming Hello was received, the phone still expects to receive another Hello. Thread.Sleep(2000);
LogFile.Log("Waiting...OK", LogType.FileAndConsole);
int HelloSendCount = 0;
bool HandshakeCompleted = false; bool Terminated = false;
string Incoming; bool Connected = false;
do bool ProgrammerRawMode = false;
{
Serial.SetTimeOut(200); string Incoming;
HelloSendCount++;
try while (!Terminated)
{ {
LogFile.Log("Send Hello to programmer (" + HelloSendCount.ToString() + ")", LogType.FileOnly); PayloadInformationBlock = new byte[0x200];
Serial.SendData(PacketFromPcToProgrammer); PayloadStream.Read(PayloadInformationBlock, 0, 0x200);
LogFile.Log("Hello packet accepted", LogType.FileOnly); string ProgrammerCommand = Encoding.ASCII.GetString(PayloadInformationBlock.Skip(0xC).ToArray()).Trim('\0');
}
catch LogFile.Log(ProgrammerCommand, LogType.FileAndConsole);
{
LogFile.Log("Hello packet not accepted", LogType.FileOnly); byte[] PacketFromPcToProgrammer = [];
} byte[] temp = new byte[0x200];
try while (true)
{ {
Serial.SetTimeOut(500); if (PayloadStream.Position == PayloadStream.Length)
Incoming = Encoding.ASCII.GetString(Serial.GetResponse(null)); {
LogFile.Log("In: " + Incoming, LogType.FileOnly); Terminated = true;
Serial.SetTimeOut(200); break;
if (Incoming.Contains("Chip serial num")) }
{
Incoming = Encoding.ASCII.GetString(Serial.GetResponse(null)); PayloadStream.Read(temp, 0, 0x200);
LogFile.Log("In: " + Incoming, LogType.FileOnly);
LogFile.Log("Incoming Hello-packets received", LogType.FileOnly); if (temp[12] == 77 && temp[13] == 83 && temp[14] == 71 && temp[15] == 95)
} {
PayloadStream.Seek(-0x200, SeekOrigin.Current);
while (Incoming.IndexOf("response value") < 0) break;
{ }
Incoming = Encoding.ASCII.GetString(Serial.GetResponse(null));
LogFile.Log("In: " + Incoming, LogType.FileOnly); PacketFromPcToProgrammer = [.. PacketFromPcToProgrammer, .. temp];
} }
LogFile.Log("Incoming Hello-response received", LogType.FileOnly); bool ExpectingReplyFromProgrammer = false;
if (!Incoming.Contains("Failed to authenticate Digital Signature.")) if (ProgrammerCommand.Contains("XML"))
{ {
HandshakeCompleted = true; string Outgoing = Encoding.ASCII.GetString(PacketFromPcToProgrammer).Trim('\0');
} PacketFromPcToProgrammer = Encoding.ASCII.GetBytes(Outgoing);
else LogFile.Log("Out: " + Outgoing, LogType.FileAndConsole);
{ }
LogFile.Log("Programmer failed to authenticate Digital Signature", LogType.FileOnly);
} if (!ProgrammerCommand.Contains("RAW_DATA") && !ProgrammerRawMode)
} {
catch { } ExpectingReplyFromProgrammer = true;
} }
while (!HandshakeCompleted && (HelloSendCount < 6));
if (ProgrammerCommand.Contains("LAST") && ProgrammerRawMode)
return HandshakeCompleted; {
} ExpectingReplyFromProgrammer = true;
}
public bool ConnectToProgrammerInTestMode()
{ if (ProgrammerCommand.Contains("DATA_ALL") && ProgrammerRawMode)
byte[] HelloPacketFromPcToProgrammer = new byte[0x20C]; {
ByteOperations.WriteUInt32(HelloPacketFromPcToProgrammer, 0, 0x57503730); ExpectingReplyFromProgrammer = true;
ByteOperations.WriteUInt32(HelloPacketFromPcToProgrammer, 0x28, 0x57503730); }
ByteOperations.WriteUInt32(HelloPacketFromPcToProgrammer, 0x208, 0x57503730);
ByteOperations.WriteUInt16(HelloPacketFromPcToProgrammer, 0x48, 0x4445); if (ProgrammerCommand.Contains("RAW_DATA") && !ProgrammerRawMode)
{
bool HandshakeCompleted = ConnectToProgrammer(HelloPacketFromPcToProgrammer); LogFile.Log("Phone is not in raw mode ON, leaving...", LogType.FileAndConsole);
if (HandshakeCompleted) // Workaround for problem
{ // SerialPort is sometimes not disposed correctly when the device is already removed.
LogFile.Log("Handshake completed with programmer in testmode", LogType.FileOnly); // So explicitly dispose here
} Serial.Close();
else
{ LogFile.Log("Phone has been emergency flashed unsuccessfully!", LogType.FileAndConsole);
LogFile.Log("Handshake with programmer failed", LogType.FileOnly); PayloadStream.Dispose();
}
return false;
return HandshakeCompleted; }
}
if (!ProgrammerCommand.Contains("RAW_DATA") && ProgrammerRawMode)
public async Task<bool> Reset(string ProgrammerPath) {
{ LogFile.Log("Phone is not in raw mode ON, leaving...", LogType.FileAndConsole);
bool SendImageResult = await Task.Run(() => SendImage(ProgrammerPath));
if (!SendImageResult) // Workaround for problem
{ // SerialPort is sometimes not disposed correctly when the device is already removed.
return false; // So explicitly dispose here
} Serial.Close();
await Task.Run(() => StartProgrammer()); LogFile.Log("Phone has been emergency flashed unsuccessfully!", LogType.FileAndConsole);
PayloadStream.Dispose();
bool Connected = await Task.Run(() => ConnectToProgrammerInTestMode());
if (!Connected) return false;
{ }
return false;
} if (Connected)
{
LogFile.Log("Rebooting phone", LogType.FileAndConsole); Serial.SendData(PacketFromPcToProgrammer);
const string Command03 = "<?xml version=\"1.0\" ?><data><power value=\"reset\"/></data>"; }
LogFile.Log("Out: " + Command03, LogType.FileOnly);
Serial.SendData(Encoding.ASCII.GetBytes(Command03)); if (ExpectingReplyFromProgrammer)
{
string Incoming; if (!Connected)
do {
{ Connected = ConnectToProgrammer(PacketFromPcToProgrammer);
Incoming = Encoding.ASCII.GetString(Serial.GetResponse(null));
LogFile.Log("In: " + Incoming, LogType.FileOnly); if (Connected)
} {
while (Incoming.IndexOf("response value") < 0); LogFile.Log("Handshake completed with programmer in validated image programming (VIP) mode", LogType.FileAndConsole);
}
// Workaround for problem else
// SerialPort is sometimes not disposed correctly when the device is already removed. {
// So explicitly dispose here LogFile.Log("Handshake with programmer failed", LogType.FileAndConsole);
Serial.Close(); }
return true; if (!Connected)
} {
LogFile.Log("Phone programmer is now ignoring us, leaving...", LogType.FileAndConsole);
public void SwitchMode(SaharaMode Mode)
{ // Workaround for problem
byte[] SwitchModeCommand = new byte[] { 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // SerialPort is sometimes not disposed correctly when the device is already removed.
ByteOperations.WriteUInt32(SwitchModeCommand, 8, (UInt32)Mode); // So explicitly dispose here
byte[] ResponsePattern = null; Serial.Close();
switch (Mode)
{ LogFile.Log("Phone has been emergency flashed unsuccessfully!", LogType.FileAndConsole);
case SaharaMode.ImageTransferPending: PayloadStream.Dispose();
ResponsePattern = new byte[] { 0x04, 0x00, 0x00, 0x00 };
break; return false;
case SaharaMode.MemoryDebug: }
ResponsePattern = new byte[] { 0x09, 0x00, 0x00, 0x00 }; }
break; else
case SaharaMode.Command: {
ResponsePattern = new byte[] { 0x0B, 0x00, 0x00, 0x00 }; do
break; {
} Serial.SetTimeOut(500);
Serial.SendCommand(SwitchModeCommand, ResponsePattern); Incoming = Encoding.ASCII.GetString(Serial.GetResponse(null));
} Serial.SetTimeOut(200);
LogFile.Log("In: " + Incoming, LogType.FileAndConsole);
public void StartProgrammer() }
{ while (Incoming.IndexOf("response value") < 0);
LogFile.Log("Starting programmer", LogType.FileAndConsole);
byte[] DoneCommand = new byte[] { 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }; if (Incoming.Contains("rawmode=\"false\""))
bool Started = false; {
int count = 0; ProgrammerRawMode = false;
do LogFile.Log("Raw mode: OFF", LogType.FileAndConsole);
{ }
count++;
try if (Incoming.Contains("rawmode=\"true\""))
{ {
byte[] DoneResponse = Serial.SendCommand(DoneCommand, new byte[] { 0x06, 0x00, 0x00, 0x00 }); ProgrammerRawMode = true;
Started = true; LogFile.Log("Raw mode: ON", LogType.FileAndConsole);
} }
catch (BadConnectionException)
{ if (!Incoming.Contains("ACK"))
LogFile.Log("Problem while starting programmer. Attempting again.", LogType.FileAndConsole); {
} LogFile.Log("Phone programmer is now ignoring us, leaving...", LogType.FileAndConsole);
} while (!Started && count < 3);
if (count >= 3 && !Started) // Workaround for problem
{ // SerialPort is sometimes not disposed correctly when the device is already removed.
LogFile.Log("Maximum number of attempts to start the programmer exceeded.", LogType.FileAndConsole); // So explicitly dispose here
throw new BadConnectionException(); Serial.Close();
}
LogFile.Log("Programmer being launched on phone", LogType.FileOnly); LogFile.Log("Phone has been emergency flashed unsuccessfully!", LogType.FileAndConsole);
} PayloadStream.Dispose();
public async Task<bool> SendEdPayload(string ProgrammerPath, string PayloadPath) return false;
{ }
// First, let's read the Emergency Download payload header and verify its validity }
FileStream PayloadStream = File.OpenRead(PayloadPath); }
}
byte[] ValidReferencePayloadHeader = new byte[] { 0x45, 0x6D, 0x65, 0x72, 0x67, 0x65, 0x6E, 0x63, 0x79, 0x20, 0x50, 0x61, 0x79, 0x6C, 0x6F, 0x61, 0x64 };
// Workaround for problem
byte[] PayloadHeader = new byte[17]; // SerialPort is sometimes not disposed correctly when the device is already removed.
PayloadStream.Read(PayloadHeader, 0, 17); // So explicitly dispose here
Serial.Close();
bool IsValidEdPayloadImage = StructuralComparisons.StructuralEqualityComparer.Equals(PayloadHeader, ValidReferencePayloadHeader);
if (!IsValidEdPayloadImage) LogFile.Log("Phone has been emergency flashed successfully!", LogType.FileAndConsole);
{ PayloadStream.Dispose();
return false;
} return true;
}
// Now let's read the information block }
PayloadStream.Seek(0x64, SeekOrigin.Begin); }
byte[] PayloadInformationBlock = new byte[0x64];
PayloadStream.Read(PayloadInformationBlock, 0, 0x64);
string buildtime = Encoding.ASCII.GetString(PayloadInformationBlock).Trim('\0');
PayloadStream.Read(PayloadInformationBlock, 0, 0x64);
string builddate = Encoding.ASCII.GetString(PayloadInformationBlock).Trim('\0');
PayloadStream.Read(PayloadInformationBlock, 0, 0x64);
string version = Encoding.ASCII.GetString(PayloadInformationBlock).Trim('\0');
PayloadInformationBlock = new byte[0x670];
PayloadStream.Read(PayloadInformationBlock, 0, 0x670);
string Info = Encoding.ASCII.GetString(PayloadInformationBlock).Trim('\0');
// Print some information about the payload
LogFile.Log("Emerency flasher version 0.1", LogType.FileAndConsole);
LogFile.Log("Programmer information:", LogType.FileAndConsole);
LogFile.Log("Build time: " + buildtime, LogType.FileAndConsole);
LogFile.Log("Build date: " + builddate, LogType.FileAndConsole);
LogFile.Log("Version: " + version, LogType.FileAndConsole);
LogFile.Log("Info: " + Info, LogType.FileAndConsole);
// Send the emergency programmer to the phone
bool SendImageResult = await Task.Run(() => SendImage(ProgrammerPath));
if (!SendImageResult)
{
return false;
}
// Start the emergency programmer on the phone
await Task.Run(() => StartProgrammer());
// Wait a few seconds before sending commands
LogFile.Log("Waiting...", LogType.FileAndConsole);
Thread.Sleep(2000);
LogFile.Log("Waiting...OK", LogType.FileAndConsole);
bool Terminated = false;
bool Connected = false;
bool ProgrammerRawMode = false;
string Incoming;
while (!Terminated)
{
PayloadInformationBlock = new byte[0x200];
PayloadStream.Read(PayloadInformationBlock, 0, 0x200);
string ProgrammerCommand = Encoding.ASCII.GetString(PayloadInformationBlock.Skip(0xC).ToArray()).Trim('\0');
LogFile.Log(ProgrammerCommand, LogType.FileAndConsole);
byte[] PacketFromPcToProgrammer = Array.Empty<byte>();
byte[] temp = new byte[0x200];
while (true)
{
if (PayloadStream.Position == PayloadStream.Length)
{
Terminated = true;
break;
}
PayloadStream.Read(temp, 0, 0x200);
if (temp[12] == 77 && temp[13] == 83 && temp[14] == 71 && temp[15] == 95)
{
PayloadStream.Seek(-0x200, SeekOrigin.Current);
break;
}
PacketFromPcToProgrammer = PacketFromPcToProgrammer.Concat(temp).ToArray();
}
bool ExpectingReplyFromProgrammer = false;
if (ProgrammerCommand.Contains("XML"))
{
string Outgoing = Encoding.ASCII.GetString(PacketFromPcToProgrammer).Trim('\0');
PacketFromPcToProgrammer = Encoding.ASCII.GetBytes(Outgoing);
LogFile.Log("Out: " + Outgoing, LogType.FileAndConsole);
}
if (!ProgrammerCommand.Contains("RAW_DATA") && !ProgrammerRawMode)
{
ExpectingReplyFromProgrammer = true;
}
if (ProgrammerCommand.Contains("LAST") && ProgrammerRawMode)
{
ExpectingReplyFromProgrammer = true;
}
if (ProgrammerCommand.Contains("DATA_ALL") && ProgrammerRawMode)
{
ExpectingReplyFromProgrammer = true;
}
if (ProgrammerCommand.Contains("RAW_DATA") && !ProgrammerRawMode)
{
LogFile.Log("Phone is not in raw mode ON, leaving...", LogType.FileAndConsole);
// Workaround for problem
// SerialPort is sometimes not disposed correctly when the device is already removed.
// So explicitly dispose here
Serial.Close();
LogFile.Log("Phone has been emergency flashed unsuccessfully!", LogType.FileAndConsole);
PayloadStream.Dispose();
return false;
}
if (!ProgrammerCommand.Contains("RAW_DATA") && ProgrammerRawMode)
{
LogFile.Log("Phone is not in raw mode ON, leaving...", LogType.FileAndConsole);
// Workaround for problem
// SerialPort is sometimes not disposed correctly when the device is already removed.
// So explicitly dispose here
Serial.Close();
LogFile.Log("Phone has been emergency flashed unsuccessfully!", LogType.FileAndConsole);
PayloadStream.Dispose();
return false;
}
if (Connected)
{
Serial.SendData(PacketFromPcToProgrammer);
}
if (ExpectingReplyFromProgrammer)
{
if (!Connected)
{
Connected = ConnectToProgrammer(PacketFromPcToProgrammer);
if (Connected)
{
LogFile.Log("Handshake completed with programmer in validated image programming (VIP) mode", LogType.FileAndConsole);
}
else
{
LogFile.Log("Handshake with programmer failed", LogType.FileAndConsole);
}
if (!Connected)
{
LogFile.Log("Phone programmer is now ignoring us, leaving...", LogType.FileAndConsole);
// Workaround for problem
// SerialPort is sometimes not disposed correctly when the device is already removed.
// So explicitly dispose here
Serial.Close();
LogFile.Log("Phone has been emergency flashed unsuccessfully!", LogType.FileAndConsole);
PayloadStream.Dispose();
return false;
}
}
else
{
do
{
Serial.SetTimeOut(500);
Incoming = Encoding.ASCII.GetString(Serial.GetResponse(null));
Serial.SetTimeOut(200);
LogFile.Log("In: " + Incoming, LogType.FileAndConsole);
}
while (Incoming.IndexOf("response value") < 0);
if (Incoming.Contains("rawmode=\"false\""))
{
ProgrammerRawMode = false;
LogFile.Log("Raw mode: OFF", LogType.FileAndConsole);
}
if (Incoming.Contains("rawmode=\"true\""))
{
ProgrammerRawMode = true;
LogFile.Log("Raw mode: ON", LogType.FileAndConsole);
}
if (!Incoming.Contains("ACK"))
{
LogFile.Log("Phone programmer is now ignoring us, leaving...", LogType.FileAndConsole);
// Workaround for problem
// SerialPort is sometimes not disposed correctly when the device is already removed.
// So explicitly dispose here
Serial.Close();
LogFile.Log("Phone has been emergency flashed unsuccessfully!", LogType.FileAndConsole);
PayloadStream.Dispose();
return false;
}
}
}
}
// Workaround for problem
// SerialPort is sometimes not disposed correctly when the device is already removed.
// So explicitly dispose here
Serial.Close();
LogFile.Log("Phone has been emergency flashed successfully!", LogType.FileAndConsole);
PayloadStream.Dispose();
return true;
}
}
}
@@ -1,228 +1,224 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.IO; using System.IO;
namespace WPinternals namespace WPinternals
{ {
internal enum FlashUnit internal enum FlashUnit
{ {
Bytes, Bytes,
Sectors Sectors
} }
internal class QualcommFlasher internal class QualcommFlasher
{ {
private readonly QualcommSerial Serial; private readonly QualcommSerial Serial;
public QualcommFlasher(QualcommSerial Serial) public QualcommFlasher(QualcommSerial Serial)
{ {
this.Serial = Serial; this.Serial = Serial;
} }
public void CloseSerial() public void CloseSerial()
{ {
Serial.Close(); Serial.Close();
} }
public void Hello() public void Hello()
{ {
byte[] Command = new byte[] byte[] Command =
{ [
0x01, // Hello command 0x01, // Hello command
0x51, 0x43, 0x4F, 0x4D, 0x20, 0x66, 0x61, 0x73, 0x74, 0x20, 0x64, 0x6F, 0x77, 0x6E, 0x6C, 0x6F, // "QCOM fast download protocol host" 0x51, 0x43, 0x4F, 0x4D, 0x20, 0x66, 0x61, 0x73, 0x74, 0x20, 0x64, 0x6F, 0x77, 0x6E, 0x6C, 0x6F, // "QCOM fast download protocol host"
0x61, 0x64, 0x20, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x20, 0x68, 0x6F, 0x73, 0x74, 0x61, 0x64, 0x20, 0x70, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x20, 0x68, 0x6F, 0x73, 0x74,
0x02, 0x02,
0x02, // Protocol version - Must be at least 0x02 0x02, // Protocol version - Must be at least 0x02
0x01 0x01
}; ];
Serial.SendCommand(Command, new byte[] { 0x02 }); Serial.SendCommand(Command, [0x02]);
} }
public void SetSecurityMode(byte Mode) public void SetSecurityMode(byte Mode)
{ {
byte[] Command = new byte[2]; byte[] Command = [0x17, Mode];
Command[0] = 0x17;
Command[1] = Mode; Serial.SendCommand(Command, [0x18]);
}
Serial.SendCommand(Command, new byte[] { 0x18 });
} // Use PartitionID 0x21
public void OpenPartition(byte PartitionID)
// Use PartitionID 0x21 {
public void OpenPartition(byte PartitionID) byte[] Command = [0x1B, PartitionID];
{
byte[] Command = new byte[2]; Serial.SendCommand(Command, [0x1C]);
Command[0] = 0x1B; }
Command[1] = PartitionID;
public void ClosePartition()
Serial.SendCommand(Command, new byte[] { 0x1C }); {
} Serial.SendCommand([0x15], [0x16]);
}
public void ClosePartition()
{ public void Flash(UInt32 StartInBytes, Stream Data, UInt32 LengthInBytes = UInt32.MaxValue)
Serial.SendCommand(new byte[] { 0x15 }, new byte[] { 0x16 }); {
} Flash(StartInBytes, Data, null, null, LengthInBytes);
}
public void Flash(UInt32 StartInBytes, Stream Data, UInt32 LengthInBytes = UInt32.MaxValue)
{ public void Flash(UInt32 StartInBytes, Stream Data, Action<int, TimeSpan?> ProgressUpdateCallback, UInt32 LengthInBytes = UInt32.MaxValue)
Flash(StartInBytes, Data, null, null, LengthInBytes); {
} Flash(StartInBytes, Data, ProgressUpdateCallback, null, LengthInBytes);
}
public void Flash(UInt32 StartInBytes, Stream Data, Action<int, TimeSpan?> ProgressUpdateCallback, UInt32 LengthInBytes = UInt32.MaxValue)
{ public void Flash(UInt32 StartInBytes, Stream Data, ProgressUpdater UpdaterPerSector, UInt32 LengthInBytes = UInt32.MaxValue)
Flash(StartInBytes, Data, ProgressUpdateCallback, null, LengthInBytes); {
} Flash(StartInBytes, Data, null, UpdaterPerSector, LengthInBytes);
}
public void Flash(UInt32 StartInBytes, Stream Data, ProgressUpdater UpdaterPerSector, UInt32 LengthInBytes = UInt32.MaxValue)
{ public void Flash(UInt32 StartInBytes, Stream Data, Action<int, TimeSpan?> ProgressUpdateCallback, ProgressUpdater UpdaterPerSector, UInt32 LengthInBytes = UInt32.MaxValue)
Flash(StartInBytes, Data, null, UpdaterPerSector, LengthInBytes); {
} long Remaining = (LengthInBytes == UInt32.MaxValue) || (LengthInBytes > (Data.Length - Data.Position))
? Data.Length - Data.Position
public void Flash(UInt32 StartInBytes, Stream Data, Action<int, TimeSpan?> ProgressUpdateCallback, ProgressUpdater UpdaterPerSector, UInt32 LengthInBytes = UInt32.MaxValue) : LengthInBytes;
{ UInt32 CurrentLength;
long Remaining = (LengthInBytes == UInt32.MaxValue) || (LengthInBytes > (Data.Length - Data.Position)) byte[] Buffer = new byte[0x405];
? Data.Length - Data.Position byte[] ResponsePattern = new byte[5];
: LengthInBytes; byte[] FinalCommand;
UInt32 CurrentLength; Buffer[0] = 0x07;
byte[] Buffer = new byte[0x405]; ResponsePattern[0] = 0x08;
byte[] ResponsePattern = new byte[5]; UInt32 CurrentPosition = StartInBytes;
byte[] FinalCommand;
Buffer[0] = 0x07; ProgressUpdater Progress = UpdaterPerSector;
ResponsePattern[0] = 0x08; if ((Progress == null) && (ProgressUpdateCallback != null))
UInt32 CurrentPosition = StartInBytes; {
Progress = new ProgressUpdater(GetSectorCount((UInt64)Remaining), ProgressUpdateCallback);
ProgressUpdater Progress = UpdaterPerSector; }
if ((Progress == null) && (ProgressUpdateCallback != null))
{ while (Remaining > 0)
Progress = new ProgressUpdater(GetSectorCount((UInt64)Remaining), ProgressUpdateCallback); {
} System.Buffer.BlockCopy(BitConverter.GetBytes(CurrentPosition), 0, Buffer, 1, 4); // Start is in bytes and in Little Endian (on Samsung devices start is in sectors!)
System.Buffer.BlockCopy(BitConverter.GetBytes(CurrentPosition), 0, ResponsePattern, 1, 4); // Start is in bytes and in Little Endian (on Samsung devices start is in sectors!)
while (Remaining > 0)
{ CurrentLength = Remaining >= 0x400 ? 0x400 : (UInt32)Remaining;
System.Buffer.BlockCopy(BitConverter.GetBytes(CurrentPosition), 0, Buffer, 1, 4); // Start is in bytes and in Little Endian (on Samsung devices start is in sectors!)
System.Buffer.BlockCopy(BitConverter.GetBytes(CurrentPosition), 0, ResponsePattern, 1, 4); // Start is in bytes and in Little Endian (on Samsung devices start is in sectors!) CurrentLength = (uint)Data.Read(Buffer, 5, (int)CurrentLength);
CurrentLength = Remaining >= 0x400 ? 0x400 : (UInt32)Remaining; if (CurrentLength < 0x400)
{
CurrentLength = (uint)Data.Read(Buffer, 5, (int)CurrentLength); FinalCommand = new byte[CurrentLength + 5];
System.Buffer.BlockCopy(Buffer, 0, FinalCommand, 0, (int)CurrentLength + 5);
if (CurrentLength < 0x400) }
{ else
FinalCommand = new byte[CurrentLength + 5]; {
System.Buffer.BlockCopy(Buffer, 0, FinalCommand, 0, (int)CurrentLength + 5); FinalCommand = Buffer;
} }
else
{ Serial.SendCommand(FinalCommand, ResponsePattern);
FinalCommand = Buffer;
} CurrentPosition += CurrentLength;
Remaining -= CurrentLength;
Serial.SendCommand(FinalCommand, ResponsePattern);
Progress?.IncreaseProgress(GetSectorCount(CurrentLength));
CurrentPosition += CurrentLength; }
Remaining -= CurrentLength; }
Progress?.IncreaseProgress(GetSectorCount(CurrentLength)); public void Flash(UInt32 StartInBytes, byte[] Data, UInt32 OffsetInBytes = 0, UInt32 LengthInBytes = UInt32.MaxValue)
} {
} Flash(StartInBytes, Data, null, null, OffsetInBytes, LengthInBytes);
}
public void Flash(UInt32 StartInBytes, byte[] Data, UInt32 OffsetInBytes = 0, UInt32 LengthInBytes = UInt32.MaxValue)
{ public void Flash(UInt32 StartInBytes, byte[] Data, Action<int, TimeSpan?> ProgressUpdateCallback, UInt32 OffsetInBytes = 0, UInt32 LengthInBytes = UInt32.MaxValue)
Flash(StartInBytes, Data, null, null, OffsetInBytes, LengthInBytes); {
} Flash(StartInBytes, Data, ProgressUpdateCallback, null, OffsetInBytes, LengthInBytes);
}
public void Flash(UInt32 StartInBytes, byte[] Data, Action<int, TimeSpan?> ProgressUpdateCallback, UInt32 OffsetInBytes = 0, UInt32 LengthInBytes = UInt32.MaxValue)
{ public void Flash(UInt32 StartInBytes, byte[] Data, ProgressUpdater UpdaterPerSector, UInt32 OffsetInBytes = 0, UInt32 LengthInBytes = UInt32.MaxValue)
Flash(StartInBytes, Data, ProgressUpdateCallback, null, OffsetInBytes, LengthInBytes); {
} Flash(StartInBytes, Data, null, UpdaterPerSector, OffsetInBytes, LengthInBytes);
}
public void Flash(UInt32 StartInBytes, byte[] Data, ProgressUpdater UpdaterPerSector, UInt32 OffsetInBytes = 0, UInt32 LengthInBytes = UInt32.MaxValue)
{ public void Flash(UInt32 StartInBytes, byte[] Data, Action<int, TimeSpan?> ProgressUpdateCallback, ProgressUpdater UpdaterPerSector, UInt32 OffsetInBytes = 0, UInt32 LengthInBytes = UInt32.MaxValue)
Flash(StartInBytes, Data, null, UpdaterPerSector, OffsetInBytes, LengthInBytes); {
} long RemainingBytes;
if (OffsetInBytes > (Data.Length - 1))
public void Flash(UInt32 StartInBytes, byte[] Data, Action<int, TimeSpan?> ProgressUpdateCallback, ProgressUpdater UpdaterPerSector, UInt32 OffsetInBytes = 0, UInt32 LengthInBytes = UInt32.MaxValue) {
{ throw new ArgumentException("Wrong offset");
long RemainingBytes; }
if (OffsetInBytes > (Data.Length - 1))
{ RemainingBytes = (LengthInBytes == UInt32.MaxValue) || (LengthInBytes > (Data.Length - OffsetInBytes))
throw new ArgumentException("Wrong offset"); ? Data.Length - OffsetInBytes
} : LengthInBytes;
RemainingBytes = (LengthInBytes == UInt32.MaxValue) || (LengthInBytes > (Data.Length - OffsetInBytes)) UInt32 CurrentLength;
? Data.Length - OffsetInBytes UInt32 CurrentOffset = OffsetInBytes;
: LengthInBytes; byte[] Buffer = new byte[0x405];
byte[] ResponsePattern = new byte[5];
UInt32 CurrentLength; byte[] FinalCommand;
UInt32 CurrentOffset = OffsetInBytes; Buffer[0] = 0x07;
byte[] Buffer = new byte[0x405]; ResponsePattern[0] = 0x08;
byte[] ResponsePattern = new byte[5]; UInt32 CurrentPosition = StartInBytes;
byte[] FinalCommand;
Buffer[0] = 0x07; ProgressUpdater Progress = UpdaterPerSector;
ResponsePattern[0] = 0x08; if ((Progress == null) && (ProgressUpdateCallback != null))
UInt32 CurrentPosition = StartInBytes; {
Progress = new ProgressUpdater(GetSectorCount((UInt64)RemainingBytes), ProgressUpdateCallback);
ProgressUpdater Progress = UpdaterPerSector; }
if ((Progress == null) && (ProgressUpdateCallback != null))
{ while (RemainingBytes > 0)
Progress = new ProgressUpdater(GetSectorCount((UInt64)RemainingBytes), ProgressUpdateCallback); {
} System.Buffer.BlockCopy(BitConverter.GetBytes(CurrentPosition), 0, Buffer, 1, 4); // Start position is in bytes and in Little Endian (on Samsung phones the start position is in Sectors!!)
System.Buffer.BlockCopy(BitConverter.GetBytes(CurrentPosition), 0, ResponsePattern, 1, 4); // Start position is in bytes and in Little Endian (on Samsung phones the start position is in Sectors!!)
while (RemainingBytes > 0)
{ CurrentLength = RemainingBytes >= 0x400 ? 0x400 : (UInt32)RemainingBytes;
System.Buffer.BlockCopy(BitConverter.GetBytes(CurrentPosition), 0, Buffer, 1, 4); // Start position is in bytes and in Little Endian (on Samsung phones the start position is in Sectors!!)
System.Buffer.BlockCopy(BitConverter.GetBytes(CurrentPosition), 0, ResponsePattern, 1, 4); // Start position is in bytes and in Little Endian (on Samsung phones the start position is in Sectors!!) System.Buffer.BlockCopy(Data, (int)CurrentOffset, Buffer, 5, (int)CurrentLength);
CurrentLength = RemainingBytes >= 0x400 ? 0x400 : (UInt32)RemainingBytes; if (CurrentLength < 0x400)
{
System.Buffer.BlockCopy(Data, (int)CurrentOffset, Buffer, 5, (int)CurrentLength); FinalCommand = new byte[CurrentLength + 5];
System.Buffer.BlockCopy(Buffer, 0, FinalCommand, 0, (int)CurrentLength + 5);
if (CurrentLength < 0x400) }
{ else
FinalCommand = new byte[CurrentLength + 5]; {
System.Buffer.BlockCopy(Buffer, 0, FinalCommand, 0, (int)CurrentLength + 5); FinalCommand = Buffer;
} }
else
{ Serial.SendCommand(FinalCommand, ResponsePattern);
FinalCommand = Buffer;
} CurrentPosition += CurrentLength;
CurrentOffset += CurrentLength;
Serial.SendCommand(FinalCommand, ResponsePattern); RemainingBytes -= CurrentLength;
CurrentPosition += CurrentLength; Progress?.IncreaseProgress(GetSectorCount(CurrentLength));
CurrentOffset += CurrentLength; }
RemainingBytes -= CurrentLength; }
Progress?.IncreaseProgress(GetSectorCount(CurrentLength)); public UInt64 GetSectorCount(UInt64 ByteCount)
} {
} return (ByteCount / 0x200) + ((ByteCount % 0x200) > 0 ? 1 : (UInt64)0);
}
public UInt64 GetSectorCount(UInt64 ByteCount)
{ public void Reboot()
return (ByteCount / 0x200) + ((ByteCount % 0x200) > 0 ? 1 : (UInt64)0); {
} Serial.SendCommand([0x0B], [0x0C]);
}
public void Reboot() }
{ }
Serial.SendCommand(new byte[] { 0x0B }, new byte[] { 0x0C });
}
}
}
@@ -1,125 +1,124 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
namespace WPinternals namespace WPinternals
{ {
internal static class QualcommLoaders internal static class QualcommLoaders
{ {
internal static List<QualcommPartition> GetPossibleLoadersForRootKeyHash(string Path, byte[] RootKeyHash) internal static List<QualcommPartition> GetPossibleLoadersForRootKeyHash(string Path, byte[] RootKeyHash)
{ {
List<QualcommPartition> Result = new(); List<QualcommPartition> Result = new();
try try
{ {
IEnumerable<string> FilePaths = Directory.EnumerateFiles(Path); foreach (string FilePath in Directory.EnumerateFiles(Path))
foreach (string FilePath in FilePaths) {
{ try
try {
{ FileInfo Info = new(FilePath);
FileInfo Info = new(FilePath); if (Info.Length <= 0x80000)
if (Info.Length <= 0x80000) {
{ QualcommPartition Loader;
QualcommPartition Loader;
#if DEBUG
#if DEBUG System.Diagnostics.Debug.Print("Evaluating loader: " + FilePath);
System.Diagnostics.Debug.Print("Evaluating loader: " + FilePath); #endif
#endif
byte[] Binary = ParseAsHexFile(FilePath);
byte[] Binary = ParseAsHexFile(FilePath); Loader = Binary == null ? new QualcommPartition(FilePath) : new QualcommPartition(Binary);
Loader = Binary == null ? new QualcommPartition(FilePath) : new QualcommPartition(Binary);
// Make sure the RootKeyHash is not blank
// Make sure the RootKeyHash is not blank // If the RootKeyHash is blank, this is an engineering device, and it will accept any RKH
// If the RootKeyHash is blank, this is an engineering device, and it will accept any RKH // We expect the user to know what he is doing in such case and we will ignore checks
// We expect the user to know what he is doing in such case and we will ignore checks if (!StructuralComparisons.StructuralEqualityComparer.Equals(RootKeyHash, new byte[RootKeyHash.Length]))
if (!StructuralComparisons.StructuralEqualityComparer.Equals(RootKeyHash, new byte[RootKeyHash.Length])) {
{ if (StructuralComparisons.StructuralEqualityComparer.Equals(Loader.RootKeyHash, RootKeyHash)
if (StructuralComparisons.StructuralEqualityComparer.Equals(Loader.RootKeyHash, RootKeyHash) && (ByteOperations.FindUnicode(Loader.Binary, "QHSUSB_ARMPRG") != null)) // To detect that this is a loader, and not SBL1 or something. V1 loaders are QHSUSB_ARMPRG. V2 loaders are QHSUSB__BULK. Only V1 supported for now, because V2 only accepts signed payload.
&& (ByteOperations.FindUnicode(Loader.Binary, "QHSUSB_ARMPRG") != null)) // To detect that this is a loader, and not SBL1 or something. V1 loaders are QHSUSB_ARMPRG. V2 loaders are QHSUSB__BULK. Only V1 supported for now, because V2 only accepts signed payload. {
{ Result.Add(Loader);
Result.Add(Loader); }
} }
} else
else {
{ if (ByteOperations.FindUnicode(Loader.Binary, "QHSUSB_ARMPRG") != null) // To detect that this is a loader, and not SBL1 or something. V1 loaders are QHSUSB_ARMPRG. V2 loaders are QHSUSB__BULK. Only V1 supported for now, because V2 only accepts signed payload.
if (ByteOperations.FindUnicode(Loader.Binary, "QHSUSB_ARMPRG") != null) // To detect that this is a loader, and not SBL1 or something. V1 loaders are QHSUSB_ARMPRG. V2 loaders are QHSUSB__BULK. Only V1 supported for now, because V2 only accepts signed payload. {
{ Result.Add(Loader);
Result.Add(Loader); }
} }
} }
} }
} catch { }
catch { } }
} }
} catch { }
catch { }
return Result;
return Result; }
}
internal static byte[] ParseAsHexFile(string FilePath)
internal static byte[] ParseAsHexFile(string FilePath) {
{ byte[] Result = null;
byte[] Result = null;
try
try {
{ string[] Lines = File.ReadAllLines(FilePath);
string[] Lines = File.ReadAllLines(FilePath); byte[] Buffer = null;
byte[] Buffer = null; int BufferSize = 0;
int BufferSize = 0;
foreach (string Line in Lines)
foreach (string Line in Lines) {
{ if (Line[0] != ':')
if (Line[0] != ':') {
{ throw new BadImageFormatException();
throw new BadImageFormatException(); }
}
byte[] LineBytes = Converter.ConvertStringToHex(Line[1..]);
byte[] LineBytes = Converter.ConvertStringToHex(Line[1..]);
if ((LineBytes[0] + 5) != LineBytes.Length)
if ((LineBytes[0] + 5) != LineBytes.Length) {
{ throw new BadImageFormatException();
throw new BadImageFormatException(); }
}
if (Buffer == null)
if (Buffer == null) {
{ Buffer = new byte[0x40000];
Buffer = new byte[0x40000]; }
}
if (LineBytes[3] == 0) // This is mem data
if (LineBytes[3] == 0) // This is mem data {
{ System.Buffer.BlockCopy(LineBytes, 4, Buffer, BufferSize, LineBytes[0]);
System.Buffer.BlockCopy(LineBytes, 4, Buffer, BufferSize, LineBytes[0]); BufferSize += LineBytes[0];
BufferSize += LineBytes[0]; }
} }
}
Result = new byte[BufferSize];
Result = new byte[BufferSize]; System.Buffer.BlockCopy(Buffer, 0, Result, 0, BufferSize);
System.Buffer.BlockCopy(Buffer, 0, Result, 0, BufferSize); }
} catch { }
catch { }
return Result;
return Result; }
} }
} }
}
@@ -1,174 +1,197 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.IO; using System.IO;
using System.Security.Cryptography; using System.Security.Cryptography;
namespace WPinternals namespace WPinternals
{ {
internal enum QualcommPartitionHeaderType internal enum QualcommPartitionHeaderType
{ {
Long, Long,
Short Short
}; };
internal class QualcommPartition internal class QualcommPartition
{ {
internal byte[] Binary; internal byte[] Binary;
internal uint HeaderOffset; internal uint HeaderOffset;
internal QualcommPartitionHeaderType HeaderType; internal QualcommPartitionHeaderType HeaderType;
internal uint ImageOffset; internal uint ImageOffset;
internal uint ImageAddress; internal uint ImageAddress;
internal uint ImageSize; internal uint ImageSize;
internal uint CodeSize; internal uint CodeSize;
internal uint SignatureAddress; internal uint SignatureAddress;
internal uint SignatureSize; internal uint SignatureSize;
internal uint SignatureOffset; internal uint SignatureOffset;
internal uint CertificatesAddress; internal uint CertificatesAddress;
internal uint CertificatesSize; internal uint CertificatesSize;
internal uint CertificatesOffset; internal uint CertificatesOffset;
internal byte[] RootKeyHash = null; internal byte[] RootKeyHash = null;
internal QualcommPartition(string Path) : this(File.ReadAllBytes(Path)) { } internal QualcommPartition(string Path) : this(File.ReadAllBytes(Path)) { }
internal QualcommPartition(byte[] Binary, uint Offset = 0) internal QualcommPartition(byte[] Binary, uint Offset = 0)
{ {
#if DEBUG #if DEBUG
System.Diagnostics.Debug.Print("Loader: " + Converter.ConvertHexToString(new SHA256Managed().ComputeHash(Binary, 0, Binary.Length), "")); System.Diagnostics.Debug.Print("Loader: " + Converter.ConvertHexToString(SHA256.HashData(Binary.AsSpan(0, Binary.Length)), ""));
#endif #endif
this.Binary = Binary; this.Binary = Binary;
byte[] LongHeaderPattern = new byte[] { 0xD1, 0xDC, 0x4B, 0x84, 0x34, 0x10, 0xD7, 0x73, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; byte[] LongHeaderPattern = [0xD1, 0xDC, 0x4B, 0x84, 0x34, 0x10, 0xD7, 0x73, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
byte[] LongHeaderMask = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; byte[] LongHeaderMask = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
if (ByteOperations.FindPattern(Binary, Offset, 4, new byte[] { 0x7F, 0x45, 0x4C, 0x46 }, new byte[] { 0x00, 0x00, 0x00, 0x00 }, null) == 0) if (ByteOperations.FindPattern(Binary, Offset, 4, [0x7F, 0x45, 0x4C, 0x46], [0x00, 0x00, 0x00, 0x00], null) == 0)
{ {
// This is an ELF image // This is an ELF image
// First program header is a reference to the elf-header // First program header is a reference to the elf-header
// Second program header is a reference to the signed hash-table // Second program header is a reference to the signed hash-table
HeaderType = QualcommPartitionHeaderType.Short; HeaderType = QualcommPartitionHeaderType.Short;
UInt32 ProgramHeaderOffset; UInt32 ProgramHeaderOffset;
UInt16 ProgramHeaderEntrySize; UInt16 ProgramHeaderEntrySize;
UInt32 HashTableProgramHeaderOffset; UInt32 HashTableProgramHeaderOffset;
if (Binary[Offset + 0x04] == 1) if (Binary[Offset + 0x04] == 1)
{ {
// 32-bit elf image // 32-bit elf image
ProgramHeaderOffset = Offset + ByteOperations.ReadUInt32(Binary, Offset + 0x1c); ProgramHeaderOffset = Offset + ByteOperations.ReadUInt32(Binary, Offset + 0x1c);
ProgramHeaderEntrySize = ByteOperations.ReadUInt16(Binary, Offset + 0x2a); ProgramHeaderEntrySize = ByteOperations.ReadUInt16(Binary, Offset + 0x2a);
HashTableProgramHeaderOffset = ProgramHeaderOffset + ProgramHeaderEntrySize; HashTableProgramHeaderOffset = ProgramHeaderOffset + ProgramHeaderEntrySize;
ImageOffset = Offset + ByteOperations.ReadUInt32(Binary, HashTableProgramHeaderOffset + 0x04); ImageOffset = Offset + ByteOperations.ReadUInt32(Binary, HashTableProgramHeaderOffset + 0x04);
HeaderOffset = ImageOffset + 8; HeaderOffset = ImageOffset + 8;
} }
else if (Binary[Offset + 0x04] == 2) else if (Binary[Offset + 0x04] == 2)
{ {
// 64-bit elf image // 64-bit elf image
ProgramHeaderOffset = Offset + ByteOperations.ReadUInt32(Binary, Offset + 0x20); ProgramHeaderOffset = Offset + ByteOperations.ReadUInt32(Binary, Offset + 0x20);
ProgramHeaderEntrySize = ByteOperations.ReadUInt16(Binary, Offset + 0x36); ProgramHeaderEntrySize = ByteOperations.ReadUInt16(Binary, Offset + 0x36);
HashTableProgramHeaderOffset = ProgramHeaderOffset + ProgramHeaderEntrySize; HashTableProgramHeaderOffset = ProgramHeaderOffset + ProgramHeaderEntrySize;
ImageOffset = Offset + (UInt32)ByteOperations.ReadUInt64(Binary, HashTableProgramHeaderOffset + 0x08); ImageOffset = Offset + (UInt32)ByteOperations.ReadUInt64(Binary, HashTableProgramHeaderOffset + 0x08);
HeaderOffset = ImageOffset + 8; HeaderOffset = ImageOffset + 8;
} }
else else
{ {
throw new WPinternalsException("Invalid programmer", "The type of elf image could not be determined from the provided programmer."); throw new WPinternalsException("Invalid programmer", "The type of elf image could not be determined from the provided programmer.");
} }
} }
else if (ByteOperations.FindPattern(Binary, Offset, (uint)LongHeaderPattern.Length, LongHeaderPattern, LongHeaderMask, null) == null) else if (ByteOperations.FindPattern(Binary, Offset, (uint)LongHeaderPattern.Length, LongHeaderPattern, LongHeaderMask, null) == null)
{ {
HeaderType = QualcommPartitionHeaderType.Short; HeaderType = QualcommPartitionHeaderType.Short;
ImageOffset = Offset; ImageOffset = Offset;
HeaderOffset = ImageOffset + 8; HeaderOffset = ImageOffset + 8;
} }
else else
{ {
HeaderType = QualcommPartitionHeaderType.Long; HeaderType = QualcommPartitionHeaderType.Long;
ImageOffset = Offset; ImageOffset = Offset;
HeaderOffset = ImageOffset + (uint)LongHeaderPattern.Length; HeaderOffset = ImageOffset + (uint)LongHeaderPattern.Length;
} }
if (ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X00) != 0) uint Version = ByteOperations.ReadUInt32(Binary, ImageOffset + 0X04);
{
ImageOffset = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X00); if (ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X00) != 0)
} {
else if (HeaderType == QualcommPartitionHeaderType.Short) ImageOffset = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X00);
{ }
ImageOffset += 0x28; else if (HeaderType == QualcommPartitionHeaderType.Short)
} {
else ImageOffset += 0x28;
{ }
ImageOffset += 0x50; else
} {
ImageOffset += 0x50;
ImageAddress = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X04); }
ImageSize = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X08);
CodeSize = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X0C); ImageAddress = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X04);
SignatureAddress = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X10); ImageSize = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X08);
SignatureSize = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X14); CodeSize = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X0C);
SignatureOffset = SignatureAddress - ImageAddress + ImageOffset; SignatureAddress = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X10);
CertificatesAddress = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X18); SignatureSize = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X14);
CertificatesSize = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X1C); CertificatesAddress = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X18);
CertificatesOffset = CertificatesAddress - ImageAddress + ImageOffset; CertificatesSize = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X1C);
uint CurrentCertificateOffset = CertificatesOffset; if (SignatureAddress == 0xFFFFFFFF)
uint CertificateSize = 0; {
while (CurrentCertificateOffset < (CertificatesOffset + CertificatesSize)) SignatureAddress = ImageAddress + CodeSize;
{ }
if ((Binary[CurrentCertificateOffset] == 0x30) && (Binary[CurrentCertificateOffset + 1] == 0x82))
{ if (CertificatesAddress == 0xFFFFFFFF)
CertificateSize = (uint)(Binary[CurrentCertificateOffset + 2] * 0x100) + Binary[CurrentCertificateOffset + 3] + 4; // Big endian! {
CertificatesAddress = SignatureAddress + SignatureSize;
if ((CurrentCertificateOffset + CertificateSize) == (CertificatesOffset + CertificatesSize)) }
{
// This is the last certificate. So this is the root key. // Headers newer than version 5 need more padding here
RootKeyHash = new SHA256Managed().ComputeHash(Binary, (int)CurrentCertificateOffset, (int)CertificateSize); if (Version > 5)
{
#if DEBUG ImageOffset += 0x80;
System.Diagnostics.Debug.Print("RKH: " + Converter.ConvertHexToString(RootKeyHash, "")); }
#endif
} SignatureOffset = ImageOffset + CodeSize;
#if DEBUG CertificatesOffset = ImageOffset + CodeSize + SignatureSize;
else
{ // Keeping just in case
System.Diagnostics.Debug.Print("Cert: " + Converter.ConvertHexToString(new SHA256Managed().ComputeHash(Binary, (int)CurrentCertificateOffset, (int)CertificateSize), "")); // SignatureOffset = SignatureAddress - ImageAddress + ImageOffset;
} // CertificatesOffset = ImageSize - CertificatesSize + ImageOffset;
#endif
CurrentCertificateOffset += CertificateSize; uint CurrentCertificateOffset = CertificatesOffset;
} uint CertificateSize = 0;
else while (CurrentCertificateOffset < (CertificatesOffset + CertificatesSize))
{ {
if ((RootKeyHash == null) && (CurrentCertificateOffset > CertificatesOffset)) if ((Binary[CurrentCertificateOffset] == 0x30) && (Binary[CurrentCertificateOffset + 1] == 0x82))
{ {
CurrentCertificateOffset -= CertificateSize; CertificateSize = (uint)(Binary[CurrentCertificateOffset + 2] * 0x100) + Binary[CurrentCertificateOffset + 3] + 4; // Big endian!
// This is the last certificate. So this is the root key. if ((CurrentCertificateOffset + CertificateSize) == (CertificatesOffset + CertificatesSize))
RootKeyHash = new SHA256Managed().ComputeHash(Binary, (int)CurrentCertificateOffset, (int)CertificateSize); {
// This is the last certificate. So this is the root key.
#if DEBUG RootKeyHash = SHA256.HashData(Binary.AsSpan((int)CurrentCertificateOffset, (int)CertificateSize));
System.Diagnostics.Debug.Print("RKH: " + Converter.ConvertHexToString(RootKeyHash, ""));
#endif #if DEBUG
} System.Diagnostics.Debug.Print("RKH: " + Converter.ConvertHexToString(RootKeyHash, ""));
break; #endif
} }
} #if DEBUG
} else
} {
} System.Diagnostics.Debug.Print("Cert: " + Converter.ConvertHexToString(SHA256.HashData(Binary.AsSpan((int)CurrentCertificateOffset, (int)CertificateSize)), ""));
}
#endif
CurrentCertificateOffset += CertificateSize;
}
else
{
if ((RootKeyHash == null) && (CurrentCertificateOffset > CertificatesOffset))
{
CurrentCertificateOffset -= CertificateSize;
// This is the last certificate. So this is the root key.
RootKeyHash = SHA256.HashData(Binary.AsSpan((int)CurrentCertificateOffset, (int)CertificateSize));
#if DEBUG
System.Diagnostics.Debug.Print("RKH: " + Converter.ConvertHexToString(RootKeyHash, ""));
#endif
}
break;
}
}
}
}
}
+361
View File
@@ -0,0 +1,361 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
namespace WPinternals
{
internal delegate void ReadyHandler();
internal class QualcommSahara
{
private readonly QualcommSerial Serial;
public QualcommSahara(QualcommSerial Serial)
{
Serial.EncodeCommands = false;
Serial.DecodeResponses = false;
this.Serial = Serial;
}
private static byte[] BuildCommandPacket(QualcommSaharaCommand SaharaCommand, byte[] CommandBuffer = null)
{
UInt32 CommandID = (uint)SaharaCommand;
UInt32 CommandBufferLength = 0;
if (CommandBuffer != null)
{
CommandBufferLength = (UInt32)CommandBuffer.Length;
}
UInt32 Length = 0x8u + CommandBufferLength;
byte[] Packet = new byte[Length];
ByteOperations.WriteUInt32(Packet, 0x00, CommandID);
ByteOperations.WriteUInt32(Packet, 0x04, Length);
if (CommandBuffer != null && CommandBufferLength != 0)
{
Buffer.BlockCopy(CommandBuffer, 0, Packet, 0x08, CommandBuffer.Length);
}
return Packet;
}
private static byte[] BuildHelloResponsePacket(QualcommSaharaMode SaharaMode, UInt32 ProtocolVersion = 2, UInt32 SupportedVersion = 1, UInt32 MaxPacketLength = 0 /* 0: Status OK */)
{
UInt32 Mode = (uint)SaharaMode;
// Hello packet:
// xxxxxxxx = Protocol version
// xxxxxxxx = Supported version
// xxxxxxxx = Max packet length
// xxxxxxxx = Expected mode
// 6 dwords reserved space
byte[] Hello = new byte[0x28];
ByteOperations.WriteUInt32(Hello, 0x00, ProtocolVersion);
ByteOperations.WriteUInt32(Hello, 0x04, SupportedVersion);
ByteOperations.WriteUInt32(Hello, 0x08, MaxPacketLength);
ByteOperations.WriteUInt32(Hello, 0x0C, Mode);
ByteOperations.WriteUInt32(Hello, 0x10, 0);
ByteOperations.WriteUInt32(Hello, 0x14, 0);
ByteOperations.WriteUInt32(Hello, 0x18, 0);
ByteOperations.WriteUInt32(Hello, 0x1C, 0);
ByteOperations.WriteUInt32(Hello, 0x20, 0);
ByteOperations.WriteUInt32(Hello, 0x24, 0);
return BuildCommandPacket(QualcommSaharaCommand.HelloResponse, Hello);
}
private static byte[] BuildExecuteRequestPacket(UInt32 RequestID)
{
byte[] Execute = new byte[0x04];
ByteOperations.WriteUInt32(Execute, 0x00, RequestID);
return BuildCommandPacket(QualcommSaharaCommand.ExecuteRequest, Execute);
}
private static byte[] BuildExecuteDataPacket(UInt32 RequestID)
{
byte[] Execute = new byte[0x04];
ByteOperations.WriteUInt32(Execute, 0x00, RequestID);
return BuildCommandPacket(QualcommSaharaCommand.ExecuteData, Execute);
}
public byte[][] GetRKHs()
{
Serial.SendData(BuildExecuteRequestPacket(0x3));
byte[] ReadDataRequest = Serial.GetResponse(null);
UInt32 ResponseID = ByteOperations.ReadUInt32(ReadDataRequest, 0);
if (ResponseID != 0xE)
{
throw new BadConnectionException();
}
uint RKHLength = ByteOperations.ReadUInt32(ReadDataRequest, 0x0C);
Serial.SendData(BuildExecuteDataPacket(0x3));
byte[] Response = Serial.GetResponse(null, Length: (int)RKHLength);
List<byte[]> RootKeyHashes = new();
for (int i = 0; i < RKHLength / 0x20; i++)
{
RootKeyHashes.Add(Response[(i * 0x20)..((i + 1) * 0x20)]);
}
return [.. RootKeyHashes];
}
public byte[] GetRKH()
{
int Step = 0;
UInt32 Offset = 0;
UInt32 Length = 0;
try
{
Step = 1;
byte[] Hello = Serial.GetResponse([0x01, 0x00, 0x00, 0x00]);
// Incoming Hello packet:
// 00000001 = Hello command id
// xxxxxxxx = Length
// xxxxxxxx = Protocol version
// xxxxxxxx = Supported version
// xxxxxxxx = Max packet length
// xxxxxxxx = Expected mode
// 6 dwords reserved space
LogFile.Log("Protocol: 0x" + ByteOperations.ReadUInt32(Hello, 0x08).ToString("X8"), LogType.FileOnly);
LogFile.Log("Supported: 0x" + ByteOperations.ReadUInt32(Hello, 0x0C).ToString("X8"), LogType.FileOnly);
LogFile.Log("MaxLength: 0x" + ByteOperations.ReadUInt32(Hello, 0x10).ToString("X8"), LogType.FileOnly);
LogFile.Log("Mode: 0x" + ByteOperations.ReadUInt32(Hello, 0x14).ToString("X8"), LogType.FileOnly);
Step = 2;
byte[] HelloResponse = BuildHelloResponsePacket(QualcommSaharaMode.Command);
Serial.SendData(HelloResponse);
Step = 3;
byte[] ReadDataRequest = Serial.GetResponse(null);
UInt32 ResponseID = ByteOperations.ReadUInt32(ReadDataRequest, 0);
if (ResponseID != 0xB)
{
throw new BadConnectionException();
}
Step = 4;
byte[][] RKHs = GetRKHs();
return RKHs[0];
}
catch (Exception Ex)
{
LogFile.LogException(Ex, LogType.FileAndConsole, Step.ToString() + " 0x" + Offset.ToString("X8") + " 0x" + Length.ToString("X8"));
}
return null;
}
public bool SendImage(string Path)
{
bool Result = true;
LogFile.Log("Sending programmer: " + Path, LogType.FileOnly);
int Step = 0;
UInt32 Offset = 0;
UInt32 Length = 0;
byte[] ImageBuffer = null;
try
{
Step = 1;
byte[] Hello = Serial.GetResponse([0x01, 0x00, 0x00, 0x00]);
// Incoming Hello packet:
// 00000001 = Hello command id
// xxxxxxxx = Length
// xxxxxxxx = Protocol version
// xxxxxxxx = Supported version
// xxxxxxxx = Max packet length
// xxxxxxxx = Expected mode
// 6 dwords reserved space
LogFile.Log("Protocol: 0x" + ByteOperations.ReadUInt32(Hello, 0x08).ToString("X8"), LogType.FileOnly);
LogFile.Log("Supported: 0x" + ByteOperations.ReadUInt32(Hello, 0x0C).ToString("X8"), LogType.FileOnly);
LogFile.Log("MaxLength: 0x" + ByteOperations.ReadUInt32(Hello, 0x10).ToString("X8"), LogType.FileOnly);
LogFile.Log("Mode: 0x" + ByteOperations.ReadUInt32(Hello, 0x14).ToString("X8"), LogType.FileOnly);
Step = 2;
byte[] HelloResponse = BuildHelloResponsePacket(QualcommSaharaMode.ImageTransferPending);
Serial.SendData(HelloResponse);
Step = 3;
using FileStream FileStream = new(Path, FileMode.Open, FileAccess.Read);
while (true)
{
Step = 4;
byte[] ReadDataRequest = Serial.GetResponse(null);
UInt32 ResponseID = ByteOperations.ReadUInt32(ReadDataRequest, 0);
if (ResponseID == 4)
{
break;
}
if (ResponseID != 3)
{
Step = 5;
throw new BadConnectionException();
}
Offset = ByteOperations.ReadUInt32(ReadDataRequest, 0x0C);
Length = ByteOperations.ReadUInt32(ReadDataRequest, 0x10);
if ((ImageBuffer == null) || (ImageBuffer.Length != Length))
{
ImageBuffer = new byte[Length];
}
if (FileStream.Position != Offset)
{
FileStream.Seek(Offset, SeekOrigin.Begin);
}
Step = 6;
FileStream.Read(ImageBuffer, 0, (int)Length);
Step = 7;
Serial.SendData(ImageBuffer);
}
}
catch (Exception Ex)
{
LogFile.LogException(Ex, LogType.FileAndConsole, Step.ToString() + " 0x" + Offset.ToString("X8") + " 0x" + Length.ToString("X8"));
Result = false;
}
if (Result)
{
LogFile.Log("Programmer loaded into phone memory", LogType.FileOnly);
}
return Result;
}
public bool Handshake()
{
bool Result = true;
try
{
byte[] Hello = Serial.GetResponse([0x01, 0x00, 0x00, 0x00]);
// Incoming Hello packet:
// 00000001 = Hello command id
// xxxxxxxx = Length
// xxxxxxxx = Protocol version
// xxxxxxxx = Supported version
// xxxxxxxx = Max packet length
// xxxxxxxx = Expected mode
// 6 dwords reserved space
LogFile.Log("Protocol: 0x" + ByteOperations.ReadUInt32(Hello, 0x08).ToString("X8"), LogType.FileOnly);
LogFile.Log("Supported: 0x" + ByteOperations.ReadUInt32(Hello, 0x0C).ToString("X8"), LogType.FileOnly);
LogFile.Log("MaxLength: 0x" + ByteOperations.ReadUInt32(Hello, 0x10).ToString("X8"), LogType.FileOnly);
LogFile.Log("Mode: 0x" + ByteOperations.ReadUInt32(Hello, 0x14).ToString("X8"), LogType.FileOnly);
byte[] HelloResponse = BuildHelloResponsePacket(QualcommSaharaMode.ImageTransferPending);
byte[] Ready = Serial.SendCommand(HelloResponse, [0x03, 0x00, 0x00, 0x00]);
}
catch
{
Result = false;
}
return Result;
}
public void ResetSahara()
{
Serial.SendCommand(BuildCommandPacket(QualcommSaharaCommand.ResetRequest), [0x08, 0x00, 0x00, 0x00]);
}
public void SwitchMode(QualcommSaharaMode Mode)
{
byte[] SwitchMode = new byte[0x04];
ByteOperations.WriteUInt32(SwitchMode, 0x00, (UInt32)Mode);
byte[] SwitchModeCommand = BuildCommandPacket(QualcommSaharaCommand.SwitchMode, SwitchMode);
byte[] ResponsePattern = null;
switch (Mode)
{
case QualcommSaharaMode.ImageTransferPending:
ResponsePattern = [0x04, 0x00, 0x00, 0x00];
break;
case QualcommSaharaMode.MemoryDebug:
ResponsePattern = [0x09, 0x00, 0x00, 0x00];
break;
case QualcommSaharaMode.Command:
ResponsePattern = [0x0B, 0x00, 0x00, 0x00];
break;
}
Serial.SendCommand(SwitchModeCommand, ResponsePattern);
}
public void StartProgrammer()
{
LogFile.Log("Starting programmer", LogType.FileAndConsole);
byte[] DoneCommand = BuildCommandPacket(QualcommSaharaCommand.DoneRequest);
bool Started = false;
int count = 0;
do
{
count++;
try
{
byte[] DoneResponse = Serial.SendCommand(DoneCommand, [0x06, 0x00, 0x00, 0x00]);
Started = true;
}
catch (BadConnectionException)
{
LogFile.Log("Problem while starting programmer. Attempting again.", LogType.FileAndConsole);
}
} while (!Started && count < 3);
if (count >= 3 && !Started)
{
LogFile.Log("Maximum number of attempts to start the programmer exceeded.", LogType.FileAndConsole);
throw new BadConnectionException();
}
LogFile.Log("Programmer being launched on phone", LogType.FileOnly);
}
public async Task<bool> LoadProgrammer(string ProgrammerPath)
{
bool SendImageResult = await Task.Run(() => SendImage(ProgrammerPath));
if (!SendImageResult)
{
return false;
}
await Task.Run(() => StartProgrammer());
return true;
}
}
}
@@ -0,0 +1,45 @@
// 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
{
internal enum QualcommSaharaCommand : uint
{
HelloRequest = 0x01,
HelloResponse = 0x02,
ReadData = 0x03,
EndTransfer = 0x04,
DoneRequest = 0x05,
DoneResponse = 0x06,
ResetRequest = 0x07,
ResetResponse = 0x08,
MemoryDebug = 0x09,
MemoryRead = 0x0A,
CommandReady = 0x0B,
SwitchMode = 0x0C,
ExecuteRequest = 0x0D,
ExecuteResponse = 0x0E,
ExecuteData = 0x0F,
MemoryDebug64 = 0x10,
MemoryRead64 = 0x11,
MemoryReadData64 = 0x12,
ResetStateMachineIdentifier = 0x13
}
}
+30
View File
@@ -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.
namespace WPinternals
{
internal enum QualcommSaharaMode : uint
{
ImageTransferPending = 0x00,
ImagetransferComplete = 0x01,
MemoryDebug = 0x02,
Command = 0x03
}
}
@@ -1,379 +1,379 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using MadWizard.WinUSBNet; using MadWizard.WinUSBNet;
using System; using System;
using System.IO.Ports; using System.IO.Ports;
namespace WPinternals namespace WPinternals
{ {
internal class QualcommSerial : IDisposable internal class QualcommSerial : IDisposable
{ {
private bool Disposed = false; private bool Disposed = false;
private readonly SerialPort Port = null; private readonly SerialPort Port = null;
private readonly USBDevice USBDevice = null; private readonly USBDevice USBDevice = null;
private readonly CRC16 CRC16; private readonly CRC16 CRC16;
public bool EncodeCommands = true; public bool EncodeCommands = true;
public bool DecodeResponses = true; public bool DecodeResponses = true;
public QualcommSerial(string DevicePath) public QualcommSerial(string DevicePath)
{ {
CRC16 = new CRC16(0x1189, 0xFFFF, 0xFFFF); CRC16 = new CRC16(0x1189, 0xFFFF, 0xFFFF);
string[] DevicePathElements = DevicePath.Split(new char[] { '#' }); string[] DevicePathElements = DevicePath.Split(['#']);
if (string.Equals(DevicePathElements[3], "{86E0D1E0-8089-11D0-9CE4-08003E301F73}", StringComparison.CurrentCultureIgnoreCase)) if (string.Equals(DevicePathElements[3], "{86E0D1E0-8089-11D0-9CE4-08003E301F73}", StringComparison.CurrentCultureIgnoreCase))
{ {
string PortName = (string)Microsoft.Win32.Registry.GetValue(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\" + DevicePathElements[1] + @"\" + DevicePathElements[2] + @"\Device Parameters", "PortName", null); string PortName = (string)Microsoft.Win32.Registry.GetValue(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\" + DevicePathElements[1] + @"\" + DevicePathElements[2] + @"\Device Parameters", "PortName", null);
if (PortName != null) if (PortName != null)
{ {
Port = new SerialPort(PortName, 115200) Port = new SerialPort(PortName, 115200)
{ {
ReadTimeout = 1000, ReadTimeout = 1000,
WriteTimeout = 1000 WriteTimeout = 1000
}; };
Port.Open(); Port.Open();
} }
} }
else else
{ {
try try
{ {
this.USBDevice = new USBDevice(DevicePath); this.USBDevice = new USBDevice(DevicePath);
} }
catch { } catch { }
} }
} }
public void SendData(byte[] Data) public void SendData(byte[] Data)
{ {
byte[] FormattedData = EncodeCommands ? FormatCommand(Data) : Data; byte[] FormattedData = EncodeCommands ? FormatCommand(Data) : Data;
Port?.Write(FormattedData, 0, FormattedData.Length); Port?.Write(FormattedData, 0, FormattedData.Length);
if (USBDevice != null) if (USBDevice != null)
{ {
USBDevice.OutputPipe.Write(FormattedData); USBDevice.OutputPipe.Write(FormattedData);
} }
} }
public byte[] SendCommand(byte[] Command, byte[] ResponsePattern) public byte[] SendCommand(byte[] Command, byte[] ResponsePattern)
{ {
byte[] FormattedCommand = EncodeCommands ? FormatCommand(Command) : Command; byte[] FormattedCommand = EncodeCommands ? FormatCommand(Command) : Command;
Port?.Write(FormattedCommand, 0, FormattedCommand.Length); Port?.Write(FormattedCommand, 0, FormattedCommand.Length);
if (USBDevice != null) if (USBDevice != null)
{ {
USBDevice.OutputPipe.Write(FormattedCommand); USBDevice.OutputPipe.Write(FormattedCommand);
} }
return GetResponse(ResponsePattern); return GetResponse(ResponsePattern);
} }
internal byte[] GetResponse(byte[] ResponsePattern) internal byte[] GetResponse(byte[] ResponsePattern, int Length = 0x2000)
{ {
byte[] ResponseBuffer = new byte[0x2000]; byte[] ResponseBuffer = new byte[Length];
int Length = 0; Length = 0;
bool IsIncomplete = false; bool IsIncomplete = false;
do do
{ {
IsIncomplete = false; IsIncomplete = false;
try try
{ {
int BytesRead = 0; int BytesRead = 0;
if (Port != null) if (Port != null)
{ {
BytesRead = Port.Read(ResponseBuffer, Length, ResponseBuffer.Length - Length); BytesRead = Port.Read(ResponseBuffer, Length, ResponseBuffer.Length - Length);
} }
if (USBDevice != null) if (USBDevice != null)
{ {
BytesRead = USBDevice.InputPipe.Read(ResponseBuffer); BytesRead = USBDevice.InputPipe.Read(ResponseBuffer);
} }
if (BytesRead == 0) if (BytesRead == 0)
{ {
LogFile.Log("Emergency mode of phone is ignoring us", LogType.FileAndConsole); LogFile.Log("Emergency mode of phone is ignoring us", LogType.FileAndConsole);
throw new BadMessageException(); throw new BadMessageException();
} }
Length += BytesRead; Length += BytesRead;
byte[] DecodedResponse; byte[] DecodedResponse;
if (DecodeResponses) if (DecodeResponses)
{ {
DecodedResponse = DecodeResponse(ResponseBuffer, (UInt32)Length); DecodedResponse = DecodeResponse(ResponseBuffer, (UInt32)Length);
} }
else else
{ {
DecodedResponse = new byte[Length]; DecodedResponse = new byte[Length];
Buffer.BlockCopy(ResponseBuffer, 0, DecodedResponse, 0, Length); Buffer.BlockCopy(ResponseBuffer, 0, DecodedResponse, 0, Length);
} }
if (ResponsePattern != null) if (ResponsePattern != null)
{ {
for (int i = 0; i < ResponsePattern.Length; i++) for (int i = 0; i < ResponsePattern.Length; i++)
{ {
if (DecodedResponse[i] != ResponsePattern[i]) if (DecodedResponse[i] != ResponsePattern[i])
{ {
byte[] LogResponse = new byte[DecodedResponse.Length < 0x10 ? DecodedResponse.Length : 0x10]; byte[] LogResponse = new byte[DecodedResponse.Length < 0x10 ? DecodedResponse.Length : 0x10];
LogFile.Log("Qualcomm serial response: " + Converter.ConvertHexToString(LogResponse, ""), LogType.FileOnly); LogFile.Log("Qualcomm serial response: " + Converter.ConvertHexToString(LogResponse, ""), LogType.FileOnly);
LogFile.Log("Expected: " + Converter.ConvertHexToString(ResponsePattern, ""), LogType.FileOnly); LogFile.Log("Expected: " + Converter.ConvertHexToString(ResponsePattern, ""), LogType.FileOnly);
throw new BadMessageException(); throw new BadMessageException();
} }
} }
} }
return DecodedResponse; return DecodedResponse;
} }
catch (IncompleteMessageException) catch (IncompleteMessageException)
{ {
IsIncomplete = true; IsIncomplete = true;
} }
catch { } // Will be rethrown as BadConnectionException catch { } // Will be rethrown as BadConnectionException
} }
while (IsIncomplete); while (IsIncomplete);
Port?.DiscardInBuffer(); Port?.DiscardInBuffer();
if (USBDevice != null) if (USBDevice != null)
{ {
USBDevice.InputPipe.Flush(); USBDevice.InputPipe.Flush();
} }
throw new BadConnectionException(); throw new BadConnectionException();
} }
private byte[] FormatCommand(byte[] Command) private byte[] FormatCommand(byte[] Command)
{ {
if ((Command == null) || (Command.Length == 0)) if ((Command == null) || (Command.Length == 0))
{ {
throw new BadMessageException(); throw new BadMessageException();
} }
byte[] Decoded = new byte[(Command.Length * 2) + 4]; byte[] Decoded = new byte[(Command.Length * 2) + 4];
int Length = 0; int Length = 0;
Decoded[Length++] = 0x7E; Decoded[Length++] = 0x7E;
for (int i = 0; i < Command.Length; i++) for (int i = 0; i < Command.Length; i++)
{ {
if ((Command[i] == 0x7D) || (Command[i] == 0x7E)) if ((Command[i] == 0x7D) || (Command[i] == 0x7E))
{ {
Decoded[Length++] = 0x7D; Decoded[Length++] = 0x7D;
Decoded[Length++] = (byte)(Command[i] ^ 0x20); Decoded[Length++] = (byte)(Command[i] ^ 0x20);
} }
else else
{ {
Decoded[Length++] = Command[i]; Decoded[Length++] = Command[i];
} }
} }
UInt16 Checksum = CRC16.CalculateChecksum(Command); UInt16 Checksum = CRC16.CalculateChecksum(Command);
if (((byte)(Checksum & 0xFF) == 0x7D) || ((byte)(Checksum & 0xFF) == 0x7E)) if (((byte)(Checksum & 0xFF) == 0x7D) || ((byte)(Checksum & 0xFF) == 0x7E))
{ {
Decoded[Length++] = 0x7D; Decoded[Length++] = 0x7D;
Decoded[Length++] = (byte)((Checksum & 0xFF) ^ 0x20); Decoded[Length++] = (byte)((Checksum & 0xFF) ^ 0x20);
} }
else else
{ {
Decoded[Length++] = (byte)(Checksum & 0xFF); Decoded[Length++] = (byte)(Checksum & 0xFF);
} }
if (((byte)(Checksum >> 8) == 0x7D) || ((byte)(Checksum >> 8) == 0x7E)) if (((byte)(Checksum >> 8) == 0x7D) || ((byte)(Checksum >> 8) == 0x7E))
{ {
Decoded[Length++] = 0x7D; Decoded[Length++] = 0x7D;
Decoded[Length++] = (byte)((Checksum >> 8) ^ 0x20); Decoded[Length++] = (byte)((Checksum >> 8) ^ 0x20);
} }
else else
{ {
Decoded[Length++] = (byte)(Checksum >> 8); Decoded[Length++] = (byte)(Checksum >> 8);
} }
Decoded[Length++] = 0x7E; Decoded[Length++] = 0x7E;
if (Length > 0) if (Length > 0)
{ {
byte[] Result = new byte[Length]; byte[] Result = new byte[Length];
Buffer.BlockCopy(Decoded, 0, Result, 0, Length); Buffer.BlockCopy(Decoded, 0, Result, 0, Length);
return Result; return Result;
} }
else else
{ {
return null; return null;
} }
} }
private byte[] DecodeResponse(byte[] Response, UInt32 Length) private byte[] DecodeResponse(byte[] Response, UInt32 Length)
{ {
if ((Response == null) || (Response.Length == 0) || (Response[0] != 0x7E)) if ((Response == null) || (Response.Length == 0) || (Response[0] != 0x7E))
{ {
throw new BadMessageException(); throw new BadMessageException();
} }
UInt32 SourceLength = Length; UInt32 SourceLength = Length;
Length = 0; Length = 0;
UInt32 SourcePos = 1; UInt32 SourcePos = 1;
byte[] Message = new byte[SourceLength]; byte[] Message = new byte[SourceLength];
while (SourcePos < SourceLength) while (SourcePos < SourceLength)
{ {
if (Response[SourcePos] == 0x7E) if (Response[SourcePos] == 0x7E)
{ {
break; break;
} }
Message[Length++] = Response[SourcePos] == 0x7D ? (byte)(Response[++SourcePos] ^ 0x20) : Response[SourcePos]; Message[Length++] = Response[SourcePos] == 0x7D ? (byte)(Response[++SourcePos] ^ 0x20) : Response[SourcePos];
SourcePos++; SourcePos++;
} }
if (SourcePos == SourceLength) if (SourcePos == SourceLength)
{ {
throw new IncompleteMessageException(); throw new IncompleteMessageException();
} }
if (Length < 3) if (Length < 3)
{ {
throw new BadMessageException(); throw new BadMessageException();
} }
byte[] TrimmedMessage = new byte[Length - 2]; byte[] TrimmedMessage = new byte[Length - 2];
Buffer.BlockCopy(Message, 0, TrimmedMessage, 0, (int)(Length - 2)); Buffer.BlockCopy(Message, 0, TrimmedMessage, 0, (int)(Length - 2));
UInt16 Checksum = CRC16.CalculateChecksum(TrimmedMessage); UInt16 Checksum = CRC16.CalculateChecksum(TrimmedMessage);
if (((byte)(Checksum & 0xFF) != Message[Length - 2]) || ((byte)(Checksum >> 8) != Message[Length - 1])) if (((byte)(Checksum & 0xFF) != Message[Length - 2]) || ((byte)(Checksum >> 8) != Message[Length - 1]))
{ {
throw new BadMessageException(); throw new BadMessageException();
} }
return TrimmedMessage; return TrimmedMessage;
} }
public void Dispose() public void Dispose()
{ {
Dispose(true); Dispose(true);
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
~QualcommSerial() ~QualcommSerial()
{ {
Dispose(false); Dispose(false);
} }
public void Close() public void Close()
{ {
Port?.Close(); Port?.Close();
USBDevice?.Dispose(); USBDevice?.Dispose();
} }
protected virtual void Dispose(bool disposing) protected virtual void Dispose(bool disposing)
{ {
if (Disposed) if (Disposed)
{ {
return; return;
} }
if (disposing) if (disposing)
{ {
// Other disposables // Other disposables
} }
// Clean unmanaged resources here. // Clean unmanaged resources here.
Close(); Close();
Disposed = true; Disposed = true;
} }
internal void SetTimeOut(int v) internal void SetTimeOut(int v)
{ {
if (USBDevice != null) if (USBDevice != null)
{ {
USBDevice.ControlPipeTimeout = v; USBDevice.ControlPipeTimeout = v;
} }
if (Port != null) if (Port != null)
{ {
Port.ReadTimeout = v; Port.ReadTimeout = v;
Port.WriteTimeout = v; Port.WriteTimeout = v;
} }
} }
} }
public class IncompleteMessageException : Exception { public IncompleteMessageException() { } public IncompleteMessageException(string message) : base(message) { } public IncompleteMessageException(string message, Exception innerException) : base(message, innerException) { } } public class IncompleteMessageException : Exception { public IncompleteMessageException() { } public IncompleteMessageException(string message) : base(message) { } public IncompleteMessageException(string message, Exception innerException) : base(message, innerException) { } }
public class BadMessageException : Exception { public BadMessageException() { } public BadMessageException(string message) : base(message) { } public BadMessageException(string message, Exception innerException) : base(message, innerException) { } } public class BadMessageException : Exception { public BadMessageException() { } public BadMessageException(string message) : base(message) { } public BadMessageException(string message, Exception innerException) : base(message, innerException) { } }
public class BadConnectionException : Exception { public BadConnectionException() { } public BadConnectionException(string message) : base(message) { } public BadConnectionException(string message, Exception innerException) : base(message, innerException) { } } public class BadConnectionException : Exception { public BadConnectionException() { } public BadConnectionException(string message) : base(message) { } public BadConnectionException(string message, Exception innerException) : base(message, innerException) { } }
public class CRC16 public class CRC16
{ {
private readonly UInt16[] ChecksumTable = private readonly UInt16[] ChecksumTable =
new UInt16[] { [
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
}; ];
private readonly UInt16 Seed, FinalXor; private readonly UInt16 Seed, FinalXor;
public CRC16(UInt16 Polynomial, UInt16 Seed, UInt16 FinalXor) public CRC16(UInt16 Polynomial, UInt16 Seed, UInt16 FinalXor)
{ {
this.Seed = Seed; this.Seed = Seed;
this.FinalXor = FinalXor; this.FinalXor = FinalXor;
} }
public UInt16 CalculateChecksum(byte[] Bytes) public UInt16 CalculateChecksum(byte[] Bytes)
{ {
UInt16 Crc = Seed; UInt16 Crc = Seed;
for (int i = 0; i < Bytes.Length; ++i) for (int i = 0; i < Bytes.Length; ++i)
{ {
Crc = (UInt16)((Crc >> 8) ^ ChecksumTable[(byte)(Crc ^ Bytes[i])]); // Qualcomm implementation Crc = (UInt16)((Crc >> 8) ^ ChecksumTable[(byte)(Crc ^ Bytes[i])]); // Qualcomm implementation
} }
return (UInt16)(Crc ^ FinalXor); return (UInt16)(Crc ^ FinalXor);
} }
} }
} }
+119 -119
View File
@@ -1,119 +1,119 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
namespace WPinternals namespace WPinternals
{ {
internal class SBL1 : QualcommPartition internal class SBL1 : QualcommPartition
{ {
internal SBL1(byte[] Binary) : base(Binary, 0x2800) { } internal SBL1(byte[] Binary) : base(Binary, 0x2800) { }
internal byte[] GenerateExtraSector(byte[] PartitionHeader) internal byte[] GenerateExtraSector(byte[] PartitionHeader)
{ {
UInt32? Offset = ByteOperations.FindPattern(Binary, UInt32? Offset = ByteOperations.FindPattern(Binary,
new byte[] { [
0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}, null, null); ], null, null);
if (Offset == null) if (Offset == null)
{ {
throw new BadImageFormatException(); throw new BadImageFormatException();
} }
UInt32 PartitionLoaderTableOffset = (UInt32)Offset; UInt32 PartitionLoaderTableOffset = (UInt32)Offset;
byte[] FoundPattern = new byte[0x10]; byte[] FoundPattern = new byte[0x10];
Offset = ByteOperations.FindPattern(Binary, Offset = ByteOperations.FindPattern(Binary,
new byte[] { [
0x04, 0x00, 0x9F, 0xE5, 0x28, 0x00, 0xD0, 0xE5, 0x1E, 0xFF, 0x2F, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF 0x04, 0x00, 0x9F, 0xE5, 0x28, 0x00, 0xD0, 0xE5, 0x1E, 0xFF, 0x2F, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF
}, ],
new byte[] { [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF
}, ],
FoundPattern); FoundPattern);
if (Offset == null) if (Offset == null)
{ {
throw new BadImageFormatException(); throw new BadImageFormatException();
} }
UInt32 SharedMemoryAddress = ByteOperations.ReadUInt32(FoundPattern, 0x0C); UInt32 SharedMemoryAddress = ByteOperations.ReadUInt32(FoundPattern, 0x0C);
UInt32 GlobalIsSecurityEnabledAddress = SharedMemoryAddress + 0x28; UInt32 GlobalIsSecurityEnabledAddress = SharedMemoryAddress + 0x28;
Offset = ByteOperations.FindPattern(Binary, Offset = ByteOperations.FindPattern(Binary,
new byte[] { [
0x01, 0xFF, 0xA0, 0xE3, 0xFF, 0xFF, 0xA0, 0xE1, 0x1C, 0xD0, 0x8D, 0xE2, 0xF0, 0x4F, 0xBD, 0xE8, 0x01, 0xFF, 0xA0, 0xE3, 0xFF, 0xFF, 0xA0, 0xE1, 0x1C, 0xD0, 0x8D, 0xE2, 0xF0, 0x4F, 0xBD, 0xE8,
0x1E, 0xFF, 0x2F, 0xE1 0x1E, 0xFF, 0x2F, 0xE1
}, ],
new byte[] { [
0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00
}, ],
null); null);
if (Offset == null) if (Offset == null)
{ {
throw new BadImageFormatException(); throw new BadImageFormatException();
} }
UInt32 ReturnAddress = (UInt32)Offset - ImageOffset + ImageAddress; UInt32 ReturnAddress = (UInt32)Offset - ImageOffset + ImageAddress;
byte[] Sector = new byte[0x200]; byte[] Sector = new byte[0x200];
Array.Clear(Sector, 0, 0x200); Array.Clear(Sector, 0, 0x200);
byte[] Content = new byte[] { byte[] Content = [
0x16, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0xBD, 0x02, 0x00, 0x16, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0xBD, 0x02, 0x00,
0xD8, 0x01, 0x00, 0x00, 0xD8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x01, 0x00, 0x00, 0xD8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xE3, 0x3C, 0x10, 0x9F, 0xE5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xE3, 0x3C, 0x10, 0x9F, 0xE5,
0x00, 0x00, 0xC1, 0xE5, 0x38, 0x00, 0x9F, 0xE5, 0x38, 0x10, 0x9F, 0xE5, 0x00, 0x00, 0x81, 0xE5, 0x00, 0x00, 0xC1, 0xE5, 0x38, 0x00, 0x9F, 0xE5, 0x38, 0x10, 0x9F, 0xE5, 0x00, 0x00, 0x81, 0xE5,
0x34, 0x10, 0x9F, 0xE5, 0x00, 0x00, 0x81, 0xE5, 0x30, 0x00, 0x9F, 0xE5, 0x20, 0x10, 0x9F, 0xE5, 0x34, 0x10, 0x9F, 0xE5, 0x00, 0x00, 0x81, 0xE5, 0x30, 0x00, 0x9F, 0xE5, 0x20, 0x10, 0x9F, 0xE5,
0x2C, 0x30, 0x9F, 0xE5, 0x00, 0x20, 0x90, 0xE5, 0x00, 0x20, 0x81, 0xE5, 0x04, 0x00, 0x80, 0xE2, 0x2C, 0x30, 0x9F, 0xE5, 0x00, 0x20, 0x90, 0xE5, 0x00, 0x20, 0x81, 0xE5, 0x04, 0x00, 0x80, 0xE2,
0x04, 0x10, 0x81, 0xE2, 0x03, 0x00, 0x50, 0xE1, 0xF9, 0xFF, 0xFF, 0xBA, 0x14, 0xF0, 0x9F, 0xE5, 0x04, 0x10, 0x81, 0xE2, 0x03, 0x00, 0x50, 0xE1, 0xF9, 0xFF, 0xFF, 0xBA, 0x14, 0xF0, 0x9F, 0xE5,
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x90, 0xBF, 0x02, 0x00, 0xD0, 0xBF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x90, 0xBF, 0x02, 0x00, 0xD0, 0xBF, 0x02, 0x00,
0xA0, 0xBD, 0x02, 0x00, 0xA0, 0xBE, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 0xA0, 0xBD, 0x02, 0x00, 0xA0, 0xBE, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
}; ];
byte[] PartitionTypeGuid = new byte[] { byte[] PartitionTypeGuid = [
0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74
}; ];
Buffer.BlockCopy(Content, 0, Sector, 0, Content.Length); Buffer.BlockCopy(Content, 0, Sector, 0, Content.Length);
// Overwrite first part of partition-header with model-specific header // Overwrite first part of partition-header with model-specific header
Buffer.BlockCopy(PartitionHeader, 0, Sector, 0, PartitionHeader.Length); Buffer.BlockCopy(PartitionHeader, 0, Sector, 0, PartitionHeader.Length);
ByteOperations.WriteUInt32(Sector, 0x70, GlobalIsSecurityEnabledAddress); ByteOperations.WriteUInt32(Sector, 0x70, GlobalIsSecurityEnabledAddress);
ByteOperations.WriteUInt32(Sector, 0x88, ReturnAddress); ByteOperations.WriteUInt32(Sector, 0x88, ReturnAddress);
Buffer.BlockCopy(Binary, (int)PartitionLoaderTableOffset, Sector, 0xA0, 0x50); Buffer.BlockCopy(Binary, (int)PartitionLoaderTableOffset, Sector, 0xA0, 0x50);
ByteOperations.WriteUInt32(Sector, 0xA0 + 0x30, 0); ByteOperations.WriteUInt32(Sector, 0xA0 + 0x30, 0);
Buffer.BlockCopy(Binary, (int)PartitionLoaderTableOffset, Sector, 0xF0, 0x50); Buffer.BlockCopy(Binary, (int)PartitionLoaderTableOffset, Sector, 0xF0, 0x50);
ByteOperations.WriteUInt32(Sector, 0xF0 + 0x2C, 0); ByteOperations.WriteUInt32(Sector, 0xF0 + 0x2C, 0);
ByteOperations.WriteUInt32(Sector, 0xF0 + 0x38, 0x210F0); ByteOperations.WriteUInt32(Sector, 0xF0 + 0x38, 0x210F0);
Buffer.BlockCopy(PartitionTypeGuid, 0, Sector, 0x190, 0x10); Buffer.BlockCopy(PartitionTypeGuid, 0, Sector, 0x190, 0x10);
ByteOperations.WriteUInt32(Sector, 0x1FC, 0x0002BD28); ByteOperations.WriteUInt32(Sector, 0x1FC, 0x0002BD28);
return Sector; return Sector;
} }
} }
} }
+56 -56
View File
@@ -1,56 +1,56 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
namespace WPinternals namespace WPinternals
{ {
internal class SBL2 internal class SBL2
{ {
internal byte[] Binary; internal byte[] Binary;
internal SBL2(byte[] Binary) internal SBL2(byte[] Binary)
{ {
this.Binary = Binary; this.Binary = Binary;
} }
// Magic! // Magic!
internal byte[] Patch() internal byte[] Patch()
{ {
UInt32? PatchOffset = ByteOperations.FindPattern(Binary, UInt32? PatchOffset = ByteOperations.FindPattern(Binary,
new byte[] { [
0xFF, 0xFF, 0xFF, 0xE3, 0x01, 0x0E, 0x42, 0xE3, 0x28, 0x00, 0xD0, 0xE5, 0x1E, 0xFF, 0x2F, 0xE1 0xFF, 0xFF, 0xFF, 0xE3, 0x01, 0x0E, 0x42, 0xE3, 0x28, 0x00, 0xD0, 0xE5, 0x1E, 0xFF, 0x2F, 0xE1
}, ],
new byte[] { [
0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}, ],
null); null);
if (PatchOffset == null) if (PatchOffset == null)
{ {
throw new BadImageFormatException(); throw new BadImageFormatException();
} }
Buffer.BlockCopy(new byte[] { 0x00, 0x00, 0xA0, 0xE3 }, 0, Binary, (int)PatchOffset + 8, 4); Buffer.BlockCopy(new byte[] { 0x00, 0x00, 0xA0, 0xE3 }, 0, Binary, (int)PatchOffset + 8, 4);
return Binary; return Binary;
} }
} }
} }
+88 -88
View File
@@ -1,88 +1,88 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.IO; using System.IO;
namespace WPinternals namespace WPinternals
{ {
internal class SBL3 internal class SBL3
{ {
internal byte[] Binary; internal byte[] Binary;
internal SBL3(byte[] Binary) internal SBL3(byte[] Binary)
{ {
this.Binary = Binary; this.Binary = Binary;
} }
internal SBL3(string FileName) internal SBL3(string FileName)
{ {
Binary = null; Binary = null;
// First try to parse as FFU // First try to parse as FFU
try try
{ {
if (FFU.IsFFU(FileName)) if (FFU.IsFFU(FileName))
{ {
FFU FFUFile = new(FileName); FFU FFUFile = new(FileName);
Binary = FFUFile.GetPartition("SBL3"); Binary = FFUFile.GetPartition("SBL3");
} }
} }
catch { } catch { }
// If not succeeded, then try to parse it as raw image // If not succeeded, then try to parse it as raw image
if (Binary == null) if (Binary == null)
{ {
byte[] SBL3Pattern = new byte[] { 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF }; byte[] SBL3Pattern = [0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF];
byte[] SBL3Mask = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF }; byte[] SBL3Mask = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF];
UInt32? Offset = ByteOperations.FindPatternInFile(FileName, SBL3Pattern, SBL3Mask, out byte[] SBL3Header); UInt32? Offset = ByteOperations.FindPatternInFile(FileName, SBL3Pattern, SBL3Mask, out byte[] SBL3Header);
if (Offset != null) if (Offset != null)
{ {
UInt32 Length = ByteOperations.ReadUInt32(SBL3Header, 0x10) + 0x28; // SBL3 Image Size + Header Size UInt32 Length = ByteOperations.ReadUInt32(SBL3Header, 0x10) + 0x28; // SBL3 Image Size + Header Size
Binary = new byte[Length]; Binary = new byte[Length];
FileStream Stream = new(FileName, FileMode.Open, FileAccess.Read); FileStream Stream = new(FileName, FileMode.Open, FileAccess.Read);
Stream.Seek((long)Offset, SeekOrigin.Begin); Stream.Seek((long)Offset, SeekOrigin.Begin);
Stream.Read(Binary, 0, (int)Length); Stream.Read(Binary, 0, (int)Length);
Stream.Close(); Stream.Close();
} }
} }
} }
// Magic! // Magic!
internal byte[] Patch() internal byte[] Patch()
{ {
UInt32? PatchOffset = ByteOperations.FindPattern(Binary, UInt32? PatchOffset = ByteOperations.FindPattern(Binary,
new byte[] { 0x04, 0x00, 0x9F, 0xE5, 0x28, 0x00, 0xD0, 0xE5, 0x1E, 0xFF, 0x2F, 0xE1 }, [0x04, 0x00, 0x9F, 0xE5, 0x28, 0x00, 0xD0, 0xE5, 0x1E, 0xFF, 0x2F, 0xE1],
null, null); null, null);
if (PatchOffset == null) if (PatchOffset == null)
{ {
throw new BadImageFormatException(); throw new BadImageFormatException();
} }
Buffer.BlockCopy(new byte[] { 0x00, 0x00, 0xA0, 0xE3 }, 0, Binary, (int)PatchOffset + 4, 4); Buffer.BlockCopy(new byte[] { 0x00, 0x00, 0xA0, 0xE3 }, 0, Binary, (int)PatchOffset + 4, 4);
return Binary; return Binary;
} }
} }
} }
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

@@ -1,51 +1,51 @@
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Windows; using System.Windows;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information // set of attributes. Change these attribute values to modify the information
// associated with an assembly. // associated with an assembly.
[assembly: AssemblyTitle("WPinternals")] [assembly: AssemblyTitle("WPinternals")]
[assembly: AssemblyDescription("")] [assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")] [assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("WPinternals")] [assembly: AssemblyProduct("WPinternals")]
[assembly: AssemblyCopyright("Copyright © 2018-2019")] [assembly: AssemblyCopyright("Copyright © 2018-2023")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible // Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from // to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type. // COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)] [assembly: ComVisible(false)]
//In order to begin building localizable applications, set //In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file //<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english //inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment //in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in //the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file. //the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo( [assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page, //(used if a resource is not found in the page,
// or application resource dictionaries) // or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page, //(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries) // app, or any theme specific resource dictionaries)
)] )]
// Version information for an assembly consists of the following four values: // Version information for an assembly consists of the following four values:
// //
// Major Version // Major Version
// Minor Version // Minor Version
// Build Number // Build Number
// Revision // Revision
// //
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.9.*")] [assembly: AssemblyVersion("3.0.*")]
// [assembly: AssemblyFileVersion("1.0.0.0")] // [assembly: AssemblyFileVersion("1.0.0.0")]
@@ -1,63 +1,63 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.
// Runtime Version:4.0.30319.42000 // Runtime Version:4.0.30319.42000
// //
// Changes to this file may cause incorrect behavior and will be lost if // Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated. // the code is regenerated.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace WPinternals.Properties { namespace WPinternals.Properties {
using System; using System;
/// <summary> /// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc. /// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary> /// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder // This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio. // class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen // To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project. // with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources { internal class Resources {
private static global::System.Resources.ResourceManager resourceMan; private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture; private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() { internal Resources() {
} }
/// <summary> /// <summary>
/// Returns the cached ResourceManager instance used by this class. /// Returns the cached ResourceManager instance used by this class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager { internal static global::System.Resources.ResourceManager ResourceManager {
get { get {
if (object.ReferenceEquals(resourceMan, null)) { if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WPinternals.Properties.Resources", typeof(Resources).Assembly); global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WPinternals.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp; resourceMan = temp;
} }
return resourceMan; return resourceMan;
} }
} }
/// <summary> /// <summary>
/// Overrides the current thread's CurrentUICulture property for all /// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class. /// resource lookups using this strongly typed resource class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture { internal static global::System.Globalization.CultureInfo Culture {
get { get {
return resourceCulture; return resourceCulture;
} }
set { set {
resourceCulture = value; resourceCulture = value;
} }
} }
} }
} }
@@ -1,117 +1,117 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<root> <root>
<!-- <!--
Microsoft ResX Schema Microsoft ResX Schema
Version 2.0 Version 2.0
The primary goals of this format is to allow a simple XML format The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes various data types are done through the TypeConverter classes
associated with the data types. associated with the data types.
Example: Example:
... ado.net/XML headers & schema ... ... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader> <resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader> <resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value> <value>[base64 mime encoded serialized .NET Framework object]</value>
</data> </data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment> <comment>This is a comment</comment>
</data> </data>
There are any number of "resheader" rows that contain simple There are any number of "resheader" rows that contain simple
name/value pairs. name/value pairs.
Each data row contains a name, and value. The row also contains a Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture. text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the Classes that don't support this are serialized and stored with the
mimetype set. mimetype set.
The mimetype is used for serialized objects, and tells the The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly: extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below. read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64 mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter : System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64 mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64 mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter : using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
--> -->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true"> <xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType> <xsd:complexType>
<xsd:choice maxOccurs="unbounded"> <xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata"> <xsd:element name="metadata">
<xsd:complexType> <xsd:complexType>
<xsd:sequence> <xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" /> <xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence> </xsd:sequence>
<xsd:attribute name="name" type="xsd:string" /> <xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" /> <xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" /> <xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
<xsd:element name="assembly"> <xsd:element name="assembly">
<xsd:complexType> <xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" /> <xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" /> <xsd:attribute name="name" type="xsd:string" />
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
<xsd:element name="data"> <xsd:element name="data">
<xsd:complexType> <xsd:complexType>
<xsd:sequence> <xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence> </xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
<xsd:element name="resheader"> <xsd:element name="resheader">
<xsd:complexType> <xsd:complexType>
<xsd:sequence> <xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence> </xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" /> <xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
</xsd:choice> </xsd:choice>
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
</xsd:schema> </xsd:schema>
<resheader name="resmimetype"> <resheader name="resmimetype">
<value>text/microsoft-resx</value> <value>text/microsoft-resx</value>
</resheader> </resheader>
<resheader name="version"> <resheader name="version">
<value>2.0</value> <value>2.0</value>
</resheader> </resheader>
<resheader name="reader"> <resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
</root> </root>
@@ -1,26 +1,26 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.
// Runtime Version:4.0.30319.42000 // Runtime Version:4.0.30319.42000
// //
// Changes to this file may cause incorrect behavior and will be lost if // Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated. // the code is regenerated.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace WPinternals.Properties { namespace WPinternals.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.5.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.5.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default { public static Settings Default {
get { get {
return defaultInstance; return defaultInstance;
} }
} }
} }
} }
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)"> <SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles> <Profiles>
<Profile Name="(Default)" /> <Profile Name="(Default)" />
</Profiles> </Profiles>
<Settings /> <Settings />
</SettingsFile> </SettingsFile>
View File
View File
View File
+68 -68
View File
@@ -1,68 +1,68 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace WPinternals namespace WPinternals
{ {
internal static class Terminal internal static class Terminal
{ {
public static TerminalResponse Parse(byte[] Buffer, int Offset) public static TerminalResponse Parse(byte[] Buffer, int Offset)
{ {
TerminalResponse Response = new(); TerminalResponse Response = new();
// Get root node // Get root node
if (Buffer.Length >= (Offset + 8)) if (Buffer.Length >= (Offset + 8))
{ {
int NodeNumber = BitConverter.ToInt32(Buffer, Offset); int NodeNumber = BitConverter.ToInt32(Buffer, Offset);
int NodeSize = BitConverter.ToInt32(Buffer, Offset + 4); int NodeSize = BitConverter.ToInt32(Buffer, Offset + 4);
int End = NodeSize + Offset + 8; int End = NodeSize + Offset + 8;
int Index = Offset + 8; int Index = Offset + 8;
if ((NodeNumber == 0x10000) && (End <= Buffer.Length)) if ((NodeNumber == 0x10000) && (End <= Buffer.Length))
{ {
// Get subnodes // Get subnodes
while (Index < End) while (Index < End)
{ {
NodeNumber = BitConverter.ToInt32(Buffer, Index); NodeNumber = BitConverter.ToInt32(Buffer, Index);
NodeSize = BitConverter.ToInt32(Buffer, Index + 4); NodeSize = BitConverter.ToInt32(Buffer, Index + 4);
byte[] Raw = new byte[NodeSize]; byte[] Raw = new byte[NodeSize];
Array.Copy(Buffer, Index + 8, Raw, 0, NodeSize); Array.Copy(Buffer, Index + 8, Raw, 0, NodeSize);
Response.RawEntries.Add(NodeNumber, Raw); Response.RawEntries.Add(NodeNumber, Raw);
Index += NodeSize + 8; Index += NodeSize + 8;
} }
} }
} }
// Parse subnodes // Parse subnodes
Response.RawEntries.TryGetValue(3, out Response.PublicId); Response.RawEntries.TryGetValue(3, out Response.PublicId);
Response.RawEntries.TryGetValue(7, out Response.RootKeyHash); Response.RawEntries.TryGetValue(7, out Response.RootKeyHash);
return Response; return Response;
} }
} }
internal class TerminalResponse internal class TerminalResponse
{ {
public Dictionary<int, byte[]> RawEntries = new(); public Dictionary<int, byte[]> RawEntries = new();
public byte[] PublicId = null; public byte[] PublicId = null;
public byte[] RootKeyHash = null; public byte[] RootKeyHash = null;
} }
} }
+296 -295
View File
@@ -1,295 +1,296 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace WPinternals namespace WPinternals
{ {
internal static class TestCode internal static class TestCode
{ {
internal static async Task Test(System.Threading.SynchronizationContext UIContext) internal static async Task Test(System.Threading.SynchronizationContext UIContext)
{ {
// To avoid warnings when there is no code here. // To avoid warnings when there is no code here.
await Task.Run(() => { }); await Task.Run(() => { });
// PhoneNotifierViewModel Notifier = new PhoneNotifierViewModel(); // PhoneNotifierViewModel Notifier = new PhoneNotifierViewModel();
// Notifier.Start(); // Notifier.Start();
// await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage); // await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage);
// MassStorage MassStorage = (MassStorage)Notifier.CurrentModel; // MassStorage MassStorage = (MassStorage)Notifier.CurrentModel;
} }
internal static async Task RecoverBadGPT(string GPTPath, string LoadersPath) internal static async Task RecoverBadGPT(string GPTPath, string LoadersPath)
{ {
byte[] GPT = File.ReadAllBytes(GPTPath); byte[] GPT = File.ReadAllBytes(GPTPath);
PhoneNotifierViewModel PhoneNotifier = new(); PhoneNotifierViewModel PhoneNotifier = new();
PhoneNotifier.Start(); PhoneNotifier.Start();
await SwitchModeViewModel.SwitchTo(PhoneNotifier, PhoneInterfaces.Qualcomm_Download); await SwitchModeViewModel.SwitchTo(PhoneNotifier, PhoneInterfaces.Qualcomm_Download);
byte[] RootKeyHash = null; byte[] RootKeyHash = null;
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Qualcomm_Download) if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Qualcomm_Download)
{ {
QualcommDownload Download2 = new((QualcommSerial)PhoneNotifier.CurrentModel); QualcommDownload Download2 = new((QualcommSerial)PhoneNotifier.CurrentModel);
RootKeyHash = Download2.GetRKH(); RootKeyHash = Download2.GetRKH();
} }
List<QualcommPartition> PossibleLoaders = null; List<QualcommPartition> PossibleLoaders = null;
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Qualcomm_Download) if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Qualcomm_Download)
{ {
try try
{ {
PossibleLoaders = QualcommLoaders.GetPossibleLoadersForRootKeyHash(LoadersPath, RootKeyHash); PossibleLoaders = QualcommLoaders.GetPossibleLoadersForRootKeyHash(LoadersPath, RootKeyHash);
if (PossibleLoaders.Count == 0) if (PossibleLoaders.Count == 0)
{ {
throw new Exception("Error: No matching loaders found for RootKeyHash."); throw new Exception("Error: No matching loaders found for RootKeyHash.");
} }
} }
catch (Exception Ex) catch (Exception Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
throw new Exception("Error: Unexpected error during scanning for loaders."); throw new Exception("Error: Unexpected error during scanning for loaders.");
} }
} }
QualcommSerial Serial = (QualcommSerial)PhoneNotifier.CurrentModel; QualcommSerial Serial = (QualcommSerial)PhoneNotifier.CurrentModel;
QualcommDownload Download = new(Serial); QualcommDownload Download = new(Serial);
if (Download.IsAlive()) if (Download.IsAlive())
{ {
int Attempt = 1; int Attempt = 1;
bool Result = false; bool Result = false;
foreach (QualcommPartition Loader in PossibleLoaders) foreach (QualcommPartition Loader in PossibleLoaders)
{ {
LogFile.Log("Attempt " + Attempt.ToString(), LogType.ConsoleOnly); LogFile.Log("Attempt " + Attempt.ToString(), LogType.ConsoleOnly);
try try
{ {
Download.SendToPhoneMemory(0x2A000000, Loader.Binary); Download.SendToPhoneMemory(0x2A000000, Loader.Binary);
Download.StartBootloader(0x2A000000); Download.StartBootloader(0x2A000000);
Result = true; Result = true;
LogFile.Log("Loader sent successfully", LogType.ConsoleOnly); LogFile.Log("Loader sent successfully", LogType.ConsoleOnly);
} }
catch { } catch { }
if (Result) if (Result)
{ {
break; break;
} }
Attempt++; Attempt++;
} }
Serial.Close(); Serial.Close();
if (!Result) if (!Result)
{ {
LogFile.Log("Loader failed", LogType.ConsoleOnly); LogFile.Log("Loader failed", LogType.ConsoleOnly);
} }
} }
else else
{ {
LogFile.Log("Failed to communicate to Qualcomm Emergency Download mode", LogType.ConsoleOnly); LogFile.Log("Failed to communicate to Qualcomm Emergency Download mode", LogType.ConsoleOnly);
throw new BadConnectionException(); throw new BadConnectionException();
} }
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Qualcomm_Flash) if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Qualcomm_Flash)
{ {
await PhoneNotifier.WaitForArrival(); await PhoneNotifier.WaitForArrival();
} }
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Qualcomm_Flash) if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Qualcomm_Flash)
{ {
throw new WPinternalsException("Phone failed to switch to emergency flash mode."); throw new WPinternalsException("Phone failed to switch to emergency flash mode.");
} }
// Flash bootloader // Flash bootloader
QualcommSerial Serial2 = (QualcommSerial)PhoneNotifier.CurrentModel; QualcommSerial Serial2 = (QualcommSerial)PhoneNotifier.CurrentModel;
Serial2.EncodeCommands = false; Serial2.EncodeCommands = false;
QualcommFlasher Flasher = new(Serial2); QualcommFlasher Flasher = new(Serial2);
Flasher.Hello(); Flasher.Hello();
Flasher.SetSecurityMode(0); Flasher.SetSecurityMode(0);
Flasher.OpenPartition(0x21); Flasher.OpenPartition(0x21);
LogFile.Log("Partition opened.", LogType.ConsoleOnly); LogFile.Log("Partition opened.", LogType.ConsoleOnly);
LogFile.Log("Flash GPT at 0x" + ((UInt32)0x200).ToString("X8"), LogType.ConsoleOnly); LogFile.Log("Flash GPT at 0x" + ((UInt32)0x200).ToString("X8"), LogType.ConsoleOnly);
Flasher.Flash(0x200, GPT, 0, 0x41FF); // Bad bounds-check in the flash-loader prohibits to write the last byte. Flasher.Flash(0x200, GPT, 0, 0x41FF); // Bad bounds-check in the flash-loader prohibits to write the last byte.
Flasher.ClosePartition(); Flasher.ClosePartition();
LogFile.Log("Partition closed. Flashing ready. Rebooting."); LogFile.Log("Partition closed. Flashing ready. Rebooting.");
Flasher.Reboot(); Flasher.Reboot();
Flasher.CloseSerial(); Flasher.CloseSerial();
} }
internal static async Task RewriteGPT(string GPTPath) internal static async Task RewriteGPT(string GPTPath)
{ {
PhoneNotifierViewModel Notifier = new(); PhoneNotifierViewModel Notifier = new();
Notifier.Start(); Notifier.Start();
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage); await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage);
MassStorage MassStorage = (MassStorage)Notifier.CurrentModel; MassStorage MassStorage = (MassStorage)Notifier.CurrentModel;
LogFile.Log("Writing GPT to the device.", LogType.ConsoleOnly); LogFile.Log("Writing GPT to the device.", LogType.ConsoleOnly);
MassStorage.WriteSectors(1, GPTPath); MassStorage.WriteSectors(1, GPTPath);
} }
internal static async Task RewriteMBRGPT() internal static async Task RewriteMBRGPT()
{ {
FFU FFU = new(@"E:\Device Backups\Alpha\9200_1230.0025.9200.9825\RX100_9825.ffu"); FFU FFU = new(@"E:\Device Backups\Alpha\9200_1230.0025.9200.9825\RX100_9825.ffu");
const string GPTPath = @"E:\Device Backups\Alpha\9200_1230.0025.9200.9825\CorrectGPT.bin"; const string GPTPath = @"E:\Device Backups\Alpha\9200_1230.0025.9200.9825\CorrectGPT.bin";
PhoneNotifierViewModel Notifier = new(); PhoneNotifierViewModel Notifier = new();
Notifier.Start(); Notifier.Start();
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage); await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage);
MassStorage MassStorage = (MassStorage)Notifier.CurrentModel; MassStorage MassStorage = (MassStorage)Notifier.CurrentModel;
byte[] MBR = FFU.GetSectors(0, 1); byte[] MBR = FFU.GetSectors(0, 1);
LogFile.Log("Writing MBR to the device.", LogType.ConsoleOnly); LogFile.Log("Writing MBR to the device.", LogType.ConsoleOnly);
MassStorage.WriteSectors(0, MBR); MassStorage.WriteSectors(0, MBR);
LogFile.Log("Writing GPT to the device.", LogType.ConsoleOnly); LogFile.Log("Writing GPT to the device.", LogType.ConsoleOnly);
MassStorage.WriteSectors(1, GPTPath); MassStorage.WriteSectors(1, GPTPath);
} }
internal static async Task RewriteParts(string PartPath) internal static async Task RewriteParts(string PartPath)
{ {
PhoneNotifierViewModel Notifier = new(); PhoneNotifierViewModel Notifier = new();
Notifier.Start(); Notifier.Start();
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage); await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage);
MassStorage MassStorage = (MassStorage)Notifier.CurrentModel; MassStorage MassStorage = (MassStorage)Notifier.CurrentModel;
foreach (var part in Directory.EnumerateFiles(PartPath)) foreach (var part in Directory.EnumerateFiles(PartPath))
{ {
var partname = part.Split('\\').Last().Replace(".img", ""); var partname = part.Split('\\').Last().Replace(".img", "");
try try
{ {
LogFile.Log($"Writing {partname} to the device.", LogType.ConsoleOnly); LogFile.Log($"Writing {partname} to the device.", LogType.ConsoleOnly);
LogFile.Log("", LogType.ConsoleOnly); LogFile.Log("", LogType.ConsoleOnly);
MassStorage.RestorePartition(part, partname, (v, t) => LogFile.Log("Progress: " + v + "%", LogType.ConsoleOnly)); MassStorage.RestorePartition(part, partname, (v, t) => LogFile.Log("Progress: " + v + "%", LogType.ConsoleOnly));
LogFile.Log("", LogType.ConsoleOnly); LogFile.Log("", LogType.ConsoleOnly);
} }
catch catch
{ {
LogFile.Log("", LogType.ConsoleOnly); LogFile.Log("", LogType.ConsoleOnly);
LogFile.Log($"Failed writing {partname} to the device.", LogType.ConsoleOnly); LogFile.Log($"Failed writing {partname} to the device.", LogType.ConsoleOnly);
} }
} }
} }
internal static void PatchImg(string dump) internal static void PatchImg(string dump)
{ {
using var fil = File.Open(dump, FileMode.Open); using var fil = File.Open(dump, FileMode.Open);
byte[] gptbuffer = new byte[0x4200]; byte[] gptbuffer = new byte[0x4200];
fil.Seek(0x200, SeekOrigin.Begin); fil.Seek(0x200, SeekOrigin.Begin);
fil.Read(gptbuffer, 0, 0x4200); fil.Read(gptbuffer, 0, 0x4200);
uint BackupLBA = ByteOperations.ReadUInt32(gptbuffer, 0x20); uint BackupLBA = ByteOperations.ReadUInt32(gptbuffer, 0x20);
uint LastUsableLBA = ByteOperations.ReadUInt32(gptbuffer, 0x30); uint LastUsableLBA = ByteOperations.ReadUInt32(gptbuffer, 0x30);
LogFile.Log("Previous BackupLBA: " + BackupLBA, LogType.ConsoleOnly); LogFile.Log("Previous BackupLBA: " + BackupLBA, LogType.ConsoleOnly);
LogFile.Log("Previous LastUsableLBA: " + LastUsableLBA, LogType.ConsoleOnly); LogFile.Log("Previous LastUsableLBA: " + LastUsableLBA, LogType.ConsoleOnly);
const uint NewBackupLBA = 62078975u; const uint NewBackupLBA = 62078975u;
const uint NewLastUsableLBA = 62078942u; const uint NewLastUsableLBA = 62078942u;
ByteOperations.WriteUInt32(gptbuffer, 0x20, NewBackupLBA); ByteOperations.WriteUInt32(gptbuffer, 0x20, NewBackupLBA);
ByteOperations.WriteUInt32(gptbuffer, 0x30, NewLastUsableLBA); ByteOperations.WriteUInt32(gptbuffer, 0x30, NewLastUsableLBA);
uint HeaderSize = ByteOperations.ReadUInt32(gptbuffer, 0x0C); uint HeaderSize = ByteOperations.ReadUInt32(gptbuffer, 0x0C);
uint PrevCRC = ByteOperations.ReadUInt32(gptbuffer, 0x10); uint PrevCRC = ByteOperations.ReadUInt32(gptbuffer, 0x10);
LogFile.Log("Previous CRC: " + PrevCRC, LogType.ConsoleOnly); LogFile.Log("Previous CRC: " + PrevCRC, LogType.ConsoleOnly);
ByteOperations.WriteUInt32(gptbuffer, 0x10, 0); ByteOperations.WriteUInt32(gptbuffer, 0x10, 0);
uint NewCRC = ByteOperations.CRC32(gptbuffer, 0, HeaderSize); uint NewCRC = ByteOperations.CRC32(gptbuffer, 0, HeaderSize);
LogFile.Log("New CRC: " + NewCRC, LogType.ConsoleOnly); LogFile.Log("New CRC: " + NewCRC, LogType.ConsoleOnly);
ByteOperations.WriteUInt32(gptbuffer, 0x10, NewCRC); ByteOperations.WriteUInt32(gptbuffer, 0x10, NewCRC);
LogFile.Log("Writing", LogType.ConsoleOnly); LogFile.Log("Writing", LogType.ConsoleOnly);
fil.Seek(0x200, SeekOrigin.Begin); fil.Seek(0x200, SeekOrigin.Begin);
fil.Write(gptbuffer, 0, 0x4200); fil.Write(gptbuffer, 0, 0x4200);
LogFile.Log("Done!", LogType.ConsoleOnly); LogFile.Log("Done!", LogType.ConsoleOnly);
} }
internal static async Task TestProgrammer(System.Threading.SynchronizationContext UIContext, string ProgrammerPath) internal static async Task TestProgrammer(System.Threading.SynchronizationContext UIContext, string ProgrammerPath)
{ {
LogFile.BeginAction("TestProgrammer"); LogFile.BeginAction("TestProgrammer");
try try
{ {
LogFile.Log("Starting Firehose Test", LogType.FileAndConsole); LogFile.Log("Starting Firehose Test", LogType.FileAndConsole);
PhoneNotifierViewModel Notifier = new(); PhoneNotifierViewModel Notifier = new();
UIContext.Send(s => Notifier.Start(), null); UIContext.Send(s => Notifier.Start(), null);
if (Notifier.CurrentInterface == PhoneInterfaces.Qualcomm_Download) if (Notifier.CurrentInterface == PhoneInterfaces.Qualcomm_Download)
{ {
LogFile.Log("Phone found in emergency mode", LogType.FileAndConsole); LogFile.Log("Phone found in emergency mode", LogType.FileAndConsole);
} }
else else
{ {
LogFile.Log("Phone needs to be switched to emergency mode.", LogType.FileAndConsole); LogFile.Log("Phone needs to be switched to emergency mode.", LogType.FileAndConsole);
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash); await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
PhoneInfo Info = ((NokiaFlashModel)Notifier.CurrentModel).ReadPhoneInfo(); PhoneInfo Info = ((NokiaFlashModel)Notifier.CurrentModel).ReadPhoneInfo();
Info.Log(LogType.ConsoleOnly); Info.Log(LogType.ConsoleOnly);
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Qualcomm_Download); await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Qualcomm_Download);
if (Notifier.CurrentInterface != PhoneInterfaces.Qualcomm_Download) if (Notifier.CurrentInterface != PhoneInterfaces.Qualcomm_Download)
{ {
throw new WPinternalsException("Switching mode failed.", "Could not switch the phone to Qualcomm Emergency 9008."); throw new WPinternalsException("Switching mode failed.", "Could not switch the phone to Qualcomm Emergency 9008.");
} }
LogFile.Log("Phone is in emergency mode.", LogType.FileAndConsole); LogFile.Log("Phone is in emergency mode.", LogType.FileAndConsole);
} }
// Send and start programmer // Send and start programmer
QualcommSerial Serial = (QualcommSerial)Notifier.CurrentModel; QualcommSerial Serial = (QualcommSerial)Notifier.CurrentModel;
QualcommSahara Sahara = new(Serial); QualcommSahara Sahara = new(Serial);
QualcommFirehose Firehose = new(Serial);
if (await Sahara.Reset(ProgrammerPath))
{ if (await Sahara.LoadProgrammer(ProgrammerPath) && await Firehose.Reset())
LogFile.Log("Emergency programmer test succeeded", LogType.FileAndConsole); {
} LogFile.Log("Emergency programmer test succeeded", LogType.FileAndConsole);
else }
{ else
LogFile.Log("Emergency programmer test failed", LogType.FileAndConsole); {
} LogFile.Log("Emergency programmer test failed", LogType.FileAndConsole);
} }
catch (Exception Ex) }
{ catch (Exception Ex)
LogFile.LogException(Ex); {
} LogFile.LogException(Ex);
finally }
{ finally
LogFile.EndAction("TestProgrammer"); {
} LogFile.EndAction("TestProgrammer");
} }
} }
} }
}
@@ -1,43 +1,59 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
namespace WPinternals namespace WPinternals
{ {
internal class AboutViewModel : ContextViewModel internal class AboutViewModel : ContextViewModel
{ {
internal AboutViewModel() : base() { } internal AboutViewModel() : base() { }
public int MajorVersion public int MajorVersion
{
get
{
return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Major;
}
}
public int MinorVersion
{
get
{
return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Minor;
}
}
public int BuildVersion
{ {
get get
{ {
return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Major; return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Build;
} }
} }
public int MinorVersion public int RevisionVersion
{ {
get get
{ {
return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Minor; return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Revision;
} }
} }
} }
} }
@@ -1,237 +1,237 @@
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Threading; using System.Threading;
namespace WPinternals namespace WPinternals
{ {
internal class BackupTargetSelectionViewModel : ContextViewModel internal class BackupTargetSelectionViewModel : ContextViewModel
{ {
private readonly PhoneNotifierViewModel PhoneNotifier; private readonly PhoneNotifierViewModel PhoneNotifier;
private readonly Action<string, string, string> BackupCallback; private readonly Action<string, string, string> BackupCallback;
private readonly Action<string> BackupArchiveCallback; private readonly Action<string> BackupArchiveCallback;
private readonly Action<string> BackupArchiveProvisioningCallback; private readonly Action<string> BackupArchiveProvisioningCallback;
internal Action SwitchToUnlockBoot; internal Action SwitchToUnlockBoot;
internal BackupTargetSelectionViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action<string> BackupArchiveCallback, Action<string, string, string> BackupCallback, Action<string> BackupArchiveProvisioningCallback) internal BackupTargetSelectionViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action<string> BackupArchiveCallback, Action<string, string, string> BackupCallback, Action<string> BackupArchiveProvisioningCallback)
: base() : base()
{ {
this.PhoneNotifier = PhoneNotifier; this.PhoneNotifier = PhoneNotifier;
this.BackupCallback = BackupCallback; this.BackupCallback = BackupCallback;
this.BackupArchiveCallback = BackupArchiveCallback; this.BackupArchiveCallback = BackupArchiveCallback;
this.BackupArchiveProvisioningCallback = BackupArchiveProvisioningCallback; this.BackupArchiveProvisioningCallback = BackupArchiveProvisioningCallback;
this.SwitchToUnlockBoot = SwitchToUnlockBoot; this.SwitchToUnlockBoot = SwitchToUnlockBoot;
this.PhoneNotifier.NewDeviceArrived += NewDeviceArrived; this.PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
this.PhoneNotifier.DeviceRemoved += DeviceRemoved; this.PhoneNotifier.DeviceRemoved += DeviceRemoved;
new Thread(() => EvaluateViewState()).Start(); new Thread(() => EvaluateViewState()).Start();
} }
private string _ArchivePath; private string _ArchivePath;
public string ArchivePath public string ArchivePath
{ {
get get
{ {
return _ArchivePath; return _ArchivePath;
} }
set set
{ {
if (value != _ArchivePath) if (value != _ArchivePath)
{ {
_ArchivePath = value; _ArchivePath = value;
OnPropertyChanged(nameof(ArchivePath)); OnPropertyChanged(nameof(ArchivePath));
} }
} }
} }
private string _EFIESPPath; private string _EFIESPPath;
public string EFIESPPath public string EFIESPPath
{ {
get get
{ {
return _EFIESPPath; return _EFIESPPath;
} }
set set
{ {
if (value != _EFIESPPath) if (value != _EFIESPPath)
{ {
_EFIESPPath = value; _EFIESPPath = value;
OnPropertyChanged(nameof(EFIESPPath)); OnPropertyChanged(nameof(EFIESPPath));
} }
} }
} }
private string _MainOSPath; private string _MainOSPath;
public string MainOSPath public string MainOSPath
{ {
get get
{ {
return _MainOSPath; return _MainOSPath;
} }
set set
{ {
if (value != _MainOSPath) if (value != _MainOSPath)
{ {
_MainOSPath = value; _MainOSPath = value;
OnPropertyChanged(nameof(MainOSPath)); OnPropertyChanged(nameof(MainOSPath));
} }
} }
} }
private string _DataPath; private string _DataPath;
public string DataPath public string DataPath
{ {
get get
{ {
return _DataPath; return _DataPath;
} }
set set
{ {
if (value != _DataPath) if (value != _DataPath)
{ {
_DataPath = value; _DataPath = value;
OnPropertyChanged(nameof(DataPath)); OnPropertyChanged(nameof(DataPath));
} }
} }
} }
private string _ArchiveProvisioningPath; private string _ArchiveProvisioningPath;
public string ArchiveProvisioningPath public string ArchiveProvisioningPath
{ {
get get
{ {
return _ArchiveProvisioningPath; return _ArchiveProvisioningPath;
} }
set set
{ {
if (value != _ArchiveProvisioningPath) if (value != _ArchiveProvisioningPath)
{ {
_ArchiveProvisioningPath = value; _ArchiveProvisioningPath = value;
OnPropertyChanged(nameof(ArchiveProvisioningPath)); OnPropertyChanged(nameof(ArchiveProvisioningPath));
} }
} }
} }
private bool _IsPhoneDisconnected; private bool _IsPhoneDisconnected;
public bool IsPhoneDisconnected public bool IsPhoneDisconnected
{ {
get get
{ {
return _IsPhoneDisconnected; return _IsPhoneDisconnected;
} }
set set
{ {
if (value != _IsPhoneDisconnected) if (value != _IsPhoneDisconnected)
{ {
_IsPhoneDisconnected = value; _IsPhoneDisconnected = value;
OnPropertyChanged(nameof(IsPhoneDisconnected)); OnPropertyChanged(nameof(IsPhoneDisconnected));
} }
} }
} }
private bool _IsPhoneInMassStorage; private bool _IsPhoneInMassStorage;
public bool IsPhoneInMassStorage public bool IsPhoneInMassStorage
{ {
get get
{ {
return _IsPhoneInMassStorage; return _IsPhoneInMassStorage;
} }
set set
{ {
if (value != _IsPhoneInMassStorage) if (value != _IsPhoneInMassStorage)
{ {
_IsPhoneInMassStorage = value; _IsPhoneInMassStorage = value;
OnPropertyChanged(nameof(IsPhoneInMassStorage)); OnPropertyChanged(nameof(IsPhoneInMassStorage));
} }
} }
} }
private bool _IsPhoneInOtherMode; private bool _IsPhoneInOtherMode;
public bool IsPhoneInOtherMode public bool IsPhoneInOtherMode
{ {
get get
{ {
return _IsPhoneInOtherMode; return _IsPhoneInOtherMode;
} }
set set
{ {
if (value != _IsPhoneInOtherMode) if (value != _IsPhoneInOtherMode)
{ {
_IsPhoneInOtherMode = value; _IsPhoneInOtherMode = value;
OnPropertyChanged(nameof(IsPhoneInOtherMode)); OnPropertyChanged(nameof(IsPhoneInOtherMode));
} }
} }
} }
private DelegateCommand _BackupArchiveCommand; private DelegateCommand _BackupArchiveCommand;
public DelegateCommand BackupArchiveCommand public DelegateCommand BackupArchiveCommand
{ {
get get
{ {
return _BackupArchiveCommand ??= new DelegateCommand(() => BackupArchiveCallback(ArchivePath), () => (ArchivePath != null) && (PhoneNotifier.CurrentInterface != null)); return _BackupArchiveCommand ??= new DelegateCommand(() => BackupArchiveCallback(ArchivePath), () => (ArchivePath != null) && (PhoneNotifier.CurrentInterface != null));
} }
} }
private DelegateCommand _BackupCommand; private DelegateCommand _BackupCommand;
public DelegateCommand BackupCommand public DelegateCommand BackupCommand
{ {
get get
{ {
return _BackupCommand ??= new DelegateCommand(() => BackupCallback(EFIESPPath, MainOSPath, DataPath), () => ((EFIESPPath != null) || (MainOSPath != null) || (DataPath != null)) && (PhoneNotifier.CurrentInterface != null)); return _BackupCommand ??= new DelegateCommand(() => BackupCallback(EFIESPPath, MainOSPath, DataPath), () => ((EFIESPPath != null) || (MainOSPath != null) || (DataPath != null)) && (PhoneNotifier.CurrentInterface != null));
} }
} }
private DelegateCommand _BackupArchiveProvisioningCommand; private DelegateCommand _BackupArchiveProvisioningCommand;
public DelegateCommand BackupArchiveProvisioningCommand public DelegateCommand BackupArchiveProvisioningCommand
{ {
get get
{ {
return _BackupArchiveProvisioningCommand ??= new DelegateCommand(() => BackupArchiveProvisioningCallback(ArchiveProvisioningPath), () => (ArchiveProvisioningPath != null) && (PhoneNotifier.CurrentInterface != null)); return _BackupArchiveProvisioningCommand ??= new DelegateCommand(() => BackupArchiveProvisioningCallback(ArchiveProvisioningPath), () => (ArchiveProvisioningPath != null) && (PhoneNotifier.CurrentInterface != null));
} }
} }
~BackupTargetSelectionViewModel() ~BackupTargetSelectionViewModel()
{ {
PhoneNotifier.NewDeviceArrived -= NewDeviceArrived; PhoneNotifier.NewDeviceArrived -= NewDeviceArrived;
} }
private void NewDeviceArrived(ArrivalEventArgs Args) private void NewDeviceArrived(ArrivalEventArgs Args)
{ {
new Thread(() => EvaluateViewState()).Start(); new Thread(() => EvaluateViewState()).Start();
} }
private void DeviceRemoved() private void DeviceRemoved()
{ {
new Thread(() => EvaluateViewState()).Start(); new Thread(() => EvaluateViewState()).Start();
} }
internal override void EvaluateViewState() internal override void EvaluateViewState()
{ {
IsPhoneDisconnected = PhoneNotifier.CurrentInterface == null; IsPhoneDisconnected = PhoneNotifier.CurrentInterface == null;
IsPhoneInMassStorage = PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_MassStorage; IsPhoneInMassStorage = PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_MassStorage;
IsPhoneInOtherMode = !IsPhoneDisconnected && !IsPhoneInMassStorage; IsPhoneInOtherMode = !IsPhoneDisconnected && !IsPhoneInMassStorage;
BackupCommand.RaiseCanExecuteChanged(); BackupCommand.RaiseCanExecuteChanged();
BackupArchiveCommand.RaiseCanExecuteChanged(); BackupArchiveCommand.RaiseCanExecuteChanged();
BackupArchiveProvisioningCommand.RaiseCanExecuteChanged(); BackupArchiveProvisioningCommand.RaiseCanExecuteChanged();
} }
} }
} }

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