diff --git a/WPinternals.sln b/WPinternals.sln
index 7acdd45..d8e6f9d 100644
--- a/WPinternals.sln
+++ b/WPinternals.sln
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31606.5
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WPinternals", "WPinternals.csproj", "{AED6DEB8-F54C-4B41-9655-793E7096AE6E}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WPinternals", "WPinternals\WPinternals.csproj", "{AED6DEB8-F54C-4B41-9655-793E7096AE6E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/7zip/Common/CRC.cs b/WPinternals/7zip/Common/CRC.cs
similarity index 96%
rename from 7zip/Common/CRC.cs
rename to WPinternals/7zip/Common/CRC.cs
index ce5e76c..d9260cc 100644
--- a/7zip/Common/CRC.cs
+++ b/WPinternals/7zip/Common/CRC.cs
@@ -1,64 +1,64 @@
-// Common/CRC.cs
-
-namespace SevenZip
-{
- internal class CRC
- {
- public static readonly uint[] Table;
-
- static CRC()
- {
- Table = new uint[256];
- const uint kPoly = 0xEDB88320;
- for (uint i = 0; i < 256; i++)
- {
- uint r = i;
- for (int j = 0; j < 8; j++)
- {
- if ((r & 1) != 0)
- {
- r = (r >> 1) ^ kPoly;
- }
- else
- {
- r >>= 1;
- }
- }
-
- Table[i] = r;
- }
- }
-
- private uint _value = 0xFFFFFFFF;
-
- public void Init() { _value = 0xFFFFFFFF; }
-
- public void UpdateByte(byte b)
- {
- _value = Table[((byte)_value) ^ b] ^ (_value >> 8);
- }
-
- public void Update(byte[] data, uint offset, uint size)
- {
- for (uint i = 0; i < size; i++)
- {
- _value = Table[((byte)_value) ^ data[offset + i]] ^ (_value >> 8);
- }
- }
-
- public uint GetDigest() { return _value ^ 0xFFFFFFFF; }
-
- private static uint CalculateDigest(byte[] data, uint offset, uint size)
- {
- CRC crc = new();
- // crc.Init();
- crc.Update(data, offset, size);
- return crc.GetDigest();
- }
-
- private static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size)
- {
- return CalculateDigest(data, offset, size) == digest;
- }
- }
-}
+// Common/CRC.cs
+
+namespace SevenZip
+{
+ internal class CRC
+ {
+ public static readonly uint[] Table;
+
+ static CRC()
+ {
+ Table = new uint[256];
+ const uint kPoly = 0xEDB88320;
+ for (uint i = 0; i < 256; i++)
+ {
+ uint r = i;
+ for (int j = 0; j < 8; j++)
+ {
+ if ((r & 1) != 0)
+ {
+ r = (r >> 1) ^ kPoly;
+ }
+ else
+ {
+ r >>= 1;
+ }
+ }
+
+ Table[i] = r;
+ }
+ }
+
+ private uint _value = 0xFFFFFFFF;
+
+ public void Init() { _value = 0xFFFFFFFF; }
+
+ public void UpdateByte(byte b)
+ {
+ _value = Table[((byte)_value) ^ b] ^ (_value >> 8);
+ }
+
+ public void Update(byte[] data, uint offset, uint size)
+ {
+ for (uint i = 0; i < size; i++)
+ {
+ _value = Table[((byte)_value) ^ data[offset + i]] ^ (_value >> 8);
+ }
+ }
+
+ public uint GetDigest() { return _value ^ 0xFFFFFFFF; }
+
+ private static uint CalculateDigest(byte[] data, uint offset, uint size)
+ {
+ CRC crc = new();
+ // crc.Init();
+ crc.Update(data, offset, size);
+ return crc.GetDigest();
+ }
+
+ private static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size)
+ {
+ return CalculateDigest(data, offset, size) == digest;
+ }
+ }
+}
diff --git a/7zip/Common/CommandLineParser.cs b/WPinternals/7zip/Common/CommandLineParser.cs
similarity index 97%
rename from 7zip/Common/CommandLineParser.cs
rename to WPinternals/7zip/Common/CommandLineParser.cs
index 1419528..6facd78 100644
--- a/7zip/Common/CommandLineParser.cs
+++ b/WPinternals/7zip/Common/CommandLineParser.cs
@@ -1,325 +1,325 @@
-// CommandLineParser.cs
-
-using System;
-using System.Collections;
-
-namespace SevenZip.CommandLineParser
-{
- public enum SwitchType
- {
- Simple,
- PostMinus,
- LimitedPostString,
- UnLimitedPostString,
- PostChar
- }
-
- public class SwitchForm
- {
- public string IDString;
- public SwitchType Type;
- public bool Multi;
- public int MinLen;
- public int MaxLen;
- public string PostCharSet;
-
- public SwitchForm(string idString, SwitchType type, bool multi,
- int minLen, int maxLen, string postCharSet)
- {
- IDString = idString;
- Type = type;
- Multi = multi;
- MinLen = minLen;
- MaxLen = maxLen;
- PostCharSet = postCharSet;
- }
- public SwitchForm(string idString, SwitchType type, bool multi, int minLen) :
- this(idString, type, multi, minLen, 0, "")
- {
- }
- public SwitchForm(string idString, SwitchType type, bool multi) :
- this(idString, type, multi, 0)
- {
- }
- }
-
- public class SwitchResult
- {
- public bool ThereIs;
- public bool WithMinus;
- public ArrayList PostStrings = new();
- public int PostCharIndex;
- public SwitchResult()
- {
- ThereIs = false;
- }
- }
-
- public class Parser
- {
- public ArrayList NonSwitchStrings = new();
- private readonly SwitchResult[] _switches;
-
- public Parser(int numSwitches)
- {
- _switches = new SwitchResult[numSwitches];
- for (int i = 0; i < numSwitches; i++)
- {
- _switches[i] = new SwitchResult();
- }
- }
-
- private bool ParseString(string srcString, SwitchForm[] switchForms)
- {
- int len = srcString.Length;
- if (len == 0)
- {
- return false;
- }
-
- int pos = 0;
- if (!IsItSwitchChar(srcString[pos]))
- {
- return false;
- }
-
- while (pos < len)
- {
- if (IsItSwitchChar(srcString[pos]))
- {
- pos++;
- }
-
- const int kNoLen = -1;
- int matchedSwitchIndex = 0;
- int maxLen = kNoLen;
- for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++)
- {
- int switchLen = switchForms[switchIndex].IDString.Length;
- if (switchLen <= maxLen || pos + switchLen > len)
- {
- continue;
- }
-
- if (String.Compare(switchForms[switchIndex].IDString, 0,
- srcString, pos, switchLen, true) == 0)
- {
- matchedSwitchIndex = switchIndex;
- maxLen = switchLen;
- }
- }
- if (maxLen == kNoLen)
- {
- throw new Exception("maxLen == kNoLen");
- }
-
- SwitchResult matchedSwitch = _switches[matchedSwitchIndex];
- SwitchForm switchForm = switchForms[matchedSwitchIndex];
- if ((!switchForm.Multi) && matchedSwitch.ThereIs)
- {
- throw new Exception("switch must be single");
- }
-
- matchedSwitch.ThereIs = true;
- pos += maxLen;
- int tailSize = len - pos;
- SwitchType type = switchForm.Type;
- switch (type)
- {
- case SwitchType.PostMinus:
- {
- if (tailSize == 0)
- {
- matchedSwitch.WithMinus = false;
- }
- else
- {
- matchedSwitch.WithMinus = srcString[pos] == kSwitchMinus;
- if (matchedSwitch.WithMinus)
- {
- pos++;
- }
- }
- break;
- }
- case SwitchType.PostChar:
- {
- if (tailSize < switchForm.MinLen)
- {
- throw new Exception("switch is not full");
- }
-
- string charSet = switchForm.PostCharSet;
- const int kEmptyCharValue = -1;
- if (tailSize == 0)
- {
- matchedSwitch.PostCharIndex = kEmptyCharValue;
- }
- else
- {
- int index = charSet.IndexOf(srcString[pos]);
- if (index < 0)
- {
- matchedSwitch.PostCharIndex = kEmptyCharValue;
- }
- else
- {
- matchedSwitch.PostCharIndex = index;
- pos++;
- }
- }
- break;
- }
- case SwitchType.LimitedPostString:
- case SwitchType.UnLimitedPostString:
- {
- int minLen = switchForm.MinLen;
- if (tailSize < minLen)
- {
- throw new Exception("switch is not full");
- }
-
- if (type == SwitchType.UnLimitedPostString)
- {
- matchedSwitch.PostStrings.Add(srcString[pos..]);
- return true;
- }
- String stringSwitch = srcString.Substring(pos, minLen);
- pos += minLen;
- for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++)
- {
- char c = srcString[pos];
- if (IsItSwitchChar(c))
- {
- break;
- }
-
- stringSwitch += c;
- }
- matchedSwitch.PostStrings.Add(stringSwitch);
- break;
- }
- }
- }
- return true;
- }
-
- public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings)
- {
- int numCommandStrings = commandStrings.Length;
- bool stopSwitch = false;
- for (int i = 0; i < numCommandStrings; i++)
- {
- string s = commandStrings[i];
- if (stopSwitch)
- {
- NonSwitchStrings.Add(s);
- }
- else
- if (s == kStopSwitchParsing)
- {
- stopSwitch = true;
- }
- else
- if (!ParseString(s, switchForms))
- {
- NonSwitchStrings.Add(s);
- }
- }
- }
-
- public SwitchResult this[int index] { get { return _switches[index]; } }
-
- public static int ParseCommand(CommandForm[] commandForms, string commandString,
- out string postString)
- {
- for (int i = 0; i < commandForms.Length; i++)
- {
- string id = commandForms[i].IDString;
- if (commandForms[i].PostStringMode)
- {
- if (commandString.IndexOf(id) == 0)
- {
- postString = commandString[id.Length..];
- return i;
- }
- }
- else
- if (commandString == id)
- {
- postString = "";
- return i;
- }
- }
- postString = "";
- return -1;
- }
-
- private static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms,
- string commandString, ArrayList indices)
- {
- indices.Clear();
- int numUsedChars = 0;
- for (int i = 0; i < numForms; i++)
- {
- CommandSubCharsSet charsSet = forms[i];
- int currentIndex = -1;
- int len = charsSet.Chars.Length;
- for (int j = 0; j < len; j++)
- {
- char c = charsSet.Chars[j];
- int newIndex = commandString.IndexOf(c);
- if (newIndex >= 0)
- {
- if (currentIndex >= 0)
- {
- return false;
- }
-
- if (commandString.IndexOf(c, newIndex + 1) >= 0)
- {
- return false;
- }
-
- currentIndex = j;
- numUsedChars++;
- }
- }
- if (currentIndex == -1 && !charsSet.EmptyAllowed)
- {
- return false;
- }
-
- indices.Add(currentIndex);
- }
- return numUsedChars == commandString.Length;
- }
- private const char kSwitchID1 = '-';
- private const char kSwitchID2 = '/';
-
- private const char kSwitchMinus = '-';
- private const string kStopSwitchParsing = "--";
-
- private static bool IsItSwitchChar(char c)
- {
- return c == kSwitchID1 || c == kSwitchID2;
- }
- }
-
- public class CommandForm
- {
- public string IDString = "";
- public bool PostStringMode = false;
- public CommandForm(string idString, bool postStringMode)
- {
- IDString = idString;
- PostStringMode = postStringMode;
- }
- }
-
- internal class CommandSubCharsSet
- {
- public string Chars = "";
- public bool EmptyAllowed = false;
- }
-}
+// CommandLineParser.cs
+
+using System;
+using System.Collections;
+
+namespace SevenZip.CommandLineParser
+{
+ public enum SwitchType
+ {
+ Simple,
+ PostMinus,
+ LimitedPostString,
+ UnLimitedPostString,
+ PostChar
+ }
+
+ public class SwitchForm
+ {
+ public string IDString;
+ public SwitchType Type;
+ public bool Multi;
+ public int MinLen;
+ public int MaxLen;
+ public string PostCharSet;
+
+ public SwitchForm(string idString, SwitchType type, bool multi,
+ int minLen, int maxLen, string postCharSet)
+ {
+ IDString = idString;
+ Type = type;
+ Multi = multi;
+ MinLen = minLen;
+ MaxLen = maxLen;
+ PostCharSet = postCharSet;
+ }
+ public SwitchForm(string idString, SwitchType type, bool multi, int minLen) :
+ this(idString, type, multi, minLen, 0, "")
+ {
+ }
+ public SwitchForm(string idString, SwitchType type, bool multi) :
+ this(idString, type, multi, 0)
+ {
+ }
+ }
+
+ public class SwitchResult
+ {
+ public bool ThereIs;
+ public bool WithMinus;
+ public ArrayList PostStrings = new();
+ public int PostCharIndex;
+ public SwitchResult()
+ {
+ ThereIs = false;
+ }
+ }
+
+ public class Parser
+ {
+ public ArrayList NonSwitchStrings = new();
+ private readonly SwitchResult[] _switches;
+
+ public Parser(int numSwitches)
+ {
+ _switches = new SwitchResult[numSwitches];
+ for (int i = 0; i < numSwitches; i++)
+ {
+ _switches[i] = new SwitchResult();
+ }
+ }
+
+ private bool ParseString(string srcString, SwitchForm[] switchForms)
+ {
+ int len = srcString.Length;
+ if (len == 0)
+ {
+ return false;
+ }
+
+ int pos = 0;
+ if (!IsItSwitchChar(srcString[pos]))
+ {
+ return false;
+ }
+
+ while (pos < len)
+ {
+ if (IsItSwitchChar(srcString[pos]))
+ {
+ pos++;
+ }
+
+ const int kNoLen = -1;
+ int matchedSwitchIndex = 0;
+ int maxLen = kNoLen;
+ for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++)
+ {
+ int switchLen = switchForms[switchIndex].IDString.Length;
+ if (switchLen <= maxLen || pos + switchLen > len)
+ {
+ continue;
+ }
+
+ if (String.Compare(switchForms[switchIndex].IDString, 0,
+ srcString, pos, switchLen, true) == 0)
+ {
+ matchedSwitchIndex = switchIndex;
+ maxLen = switchLen;
+ }
+ }
+ if (maxLen == kNoLen)
+ {
+ throw new Exception("maxLen == kNoLen");
+ }
+
+ SwitchResult matchedSwitch = _switches[matchedSwitchIndex];
+ SwitchForm switchForm = switchForms[matchedSwitchIndex];
+ if ((!switchForm.Multi) && matchedSwitch.ThereIs)
+ {
+ throw new Exception("switch must be single");
+ }
+
+ matchedSwitch.ThereIs = true;
+ pos += maxLen;
+ int tailSize = len - pos;
+ SwitchType type = switchForm.Type;
+ switch (type)
+ {
+ case SwitchType.PostMinus:
+ {
+ if (tailSize == 0)
+ {
+ matchedSwitch.WithMinus = false;
+ }
+ else
+ {
+ matchedSwitch.WithMinus = srcString[pos] == kSwitchMinus;
+ if (matchedSwitch.WithMinus)
+ {
+ pos++;
+ }
+ }
+ break;
+ }
+ case SwitchType.PostChar:
+ {
+ if (tailSize < switchForm.MinLen)
+ {
+ throw new Exception("switch is not full");
+ }
+
+ string charSet = switchForm.PostCharSet;
+ const int kEmptyCharValue = -1;
+ if (tailSize == 0)
+ {
+ matchedSwitch.PostCharIndex = kEmptyCharValue;
+ }
+ else
+ {
+ int index = charSet.IndexOf(srcString[pos]);
+ if (index < 0)
+ {
+ matchedSwitch.PostCharIndex = kEmptyCharValue;
+ }
+ else
+ {
+ matchedSwitch.PostCharIndex = index;
+ pos++;
+ }
+ }
+ break;
+ }
+ case SwitchType.LimitedPostString:
+ case SwitchType.UnLimitedPostString:
+ {
+ int minLen = switchForm.MinLen;
+ if (tailSize < minLen)
+ {
+ throw new Exception("switch is not full");
+ }
+
+ if (type == SwitchType.UnLimitedPostString)
+ {
+ matchedSwitch.PostStrings.Add(srcString[pos..]);
+ return true;
+ }
+ String stringSwitch = srcString.Substring(pos, minLen);
+ pos += minLen;
+ for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++)
+ {
+ char c = srcString[pos];
+ if (IsItSwitchChar(c))
+ {
+ break;
+ }
+
+ stringSwitch += c;
+ }
+ matchedSwitch.PostStrings.Add(stringSwitch);
+ break;
+ }
+ }
+ }
+ return true;
+ }
+
+ public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings)
+ {
+ int numCommandStrings = commandStrings.Length;
+ bool stopSwitch = false;
+ for (int i = 0; i < numCommandStrings; i++)
+ {
+ string s = commandStrings[i];
+ if (stopSwitch)
+ {
+ NonSwitchStrings.Add(s);
+ }
+ else
+ if (s == kStopSwitchParsing)
+ {
+ stopSwitch = true;
+ }
+ else
+ if (!ParseString(s, switchForms))
+ {
+ NonSwitchStrings.Add(s);
+ }
+ }
+ }
+
+ public SwitchResult this[int index] { get { return _switches[index]; } }
+
+ public static int ParseCommand(CommandForm[] commandForms, string commandString,
+ out string postString)
+ {
+ for (int i = 0; i < commandForms.Length; i++)
+ {
+ string id = commandForms[i].IDString;
+ if (commandForms[i].PostStringMode)
+ {
+ if (commandString.IndexOf(id) == 0)
+ {
+ postString = commandString[id.Length..];
+ return i;
+ }
+ }
+ else
+ if (commandString == id)
+ {
+ postString = "";
+ return i;
+ }
+ }
+ postString = "";
+ return -1;
+ }
+
+ private static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms,
+ string commandString, ArrayList indices)
+ {
+ indices.Clear();
+ int numUsedChars = 0;
+ for (int i = 0; i < numForms; i++)
+ {
+ CommandSubCharsSet charsSet = forms[i];
+ int currentIndex = -1;
+ int len = charsSet.Chars.Length;
+ for (int j = 0; j < len; j++)
+ {
+ char c = charsSet.Chars[j];
+ int newIndex = commandString.IndexOf(c);
+ if (newIndex >= 0)
+ {
+ if (currentIndex >= 0)
+ {
+ return false;
+ }
+
+ if (commandString.IndexOf(c, newIndex + 1) >= 0)
+ {
+ return false;
+ }
+
+ currentIndex = j;
+ numUsedChars++;
+ }
+ }
+ if (currentIndex == -1 && !charsSet.EmptyAllowed)
+ {
+ return false;
+ }
+
+ indices.Add(currentIndex);
+ }
+ return numUsedChars == commandString.Length;
+ }
+ private const char kSwitchID1 = '-';
+ private const char kSwitchID2 = '/';
+
+ private const char kSwitchMinus = '-';
+ private const string kStopSwitchParsing = "--";
+
+ private static bool IsItSwitchChar(char c)
+ {
+ return c == kSwitchID1 || c == kSwitchID2;
+ }
+ }
+
+ public class CommandForm
+ {
+ public string IDString = "";
+ public bool PostStringMode = false;
+ public CommandForm(string idString, bool postStringMode)
+ {
+ IDString = idString;
+ PostStringMode = postStringMode;
+ }
+ }
+
+ internal class CommandSubCharsSet
+ {
+ public string Chars = "";
+ public bool EmptyAllowed = false;
+ }
+}
diff --git a/7zip/Common/InBuffer.cs b/WPinternals/7zip/Common/InBuffer.cs
similarity index 96%
rename from 7zip/Common/InBuffer.cs
rename to WPinternals/7zip/Common/InBuffer.cs
index 6205287..36ff6b4 100644
--- a/7zip/Common/InBuffer.cs
+++ b/WPinternals/7zip/Common/InBuffer.cs
@@ -1,78 +1,78 @@
-// InBuffer.cs
-
-namespace SevenZip.Buffer
-{
- public class InBuffer
- {
- private readonly byte[] m_Buffer;
- private uint m_Pos;
- private uint m_Limit;
- private readonly uint m_BufferSize;
- private System.IO.Stream m_Stream;
- private bool m_StreamWasExhausted;
- private ulong m_ProcessedSize;
-
- public InBuffer(uint bufferSize)
- {
- m_Buffer = new byte[bufferSize];
- m_BufferSize = bufferSize;
- }
-
- public void Init(System.IO.Stream stream)
- {
- m_Stream = stream;
- m_ProcessedSize = 0;
- m_Limit = 0;
- m_Pos = 0;
- m_StreamWasExhausted = false;
- }
-
- public bool ReadBlock()
- {
- if (m_StreamWasExhausted)
- {
- return false;
- }
-
- m_ProcessedSize += m_Pos;
- int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize);
- m_Pos = 0;
- m_Limit = (uint)aNumProcessedBytes;
- m_StreamWasExhausted = aNumProcessedBytes == 0;
- return !m_StreamWasExhausted;
- }
-
- public void ReleaseStream()
- {
- // m_Stream.Close();
- m_Stream = null;
- }
-
- public bool ReadByte(byte b) // check it
- {
- if (m_Pos >= m_Limit && !ReadBlock())
- {
- return false;
- }
-
- b = m_Buffer[m_Pos++];
- return true;
- }
-
- public byte ReadByte()
- {
- // return (byte)m_Stream.ReadByte();
- if (m_Pos >= m_Limit && !ReadBlock())
- {
- return 0xFF;
- }
-
- return m_Buffer[m_Pos++];
- }
-
- public ulong GetProcessedSize()
- {
- return m_ProcessedSize + m_Pos;
- }
- }
-}
+// InBuffer.cs
+
+namespace SevenZip.Buffer
+{
+ public class InBuffer
+ {
+ private readonly byte[] m_Buffer;
+ private uint m_Pos;
+ private uint m_Limit;
+ private readonly uint m_BufferSize;
+ private System.IO.Stream m_Stream;
+ private bool m_StreamWasExhausted;
+ private ulong m_ProcessedSize;
+
+ public InBuffer(uint bufferSize)
+ {
+ m_Buffer = new byte[bufferSize];
+ m_BufferSize = bufferSize;
+ }
+
+ public void Init(System.IO.Stream stream)
+ {
+ m_Stream = stream;
+ m_ProcessedSize = 0;
+ m_Limit = 0;
+ m_Pos = 0;
+ m_StreamWasExhausted = false;
+ }
+
+ public bool ReadBlock()
+ {
+ if (m_StreamWasExhausted)
+ {
+ return false;
+ }
+
+ m_ProcessedSize += m_Pos;
+ int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize);
+ m_Pos = 0;
+ m_Limit = (uint)aNumProcessedBytes;
+ m_StreamWasExhausted = aNumProcessedBytes == 0;
+ return !m_StreamWasExhausted;
+ }
+
+ public void ReleaseStream()
+ {
+ // m_Stream.Close();
+ m_Stream = null;
+ }
+
+ public bool ReadByte(byte b) // check it
+ {
+ if (m_Pos >= m_Limit && !ReadBlock())
+ {
+ return false;
+ }
+
+ b = m_Buffer[m_Pos++];
+ return true;
+ }
+
+ public byte ReadByte()
+ {
+ // return (byte)m_Stream.ReadByte();
+ if (m_Pos >= m_Limit && !ReadBlock())
+ {
+ return 0xFF;
+ }
+
+ return m_Buffer[m_Pos++];
+ }
+
+ public ulong GetProcessedSize()
+ {
+ return m_ProcessedSize + m_Pos;
+ }
+ }
+}
diff --git a/7zip/Common/OutBuffer.cs b/WPinternals/7zip/Common/OutBuffer.cs
similarity index 96%
rename from 7zip/Common/OutBuffer.cs
rename to WPinternals/7zip/Common/OutBuffer.cs
index a9657df..b371901 100644
--- a/7zip/Common/OutBuffer.cs
+++ b/WPinternals/7zip/Common/OutBuffer.cs
@@ -1,52 +1,52 @@
-// OutBuffer.cs
-
-namespace SevenZip.Buffer
-{
- public class OutBuffer
- {
- private readonly byte[] m_Buffer;
- private uint m_Pos;
- private readonly uint m_BufferSize;
- private System.IO.Stream m_Stream;
- private ulong m_ProcessedSize;
-
- public OutBuffer(uint bufferSize)
- {
- m_Buffer = new byte[bufferSize];
- m_BufferSize = bufferSize;
- }
-
- public void SetStream(System.IO.Stream stream) { m_Stream = stream; }
- public void FlushStream() { m_Stream.Flush(); }
- public void CloseStream() { m_Stream.Close(); }
- public void ReleaseStream() { m_Stream = null; }
-
- public void Init()
- {
- m_ProcessedSize = 0;
- m_Pos = 0;
- }
-
- public void WriteByte(byte b)
- {
- m_Buffer[m_Pos++] = b;
- if (m_Pos >= m_BufferSize)
- {
- FlushData();
- }
- }
-
- public void FlushData()
- {
- if (m_Pos == 0)
- {
- return;
- }
-
- m_Stream.Write(m_Buffer, 0, (int)m_Pos);
- m_Pos = 0;
- }
-
- public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; }
- }
-}
+// OutBuffer.cs
+
+namespace SevenZip.Buffer
+{
+ public class OutBuffer
+ {
+ private readonly byte[] m_Buffer;
+ private uint m_Pos;
+ private readonly uint m_BufferSize;
+ private System.IO.Stream m_Stream;
+ private ulong m_ProcessedSize;
+
+ public OutBuffer(uint bufferSize)
+ {
+ m_Buffer = new byte[bufferSize];
+ m_BufferSize = bufferSize;
+ }
+
+ public void SetStream(System.IO.Stream stream) { m_Stream = stream; }
+ public void FlushStream() { m_Stream.Flush(); }
+ public void CloseStream() { m_Stream.Close(); }
+ public void ReleaseStream() { m_Stream = null; }
+
+ public void Init()
+ {
+ m_ProcessedSize = 0;
+ m_Pos = 0;
+ }
+
+ public void WriteByte(byte b)
+ {
+ m_Buffer[m_Pos++] = b;
+ if (m_Pos >= m_BufferSize)
+ {
+ FlushData();
+ }
+ }
+
+ public void FlushData()
+ {
+ if (m_Pos == 0)
+ {
+ return;
+ }
+
+ m_Stream.Write(m_Buffer, 0, (int)m_Pos);
+ m_Pos = 0;
+ }
+
+ public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; }
+ }
+}
diff --git a/7zip/Compress/LZ/IMatchFinder.cs b/WPinternals/7zip/Compress/LZ/IMatchFinder.cs
similarity index 96%
rename from 7zip/Compress/LZ/IMatchFinder.cs
rename to WPinternals/7zip/Compress/LZ/IMatchFinder.cs
index e0ebbd8..ae4590b 100644
--- a/7zip/Compress/LZ/IMatchFinder.cs
+++ b/WPinternals/7zip/Compress/LZ/IMatchFinder.cs
@@ -1,24 +1,24 @@
-// IMatchFinder.cs
-
-using System;
-
-namespace SevenZip.Compression.LZ
-{
- internal interface IInWindowStream
- {
- void SetStream(System.IO.Stream inStream);
- void Init();
- void ReleaseStream();
- Byte GetIndexByte(Int32 index);
- UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit);
- UInt32 GetNumAvailableBytes();
- }
-
- internal interface IMatchFinder : IInWindowStream
- {
- void Create(UInt32 historySize, UInt32 keepAddBufferBefore,
- UInt32 matchMaxLen, UInt32 keepAddBufferAfter);
- UInt32 GetMatches(UInt32[] distances);
- void Skip(UInt32 num);
- }
-}
+// IMatchFinder.cs
+
+using System;
+
+namespace SevenZip.Compression.LZ
+{
+ internal interface IInWindowStream
+ {
+ void SetStream(System.IO.Stream inStream);
+ void Init();
+ void ReleaseStream();
+ Byte GetIndexByte(Int32 index);
+ UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit);
+ UInt32 GetNumAvailableBytes();
+ }
+
+ internal interface IMatchFinder : IInWindowStream
+ {
+ void Create(UInt32 historySize, UInt32 keepAddBufferBefore,
+ UInt32 matchMaxLen, UInt32 keepAddBufferAfter);
+ UInt32 GetMatches(UInt32[] distances);
+ void Skip(UInt32 num);
+ }
+}
diff --git a/7zip/Compress/LZ/LzBinTree.cs b/WPinternals/7zip/Compress/LZ/LzBinTree.cs
similarity index 97%
rename from 7zip/Compress/LZ/LzBinTree.cs
rename to WPinternals/7zip/Compress/LZ/LzBinTree.cs
index c8df03c..5b02c4c 100644
--- a/7zip/Compress/LZ/LzBinTree.cs
+++ b/WPinternals/7zip/Compress/LZ/LzBinTree.cs
@@ -1,408 +1,408 @@
-// LzBinTree.cs
-
-using System;
-
-namespace SevenZip.Compression.LZ
-{
- public class BinTree : InWindow, IMatchFinder
- {
- private UInt32 _cyclicBufferPos;
- private UInt32 _cyclicBufferSize = 0;
- private UInt32 _matchMaxLen;
-
- private UInt32[] _son;
- private UInt32[] _hash;
-
- private UInt32 _cutValue = 0xFF;
- private UInt32 _hashMask;
- private UInt32 _hashSizeSum = 0;
-
- private bool HASH_ARRAY = true;
-
- private const UInt32 kHash2Size = 1 << 10;
- private const UInt32 kHash3Size = 1 << 16;
- private const UInt32 kBT2HashSize = 1 << 16;
- private const UInt32 kStartMaxLen = 1;
- private const UInt32 kHash3Offset = kHash2Size;
- private const UInt32 kEmptyHashValue = 0;
- private const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1;
-
- private UInt32 kNumHashDirectBytes = 0;
- private UInt32 kMinMatchCheck = 4;
- private UInt32 kFixHashSize = kHash2Size + kHash3Size;
-
- public void SetType(int numHashBytes)
- {
- HASH_ARRAY = numHashBytes > 2;
- if (HASH_ARRAY)
- {
- kNumHashDirectBytes = 0;
- kMinMatchCheck = 4;
- kFixHashSize = kHash2Size + kHash3Size;
- }
- else
- {
- kNumHashDirectBytes = 2;
- kMinMatchCheck = 2 + 1;
- kFixHashSize = 0;
- }
- }
-
- public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); }
- public new void ReleaseStream() { base.ReleaseStream(); }
-
- public new void Init()
- {
- base.Init();
- for (UInt32 i = 0; i < _hashSizeSum; i++)
- {
- _hash[i] = kEmptyHashValue;
- }
-
- _cyclicBufferPos = 0;
- ReduceOffsets(-1);
- }
-
- public new void MovePos()
- {
- if (++_cyclicBufferPos >= _cyclicBufferSize)
- {
- _cyclicBufferPos = 0;
- }
-
- base.MovePos();
- if (_pos == kMaxValForNormalize)
- {
- Normalize();
- }
- }
-
- public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); }
-
- public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
- { return base.GetMatchLen(index, distance, limit); }
-
- public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); }
-
- public void Create(UInt32 historySize, UInt32 keepAddBufferBefore,
- UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
- {
- if (historySize > kMaxValForNormalize - 256)
- {
- throw new Exception();
- }
-
- _cutValue = 16 + (matchMaxLen >> 1);
-
- UInt32 windowReservSize = ((historySize + keepAddBufferBefore +
- matchMaxLen + keepAddBufferAfter) / 2) + 256;
-
- Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize);
-
- _matchMaxLen = matchMaxLen;
-
- UInt32 cyclicBufferSize = historySize + 1;
- if (_cyclicBufferSize != cyclicBufferSize)
- {
- _son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2];
- }
-
- UInt32 hs = kBT2HashSize;
-
- if (HASH_ARRAY)
- {
- hs = historySize - 1;
- hs |= hs >> 1;
- hs |= hs >> 2;
- hs |= hs >> 4;
- hs |= hs >> 8;
- hs >>= 1;
- hs |= 0xFFFF;
- if (hs > (1 << 24))
- {
- hs >>= 1;
- }
-
- _hashMask = hs;
- hs++;
- hs += kFixHashSize;
- }
- if (hs != _hashSizeSum)
- {
- _hash = new UInt32[_hashSizeSum = hs];
- }
- }
-
- public UInt32 GetMatches(UInt32[] distances)
- {
- UInt32 lenLimit;
- if (_pos + _matchMaxLen <= _streamPos)
- {
- lenLimit = _matchMaxLen;
- }
- else
- {
- lenLimit = _streamPos - _pos;
- if (lenLimit < kMinMatchCheck)
- {
- MovePos();
- return 0;
- }
- }
-
- UInt32 offset = 0;
- UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
- UInt32 cur = _bufferOffset + _pos;
- UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize;
- UInt32 hashValue, hash2Value = 0, hash3Value = 0;
-
- if (HASH_ARRAY)
- {
- UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];
- hash2Value = temp & (kHash2Size - 1);
- temp ^= (UInt32)_bufferBase[cur + 2] << 8;
- hash3Value = temp & (kHash3Size - 1);
- hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;
- }
- else
- {
- hashValue = _bufferBase[cur] ^ ((UInt32)_bufferBase[cur + 1] << 8);
- }
-
- UInt32 curMatch = _hash[kFixHashSize + hashValue];
- if (HASH_ARRAY)
- {
- UInt32 curMatch2 = _hash[hash2Value];
- UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];
- _hash[hash2Value] = _pos;
- _hash[kHash3Offset + hash3Value] = _pos;
- if (curMatch2 > matchMinPos && _bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur])
- {
- distances[offset++] = maxLen = 2;
- distances[offset++] = _pos - curMatch2 - 1;
- }
-
- if (curMatch3 > matchMinPos && _bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur])
- {
- if (curMatch3 == curMatch2)
- {
- offset -= 2;
- }
-
- distances[offset++] = maxLen = 3;
- distances[offset++] = _pos - curMatch3 - 1;
- curMatch2 = curMatch3;
- }
-
- if (offset != 0 && curMatch2 == curMatch)
- {
- offset -= 2;
- maxLen = kStartMaxLen;
- }
- }
-
- _hash[kFixHashSize + hashValue] = _pos;
-
- UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
- UInt32 ptr1 = _cyclicBufferPos << 1;
-
- UInt32 len0, len1;
- len0 = len1 = kNumHashDirectBytes;
-
- if (kNumHashDirectBytes != 0 && curMatch > matchMinPos)
- {
- if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] !=
- _bufferBase[cur + kNumHashDirectBytes])
- {
- distances[offset++] = maxLen = kNumHashDirectBytes;
- distances[offset++] = _pos - curMatch - 1;
- }
- }
-
- UInt32 count = _cutValue;
-
- while (true)
- {
- if (curMatch <= matchMinPos || count-- == 0)
- {
- _son[ptr0] = _son[ptr1] = kEmptyHashValue;
- break;
- }
- UInt32 delta = _pos - curMatch;
- UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
- (_cyclicBufferPos - delta) :
- (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
-
- UInt32 pby1 = _bufferOffset + curMatch;
- UInt32 len = Math.Min(len0, len1);
- if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
- {
- while (++len != lenLimit)
- {
- if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
- {
- break;
- }
- }
-
- if (maxLen < len)
- {
- distances[offset++] = maxLen = len;
- distances[offset++] = delta - 1;
- if (len == lenLimit)
- {
- _son[ptr1] = _son[cyclicPos];
- _son[ptr0] = _son[cyclicPos + 1];
- break;
- }
- }
- }
- if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
- {
- _son[ptr1] = curMatch;
- ptr1 = cyclicPos + 1;
- curMatch = _son[ptr1];
- len1 = len;
- }
- else
- {
- _son[ptr0] = curMatch;
- ptr0 = cyclicPos;
- curMatch = _son[ptr0];
- len0 = len;
- }
- }
- MovePos();
- return offset;
- }
-
- public void Skip(UInt32 num)
- {
- do
- {
- UInt32 lenLimit;
- if (_pos + _matchMaxLen <= _streamPos)
- {
- lenLimit = _matchMaxLen;
- }
- else
- {
- lenLimit = _streamPos - _pos;
- if (lenLimit < kMinMatchCheck)
- {
- MovePos();
- continue;
- }
- }
-
- UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
- UInt32 cur = _bufferOffset + _pos;
-
- UInt32 hashValue;
-
- if (HASH_ARRAY)
- {
- UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];
- UInt32 hash2Value = temp & (kHash2Size - 1);
- _hash[hash2Value] = _pos;
- temp ^= (UInt32)_bufferBase[cur + 2] << 8;
- UInt32 hash3Value = temp & (kHash3Size - 1);
- _hash[kHash3Offset + hash3Value] = _pos;
- hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;
- }
- else
- {
- hashValue = _bufferBase[cur] ^ ((UInt32)_bufferBase[cur + 1] << 8);
- }
-
- UInt32 curMatch = _hash[kFixHashSize + hashValue];
- _hash[kFixHashSize + hashValue] = _pos;
-
- UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
- UInt32 ptr1 = _cyclicBufferPos << 1;
-
- UInt32 len0, len1;
- len0 = len1 = kNumHashDirectBytes;
-
- UInt32 count = _cutValue;
- while (true)
- {
- if (curMatch <= matchMinPos || count-- == 0)
- {
- _son[ptr0] = _son[ptr1] = kEmptyHashValue;
- break;
- }
-
- UInt32 delta = _pos - curMatch;
- UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
- (_cyclicBufferPos - delta) :
- (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
-
- UInt32 pby1 = _bufferOffset + curMatch;
- UInt32 len = Math.Min(len0, len1);
- if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
- {
- while (++len != lenLimit)
- {
- if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
- {
- break;
- }
- }
-
- if (len == lenLimit)
- {
- _son[ptr1] = _son[cyclicPos];
- _son[ptr0] = _son[cyclicPos + 1];
- break;
- }
- }
- if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
- {
- _son[ptr1] = curMatch;
- ptr1 = cyclicPos + 1;
- curMatch = _son[ptr1];
- len1 = len;
- }
- else
- {
- _son[ptr0] = curMatch;
- ptr0 = cyclicPos;
- curMatch = _son[ptr0];
- len0 = len;
- }
- }
- MovePos();
- }
- while (--num != 0);
- }
-
- private void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue)
- {
- for (UInt32 i = 0; i < numItems; i++)
- {
- UInt32 value = items[i];
- if (value <= subValue)
- {
- value = kEmptyHashValue;
- }
- else
- {
- value -= subValue;
- }
-
- items[i] = value;
- }
- }
-
- private void Normalize()
- {
- UInt32 subValue = _pos - _cyclicBufferSize;
- NormalizeLinks(_son, _cyclicBufferSize * 2, subValue);
- NormalizeLinks(_hash, _hashSizeSum, subValue);
- ReduceOffsets((Int32)subValue);
- }
-
- public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; }
- }
-}
+// LzBinTree.cs
+
+using System;
+
+namespace SevenZip.Compression.LZ
+{
+ public class BinTree : InWindow, IMatchFinder
+ {
+ private UInt32 _cyclicBufferPos;
+ private UInt32 _cyclicBufferSize = 0;
+ private UInt32 _matchMaxLen;
+
+ private UInt32[] _son;
+ private UInt32[] _hash;
+
+ private UInt32 _cutValue = 0xFF;
+ private UInt32 _hashMask;
+ private UInt32 _hashSizeSum = 0;
+
+ private bool HASH_ARRAY = true;
+
+ private const UInt32 kHash2Size = 1 << 10;
+ private const UInt32 kHash3Size = 1 << 16;
+ private const UInt32 kBT2HashSize = 1 << 16;
+ private const UInt32 kStartMaxLen = 1;
+ private const UInt32 kHash3Offset = kHash2Size;
+ private const UInt32 kEmptyHashValue = 0;
+ private const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1;
+
+ private UInt32 kNumHashDirectBytes = 0;
+ private UInt32 kMinMatchCheck = 4;
+ private UInt32 kFixHashSize = kHash2Size + kHash3Size;
+
+ public void SetType(int numHashBytes)
+ {
+ HASH_ARRAY = numHashBytes > 2;
+ if (HASH_ARRAY)
+ {
+ kNumHashDirectBytes = 0;
+ kMinMatchCheck = 4;
+ kFixHashSize = kHash2Size + kHash3Size;
+ }
+ else
+ {
+ kNumHashDirectBytes = 2;
+ kMinMatchCheck = 2 + 1;
+ kFixHashSize = 0;
+ }
+ }
+
+ public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); }
+ public new void ReleaseStream() { base.ReleaseStream(); }
+
+ public new void Init()
+ {
+ base.Init();
+ for (UInt32 i = 0; i < _hashSizeSum; i++)
+ {
+ _hash[i] = kEmptyHashValue;
+ }
+
+ _cyclicBufferPos = 0;
+ ReduceOffsets(-1);
+ }
+
+ public new void MovePos()
+ {
+ if (++_cyclicBufferPos >= _cyclicBufferSize)
+ {
+ _cyclicBufferPos = 0;
+ }
+
+ base.MovePos();
+ if (_pos == kMaxValForNormalize)
+ {
+ Normalize();
+ }
+ }
+
+ public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); }
+
+ public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
+ { return base.GetMatchLen(index, distance, limit); }
+
+ public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); }
+
+ public void Create(UInt32 historySize, UInt32 keepAddBufferBefore,
+ UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
+ {
+ if (historySize > kMaxValForNormalize - 256)
+ {
+ throw new Exception();
+ }
+
+ _cutValue = 16 + (matchMaxLen >> 1);
+
+ UInt32 windowReservSize = ((historySize + keepAddBufferBefore +
+ matchMaxLen + keepAddBufferAfter) / 2) + 256;
+
+ Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize);
+
+ _matchMaxLen = matchMaxLen;
+
+ UInt32 cyclicBufferSize = historySize + 1;
+ if (_cyclicBufferSize != cyclicBufferSize)
+ {
+ _son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2];
+ }
+
+ UInt32 hs = kBT2HashSize;
+
+ if (HASH_ARRAY)
+ {
+ hs = historySize - 1;
+ hs |= hs >> 1;
+ hs |= hs >> 2;
+ hs |= hs >> 4;
+ hs |= hs >> 8;
+ hs >>= 1;
+ hs |= 0xFFFF;
+ if (hs > (1 << 24))
+ {
+ hs >>= 1;
+ }
+
+ _hashMask = hs;
+ hs++;
+ hs += kFixHashSize;
+ }
+ if (hs != _hashSizeSum)
+ {
+ _hash = new UInt32[_hashSizeSum = hs];
+ }
+ }
+
+ public UInt32 GetMatches(UInt32[] distances)
+ {
+ UInt32 lenLimit;
+ if (_pos + _matchMaxLen <= _streamPos)
+ {
+ lenLimit = _matchMaxLen;
+ }
+ else
+ {
+ lenLimit = _streamPos - _pos;
+ if (lenLimit < kMinMatchCheck)
+ {
+ MovePos();
+ return 0;
+ }
+ }
+
+ UInt32 offset = 0;
+ UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
+ UInt32 cur = _bufferOffset + _pos;
+ UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize;
+ UInt32 hashValue, hash2Value = 0, hash3Value = 0;
+
+ if (HASH_ARRAY)
+ {
+ UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];
+ hash2Value = temp & (kHash2Size - 1);
+ temp ^= (UInt32)_bufferBase[cur + 2] << 8;
+ hash3Value = temp & (kHash3Size - 1);
+ hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;
+ }
+ else
+ {
+ hashValue = _bufferBase[cur] ^ ((UInt32)_bufferBase[cur + 1] << 8);
+ }
+
+ UInt32 curMatch = _hash[kFixHashSize + hashValue];
+ if (HASH_ARRAY)
+ {
+ UInt32 curMatch2 = _hash[hash2Value];
+ UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];
+ _hash[hash2Value] = _pos;
+ _hash[kHash3Offset + hash3Value] = _pos;
+ if (curMatch2 > matchMinPos && _bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur])
+ {
+ distances[offset++] = maxLen = 2;
+ distances[offset++] = _pos - curMatch2 - 1;
+ }
+
+ if (curMatch3 > matchMinPos && _bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur])
+ {
+ if (curMatch3 == curMatch2)
+ {
+ offset -= 2;
+ }
+
+ distances[offset++] = maxLen = 3;
+ distances[offset++] = _pos - curMatch3 - 1;
+ curMatch2 = curMatch3;
+ }
+
+ if (offset != 0 && curMatch2 == curMatch)
+ {
+ offset -= 2;
+ maxLen = kStartMaxLen;
+ }
+ }
+
+ _hash[kFixHashSize + hashValue] = _pos;
+
+ UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
+ UInt32 ptr1 = _cyclicBufferPos << 1;
+
+ UInt32 len0, len1;
+ len0 = len1 = kNumHashDirectBytes;
+
+ if (kNumHashDirectBytes != 0 && curMatch > matchMinPos)
+ {
+ if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] !=
+ _bufferBase[cur + kNumHashDirectBytes])
+ {
+ distances[offset++] = maxLen = kNumHashDirectBytes;
+ distances[offset++] = _pos - curMatch - 1;
+ }
+ }
+
+ UInt32 count = _cutValue;
+
+ while (true)
+ {
+ if (curMatch <= matchMinPos || count-- == 0)
+ {
+ _son[ptr0] = _son[ptr1] = kEmptyHashValue;
+ break;
+ }
+ UInt32 delta = _pos - curMatch;
+ UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
+ (_cyclicBufferPos - delta) :
+ (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
+
+ UInt32 pby1 = _bufferOffset + curMatch;
+ UInt32 len = Math.Min(len0, len1);
+ if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
+ {
+ while (++len != lenLimit)
+ {
+ if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
+ {
+ break;
+ }
+ }
+
+ if (maxLen < len)
+ {
+ distances[offset++] = maxLen = len;
+ distances[offset++] = delta - 1;
+ if (len == lenLimit)
+ {
+ _son[ptr1] = _son[cyclicPos];
+ _son[ptr0] = _son[cyclicPos + 1];
+ break;
+ }
+ }
+ }
+ if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
+ {
+ _son[ptr1] = curMatch;
+ ptr1 = cyclicPos + 1;
+ curMatch = _son[ptr1];
+ len1 = len;
+ }
+ else
+ {
+ _son[ptr0] = curMatch;
+ ptr0 = cyclicPos;
+ curMatch = _son[ptr0];
+ len0 = len;
+ }
+ }
+ MovePos();
+ return offset;
+ }
+
+ public void Skip(UInt32 num)
+ {
+ do
+ {
+ UInt32 lenLimit;
+ if (_pos + _matchMaxLen <= _streamPos)
+ {
+ lenLimit = _matchMaxLen;
+ }
+ else
+ {
+ lenLimit = _streamPos - _pos;
+ if (lenLimit < kMinMatchCheck)
+ {
+ MovePos();
+ continue;
+ }
+ }
+
+ UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
+ UInt32 cur = _bufferOffset + _pos;
+
+ UInt32 hashValue;
+
+ if (HASH_ARRAY)
+ {
+ UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];
+ UInt32 hash2Value = temp & (kHash2Size - 1);
+ _hash[hash2Value] = _pos;
+ temp ^= (UInt32)_bufferBase[cur + 2] << 8;
+ UInt32 hash3Value = temp & (kHash3Size - 1);
+ _hash[kHash3Offset + hash3Value] = _pos;
+ hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;
+ }
+ else
+ {
+ hashValue = _bufferBase[cur] ^ ((UInt32)_bufferBase[cur + 1] << 8);
+ }
+
+ UInt32 curMatch = _hash[kFixHashSize + hashValue];
+ _hash[kFixHashSize + hashValue] = _pos;
+
+ UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
+ UInt32 ptr1 = _cyclicBufferPos << 1;
+
+ UInt32 len0, len1;
+ len0 = len1 = kNumHashDirectBytes;
+
+ UInt32 count = _cutValue;
+ while (true)
+ {
+ if (curMatch <= matchMinPos || count-- == 0)
+ {
+ _son[ptr0] = _son[ptr1] = kEmptyHashValue;
+ break;
+ }
+
+ UInt32 delta = _pos - curMatch;
+ UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
+ (_cyclicBufferPos - delta) :
+ (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
+
+ UInt32 pby1 = _bufferOffset + curMatch;
+ UInt32 len = Math.Min(len0, len1);
+ if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
+ {
+ while (++len != lenLimit)
+ {
+ if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
+ {
+ break;
+ }
+ }
+
+ if (len == lenLimit)
+ {
+ _son[ptr1] = _son[cyclicPos];
+ _son[ptr0] = _son[cyclicPos + 1];
+ break;
+ }
+ }
+ if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
+ {
+ _son[ptr1] = curMatch;
+ ptr1 = cyclicPos + 1;
+ curMatch = _son[ptr1];
+ len1 = len;
+ }
+ else
+ {
+ _son[ptr0] = curMatch;
+ ptr0 = cyclicPos;
+ curMatch = _son[ptr0];
+ len0 = len;
+ }
+ }
+ MovePos();
+ }
+ while (--num != 0);
+ }
+
+ private void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue)
+ {
+ for (UInt32 i = 0; i < numItems; i++)
+ {
+ UInt32 value = items[i];
+ if (value <= subValue)
+ {
+ value = kEmptyHashValue;
+ }
+ else
+ {
+ value -= subValue;
+ }
+
+ items[i] = value;
+ }
+ }
+
+ private void Normalize()
+ {
+ UInt32 subValue = _pos - _cyclicBufferSize;
+ NormalizeLinks(_son, _cyclicBufferSize * 2, subValue);
+ NormalizeLinks(_hash, _hashSizeSum, subValue);
+ ReduceOffsets((Int32)subValue);
+ }
+
+ public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; }
+ }
+}
diff --git a/7zip/Compress/LZ/LzInWindow.cs b/WPinternals/7zip/Compress/LZ/LzInWindow.cs
similarity index 97%
rename from 7zip/Compress/LZ/LzInWindow.cs
rename to WPinternals/7zip/Compress/LZ/LzInWindow.cs
index f54e368..f9f5603 100644
--- a/7zip/Compress/LZ/LzInWindow.cs
+++ b/WPinternals/7zip/Compress/LZ/LzInWindow.cs
@@ -1,155 +1,155 @@
-// LzInWindow.cs
-
-using System;
-
-namespace SevenZip.Compression.LZ
-{
- public class InWindow
- {
- public Byte[] _bufferBase = null; // pointer to buffer with data
- private System.IO.Stream _stream;
- 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 UInt32 _pointerToLastSafePosition;
-
- public UInt32 _bufferOffset;
-
- public UInt32 _blockSize; // Size of Allocated memory block
- public UInt32 _pos; // offset (from _buffer) of curent byte
- 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
- public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream
-
- public void MoveBlock()
- {
- UInt32 offset = _bufferOffset + _pos - _keepSizeBefore;
- // we need one additional byte, since MovePos moves on 1 byte.
- if (offset > 0)
- {
- offset--;
- }
-
- UInt32 numBytes = _bufferOffset + _streamPos - offset;
-
- // check negative offset ????
- for (UInt32 i = 0; i < numBytes; i++)
- {
- _bufferBase[i] = _bufferBase[offset + i];
- }
-
- _bufferOffset -= offset;
- }
-
- public virtual void ReadBlock()
- {
- if (_streamEndWasReached)
- {
- return;
- }
-
- while (true)
- {
- int size = (int)(0 - _bufferOffset + _blockSize - _streamPos);
- if (size == 0)
- {
- return;
- }
-
- int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size);
- if (numReadBytes == 0)
- {
- _posLimit = _streamPos;
- UInt32 pointerToPostion = _bufferOffset + _posLimit;
- if (pointerToPostion > _pointerToLastSafePosition)
- {
- _posLimit = _pointerToLastSafePosition - _bufferOffset;
- }
-
- _streamEndWasReached = true;
- return;
- }
- _streamPos += (UInt32)numReadBytes;
- if (_streamPos >= _pos + _keepSizeAfter)
- {
- _posLimit = _streamPos - _keepSizeAfter;
- }
- }
- }
-
- private void Free() { _bufferBase = null; }
-
- public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv)
- {
- _keepSizeBefore = keepSizeBefore;
- _keepSizeAfter = keepSizeAfter;
- UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;
- if (_bufferBase == null || _blockSize != blockSize)
- {
- Free();
- _blockSize = blockSize;
- _bufferBase = new Byte[_blockSize];
- }
- _pointerToLastSafePosition = _blockSize - keepSizeAfter;
- }
-
- public void SetStream(System.IO.Stream stream) { _stream = stream; }
- public void ReleaseStream() { _stream = null; }
-
- public void Init()
- {
- _bufferOffset = 0;
- _pos = 0;
- _streamPos = 0;
- _streamEndWasReached = false;
- ReadBlock();
- }
-
- public void MovePos()
- {
- _pos++;
- if (_pos > _posLimit)
- {
- UInt32 pointerToPostion = _bufferOffset + _pos;
- if (pointerToPostion > _pointerToLastSafePosition)
- {
- MoveBlock();
- }
-
- ReadBlock();
- }
- }
-
- public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; }
-
- // index + limit have not to exceed _keepSizeAfter;
- public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
- {
- if (_streamEndWasReached && _pos + index + limit > _streamPos)
- {
- limit = _streamPos - (UInt32)(_pos + index);
- }
-
- distance++;
- // Byte *pby = _buffer + (size_t)_pos + index;
- UInt32 pby = _bufferOffset + _pos + (UInt32)index;
-
- UInt32 i;
- for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++)
- {
- }
-
- return i;
- }
-
- public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; }
-
- public void ReduceOffsets(Int32 subValue)
- {
- _bufferOffset += (UInt32)subValue;
- _posLimit -= (UInt32)subValue;
- _pos -= (UInt32)subValue;
- _streamPos -= (UInt32)subValue;
- }
- }
-}
+// LzInWindow.cs
+
+using System;
+
+namespace SevenZip.Compression.LZ
+{
+ public class InWindow
+ {
+ public Byte[] _bufferBase = null; // pointer to buffer with data
+ private System.IO.Stream _stream;
+ 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 UInt32 _pointerToLastSafePosition;
+
+ public UInt32 _bufferOffset;
+
+ public UInt32 _blockSize; // Size of Allocated memory block
+ public UInt32 _pos; // offset (from _buffer) of curent byte
+ 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
+ public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream
+
+ public void MoveBlock()
+ {
+ UInt32 offset = _bufferOffset + _pos - _keepSizeBefore;
+ // we need one additional byte, since MovePos moves on 1 byte.
+ if (offset > 0)
+ {
+ offset--;
+ }
+
+ UInt32 numBytes = _bufferOffset + _streamPos - offset;
+
+ // check negative offset ????
+ for (UInt32 i = 0; i < numBytes; i++)
+ {
+ _bufferBase[i] = _bufferBase[offset + i];
+ }
+
+ _bufferOffset -= offset;
+ }
+
+ public virtual void ReadBlock()
+ {
+ if (_streamEndWasReached)
+ {
+ return;
+ }
+
+ while (true)
+ {
+ int size = (int)(0 - _bufferOffset + _blockSize - _streamPos);
+ if (size == 0)
+ {
+ return;
+ }
+
+ int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size);
+ if (numReadBytes == 0)
+ {
+ _posLimit = _streamPos;
+ UInt32 pointerToPostion = _bufferOffset + _posLimit;
+ if (pointerToPostion > _pointerToLastSafePosition)
+ {
+ _posLimit = _pointerToLastSafePosition - _bufferOffset;
+ }
+
+ _streamEndWasReached = true;
+ return;
+ }
+ _streamPos += (UInt32)numReadBytes;
+ if (_streamPos >= _pos + _keepSizeAfter)
+ {
+ _posLimit = _streamPos - _keepSizeAfter;
+ }
+ }
+ }
+
+ private void Free() { _bufferBase = null; }
+
+ public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv)
+ {
+ _keepSizeBefore = keepSizeBefore;
+ _keepSizeAfter = keepSizeAfter;
+ UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;
+ if (_bufferBase == null || _blockSize != blockSize)
+ {
+ Free();
+ _blockSize = blockSize;
+ _bufferBase = new Byte[_blockSize];
+ }
+ _pointerToLastSafePosition = _blockSize - keepSizeAfter;
+ }
+
+ public void SetStream(System.IO.Stream stream) { _stream = stream; }
+ public void ReleaseStream() { _stream = null; }
+
+ public void Init()
+ {
+ _bufferOffset = 0;
+ _pos = 0;
+ _streamPos = 0;
+ _streamEndWasReached = false;
+ ReadBlock();
+ }
+
+ public void MovePos()
+ {
+ _pos++;
+ if (_pos > _posLimit)
+ {
+ UInt32 pointerToPostion = _bufferOffset + _pos;
+ if (pointerToPostion > _pointerToLastSafePosition)
+ {
+ MoveBlock();
+ }
+
+ ReadBlock();
+ }
+ }
+
+ public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; }
+
+ // index + limit have not to exceed _keepSizeAfter;
+ public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
+ {
+ if (_streamEndWasReached && _pos + index + limit > _streamPos)
+ {
+ limit = _streamPos - (UInt32)(_pos + index);
+ }
+
+ distance++;
+ // Byte *pby = _buffer + (size_t)_pos + index;
+ UInt32 pby = _bufferOffset + _pos + (UInt32)index;
+
+ UInt32 i;
+ for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++)
+ {
+ }
+
+ return i;
+ }
+
+ public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; }
+
+ public void ReduceOffsets(Int32 subValue)
+ {
+ _bufferOffset += (UInt32)subValue;
+ _posLimit -= (UInt32)subValue;
+ _pos -= (UInt32)subValue;
+ _streamPos -= (UInt32)subValue;
+ }
+ }
+}
diff --git a/7zip/Compress/LZ/LzOutWindow.cs b/WPinternals/7zip/Compress/LZ/LzOutWindow.cs
similarity index 96%
rename from 7zip/Compress/LZ/LzOutWindow.cs
rename to WPinternals/7zip/Compress/LZ/LzOutWindow.cs
index 24bbd49..1fa77fb 100644
--- a/7zip/Compress/LZ/LzOutWindow.cs
+++ b/WPinternals/7zip/Compress/LZ/LzOutWindow.cs
@@ -1,137 +1,137 @@
-// LzOutWindow.cs
-
-namespace SevenZip.Compression.LZ
-{
- public class OutWindow
- {
- private byte[] _buffer = null;
- private uint _pos;
- private uint _windowSize = 0;
- private uint _streamPos;
- private System.IO.Stream _stream;
-
- public uint TrainSize = 0;
-
- public void Create(uint windowSize)
- {
- if (_windowSize != windowSize)
- {
- // System.GC.Collect();
- _buffer = new byte[windowSize];
- }
- _windowSize = windowSize;
- _pos = 0;
- _streamPos = 0;
- }
-
- public void Init(System.IO.Stream stream, bool solid)
- {
- ReleaseStream();
- _stream = stream;
- if (!solid)
- {
- _streamPos = 0;
- _pos = 0;
- TrainSize = 0;
- }
- }
-
- public bool Train(System.IO.Stream stream)
- {
- long len = stream.Length;
- uint size = (len < _windowSize) ? (uint)len : _windowSize;
- TrainSize = size;
- stream.Position = len - size;
- _streamPos = _pos = 0;
- while (size > 0)
- {
- uint curSize = _windowSize - _pos;
- if (size < curSize)
- {
- curSize = size;
- }
-
- int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize);
- if (numReadBytes == 0)
- {
- return false;
- }
-
- size -= (uint)numReadBytes;
- _pos += (uint)numReadBytes;
- _streamPos += (uint)numReadBytes;
- if (_pos == _windowSize)
- {
- _streamPos = _pos = 0;
- }
- }
- return true;
- }
-
- public void ReleaseStream()
- {
- Flush();
- _stream = null;
- }
-
- public void Flush()
- {
- uint size = _pos - _streamPos;
- if (size == 0)
- {
- return;
- }
-
- _stream.Write(_buffer, (int)_streamPos, (int)size);
- if (_pos >= _windowSize)
- {
- _pos = 0;
- }
-
- _streamPos = _pos;
- }
-
- public void CopyBlock(uint distance, uint len)
- {
- uint pos = _pos - distance - 1;
- if (pos >= _windowSize)
- {
- pos += _windowSize;
- }
-
- for (; len > 0; len--)
- {
- if (pos >= _windowSize)
- {
- pos = 0;
- }
-
- _buffer[_pos++] = _buffer[pos++];
- if (_pos >= _windowSize)
- {
- Flush();
- }
- }
- }
-
- public void PutByte(byte b)
- {
- _buffer[_pos++] = b;
- if (_pos >= _windowSize)
- {
- Flush();
- }
- }
-
- public byte GetByte(uint distance)
- {
- uint pos = _pos - distance - 1;
- if (pos >= _windowSize)
- {
- pos += _windowSize;
- }
-
- return _buffer[pos];
- }
- }
-}
+// LzOutWindow.cs
+
+namespace SevenZip.Compression.LZ
+{
+ public class OutWindow
+ {
+ private byte[] _buffer = null;
+ private uint _pos;
+ private uint _windowSize = 0;
+ private uint _streamPos;
+ private System.IO.Stream _stream;
+
+ public uint TrainSize = 0;
+
+ public void Create(uint windowSize)
+ {
+ if (_windowSize != windowSize)
+ {
+ // System.GC.Collect();
+ _buffer = new byte[windowSize];
+ }
+ _windowSize = windowSize;
+ _pos = 0;
+ _streamPos = 0;
+ }
+
+ public void Init(System.IO.Stream stream, bool solid)
+ {
+ ReleaseStream();
+ _stream = stream;
+ if (!solid)
+ {
+ _streamPos = 0;
+ _pos = 0;
+ TrainSize = 0;
+ }
+ }
+
+ public bool Train(System.IO.Stream stream)
+ {
+ long len = stream.Length;
+ uint size = (len < _windowSize) ? (uint)len : _windowSize;
+ TrainSize = size;
+ stream.Position = len - size;
+ _streamPos = _pos = 0;
+ while (size > 0)
+ {
+ uint curSize = _windowSize - _pos;
+ if (size < curSize)
+ {
+ curSize = size;
+ }
+
+ int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize);
+ if (numReadBytes == 0)
+ {
+ return false;
+ }
+
+ size -= (uint)numReadBytes;
+ _pos += (uint)numReadBytes;
+ _streamPos += (uint)numReadBytes;
+ if (_pos == _windowSize)
+ {
+ _streamPos = _pos = 0;
+ }
+ }
+ return true;
+ }
+
+ public void ReleaseStream()
+ {
+ Flush();
+ _stream = null;
+ }
+
+ public void Flush()
+ {
+ uint size = _pos - _streamPos;
+ if (size == 0)
+ {
+ return;
+ }
+
+ _stream.Write(_buffer, (int)_streamPos, (int)size);
+ if (_pos >= _windowSize)
+ {
+ _pos = 0;
+ }
+
+ _streamPos = _pos;
+ }
+
+ public void CopyBlock(uint distance, uint len)
+ {
+ uint pos = _pos - distance - 1;
+ if (pos >= _windowSize)
+ {
+ pos += _windowSize;
+ }
+
+ for (; len > 0; len--)
+ {
+ if (pos >= _windowSize)
+ {
+ pos = 0;
+ }
+
+ _buffer[_pos++] = _buffer[pos++];
+ if (_pos >= _windowSize)
+ {
+ Flush();
+ }
+ }
+ }
+
+ public void PutByte(byte b)
+ {
+ _buffer[_pos++] = b;
+ if (_pos >= _windowSize)
+ {
+ Flush();
+ }
+ }
+
+ public byte GetByte(uint distance)
+ {
+ uint pos = _pos - distance - 1;
+ if (pos >= _windowSize)
+ {
+ pos += _windowSize;
+ }
+
+ return _buffer[pos];
+ }
+ }
+}
diff --git a/7zip/Compress/LZMA/LzmaBase.cs b/WPinternals/7zip/Compress/LZMA/LzmaBase.cs
similarity index 97%
rename from 7zip/Compress/LZMA/LzmaBase.cs
rename to WPinternals/7zip/Compress/LZMA/LzmaBase.cs
index 6b74137..265b016 100644
--- a/7zip/Compress/LZMA/LzmaBase.cs
+++ b/WPinternals/7zip/Compress/LZMA/LzmaBase.cs
@@ -1,88 +1,88 @@
-// LzmaBase.cs
-
-namespace SevenZip.Compression.LZMA
-{
- internal abstract class Base
- {
- public const uint kNumRepDistances = 4;
- public const uint kNumStates = 12;
-
- // 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 []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};
-
- public struct State
- {
- public uint Index;
- public void Init() { Index = 0; }
- public void UpdateChar()
- {
- if (Index < 4)
- {
- Index = 0;
- }
- else if (Index < 10)
- {
- Index -= 3;
- }
- else
- {
- Index -= 6;
- }
- }
- public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); }
- public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); }
- public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); }
- public bool IsCharState() { return Index < 7; }
- }
-
- public const int kNumPosSlotBits = 6;
- public const int kDicLogSizeMin = 0;
- // public const int kDicLogSizeMax = 30;
- // public const uint kDistTableSizeMax = kDicLogSizeMax * 2;
-
- public const int kNumLenToPosStatesBits = 2; // it's for speed optimization
- public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits;
-
- public const uint kMatchMinLen = 2;
-
- public static uint GetLenToPosState(uint len)
- {
- len -= kMatchMinLen;
- if (len < kNumLenToPosStates)
- {
- return len;
- }
-
- return kNumLenToPosStates - 1;
- }
-
- public const int kNumAlignBits = 4;
- public const uint kAlignTableSize = 1 << kNumAlignBits;
- public const uint kAlignMask = kAlignTableSize - 1;
-
- public const uint kStartPosModelIndex = 4;
- public const uint kEndPosModelIndex = 14;
- public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;
-
- public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2);
-
- public const uint kNumLitPosStatesBitsEncodingMax = 4;
- public const uint kNumLitContextBitsMax = 8;
-
- public const int kNumPosStatesBitsMax = 4;
- public const uint kNumPosStatesMax = 1 << kNumPosStatesBitsMax;
- public const int kNumPosStatesBitsEncodingMax = 4;
- public const uint kNumPosStatesEncodingMax = 1 << kNumPosStatesBitsEncodingMax;
-
- public const int kNumLowLenBits = 3;
- public const int kNumMidLenBits = 3;
- public const int kNumHighLenBits = 8;
- public const uint kNumLowLenSymbols = 1 << kNumLowLenBits;
- public const uint kNumMidLenSymbols = 1 << kNumMidLenBits;
- public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols +
- (1 << kNumHighLenBits);
- public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1;
- }
-}
+// LzmaBase.cs
+
+namespace SevenZip.Compression.LZMA
+{
+ internal abstract class Base
+ {
+ public const uint kNumRepDistances = 4;
+ public const uint kNumStates = 12;
+
+ // 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 []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};
+
+ public struct State
+ {
+ public uint Index;
+ public void Init() { Index = 0; }
+ public void UpdateChar()
+ {
+ if (Index < 4)
+ {
+ Index = 0;
+ }
+ else if (Index < 10)
+ {
+ Index -= 3;
+ }
+ else
+ {
+ Index -= 6;
+ }
+ }
+ public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); }
+ public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); }
+ public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); }
+ public bool IsCharState() { return Index < 7; }
+ }
+
+ public const int kNumPosSlotBits = 6;
+ public const int kDicLogSizeMin = 0;
+ // public const int kDicLogSizeMax = 30;
+ // public const uint kDistTableSizeMax = kDicLogSizeMax * 2;
+
+ public const int kNumLenToPosStatesBits = 2; // it's for speed optimization
+ public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits;
+
+ public const uint kMatchMinLen = 2;
+
+ public static uint GetLenToPosState(uint len)
+ {
+ len -= kMatchMinLen;
+ if (len < kNumLenToPosStates)
+ {
+ return len;
+ }
+
+ return kNumLenToPosStates - 1;
+ }
+
+ public const int kNumAlignBits = 4;
+ public const uint kAlignTableSize = 1 << kNumAlignBits;
+ public const uint kAlignMask = kAlignTableSize - 1;
+
+ public const uint kStartPosModelIndex = 4;
+ public const uint kEndPosModelIndex = 14;
+ public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;
+
+ public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2);
+
+ public const uint kNumLitPosStatesBitsEncodingMax = 4;
+ public const uint kNumLitContextBitsMax = 8;
+
+ public const int kNumPosStatesBitsMax = 4;
+ public const uint kNumPosStatesMax = 1 << kNumPosStatesBitsMax;
+ public const int kNumPosStatesBitsEncodingMax = 4;
+ public const uint kNumPosStatesEncodingMax = 1 << kNumPosStatesBitsEncodingMax;
+
+ public const int kNumLowLenBits = 3;
+ public const int kNumMidLenBits = 3;
+ public const int kNumHighLenBits = 8;
+ public const uint kNumLowLenSymbols = 1 << kNumLowLenBits;
+ public const uint kNumMidLenSymbols = 1 << kNumMidLenBits;
+ public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols +
+ (1 << kNumHighLenBits);
+ public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1;
+ }
+}
diff --git a/7zip/Compress/LZMA/LzmaDecoder.cs b/WPinternals/7zip/Compress/LZMA/LzmaDecoder.cs
similarity index 97%
rename from 7zip/Compress/LZMA/LzmaDecoder.cs
rename to WPinternals/7zip/Compress/LZMA/LzmaDecoder.cs
index a2b0847..52efad9 100644
--- a/7zip/Compress/LZMA/LzmaDecoder.cs
+++ b/WPinternals/7zip/Compress/LZMA/LzmaDecoder.cs
@@ -1,465 +1,465 @@
-// LzmaDecoder.cs
-
-using System;
-
-namespace SevenZip.Compression.LZMA
-{
- using RangeCoder;
- using System.Threading;
-
- public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream
- {
- private class LenDecoder
- {
- private BitDecoder m_Choice = new();
- private BitDecoder m_Choice2 = new();
- private readonly BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
- private readonly BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
- private readonly BitTreeDecoder m_HighCoder = new(Base.kNumHighLenBits);
- private uint m_NumPosStates = 0;
-
- public void Create(uint numPosStates)
- {
- for (uint posState = m_NumPosStates; posState < numPosStates; posState++)
- {
- m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits);
- m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits);
- }
- m_NumPosStates = numPosStates;
- }
-
- public void Init()
- {
- m_Choice.Init();
- for (uint posState = 0; posState < m_NumPosStates; posState++)
- {
- m_LowCoder[posState].Init();
- m_MidCoder[posState].Init();
- }
- m_Choice2.Init();
- m_HighCoder.Init();
- }
-
- public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState)
- {
- if (m_Choice.Decode(rangeDecoder) == 0)
- {
- return m_LowCoder[posState].Decode(rangeDecoder);
- }
- else
- {
- uint symbol = Base.kNumLowLenSymbols;
- if (m_Choice2.Decode(rangeDecoder) == 0)
- {
- symbol += m_MidCoder[posState].Decode(rangeDecoder);
- }
- else
- {
- symbol += Base.kNumMidLenSymbols;
- symbol += m_HighCoder.Decode(rangeDecoder);
- }
- return symbol;
- }
- }
- }
-
- private class LiteralDecoder
- {
- private struct Decoder2
- {
- private BitDecoder[] m_Decoders;
- public void Create() { m_Decoders = new BitDecoder[0x300]; }
- public void Init() { for (int i = 0; i < 0x300; i++)
- {
- m_Decoders[i].Init();
- }
- }
-
- public byte DecodeNormal(RangeCoder.Decoder rangeDecoder)
- {
- uint symbol = 1;
- do
- {
- symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
- }
- while (symbol < 0x100);
- return (byte)symbol;
- }
-
- public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte)
- {
- uint symbol = 1;
- do
- {
- uint matchBit = (uint)(matchByte >> 7) & 1;
- matchByte <<= 1;
- uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder);
- symbol = (symbol << 1) | bit;
- if (matchBit != bit)
- {
- while (symbol < 0x100)
- {
- symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
- }
-
- break;
- }
- }
- while (symbol < 0x100);
- return (byte)symbol;
- }
- }
-
- private Decoder2[] m_Coders;
- private int m_NumPrevBits;
- private int m_NumPosBits;
- private uint m_PosMask;
-
- public void Create(int numPosBits, int numPrevBits)
- {
- if (m_Coders != null && m_NumPrevBits == numPrevBits &&
- m_NumPosBits == numPosBits)
- {
- return;
- }
-
- m_NumPosBits = numPosBits;
- m_PosMask = ((uint)1 << numPosBits) - 1;
- m_NumPrevBits = numPrevBits;
- uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
- m_Coders = new Decoder2[numStates];
- for (uint i = 0; i < numStates; i++)
- {
- m_Coders[i].Create();
- }
- }
-
- public void Init()
- {
- uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
- for (uint i = 0; i < numStates; i++)
- {
- m_Coders[i].Init();
- }
- }
-
- private uint GetState(uint pos, byte prevByte)
- { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); }
-
- public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte)
- { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); }
-
- public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte)
- { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); }
- };
-
- private readonly LZ.OutWindow m_OutWindow = new();
- private readonly RangeCoder.Decoder m_RangeDecoder = new();
-
- private readonly BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
- private readonly BitDecoder[] m_IsRepDecoders = 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_IsRepG2Decoders = new BitDecoder[Base.kNumStates];
- private readonly BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
-
- private readonly BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates];
- private readonly BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex];
-
- private readonly BitTreeDecoder m_PosAlignDecoder = new(Base.kNumAlignBits);
-
- private readonly LenDecoder m_LenDecoder = new();
- private readonly LenDecoder m_RepLenDecoder = new();
-
- private readonly LiteralDecoder m_LiteralDecoder = new();
-
- private uint m_DictionarySize;
- private uint m_DictionarySizeCheck;
-
- private uint m_PosStateMask;
-
- public Decoder()
- {
- m_DictionarySize = 0xFFFFFFFF;
- for (int i = 0; i < Base.kNumLenToPosStates; i++)
- {
- m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits);
- }
- }
-
- private void SetDictionarySize(uint dictionarySize)
- {
- if (m_DictionarySize != dictionarySize)
- {
- m_DictionarySize = dictionarySize;
- m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1);
- uint blockSize = Math.Max(m_DictionarySizeCheck, 1 << 12);
- m_OutWindow.Create(blockSize);
- }
- }
-
- private void SetLiteralProperties(int lp, int lc)
- {
- if (lp > 8)
- {
- throw new InvalidParamException();
- }
-
- if (lc > 8)
- {
- throw new InvalidParamException();
- }
-
- m_LiteralDecoder.Create(lp, lc);
- }
-
- private void SetPosBitsProperties(int pb)
- {
- if (pb > Base.kNumPosStatesBitsMax)
- {
- throw new InvalidParamException();
- }
-
- uint numPosStates = (uint)1 << pb;
- m_LenDecoder.Create(numPosStates);
- m_RepLenDecoder.Create(numPosStates);
- m_PosStateMask = numPosStates - 1;
- }
-
- private bool _solid = false;
- private void Init(System.IO.Stream inStream, System.IO.Stream outStream)
- {
- m_RangeDecoder.Init(inStream);
- m_OutWindow.Init(outStream, _solid);
-
- uint i;
- for (i = 0; i < Base.kNumStates; i++)
- {
- for (uint j = 0; j <= m_PosStateMask; j++)
- {
- uint index = (i << Base.kNumPosStatesBitsMax) + j;
- m_IsMatchDecoders[index].Init();
- m_IsRep0LongDecoders[index].Init();
- }
- m_IsRepDecoders[i].Init();
- m_IsRepG0Decoders[i].Init();
- m_IsRepG1Decoders[i].Init();
- m_IsRepG2Decoders[i].Init();
- }
-
- m_LiteralDecoder.Init();
- for (i = 0; i < Base.kNumLenToPosStates; i++)
- {
- m_PosSlotDecoder[i].Init();
- }
- // m_PosSpecDecoder.Init();
- for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)
- {
- m_PosDecoders[i].Init();
- }
-
- m_LenDecoder.Init();
- m_RepLenDecoder.Init();
- m_PosAlignDecoder.Init();
- }
-
- public void Code(System.IO.Stream inStream, System.IO.Stream outStream,
- Int64 inSize, Int64 outSize, ICodeProgress progress, CancellationToken? token = null)
- {
- Init(inStream, outStream);
-
- Base.State state = new();
- state.Init();
- uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
-
- UInt64 nowPos64 = 0;
- UInt64 outSize64 = (UInt64)outSize;
- if (nowPos64 < outSize64)
- {
- if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0)
- {
- throw new DataErrorException();
- }
-
- state.UpdateChar();
- byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0);
- m_OutWindow.PutByte(b);
- nowPos64++;
- }
-
- try
- {
- while (nowPos64 < outSize64)
- {
- token?.ThrowIfCancellationRequested();
-
- // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64);
- // while(nowPos64 < next)
- {
- uint posState = (uint)nowPos64 & m_PosStateMask;
- if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
- {
- byte b;
- byte prevByte = m_OutWindow.GetByte(0);
- b = !state.IsCharState()
- ? m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder,
- (uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0))
- : m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte);
-
- m_OutWindow.PutByte(b);
- state.UpdateChar();
- nowPos64++;
- }
- else
- {
- uint len;
- if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1)
- {
- if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0)
- {
- if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
- {
- state.UpdateShortRep();
- m_OutWindow.PutByte(m_OutWindow.GetByte(rep0));
- nowPos64++;
- continue;
- }
- }
- else
- {
- UInt32 distance;
- if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0)
- {
- distance = rep1;
- }
- else
- {
- if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0)
- {
- distance = rep2;
- }
- else
- {
- distance = rep3;
- rep3 = rep2;
- }
- rep2 = rep1;
- }
- rep1 = rep0;
- rep0 = distance;
- }
- len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen;
- state.UpdateRep();
- }
- else
- {
- rep3 = rep2;
- rep2 = rep1;
- rep1 = rep0;
- len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState);
- state.UpdateMatch();
- uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder);
- if (posSlot >= Base.kStartPosModelIndex)
- {
- int numDirectBits = (int)((posSlot >> 1) - 1);
- rep0 = (2 | (posSlot & 1)) << numDirectBits;
- if (posSlot < Base.kEndPosModelIndex)
- {
- rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders,
- rep0 - posSlot - 1, m_RangeDecoder, numDirectBits);
- }
- else
- {
- rep0 += m_RangeDecoder.DecodeDirectBits(
- numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits;
- rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);
- }
- }
- else
- {
- rep0 = posSlot;
- }
- }
- if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck)
- {
- if (rep0 == 0xFFFFFFFF)
- {
- break;
- }
-
- throw new DataErrorException();
- }
- m_OutWindow.CopyBlock(rep0, len);
- nowPos64 += len;
- }
- }
- }
- }
- catch (OperationCanceledException)
- {
- }
-
- m_OutWindow.Flush();
- m_OutWindow.ReleaseStream();
- m_RangeDecoder.ReleaseStream();
- }
-
- public void SetDecoderProperties(byte[] properties)
- {
- if (properties.Length < 5)
- {
- throw new InvalidParamException();
- }
-
- int lc = properties[0] % 9;
- int remainder = properties[0] / 9;
- int lp = remainder % 5;
- int pb = remainder / 5;
- if (pb > Base.kNumPosStatesBitsMax)
- {
- throw new InvalidParamException();
- }
-
- UInt32 dictionarySize = 0;
- for (int i = 0; i < 4; i++)
- {
- dictionarySize += ((UInt32)properties[1 + i]) << (i * 8);
- }
-
- SetDictionarySize(dictionarySize);
- SetLiteralProperties(lp, lc);
- SetPosBitsProperties(pb);
- }
-
- public bool Train(System.IO.Stream stream)
- {
- _solid = true;
- return m_OutWindow.Train(stream);
- }
-
- /*
- public override bool CanRead { get { return true; }}
- public override bool CanWrite { get { return true; }}
- public override bool CanSeek { get { return true; }}
- public override long Length { get { return 0; }}
- public override long Position
- {
- get { return 0; }
- set { }
- }
- public override void Flush() { }
- public override int Read(byte[] buffer, int offset, int count)
- {
- return 0;
- }
- public override void Write(byte[] buffer, int offset, int count)
- {
- }
- public override long Seek(long offset, System.IO.SeekOrigin origin)
- {
- return 0;
- }
- public override void SetLength(long value) {}
- */
- }
-}
+// LzmaDecoder.cs
+
+using System;
+
+namespace SevenZip.Compression.LZMA
+{
+ using RangeCoder;
+ using System.Threading;
+
+ public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream
+ {
+ private class LenDecoder
+ {
+ private BitDecoder m_Choice = new();
+ private BitDecoder m_Choice2 = new();
+ private readonly BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
+ private readonly BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
+ private readonly BitTreeDecoder m_HighCoder = new(Base.kNumHighLenBits);
+ private uint m_NumPosStates = 0;
+
+ public void Create(uint numPosStates)
+ {
+ for (uint posState = m_NumPosStates; posState < numPosStates; posState++)
+ {
+ m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits);
+ m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits);
+ }
+ m_NumPosStates = numPosStates;
+ }
+
+ public void Init()
+ {
+ m_Choice.Init();
+ for (uint posState = 0; posState < m_NumPosStates; posState++)
+ {
+ m_LowCoder[posState].Init();
+ m_MidCoder[posState].Init();
+ }
+ m_Choice2.Init();
+ m_HighCoder.Init();
+ }
+
+ public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState)
+ {
+ if (m_Choice.Decode(rangeDecoder) == 0)
+ {
+ return m_LowCoder[posState].Decode(rangeDecoder);
+ }
+ else
+ {
+ uint symbol = Base.kNumLowLenSymbols;
+ if (m_Choice2.Decode(rangeDecoder) == 0)
+ {
+ symbol += m_MidCoder[posState].Decode(rangeDecoder);
+ }
+ else
+ {
+ symbol += Base.kNumMidLenSymbols;
+ symbol += m_HighCoder.Decode(rangeDecoder);
+ }
+ return symbol;
+ }
+ }
+ }
+
+ private class LiteralDecoder
+ {
+ private struct Decoder2
+ {
+ private BitDecoder[] m_Decoders;
+ public void Create() { m_Decoders = new BitDecoder[0x300]; }
+ public void Init() { for (int i = 0; i < 0x300; i++)
+ {
+ m_Decoders[i].Init();
+ }
+ }
+
+ public byte DecodeNormal(RangeCoder.Decoder rangeDecoder)
+ {
+ uint symbol = 1;
+ do
+ {
+ symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
+ }
+ while (symbol < 0x100);
+ return (byte)symbol;
+ }
+
+ public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte)
+ {
+ uint symbol = 1;
+ do
+ {
+ uint matchBit = (uint)(matchByte >> 7) & 1;
+ matchByte <<= 1;
+ uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder);
+ symbol = (symbol << 1) | bit;
+ if (matchBit != bit)
+ {
+ while (symbol < 0x100)
+ {
+ symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
+ }
+
+ break;
+ }
+ }
+ while (symbol < 0x100);
+ return (byte)symbol;
+ }
+ }
+
+ private Decoder2[] m_Coders;
+ private int m_NumPrevBits;
+ private int m_NumPosBits;
+ private uint m_PosMask;
+
+ public void Create(int numPosBits, int numPrevBits)
+ {
+ if (m_Coders != null && m_NumPrevBits == numPrevBits &&
+ m_NumPosBits == numPosBits)
+ {
+ return;
+ }
+
+ m_NumPosBits = numPosBits;
+ m_PosMask = ((uint)1 << numPosBits) - 1;
+ m_NumPrevBits = numPrevBits;
+ uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
+ m_Coders = new Decoder2[numStates];
+ for (uint i = 0; i < numStates; i++)
+ {
+ m_Coders[i].Create();
+ }
+ }
+
+ public void Init()
+ {
+ uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
+ for (uint i = 0; i < numStates; i++)
+ {
+ m_Coders[i].Init();
+ }
+ }
+
+ private uint GetState(uint pos, byte prevByte)
+ { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); }
+
+ public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte)
+ { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); }
+
+ public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte)
+ { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); }
+ };
+
+ private readonly LZ.OutWindow m_OutWindow = new();
+ private readonly RangeCoder.Decoder m_RangeDecoder = new();
+
+ private readonly BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
+ private readonly BitDecoder[] m_IsRepDecoders = 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_IsRepG2Decoders = new BitDecoder[Base.kNumStates];
+ private readonly BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
+
+ private readonly BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates];
+ private readonly BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex];
+
+ private readonly BitTreeDecoder m_PosAlignDecoder = new(Base.kNumAlignBits);
+
+ private readonly LenDecoder m_LenDecoder = new();
+ private readonly LenDecoder m_RepLenDecoder = new();
+
+ private readonly LiteralDecoder m_LiteralDecoder = new();
+
+ private uint m_DictionarySize;
+ private uint m_DictionarySizeCheck;
+
+ private uint m_PosStateMask;
+
+ public Decoder()
+ {
+ m_DictionarySize = 0xFFFFFFFF;
+ for (int i = 0; i < Base.kNumLenToPosStates; i++)
+ {
+ m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits);
+ }
+ }
+
+ private void SetDictionarySize(uint dictionarySize)
+ {
+ if (m_DictionarySize != dictionarySize)
+ {
+ m_DictionarySize = dictionarySize;
+ m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1);
+ uint blockSize = Math.Max(m_DictionarySizeCheck, 1 << 12);
+ m_OutWindow.Create(blockSize);
+ }
+ }
+
+ private void SetLiteralProperties(int lp, int lc)
+ {
+ if (lp > 8)
+ {
+ throw new InvalidParamException();
+ }
+
+ if (lc > 8)
+ {
+ throw new InvalidParamException();
+ }
+
+ m_LiteralDecoder.Create(lp, lc);
+ }
+
+ private void SetPosBitsProperties(int pb)
+ {
+ if (pb > Base.kNumPosStatesBitsMax)
+ {
+ throw new InvalidParamException();
+ }
+
+ uint numPosStates = (uint)1 << pb;
+ m_LenDecoder.Create(numPosStates);
+ m_RepLenDecoder.Create(numPosStates);
+ m_PosStateMask = numPosStates - 1;
+ }
+
+ private bool _solid = false;
+ private void Init(System.IO.Stream inStream, System.IO.Stream outStream)
+ {
+ m_RangeDecoder.Init(inStream);
+ m_OutWindow.Init(outStream, _solid);
+
+ uint i;
+ for (i = 0; i < Base.kNumStates; i++)
+ {
+ for (uint j = 0; j <= m_PosStateMask; j++)
+ {
+ uint index = (i << Base.kNumPosStatesBitsMax) + j;
+ m_IsMatchDecoders[index].Init();
+ m_IsRep0LongDecoders[index].Init();
+ }
+ m_IsRepDecoders[i].Init();
+ m_IsRepG0Decoders[i].Init();
+ m_IsRepG1Decoders[i].Init();
+ m_IsRepG2Decoders[i].Init();
+ }
+
+ m_LiteralDecoder.Init();
+ for (i = 0; i < Base.kNumLenToPosStates; i++)
+ {
+ m_PosSlotDecoder[i].Init();
+ }
+ // m_PosSpecDecoder.Init();
+ for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)
+ {
+ m_PosDecoders[i].Init();
+ }
+
+ m_LenDecoder.Init();
+ m_RepLenDecoder.Init();
+ m_PosAlignDecoder.Init();
+ }
+
+ public void Code(System.IO.Stream inStream, System.IO.Stream outStream,
+ Int64 inSize, Int64 outSize, ICodeProgress progress, CancellationToken? token = null)
+ {
+ Init(inStream, outStream);
+
+ Base.State state = new();
+ state.Init();
+ uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
+
+ UInt64 nowPos64 = 0;
+ UInt64 outSize64 = (UInt64)outSize;
+ if (nowPos64 < outSize64)
+ {
+ if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0)
+ {
+ throw new DataErrorException();
+ }
+
+ state.UpdateChar();
+ byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0);
+ m_OutWindow.PutByte(b);
+ nowPos64++;
+ }
+
+ try
+ {
+ while (nowPos64 < outSize64)
+ {
+ token?.ThrowIfCancellationRequested();
+
+ // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64);
+ // while(nowPos64 < next)
+ {
+ uint posState = (uint)nowPos64 & m_PosStateMask;
+ if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
+ {
+ byte b;
+ byte prevByte = m_OutWindow.GetByte(0);
+ b = !state.IsCharState()
+ ? m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder,
+ (uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0))
+ : m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte);
+
+ m_OutWindow.PutByte(b);
+ state.UpdateChar();
+ nowPos64++;
+ }
+ else
+ {
+ uint len;
+ if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1)
+ {
+ if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0)
+ {
+ if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
+ {
+ state.UpdateShortRep();
+ m_OutWindow.PutByte(m_OutWindow.GetByte(rep0));
+ nowPos64++;
+ continue;
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0)
+ {
+ distance = rep1;
+ }
+ else
+ {
+ if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0)
+ {
+ distance = rep2;
+ }
+ else
+ {
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen;
+ state.UpdateRep();
+ }
+ else
+ {
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState);
+ state.UpdateMatch();
+ uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder);
+ if (posSlot >= Base.kStartPosModelIndex)
+ {
+ int numDirectBits = (int)((posSlot >> 1) - 1);
+ rep0 = (2 | (posSlot & 1)) << numDirectBits;
+ if (posSlot < Base.kEndPosModelIndex)
+ {
+ rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders,
+ rep0 - posSlot - 1, m_RangeDecoder, numDirectBits);
+ }
+ else
+ {
+ rep0 += m_RangeDecoder.DecodeDirectBits(
+ numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits;
+ rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);
+ }
+ }
+ else
+ {
+ rep0 = posSlot;
+ }
+ }
+ if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck)
+ {
+ if (rep0 == 0xFFFFFFFF)
+ {
+ break;
+ }
+
+ throw new DataErrorException();
+ }
+ m_OutWindow.CopyBlock(rep0, len);
+ nowPos64 += len;
+ }
+ }
+ }
+ }
+ catch (OperationCanceledException)
+ {
+ }
+
+ m_OutWindow.Flush();
+ m_OutWindow.ReleaseStream();
+ m_RangeDecoder.ReleaseStream();
+ }
+
+ public void SetDecoderProperties(byte[] properties)
+ {
+ if (properties.Length < 5)
+ {
+ throw new InvalidParamException();
+ }
+
+ int lc = properties[0] % 9;
+ int remainder = properties[0] / 9;
+ int lp = remainder % 5;
+ int pb = remainder / 5;
+ if (pb > Base.kNumPosStatesBitsMax)
+ {
+ throw new InvalidParamException();
+ }
+
+ UInt32 dictionarySize = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ dictionarySize += ((UInt32)properties[1 + i]) << (i * 8);
+ }
+
+ SetDictionarySize(dictionarySize);
+ SetLiteralProperties(lp, lc);
+ SetPosBitsProperties(pb);
+ }
+
+ public bool Train(System.IO.Stream stream)
+ {
+ _solid = true;
+ return m_OutWindow.Train(stream);
+ }
+
+ /*
+ public override bool CanRead { get { return true; }}
+ public override bool CanWrite { get { return true; }}
+ public override bool CanSeek { get { return true; }}
+ public override long Length { get { return 0; }}
+ public override long Position
+ {
+ get { return 0; }
+ set { }
+ }
+ public override void Flush() { }
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ return 0;
+ }
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ }
+ public override long Seek(long offset, System.IO.SeekOrigin origin)
+ {
+ return 0;
+ }
+ public override void SetLength(long value) {}
+ */
+ }
+}
diff --git a/7zip/Compress/LZMA/LzmaEncoder.cs b/WPinternals/7zip/Compress/LZMA/LzmaEncoder.cs
similarity index 97%
rename from 7zip/Compress/LZMA/LzmaEncoder.cs
rename to WPinternals/7zip/Compress/LZMA/LzmaEncoder.cs
index f1b8461..7d1dac9 100644
--- a/7zip/Compress/LZMA/LzmaEncoder.cs
+++ b/WPinternals/7zip/Compress/LZMA/LzmaEncoder.cs
@@ -1,1692 +1,1692 @@
-// LzmaEncoder.cs
-
-using System;
-
-namespace SevenZip.Compression.LZMA
-{
- using RangeCoder;
- using System.Threading;
-
- public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties
- {
- private enum EMatchFinderType
- {
- BT2,
- BT4,
- };
-
- private const UInt32 kIfinityPrice = 0xFFFFFFF;
-
- private static readonly Byte[] g_FastPos = new Byte[1 << 11];
-
- static Encoder()
- {
- const Byte kFastSlots = 22;
- int c = 2;
- g_FastPos[0] = 0;
- g_FastPos[1] = 1;
- for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++)
- {
- UInt32 k = (UInt32)1 << ((slotFast >> 1) - 1);
- for (UInt32 j = 0; j < k; j++, c++)
- {
- g_FastPos[c] = slotFast;
- }
- }
- }
-
- private static UInt32 GetPosSlot(UInt32 pos)
- {
- if (pos < (1 << 11))
- {
- return g_FastPos[pos];
- }
-
- if (pos < (1 << 21))
- {
- return (UInt32)(g_FastPos[pos >> 10] + 20);
- }
-
- return (UInt32)(g_FastPos[pos >> 20] + 40);
- }
-
- private static UInt32 GetPosSlot2(UInt32 pos)
- {
- if (pos < (1 << 17))
- {
- return (UInt32)(g_FastPos[pos >> 6] + 12);
- }
-
- if (pos < (1 << 27))
- {
- return (UInt32)(g_FastPos[pos >> 16] + 32);
- }
-
- return (UInt32)(g_FastPos[pos >> 26] + 52);
- }
-
- private Base.State _state = new();
- private Byte _previousByte;
- private readonly UInt32[] _repDistances = new UInt32[Base.kNumRepDistances];
-
- private void BaseInit()
- {
- _state.Init();
- _previousByte = 0;
- for (UInt32 i = 0; i < Base.kNumRepDistances; i++)
- {
- _repDistances[i] = 0;
- }
- }
-
- private const int kDefaultDictionaryLogSize = 22;
- private const UInt32 kNumFastBytesDefault = 0x20;
-
- private class LiteralEncoder
- {
- public struct Encoder2
- {
- private BitEncoder[] m_Encoders;
-
- public void Create() { m_Encoders = new BitEncoder[0x300]; }
-
- public void Init() { for (int i = 0; i < 0x300; i++)
- {
- m_Encoders[i].Init();
- }
- }
-
- public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol)
- {
- uint context = 1;
- for (int i = 7; i >= 0; i--)
- {
- uint bit = (uint)((symbol >> i) & 1);
- m_Encoders[context].Encode(rangeEncoder, bit);
- context = (context << 1) | bit;
- }
- }
-
- public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol)
- {
- uint context = 1;
- bool same = true;
- for (int i = 7; i >= 0; i--)
- {
- uint bit = (uint)((symbol >> i) & 1);
- uint state = context;
- if (same)
- {
- uint matchBit = (uint)((matchByte >> i) & 1);
- state += (1 + matchBit) << 8;
- same = matchBit == bit;
- }
- m_Encoders[state].Encode(rangeEncoder, bit);
- context = (context << 1) | bit;
- }
- }
-
- public uint GetPrice(bool matchMode, byte matchByte, byte symbol)
- {
- uint price = 0;
- uint context = 1;
- int i = 7;
- if (matchMode)
- {
- for (; i >= 0; i--)
- {
- uint matchBit = (uint)(matchByte >> i) & 1;
- uint bit = (uint)(symbol >> i) & 1;
- price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit);
- context = (context << 1) | bit;
- if (matchBit != bit)
- {
- i--;
- break;
- }
- }
- }
- for (; i >= 0; i--)
- {
- uint bit = (uint)(symbol >> i) & 1;
- price += m_Encoders[context].GetPrice(bit);
- context = (context << 1) | bit;
- }
- return price;
- }
- }
-
- private Encoder2[] m_Coders;
- private int m_NumPrevBits;
- private int m_NumPosBits;
- private uint m_PosMask;
-
- public void Create(int numPosBits, int numPrevBits)
- {
- if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits)
- {
- return;
- }
-
- m_NumPosBits = numPosBits;
- m_PosMask = ((uint)1 << numPosBits) - 1;
- m_NumPrevBits = numPrevBits;
- uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
- m_Coders = new Encoder2[numStates];
- for (uint i = 0; i < numStates; i++)
- {
- m_Coders[i].Create();
- }
- }
-
- public void Init()
- {
- uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
- for (uint i = 0; i < numStates; i++)
- {
- m_Coders[i].Init();
- }
- }
-
- public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte)
- { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits))]; }
- }
-
- private class LenEncoder
- {
- private BitEncoder _choice = new();
- private BitEncoder _choice2 = new();
- private readonly BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax];
- private readonly BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax];
- private readonly BitTreeEncoder _highCoder = new(Base.kNumHighLenBits);
-
- public LenEncoder()
- {
- for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++)
- {
- _lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits);
- _midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits);
- }
- }
-
- public void Init(UInt32 numPosStates)
- {
- _choice.Init();
- _choice2.Init();
- for (UInt32 posState = 0; posState < numPosStates; posState++)
- {
- _lowCoder[posState].Init();
- _midCoder[posState].Init();
- }
- _highCoder.Init();
- }
-
- public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState)
- {
- if (symbol < Base.kNumLowLenSymbols)
- {
- _choice.Encode(rangeEncoder, 0);
- _lowCoder[posState].Encode(rangeEncoder, symbol);
- }
- else
- {
- symbol -= Base.kNumLowLenSymbols;
- _choice.Encode(rangeEncoder, 1);
- if (symbol < Base.kNumMidLenSymbols)
- {
- _choice2.Encode(rangeEncoder, 0);
- _midCoder[posState].Encode(rangeEncoder, symbol);
- }
- else
- {
- _choice2.Encode(rangeEncoder, 1);
- _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols);
- }
- }
- }
-
- public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st)
- {
- UInt32 a0 = _choice.GetPrice0();
- UInt32 a1 = _choice.GetPrice1();
- UInt32 b0 = a1 + _choice2.GetPrice0();
- UInt32 b1 = a1 + _choice2.GetPrice1();
- UInt32 i = 0;
- for (i = 0; i < Base.kNumLowLenSymbols; i++)
- {
- if (i >= numSymbols)
- {
- return;
- }
-
- prices[st + i] = a0 + _lowCoder[posState].GetPrice(i);
- }
- for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++)
- {
- if (i >= numSymbols)
- {
- return;
- }
-
- prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols);
- }
- for (; i < numSymbols; i++)
- {
- prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols);
- }
- }
- };
-
- private const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols;
-
- private class LenPriceTableEncoder : LenEncoder
- {
- private readonly UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax];
- private UInt32 _tableSize;
- private readonly UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax];
-
- public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; }
-
- public UInt32 GetPrice(UInt32 symbol, UInt32 posState)
- {
- return _prices[(posState * Base.kNumLenSymbols) + symbol];
- }
-
- private void UpdateTable(UInt32 posState)
- {
- SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols);
- _counters[posState] = _tableSize;
- }
-
- public void UpdateTables(UInt32 numPosStates)
- {
- for (UInt32 posState = 0; posState < numPosStates; posState++)
- {
- UpdateTable(posState);
- }
- }
-
- public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState)
- {
- base.Encode(rangeEncoder, symbol, posState);
- if (--_counters[posState] == 0)
- {
- UpdateTable(posState);
- }
- }
- }
-
- private const UInt32 kNumOpts = 1 << 12;
- private class Optimal
- {
- public Base.State State;
-
- public bool Prev1IsChar;
- public bool Prev2;
-
- public UInt32 PosPrev2;
- public UInt32 BackPrev2;
-
- public UInt32 Price;
- public UInt32 PosPrev;
- public UInt32 BackPrev;
-
- public UInt32 Backs0;
- public UInt32 Backs1;
- public UInt32 Backs2;
- public UInt32 Backs3;
-
- public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; }
- public void MakeAsShortRep() { BackPrev = 0; Prev1IsChar = false; }
- public bool IsShortRep() { return BackPrev == 0; }
- };
- private readonly Optimal[] _optimum = new Optimal[kNumOpts];
- private LZ.IMatchFinder _matchFinder = null;
- private readonly RangeCoder.Encoder _rangeEncoder = new();
-
- private readonly BitEncoder[] _isMatch = new BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
- private readonly BitEncoder[] _isRep = new BitEncoder[Base.kNumStates];
- private readonly BitEncoder[] _isRepG0 = new BitEncoder[Base.kNumStates];
- private readonly BitEncoder[] _isRepG1 = new BitEncoder[Base.kNumStates];
- private readonly BitEncoder[] _isRepG2 = new BitEncoder[Base.kNumStates];
- private readonly BitEncoder[] _isRep0Long = new BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
-
- private readonly BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.kNumLenToPosStates];
-
- private readonly BitEncoder[] _posEncoders = new BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex];
- private readonly BitTreeEncoder _posAlignEncoder = new(Base.kNumAlignBits);
-
- private readonly LenPriceTableEncoder _lenEncoder = new();
- private readonly LenPriceTableEncoder _repMatchLenEncoder = new();
-
- private readonly LiteralEncoder _literalEncoder = new();
-
- private readonly UInt32[] _matchDistances = new UInt32[(Base.kMatchMaxLen * 2) + 2];
-
- private UInt32 _numFastBytes = kNumFastBytesDefault;
- private UInt32 _longestMatchLength;
- private UInt32 _numDistancePairs;
-
- private UInt32 _additionalOffset;
-
- private UInt32 _optimumEndIndex;
- private UInt32 _optimumCurrentIndex;
-
- private bool _longestMatchWasFound;
-
- private readonly UInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)];
- private readonly UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits];
- private readonly UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize];
- private UInt32 _alignPriceCount;
-
- private UInt32 _distTableSize = kDefaultDictionaryLogSize * 2;
-
- private int _posStateBits = 2;
- private UInt32 _posStateMask = 4 - 1;
- private int _numLiteralPosStateBits = 0;
- private int _numLiteralContextBits = 3;
-
- private UInt32 _dictionarySize = 1 << kDefaultDictionaryLogSize;
- private UInt32 _dictionarySizePrev = 0xFFFFFFFF;
- private UInt32 _numFastBytesPrev = 0xFFFFFFFF;
-
- private Int64 nowPos64;
- private bool _finished;
- private System.IO.Stream _inStream;
-
- private EMatchFinderType _matchFinderType = EMatchFinderType.BT4;
- private bool _writeEndMark = false;
-
- private bool _needReleaseMFStream;
-
- private void Create()
- {
- if (_matchFinder == null)
- {
- LZ.BinTree bt = new();
- int numHashBytes = 4;
- if (_matchFinderType == EMatchFinderType.BT2)
- {
- numHashBytes = 2;
- }
-
- bt.SetType(numHashBytes);
- _matchFinder = bt;
- }
- _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits);
-
- if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes)
- {
- return;
- }
-
- _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1);
- _dictionarySizePrev = _dictionarySize;
- _numFastBytesPrev = _numFastBytes;
- }
-
- public Encoder()
- {
- for (int i = 0; i < kNumOpts; i++)
- {
- _optimum[i] = new Optimal();
- }
-
- for (int i = 0; i < Base.kNumLenToPosStates; i++)
- {
- _posSlotEncoder[i] = new BitTreeEncoder(Base.kNumPosSlotBits);
- }
- }
-
- private void SetWriteEndMarkerMode(bool writeEndMarker)
- {
- _writeEndMark = writeEndMarker;
- }
-
- private void Init()
- {
- BaseInit();
- _rangeEncoder.Init();
-
- uint i;
- for (i = 0; i < Base.kNumStates; i++)
- {
- for (uint j = 0; j <= _posStateMask; j++)
- {
- uint complexState = (i << Base.kNumPosStatesBitsMax) + j;
- _isMatch[complexState].Init();
- _isRep0Long[complexState].Init();
- }
- _isRep[i].Init();
- _isRepG0[i].Init();
- _isRepG1[i].Init();
- _isRepG2[i].Init();
- }
- _literalEncoder.Init();
- for (i = 0; i < Base.kNumLenToPosStates; i++)
- {
- _posSlotEncoder[i].Init();
- }
-
- for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)
- {
- _posEncoders[i].Init();
- }
-
- _lenEncoder.Init((UInt32)1 << _posStateBits);
- _repMatchLenEncoder.Init((UInt32)1 << _posStateBits);
-
- _posAlignEncoder.Init();
-
- _longestMatchWasFound = false;
- _optimumEndIndex = 0;
- _optimumCurrentIndex = 0;
- _additionalOffset = 0;
- }
-
- private void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs)
- {
- lenRes = 0;
- numDistancePairs = _matchFinder.GetMatches(_matchDistances);
- if (numDistancePairs > 0)
- {
- lenRes = _matchDistances[numDistancePairs - 2];
- if (lenRes == _numFastBytes)
- {
- lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[numDistancePairs - 1],
- Base.kMatchMaxLen - lenRes);
- }
- }
- _additionalOffset++;
- }
-
- private void MovePos(UInt32 num)
- {
- if (num > 0)
- {
- _matchFinder.Skip(num);
- _additionalOffset += num;
- }
- }
-
- private UInt32 GetRepLen1Price(Base.State state, UInt32 posState)
- {
- return _isRepG0[state.Index].GetPrice0() +
- _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0();
- }
-
- private UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState)
- {
- UInt32 price;
- if (repIndex == 0)
- {
- price = _isRepG0[state.Index].GetPrice0();
- price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();
- }
- else
- {
- price = _isRepG0[state.Index].GetPrice1();
- if (repIndex == 1)
- {
- price += _isRepG1[state.Index].GetPrice0();
- }
- else
- {
- price += _isRepG1[state.Index].GetPrice1();
- price += _isRepG2[state.Index].GetPrice(repIndex - 2);
- }
- }
- return price;
- }
-
- private UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState)
- {
- UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState);
- return price + GetPureRepPrice(repIndex, state, posState);
- }
-
- private UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState)
- {
- UInt32 price;
- UInt32 lenToPosState = Base.GetLenToPosState(len);
- price = pos < Base.kNumFullDistances
- ? _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]
- : _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] +
- _alignPrices[pos & Base.kAlignMask];
-
- return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState);
- }
-
- private UInt32 Backward(out UInt32 backRes, UInt32 cur)
- {
- _optimumEndIndex = cur;
- UInt32 posMem = _optimum[cur].PosPrev;
- UInt32 backMem = _optimum[cur].BackPrev;
- do
- {
- if (_optimum[cur].Prev1IsChar)
- {
- _optimum[posMem].MakeAsChar();
- _optimum[posMem].PosPrev = posMem - 1;
- if (_optimum[cur].Prev2)
- {
- _optimum[posMem - 1].Prev1IsChar = false;
- _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2;
- _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2;
- }
- }
- UInt32 posPrev = posMem;
- UInt32 backCur = backMem;
-
- backMem = _optimum[posPrev].BackPrev;
- posMem = _optimum[posPrev].PosPrev;
-
- _optimum[posPrev].BackPrev = backCur;
- _optimum[posPrev].PosPrev = cur;
- cur = posPrev;
- }
- while (cur > 0);
- backRes = _optimum[0].BackPrev;
- _optimumCurrentIndex = _optimum[0].PosPrev;
- return _optimumCurrentIndex;
- }
-
- private readonly UInt32[] reps = new UInt32[Base.kNumRepDistances];
- private readonly UInt32[] repLens = new UInt32[Base.kNumRepDistances];
-
- private UInt32 GetOptimum(UInt32 position, out UInt32 backRes)
- {
- if (_optimumEndIndex != _optimumCurrentIndex)
- {
- UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex;
- backRes = _optimum[_optimumCurrentIndex].BackPrev;
- _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev;
- return lenRes;
- }
- _optimumCurrentIndex = _optimumEndIndex = 0;
-
- UInt32 lenMain, numDistancePairs;
- if (!_longestMatchWasFound)
- {
- ReadMatchDistances(out lenMain, out numDistancePairs);
- }
- else
- {
- lenMain = _longestMatchLength;
- numDistancePairs = _numDistancePairs;
- _longestMatchWasFound = false;
- }
-
- UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1;
- if (numAvailableBytes < 2)
- {
- backRes = 0xFFFFFFFF;
- return 1;
- }
- if (numAvailableBytes > Base.kMatchMaxLen)
- {
- numAvailableBytes = Base.kMatchMaxLen;
- }
-
- UInt32 repMaxIndex = 0;
- UInt32 i;
- for (i = 0; i < Base.kNumRepDistances; i++)
- {
- reps[i] = _repDistances[i];
- repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen);
- if (repLens[i] > repLens[repMaxIndex])
- {
- repMaxIndex = i;
- }
- }
- if (repLens[repMaxIndex] >= _numFastBytes)
- {
- backRes = repMaxIndex;
- UInt32 lenRes = repLens[repMaxIndex];
- MovePos(lenRes - 1);
- return lenRes;
- }
-
- if (lenMain >= _numFastBytes)
- {
- backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances;
- MovePos(lenMain - 1);
- return lenMain;
- }
-
- Byte currentByte = _matchFinder.GetIndexByte(0 - 1);
- Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1));
-
- if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2)
- {
- backRes = 0xFFFFFFFF;
- return 1;
- }
-
- _optimum[0].State = _state;
-
- UInt32 posState = position & _posStateMask;
-
- _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() +
- _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte);
- _optimum[1].MakeAsChar();
-
- UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();
- UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1();
-
- if (matchByte == currentByte)
- {
- UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState);
- if (shortRepPrice < _optimum[1].Price)
- {
- _optimum[1].Price = shortRepPrice;
- _optimum[1].MakeAsShortRep();
- }
- }
-
- UInt32 lenEnd = (lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex];
-
- if (lenEnd < 2)
- {
- backRes = _optimum[1].BackPrev;
- return 1;
- }
-
- _optimum[1].PosPrev = 0;
-
- _optimum[0].Backs0 = reps[0];
- _optimum[0].Backs1 = reps[1];
- _optimum[0].Backs2 = reps[2];
- _optimum[0].Backs3 = reps[3];
-
- UInt32 len = lenEnd;
- do
- {
- _optimum[len--].Price = kIfinityPrice;
- }
- while (len >= 2);
-
- for (i = 0; i < Base.kNumRepDistances; i++)
- {
- UInt32 repLen = repLens[i];
- if (repLen < 2)
- {
- continue;
- }
-
- UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState);
- do
- {
- UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState);
- Optimal optimum = _optimum[repLen];
- if (curAndLenPrice < optimum.Price)
- {
- optimum.Price = curAndLenPrice;
- optimum.PosPrev = 0;
- optimum.BackPrev = i;
- optimum.Prev1IsChar = false;
- }
- }
- while (--repLen >= 2);
- }
-
- UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0();
-
- len = (repLens[0] >= 2) ? repLens[0] + 1 : 2;
- if (len <= lenMain)
- {
- UInt32 offs = 0;
- while (len > _matchDistances[offs])
- {
- offs += 2;
- }
-
- for (; ; len++)
- {
- UInt32 distance = _matchDistances[offs + 1];
- UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState);
- Optimal optimum = _optimum[len];
- if (curAndLenPrice < optimum.Price)
- {
- optimum.Price = curAndLenPrice;
- optimum.PosPrev = 0;
- optimum.BackPrev = distance + Base.kNumRepDistances;
- optimum.Prev1IsChar = false;
- }
- if (len == _matchDistances[offs])
- {
- offs += 2;
- if (offs == numDistancePairs)
- {
- break;
- }
- }
- }
- }
-
- UInt32 cur = 0;
-
- while (true)
- {
- cur++;
- if (cur == lenEnd)
- {
- return Backward(out backRes, cur);
- }
-
- ReadMatchDistances(out uint newLen, out numDistancePairs);
- if (newLen >= _numFastBytes)
- {
- _numDistancePairs = numDistancePairs;
- _longestMatchLength = newLen;
- _longestMatchWasFound = true;
- return Backward(out backRes, cur);
- }
- position++;
- UInt32 posPrev = _optimum[cur].PosPrev;
- Base.State state;
- if (_optimum[cur].Prev1IsChar)
- {
- posPrev--;
- if (_optimum[cur].Prev2)
- {
- state = _optimum[_optimum[cur].PosPrev2].State;
- if (_optimum[cur].BackPrev2 < Base.kNumRepDistances)
- {
- state.UpdateRep();
- }
- else
- {
- state.UpdateMatch();
- }
- }
- else
- {
- state = _optimum[posPrev].State;
- }
-
- state.UpdateChar();
- }
- else
- {
- state = _optimum[posPrev].State;
- }
-
- if (posPrev == cur - 1)
- {
- if (_optimum[cur].IsShortRep())
- {
- state.UpdateShortRep();
- }
- else
- {
- state.UpdateChar();
- }
- }
- else
- {
- UInt32 pos;
- if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2)
- {
- posPrev = _optimum[cur].PosPrev2;
- pos = _optimum[cur].BackPrev2;
- state.UpdateRep();
- }
- else
- {
- pos = _optimum[cur].BackPrev;
- if (pos < Base.kNumRepDistances)
- {
- state.UpdateRep();
- }
- else
- {
- state.UpdateMatch();
- }
- }
- Optimal opt = _optimum[posPrev];
- if (pos < Base.kNumRepDistances)
- {
- if (pos == 0)
- {
- reps[0] = opt.Backs0;
- reps[1] = opt.Backs1;
- reps[2] = opt.Backs2;
- reps[3] = opt.Backs3;
- }
- else if (pos == 1)
- {
- reps[0] = opt.Backs1;
- reps[1] = opt.Backs0;
- reps[2] = opt.Backs2;
- reps[3] = opt.Backs3;
- }
- else if (pos == 2)
- {
- reps[0] = opt.Backs2;
- reps[1] = opt.Backs0;
- reps[2] = opt.Backs1;
- reps[3] = opt.Backs3;
- }
- else
- {
- reps[0] = opt.Backs3;
- reps[1] = opt.Backs0;
- reps[2] = opt.Backs1;
- reps[3] = opt.Backs2;
- }
- }
- else
- {
- reps[0] = pos - Base.kNumRepDistances;
- reps[1] = opt.Backs0;
- reps[2] = opt.Backs1;
- reps[3] = opt.Backs2;
- }
- }
- _optimum[cur].State = state;
- _optimum[cur].Backs0 = reps[0];
- _optimum[cur].Backs1 = reps[1];
- _optimum[cur].Backs2 = reps[2];
- _optimum[cur].Backs3 = reps[3];
- UInt32 curPrice = _optimum[cur].Price;
-
- currentByte = _matchFinder.GetIndexByte(0 - 1);
- matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1));
-
- posState = position & _posStateMask;
-
- UInt32 curAnd1Price = curPrice +
- _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() +
- _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)).
- GetPrice(!state.IsCharState(), matchByte, currentByte);
-
- Optimal nextOptimum = _optimum[cur + 1];
-
- bool nextIsChar = false;
- if (curAnd1Price < nextOptimum.Price)
- {
- nextOptimum.Price = curAnd1Price;
- nextOptimum.PosPrev = cur;
- nextOptimum.MakeAsChar();
- nextIsChar = true;
- }
-
- matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();
- repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1();
-
- if (matchByte == currentByte &&
- !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0))
- {
- UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState);
- if (shortRepPrice <= nextOptimum.Price)
- {
- nextOptimum.Price = shortRepPrice;
- nextOptimum.PosPrev = cur;
- nextOptimum.MakeAsShortRep();
- nextIsChar = true;
- }
- }
-
- UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1;
- numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull);
- numAvailableBytes = numAvailableBytesFull;
-
- if (numAvailableBytes < 2)
- {
- continue;
- }
-
- if (numAvailableBytes > _numFastBytes)
- {
- numAvailableBytes = _numFastBytes;
- }
-
- if (!nextIsChar && matchByte != currentByte)
- {
- // try Literal + rep0
- UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes);
- UInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t);
- if (lenTest2 >= 2)
- {
- Base.State state2 = state;
- state2.UpdateChar();
- UInt32 posStateNext = (position + 1) & _posStateMask;
- UInt32 nextRepMatchPrice = curAnd1Price +
- _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() +
- _isRep[state2.Index].GetPrice1();
- {
- UInt32 offset = cur + 1 + lenTest2;
- while (lenEnd < offset)
- {
- _optimum[++lenEnd].Price = kIfinityPrice;
- }
-
- UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
- 0, lenTest2, state2, posStateNext);
- Optimal optimum = _optimum[offset];
- if (curAndLenPrice < optimum.Price)
- {
- optimum.Price = curAndLenPrice;
- optimum.PosPrev = cur + 1;
- optimum.BackPrev = 0;
- optimum.Prev1IsChar = true;
- optimum.Prev2 = false;
- }
- }
- }
- }
-
- UInt32 startLen = 2; // speed optimization
-
- for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++)
- {
- UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes);
- if (lenTest < 2)
- {
- continue;
- }
-
- UInt32 lenTestTemp = lenTest;
- do
- {
- while (lenEnd < cur + lenTest)
- {
- _optimum[++lenEnd].Price = kIfinityPrice;
- }
-
- UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState);
- Optimal optimum = _optimum[cur + lenTest];
- if (curAndLenPrice < optimum.Price)
- {
- optimum.Price = curAndLenPrice;
- optimum.PosPrev = cur;
- optimum.BackPrev = repIndex;
- optimum.Prev1IsChar = false;
- }
- }
- while (--lenTest >= 2);
- lenTest = lenTestTemp;
-
- if (repIndex == 0)
- {
- startLen = lenTest + 1;
- }
-
- // if (_maxMode)
- if (lenTest < numAvailableBytesFull)
- {
- UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
- UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, reps[repIndex], t);
- if (lenTest2 >= 2)
- {
- Base.State state2 = state;
- state2.UpdateRep();
- UInt32 posStateNext = (position + lenTest) & _posStateMask;
- UInt32 curAndLenCharPrice =
- repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) +
- _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() +
- _literalEncoder.GetSubCoder(position + lenTest,
- _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true,
- _matchFinder.GetIndexByte((Int32)lenTest - 1 - (Int32)(reps[repIndex] + 1)),
- _matchFinder.GetIndexByte((Int32)lenTest - 1));
- state2.UpdateChar();
- posStateNext = (position + lenTest + 1) & _posStateMask;
- UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1();
- UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();
-
- // for(; lenTest2 >= 2; lenTest2--)
- {
- UInt32 offset = lenTest + 1 + lenTest2;
- while (lenEnd < cur + offset)
- {
- _optimum[++lenEnd].Price = kIfinityPrice;
- }
-
- UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
- Optimal optimum = _optimum[cur + offset];
- if (curAndLenPrice < optimum.Price)
- {
- optimum.Price = curAndLenPrice;
- optimum.PosPrev = cur + lenTest + 1;
- optimum.BackPrev = 0;
- optimum.Prev1IsChar = true;
- optimum.Prev2 = true;
- optimum.PosPrev2 = cur;
- optimum.BackPrev2 = repIndex;
- }
- }
- }
- }
- }
-
- if (newLen > numAvailableBytes)
- {
- newLen = numAvailableBytes;
- for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2)
- {
- }
-
- _matchDistances[numDistancePairs] = newLen;
- numDistancePairs += 2;
- }
- if (newLen >= startLen)
- {
- normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0();
- while (lenEnd < cur + newLen)
- {
- _optimum[++lenEnd].Price = kIfinityPrice;
- }
-
- UInt32 offs = 0;
- while (startLen > _matchDistances[offs])
- {
- offs += 2;
- }
-
- for (UInt32 lenTest = startLen; ; lenTest++)
- {
- UInt32 curBack = _matchDistances[offs + 1];
- UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState);
- Optimal optimum = _optimum[cur + lenTest];
- if (curAndLenPrice < optimum.Price)
- {
- optimum.Price = curAndLenPrice;
- optimum.PosPrev = cur;
- optimum.BackPrev = curBack + Base.kNumRepDistances;
- optimum.Prev1IsChar = false;
- }
-
- if (lenTest == _matchDistances[offs])
- {
- if (lenTest < numAvailableBytesFull)
- {
- UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
- UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t);
- if (lenTest2 >= 2)
- {
- Base.State state2 = state;
- state2.UpdateMatch();
- UInt32 posStateNext = (position + lenTest) & _posStateMask;
- UInt32 curAndLenCharPrice = curAndLenPrice +
- _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() +
- _literalEncoder.GetSubCoder(position + lenTest,
- _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).
- GetPrice(true,
- _matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 1),
- _matchFinder.GetIndexByte((Int32)lenTest - 1));
- state2.UpdateChar();
- posStateNext = (position + lenTest + 1) & _posStateMask;
- UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1();
- UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();
-
- UInt32 offset = lenTest + 1 + lenTest2;
- while (lenEnd < cur + offset)
- {
- _optimum[++lenEnd].Price = kIfinityPrice;
- }
-
- curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
- optimum = _optimum[cur + offset];
- if (curAndLenPrice < optimum.Price)
- {
- optimum.Price = curAndLenPrice;
- optimum.PosPrev = cur + lenTest + 1;
- optimum.BackPrev = 0;
- optimum.Prev1IsChar = true;
- optimum.Prev2 = true;
- optimum.PosPrev2 = cur;
- optimum.BackPrev2 = curBack + Base.kNumRepDistances;
- }
- }
- }
- offs += 2;
- if (offs == numDistancePairs)
- {
- break;
- }
- }
- }
- }
- }
- }
-
- private bool ChangePair(UInt32 smallDist, UInt32 bigDist)
- {
- const int kDif = 7;
- return smallDist < ((UInt32)1 << (32 - kDif)) && bigDist >= (smallDist << kDif);
- }
-
- private void WriteEndMarker(UInt32 posState)
- {
- if (!_writeEndMark)
- {
- return;
- }
-
- _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1);
- _isRep[_state.Index].Encode(_rangeEncoder, 0);
- _state.UpdateMatch();
- const UInt32 len = Base.kMatchMinLen;
- _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
- const UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1;
- UInt32 lenToPosState = Base.GetLenToPosState(len);
- _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
- const int footerBits = 30;
- const UInt32 posReduced = (((UInt32)1) << footerBits) - 1;
- _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);
- _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);
- }
-
- private void Flush(UInt32 nowPos)
- {
- ReleaseMFStream();
- WriteEndMarker(nowPos & _posStateMask);
- _rangeEncoder.FlushData();
- _rangeEncoder.FlushStream();
- }
-
- public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished)
- {
- inSize = 0;
- outSize = 0;
- finished = true;
-
- if (_inStream != null)
- {
- _matchFinder.SetStream(_inStream);
- _matchFinder.Init();
- _needReleaseMFStream = true;
- _inStream = null;
- if (_trainSize > 0)
- {
- _matchFinder.Skip(_trainSize);
- }
- }
-
- if (_finished)
- {
- return;
- }
-
- _finished = true;
-
- Int64 progressPosValuePrev = nowPos64;
- if (nowPos64 == 0)
- {
- if (_matchFinder.GetNumAvailableBytes() == 0)
- {
- Flush((UInt32)nowPos64);
- return;
- }
- // it's not used
- ReadMatchDistances(out uint len, out uint numDistancePairs);
- UInt32 posState = (UInt32)nowPos64 & _posStateMask;
- _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0);
- _state.UpdateChar();
- Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset));
- _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte).Encode(_rangeEncoder, curByte);
- _previousByte = curByte;
- _additionalOffset--;
- nowPos64++;
- }
- if (_matchFinder.GetNumAvailableBytes() == 0)
- {
- Flush((UInt32)nowPos64);
- return;
- }
- while (true)
- {
- UInt32 len = GetOptimum((UInt32)nowPos64, out uint pos);
-
- UInt32 posState = ((UInt32)nowPos64) & _posStateMask;
- UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState;
- if (len == 1 && pos == 0xFFFFFFFF)
- {
- _isMatch[complexState].Encode(_rangeEncoder, 0);
- Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset));
- LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte);
- if (!_state.IsCharState())
- {
- Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset));
- subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte);
- }
- else
- {
- subCoder.Encode(_rangeEncoder, curByte);
- }
-
- _previousByte = curByte;
- _state.UpdateChar();
- }
- else
- {
- _isMatch[complexState].Encode(_rangeEncoder, 1);
- if (pos < Base.kNumRepDistances)
- {
- _isRep[_state.Index].Encode(_rangeEncoder, 1);
- if (pos == 0)
- {
- _isRepG0[_state.Index].Encode(_rangeEncoder, 0);
- if (len == 1)
- {
- _isRep0Long[complexState].Encode(_rangeEncoder, 0);
- }
- else
- {
- _isRep0Long[complexState].Encode(_rangeEncoder, 1);
- }
- }
- else
- {
- _isRepG0[_state.Index].Encode(_rangeEncoder, 1);
- if (pos == 1)
- {
- _isRepG1[_state.Index].Encode(_rangeEncoder, 0);
- }
- else
- {
- _isRepG1[_state.Index].Encode(_rangeEncoder, 1);
- _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2);
- }
- }
- if (len == 1)
- {
- _state.UpdateShortRep();
- }
- else
- {
- _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
- _state.UpdateRep();
- }
- UInt32 distance = _repDistances[pos];
- if (pos != 0)
- {
- for (UInt32 i = pos; i >= 1; i--)
- {
- _repDistances[i] = _repDistances[i - 1];
- }
-
- _repDistances[0] = distance;
- }
- }
- else
- {
- _isRep[_state.Index].Encode(_rangeEncoder, 0);
- _state.UpdateMatch();
- _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
- pos -= Base.kNumRepDistances;
- UInt32 posSlot = GetPosSlot(pos);
- UInt32 lenToPosState = Base.GetLenToPosState(len);
- _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
-
- if (posSlot >= Base.kStartPosModelIndex)
- {
- int footerBits = (int)((posSlot >> 1) - 1);
- UInt32 baseVal = (2 | (posSlot & 1)) << footerBits;
- UInt32 posReduced = pos - baseVal;
-
- if (posSlot < Base.kEndPosModelIndex)
- {
- BitTreeEncoder.ReverseEncode(_posEncoders,
- baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced);
- }
- else
- {
- _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);
- _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);
- _alignPriceCount++;
- }
- }
- UInt32 distance = pos;
- for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--)
- {
- _repDistances[i] = _repDistances[i - 1];
- }
-
- _repDistances[0] = distance;
- _matchPriceCount++;
- }
- _previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset));
- }
- _additionalOffset -= len;
- nowPos64 += len;
- if (_additionalOffset == 0)
- {
- // if (!_fastMode)
- if (_matchPriceCount >= (1 << 7))
- {
- FillDistancesPrices();
- }
-
- if (_alignPriceCount >= Base.kAlignTableSize)
- {
- FillAlignPrices();
- }
-
- inSize = nowPos64;
- outSize = _rangeEncoder.GetProcessedSizeAdd();
- if (_matchFinder.GetNumAvailableBytes() == 0)
- {
- Flush((UInt32)nowPos64);
- return;
- }
-
- if (nowPos64 - progressPosValuePrev >= (1 << 12))
- {
- _finished = false;
- finished = false;
- return;
- }
- }
- }
- }
-
- private void ReleaseMFStream()
- {
- if (_matchFinder != null && _needReleaseMFStream)
- {
- _matchFinder.ReleaseStream();
- _needReleaseMFStream = false;
- }
- }
-
- private void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); }
- private void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); }
-
- private void ReleaseStreams()
- {
- ReleaseMFStream();
- ReleaseOutStream();
- }
-
- private void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream,
- Int64 inSize, Int64 outSize)
- {
- _inStream = inStream;
- _finished = false;
- Create();
- SetOutStream(outStream);
- Init();
-
- // if (!_fastMode)
- {
- FillDistancesPrices();
- FillAlignPrices();
- }
-
- _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);
- _lenEncoder.UpdateTables((UInt32)1 << _posStateBits);
- _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);
- _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits);
-
- nowPos64 = 0;
- }
-
- public void Code(System.IO.Stream inStream, System.IO.Stream outStream,
- Int64 inSize, Int64 outSize, ICodeProgress progress, CancellationToken? token = null)
- {
- _needReleaseMFStream = false;
- try
- {
- SetStreams(inStream, outStream, inSize, outSize);
- while (true)
- {
- token?.ThrowIfCancellationRequested();
- CodeOneBlock(out long processedInSize, out long processedOutSize, out bool finished);
- if (finished)
- {
- return;
- }
-
- progress?.SetProgress(processedInSize, processedOutSize);
- }
- }
- finally
- {
- ReleaseStreams();
- }
- }
-
- private const int kPropSize = 5;
- private readonly Byte[] properties = new Byte[kPropSize];
-
- public void WriteCoderProperties(System.IO.Stream outStream)
- {
- properties[0] = (Byte)((((_posStateBits * 5) + _numLiteralPosStateBits) * 9) + _numLiteralContextBits);
- for (int i = 0; i < 4; i++)
- {
- properties[1 + i] = (Byte)((_dictionarySize >> (8 * i)) & 0xFF);
- }
-
- outStream.Write(properties, 0, kPropSize);
- }
-
- private readonly UInt32[] tempPrices = new UInt32[Base.kNumFullDistances];
- private UInt32 _matchPriceCount;
-
- private void FillDistancesPrices()
- {
- for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++)
- {
- UInt32 posSlot = GetPosSlot(i);
- int footerBits = (int)((posSlot >> 1) - 1);
- UInt32 baseVal = (2 | (posSlot & 1)) << footerBits;
- tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders,
- baseVal - posSlot - 1, footerBits, i - baseVal);
- }
-
- for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++)
- {
- UInt32 posSlot;
- BitTreeEncoder encoder = _posSlotEncoder[lenToPosState];
-
- UInt32 st = lenToPosState << Base.kNumPosSlotBits;
- for (posSlot = 0; posSlot < _distTableSize; posSlot++)
- {
- _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot);
- }
-
- for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++)
- {
- _posSlotPrices[st + posSlot] += ((posSlot >> 1) - 1 - Base.kNumAlignBits) << BitEncoder.kNumBitPriceShiftBits;
- }
-
- UInt32 st2 = lenToPosState * Base.kNumFullDistances;
- UInt32 i;
- for (i = 0; i < Base.kStartPosModelIndex; i++)
- {
- _distancesPrices[st2 + i] = _posSlotPrices[st + i];
- }
-
- for (; i < Base.kNumFullDistances; i++)
- {
- _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i];
- }
- }
- _matchPriceCount = 0;
- }
-
- private void FillAlignPrices()
- {
- for (UInt32 i = 0; i < Base.kAlignTableSize; i++)
- {
- _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);
- }
-
- _alignPriceCount = 0;
- }
-
- private static readonly string[] kMatchFinderIDs =
- {
- "BT2",
- "BT4",
- };
-
- private static int FindMatchFinder(string s)
- {
- for (int m = 0; m < kMatchFinderIDs.Length; m++)
- {
- if (s == kMatchFinderIDs[m])
- {
- return m;
- }
- }
-
- return -1;
- }
-
- public void SetCoderProperties(CoderPropID[] propIDs, object[] properties)
- {
- for (UInt32 i = 0; i < properties.Length; i++)
- {
- object prop = properties[i];
- switch (propIDs[i])
- {
- case CoderPropID.NumFastBytes:
- {
- if (!(prop is Int32))
- {
- throw new InvalidParamException();
- }
-
- Int32 numFastBytes = (Int32)prop;
- if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen)
- {
- throw new InvalidParamException();
- }
-
- _numFastBytes = (UInt32)numFastBytes;
- break;
- }
- case CoderPropID.Algorithm:
- {
- /*
- if (!(prop is Int32))
- throw new InvalidParamException();
- Int32 maximize = (Int32)prop;
- _fastMode = (maximize == 0);
- _maxMode = (maximize >= 2);
- */
- break;
- }
- case CoderPropID.MatchFinder:
- {
- if (!(prop is String))
- {
- throw new InvalidParamException();
- }
-
- EMatchFinderType matchFinderIndexPrev = _matchFinderType;
- int m = FindMatchFinder(((string)prop).ToUpper());
- if (m < 0)
- {
- throw new InvalidParamException();
- }
-
- _matchFinderType = (EMatchFinderType)m;
- if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType)
- {
- _dictionarySizePrev = 0xFFFFFFFF;
- _matchFinder = null;
- }
- break;
- }
- case CoderPropID.DictionarySize:
- {
- const int kDicLogSizeMaxCompress = 30;
- if (!(prop is Int32))
- {
- throw new InvalidParamException();
- }
- Int32 dictionarySize = (Int32)prop;
- if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) ||
- dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress))
- {
- throw new InvalidParamException();
- }
-
- _dictionarySize = (UInt32)dictionarySize;
- int dicLogSize;
- for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++)
- {
- if (dictionarySize <= ((UInt32)1 << dicLogSize))
- {
- break;
- }
- }
-
- _distTableSize = (UInt32)dicLogSize * 2;
- break;
- }
- case CoderPropID.PosStateBits:
- {
- if (!(prop is Int32))
- {
- throw new InvalidParamException();
- }
-
- Int32 v = (Int32)prop;
- if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax)
- {
- throw new InvalidParamException();
- }
-
- _posStateBits = v;
- _posStateMask = (((UInt32)1) << _posStateBits) - 1;
- break;
- }
- case CoderPropID.LitPosBits:
- {
- if (!(prop is Int32))
- {
- throw new InvalidParamException();
- }
-
- Int32 v = (Int32)prop;
- if (v < 0 || v > Base.kNumLitPosStatesBitsEncodingMax)
- {
- throw new InvalidParamException();
- }
-
- _numLiteralPosStateBits = v;
- break;
- }
- case CoderPropID.LitContextBits:
- {
- if (!(prop is Int32))
- {
- throw new InvalidParamException();
- }
-
- Int32 v = (Int32)prop;
- if (v < 0 || v > Base.kNumLitContextBitsMax)
- {
- throw new InvalidParamException();
- }
- _numLiteralContextBits = v;
- break;
- }
- case CoderPropID.EndMarker:
- {
- if (!(prop is Boolean))
- {
- throw new InvalidParamException();
- }
-
- SetWriteEndMarkerMode((Boolean)prop);
- break;
- }
- default:
- throw new InvalidParamException();
- }
- }
- }
-
- private uint _trainSize = 0;
- public void SetTrainSize(uint trainSize)
- {
- _trainSize = trainSize;
- }
- }
-}
+// LzmaEncoder.cs
+
+using System;
+
+namespace SevenZip.Compression.LZMA
+{
+ using RangeCoder;
+ using System.Threading;
+
+ public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties
+ {
+ private enum EMatchFinderType
+ {
+ BT2,
+ BT4,
+ };
+
+ private const UInt32 kIfinityPrice = 0xFFFFFFF;
+
+ private static readonly Byte[] g_FastPos = new Byte[1 << 11];
+
+ static Encoder()
+ {
+ const Byte kFastSlots = 22;
+ int c = 2;
+ g_FastPos[0] = 0;
+ g_FastPos[1] = 1;
+ for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++)
+ {
+ UInt32 k = (UInt32)1 << ((slotFast >> 1) - 1);
+ for (UInt32 j = 0; j < k; j++, c++)
+ {
+ g_FastPos[c] = slotFast;
+ }
+ }
+ }
+
+ private static UInt32 GetPosSlot(UInt32 pos)
+ {
+ if (pos < (1 << 11))
+ {
+ return g_FastPos[pos];
+ }
+
+ if (pos < (1 << 21))
+ {
+ return (UInt32)(g_FastPos[pos >> 10] + 20);
+ }
+
+ return (UInt32)(g_FastPos[pos >> 20] + 40);
+ }
+
+ private static UInt32 GetPosSlot2(UInt32 pos)
+ {
+ if (pos < (1 << 17))
+ {
+ return (UInt32)(g_FastPos[pos >> 6] + 12);
+ }
+
+ if (pos < (1 << 27))
+ {
+ return (UInt32)(g_FastPos[pos >> 16] + 32);
+ }
+
+ return (UInt32)(g_FastPos[pos >> 26] + 52);
+ }
+
+ private Base.State _state = new();
+ private Byte _previousByte;
+ private readonly UInt32[] _repDistances = new UInt32[Base.kNumRepDistances];
+
+ private void BaseInit()
+ {
+ _state.Init();
+ _previousByte = 0;
+ for (UInt32 i = 0; i < Base.kNumRepDistances; i++)
+ {
+ _repDistances[i] = 0;
+ }
+ }
+
+ private const int kDefaultDictionaryLogSize = 22;
+ private const UInt32 kNumFastBytesDefault = 0x20;
+
+ private class LiteralEncoder
+ {
+ public struct Encoder2
+ {
+ private BitEncoder[] m_Encoders;
+
+ public void Create() { m_Encoders = new BitEncoder[0x300]; }
+
+ public void Init() { for (int i = 0; i < 0x300; i++)
+ {
+ m_Encoders[i].Init();
+ }
+ }
+
+ public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol)
+ {
+ uint context = 1;
+ for (int i = 7; i >= 0; i--)
+ {
+ uint bit = (uint)((symbol >> i) & 1);
+ m_Encoders[context].Encode(rangeEncoder, bit);
+ context = (context << 1) | bit;
+ }
+ }
+
+ public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol)
+ {
+ uint context = 1;
+ bool same = true;
+ for (int i = 7; i >= 0; i--)
+ {
+ uint bit = (uint)((symbol >> i) & 1);
+ uint state = context;
+ if (same)
+ {
+ uint matchBit = (uint)((matchByte >> i) & 1);
+ state += (1 + matchBit) << 8;
+ same = matchBit == bit;
+ }
+ m_Encoders[state].Encode(rangeEncoder, bit);
+ context = (context << 1) | bit;
+ }
+ }
+
+ public uint GetPrice(bool matchMode, byte matchByte, byte symbol)
+ {
+ uint price = 0;
+ uint context = 1;
+ int i = 7;
+ if (matchMode)
+ {
+ for (; i >= 0; i--)
+ {
+ uint matchBit = (uint)(matchByte >> i) & 1;
+ uint bit = (uint)(symbol >> i) & 1;
+ price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit);
+ context = (context << 1) | bit;
+ if (matchBit != bit)
+ {
+ i--;
+ break;
+ }
+ }
+ }
+ for (; i >= 0; i--)
+ {
+ uint bit = (uint)(symbol >> i) & 1;
+ price += m_Encoders[context].GetPrice(bit);
+ context = (context << 1) | bit;
+ }
+ return price;
+ }
+ }
+
+ private Encoder2[] m_Coders;
+ private int m_NumPrevBits;
+ private int m_NumPosBits;
+ private uint m_PosMask;
+
+ public void Create(int numPosBits, int numPrevBits)
+ {
+ if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits)
+ {
+ return;
+ }
+
+ m_NumPosBits = numPosBits;
+ m_PosMask = ((uint)1 << numPosBits) - 1;
+ m_NumPrevBits = numPrevBits;
+ uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
+ m_Coders = new Encoder2[numStates];
+ for (uint i = 0; i < numStates; i++)
+ {
+ m_Coders[i].Create();
+ }
+ }
+
+ public void Init()
+ {
+ uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
+ for (uint i = 0; i < numStates; i++)
+ {
+ m_Coders[i].Init();
+ }
+ }
+
+ public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte)
+ { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits))]; }
+ }
+
+ private class LenEncoder
+ {
+ private BitEncoder _choice = new();
+ private BitEncoder _choice2 = new();
+ private readonly BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax];
+ private readonly BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax];
+ private readonly BitTreeEncoder _highCoder = new(Base.kNumHighLenBits);
+
+ public LenEncoder()
+ {
+ for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++)
+ {
+ _lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits);
+ _midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits);
+ }
+ }
+
+ public void Init(UInt32 numPosStates)
+ {
+ _choice.Init();
+ _choice2.Init();
+ for (UInt32 posState = 0; posState < numPosStates; posState++)
+ {
+ _lowCoder[posState].Init();
+ _midCoder[posState].Init();
+ }
+ _highCoder.Init();
+ }
+
+ public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState)
+ {
+ if (symbol < Base.kNumLowLenSymbols)
+ {
+ _choice.Encode(rangeEncoder, 0);
+ _lowCoder[posState].Encode(rangeEncoder, symbol);
+ }
+ else
+ {
+ symbol -= Base.kNumLowLenSymbols;
+ _choice.Encode(rangeEncoder, 1);
+ if (symbol < Base.kNumMidLenSymbols)
+ {
+ _choice2.Encode(rangeEncoder, 0);
+ _midCoder[posState].Encode(rangeEncoder, symbol);
+ }
+ else
+ {
+ _choice2.Encode(rangeEncoder, 1);
+ _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols);
+ }
+ }
+ }
+
+ public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st)
+ {
+ UInt32 a0 = _choice.GetPrice0();
+ UInt32 a1 = _choice.GetPrice1();
+ UInt32 b0 = a1 + _choice2.GetPrice0();
+ UInt32 b1 = a1 + _choice2.GetPrice1();
+ UInt32 i = 0;
+ for (i = 0; i < Base.kNumLowLenSymbols; i++)
+ {
+ if (i >= numSymbols)
+ {
+ return;
+ }
+
+ prices[st + i] = a0 + _lowCoder[posState].GetPrice(i);
+ }
+ for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++)
+ {
+ if (i >= numSymbols)
+ {
+ return;
+ }
+
+ prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols);
+ }
+ for (; i < numSymbols; i++)
+ {
+ prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols);
+ }
+ }
+ };
+
+ private const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols;
+
+ private class LenPriceTableEncoder : LenEncoder
+ {
+ private readonly UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax];
+ private UInt32 _tableSize;
+ private readonly UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax];
+
+ public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; }
+
+ public UInt32 GetPrice(UInt32 symbol, UInt32 posState)
+ {
+ return _prices[(posState * Base.kNumLenSymbols) + symbol];
+ }
+
+ private void UpdateTable(UInt32 posState)
+ {
+ SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols);
+ _counters[posState] = _tableSize;
+ }
+
+ public void UpdateTables(UInt32 numPosStates)
+ {
+ for (UInt32 posState = 0; posState < numPosStates; posState++)
+ {
+ UpdateTable(posState);
+ }
+ }
+
+ public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState)
+ {
+ base.Encode(rangeEncoder, symbol, posState);
+ if (--_counters[posState] == 0)
+ {
+ UpdateTable(posState);
+ }
+ }
+ }
+
+ private const UInt32 kNumOpts = 1 << 12;
+ private class Optimal
+ {
+ public Base.State State;
+
+ public bool Prev1IsChar;
+ public bool Prev2;
+
+ public UInt32 PosPrev2;
+ public UInt32 BackPrev2;
+
+ public UInt32 Price;
+ public UInt32 PosPrev;
+ public UInt32 BackPrev;
+
+ public UInt32 Backs0;
+ public UInt32 Backs1;
+ public UInt32 Backs2;
+ public UInt32 Backs3;
+
+ public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; }
+ public void MakeAsShortRep() { BackPrev = 0; Prev1IsChar = false; }
+ public bool IsShortRep() { return BackPrev == 0; }
+ };
+ private readonly Optimal[] _optimum = new Optimal[kNumOpts];
+ private LZ.IMatchFinder _matchFinder = null;
+ private readonly RangeCoder.Encoder _rangeEncoder = new();
+
+ private readonly BitEncoder[] _isMatch = new BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
+ private readonly BitEncoder[] _isRep = new BitEncoder[Base.kNumStates];
+ private readonly BitEncoder[] _isRepG0 = new BitEncoder[Base.kNumStates];
+ private readonly BitEncoder[] _isRepG1 = new BitEncoder[Base.kNumStates];
+ private readonly BitEncoder[] _isRepG2 = new BitEncoder[Base.kNumStates];
+ private readonly BitEncoder[] _isRep0Long = new BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
+
+ private readonly BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.kNumLenToPosStates];
+
+ private readonly BitEncoder[] _posEncoders = new BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex];
+ private readonly BitTreeEncoder _posAlignEncoder = new(Base.kNumAlignBits);
+
+ private readonly LenPriceTableEncoder _lenEncoder = new();
+ private readonly LenPriceTableEncoder _repMatchLenEncoder = new();
+
+ private readonly LiteralEncoder _literalEncoder = new();
+
+ private readonly UInt32[] _matchDistances = new UInt32[(Base.kMatchMaxLen * 2) + 2];
+
+ private UInt32 _numFastBytes = kNumFastBytesDefault;
+ private UInt32 _longestMatchLength;
+ private UInt32 _numDistancePairs;
+
+ private UInt32 _additionalOffset;
+
+ private UInt32 _optimumEndIndex;
+ private UInt32 _optimumCurrentIndex;
+
+ private bool _longestMatchWasFound;
+
+ private readonly UInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)];
+ private readonly UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits];
+ private readonly UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize];
+ private UInt32 _alignPriceCount;
+
+ private UInt32 _distTableSize = kDefaultDictionaryLogSize * 2;
+
+ private int _posStateBits = 2;
+ private UInt32 _posStateMask = 4 - 1;
+ private int _numLiteralPosStateBits = 0;
+ private int _numLiteralContextBits = 3;
+
+ private UInt32 _dictionarySize = 1 << kDefaultDictionaryLogSize;
+ private UInt32 _dictionarySizePrev = 0xFFFFFFFF;
+ private UInt32 _numFastBytesPrev = 0xFFFFFFFF;
+
+ private Int64 nowPos64;
+ private bool _finished;
+ private System.IO.Stream _inStream;
+
+ private EMatchFinderType _matchFinderType = EMatchFinderType.BT4;
+ private bool _writeEndMark = false;
+
+ private bool _needReleaseMFStream;
+
+ private void Create()
+ {
+ if (_matchFinder == null)
+ {
+ LZ.BinTree bt = new();
+ int numHashBytes = 4;
+ if (_matchFinderType == EMatchFinderType.BT2)
+ {
+ numHashBytes = 2;
+ }
+
+ bt.SetType(numHashBytes);
+ _matchFinder = bt;
+ }
+ _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits);
+
+ if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes)
+ {
+ return;
+ }
+
+ _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1);
+ _dictionarySizePrev = _dictionarySize;
+ _numFastBytesPrev = _numFastBytes;
+ }
+
+ public Encoder()
+ {
+ for (int i = 0; i < kNumOpts; i++)
+ {
+ _optimum[i] = new Optimal();
+ }
+
+ for (int i = 0; i < Base.kNumLenToPosStates; i++)
+ {
+ _posSlotEncoder[i] = new BitTreeEncoder(Base.kNumPosSlotBits);
+ }
+ }
+
+ private void SetWriteEndMarkerMode(bool writeEndMarker)
+ {
+ _writeEndMark = writeEndMarker;
+ }
+
+ private void Init()
+ {
+ BaseInit();
+ _rangeEncoder.Init();
+
+ uint i;
+ for (i = 0; i < Base.kNumStates; i++)
+ {
+ for (uint j = 0; j <= _posStateMask; j++)
+ {
+ uint complexState = (i << Base.kNumPosStatesBitsMax) + j;
+ _isMatch[complexState].Init();
+ _isRep0Long[complexState].Init();
+ }
+ _isRep[i].Init();
+ _isRepG0[i].Init();
+ _isRepG1[i].Init();
+ _isRepG2[i].Init();
+ }
+ _literalEncoder.Init();
+ for (i = 0; i < Base.kNumLenToPosStates; i++)
+ {
+ _posSlotEncoder[i].Init();
+ }
+
+ for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)
+ {
+ _posEncoders[i].Init();
+ }
+
+ _lenEncoder.Init((UInt32)1 << _posStateBits);
+ _repMatchLenEncoder.Init((UInt32)1 << _posStateBits);
+
+ _posAlignEncoder.Init();
+
+ _longestMatchWasFound = false;
+ _optimumEndIndex = 0;
+ _optimumCurrentIndex = 0;
+ _additionalOffset = 0;
+ }
+
+ private void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs)
+ {
+ lenRes = 0;
+ numDistancePairs = _matchFinder.GetMatches(_matchDistances);
+ if (numDistancePairs > 0)
+ {
+ lenRes = _matchDistances[numDistancePairs - 2];
+ if (lenRes == _numFastBytes)
+ {
+ lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[numDistancePairs - 1],
+ Base.kMatchMaxLen - lenRes);
+ }
+ }
+ _additionalOffset++;
+ }
+
+ private void MovePos(UInt32 num)
+ {
+ if (num > 0)
+ {
+ _matchFinder.Skip(num);
+ _additionalOffset += num;
+ }
+ }
+
+ private UInt32 GetRepLen1Price(Base.State state, UInt32 posState)
+ {
+ return _isRepG0[state.Index].GetPrice0() +
+ _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0();
+ }
+
+ private UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState)
+ {
+ UInt32 price;
+ if (repIndex == 0)
+ {
+ price = _isRepG0[state.Index].GetPrice0();
+ price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();
+ }
+ else
+ {
+ price = _isRepG0[state.Index].GetPrice1();
+ if (repIndex == 1)
+ {
+ price += _isRepG1[state.Index].GetPrice0();
+ }
+ else
+ {
+ price += _isRepG1[state.Index].GetPrice1();
+ price += _isRepG2[state.Index].GetPrice(repIndex - 2);
+ }
+ }
+ return price;
+ }
+
+ private UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState)
+ {
+ UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState);
+ return price + GetPureRepPrice(repIndex, state, posState);
+ }
+
+ private UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState)
+ {
+ UInt32 price;
+ UInt32 lenToPosState = Base.GetLenToPosState(len);
+ price = pos < Base.kNumFullDistances
+ ? _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]
+ : _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] +
+ _alignPrices[pos & Base.kAlignMask];
+
+ return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState);
+ }
+
+ private UInt32 Backward(out UInt32 backRes, UInt32 cur)
+ {
+ _optimumEndIndex = cur;
+ UInt32 posMem = _optimum[cur].PosPrev;
+ UInt32 backMem = _optimum[cur].BackPrev;
+ do
+ {
+ if (_optimum[cur].Prev1IsChar)
+ {
+ _optimum[posMem].MakeAsChar();
+ _optimum[posMem].PosPrev = posMem - 1;
+ if (_optimum[cur].Prev2)
+ {
+ _optimum[posMem - 1].Prev1IsChar = false;
+ _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2;
+ _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2;
+ }
+ }
+ UInt32 posPrev = posMem;
+ UInt32 backCur = backMem;
+
+ backMem = _optimum[posPrev].BackPrev;
+ posMem = _optimum[posPrev].PosPrev;
+
+ _optimum[posPrev].BackPrev = backCur;
+ _optimum[posPrev].PosPrev = cur;
+ cur = posPrev;
+ }
+ while (cur > 0);
+ backRes = _optimum[0].BackPrev;
+ _optimumCurrentIndex = _optimum[0].PosPrev;
+ return _optimumCurrentIndex;
+ }
+
+ private readonly UInt32[] reps = new UInt32[Base.kNumRepDistances];
+ private readonly UInt32[] repLens = new UInt32[Base.kNumRepDistances];
+
+ private UInt32 GetOptimum(UInt32 position, out UInt32 backRes)
+ {
+ if (_optimumEndIndex != _optimumCurrentIndex)
+ {
+ UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex;
+ backRes = _optimum[_optimumCurrentIndex].BackPrev;
+ _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev;
+ return lenRes;
+ }
+ _optimumCurrentIndex = _optimumEndIndex = 0;
+
+ UInt32 lenMain, numDistancePairs;
+ if (!_longestMatchWasFound)
+ {
+ ReadMatchDistances(out lenMain, out numDistancePairs);
+ }
+ else
+ {
+ lenMain = _longestMatchLength;
+ numDistancePairs = _numDistancePairs;
+ _longestMatchWasFound = false;
+ }
+
+ UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1;
+ if (numAvailableBytes < 2)
+ {
+ backRes = 0xFFFFFFFF;
+ return 1;
+ }
+ if (numAvailableBytes > Base.kMatchMaxLen)
+ {
+ numAvailableBytes = Base.kMatchMaxLen;
+ }
+
+ UInt32 repMaxIndex = 0;
+ UInt32 i;
+ for (i = 0; i < Base.kNumRepDistances; i++)
+ {
+ reps[i] = _repDistances[i];
+ repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen);
+ if (repLens[i] > repLens[repMaxIndex])
+ {
+ repMaxIndex = i;
+ }
+ }
+ if (repLens[repMaxIndex] >= _numFastBytes)
+ {
+ backRes = repMaxIndex;
+ UInt32 lenRes = repLens[repMaxIndex];
+ MovePos(lenRes - 1);
+ return lenRes;
+ }
+
+ if (lenMain >= _numFastBytes)
+ {
+ backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances;
+ MovePos(lenMain - 1);
+ return lenMain;
+ }
+
+ Byte currentByte = _matchFinder.GetIndexByte(0 - 1);
+ Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1));
+
+ if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2)
+ {
+ backRes = 0xFFFFFFFF;
+ return 1;
+ }
+
+ _optimum[0].State = _state;
+
+ UInt32 posState = position & _posStateMask;
+
+ _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() +
+ _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte);
+ _optimum[1].MakeAsChar();
+
+ UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();
+ UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1();
+
+ if (matchByte == currentByte)
+ {
+ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState);
+ if (shortRepPrice < _optimum[1].Price)
+ {
+ _optimum[1].Price = shortRepPrice;
+ _optimum[1].MakeAsShortRep();
+ }
+ }
+
+ UInt32 lenEnd = (lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex];
+
+ if (lenEnd < 2)
+ {
+ backRes = _optimum[1].BackPrev;
+ return 1;
+ }
+
+ _optimum[1].PosPrev = 0;
+
+ _optimum[0].Backs0 = reps[0];
+ _optimum[0].Backs1 = reps[1];
+ _optimum[0].Backs2 = reps[2];
+ _optimum[0].Backs3 = reps[3];
+
+ UInt32 len = lenEnd;
+ do
+ {
+ _optimum[len--].Price = kIfinityPrice;
+ }
+ while (len >= 2);
+
+ for (i = 0; i < Base.kNumRepDistances; i++)
+ {
+ UInt32 repLen = repLens[i];
+ if (repLen < 2)
+ {
+ continue;
+ }
+
+ UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState);
+ do
+ {
+ UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState);
+ Optimal optimum = _optimum[repLen];
+ if (curAndLenPrice < optimum.Price)
+ {
+ optimum.Price = curAndLenPrice;
+ optimum.PosPrev = 0;
+ optimum.BackPrev = i;
+ optimum.Prev1IsChar = false;
+ }
+ }
+ while (--repLen >= 2);
+ }
+
+ UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0();
+
+ len = (repLens[0] >= 2) ? repLens[0] + 1 : 2;
+ if (len <= lenMain)
+ {
+ UInt32 offs = 0;
+ while (len > _matchDistances[offs])
+ {
+ offs += 2;
+ }
+
+ for (; ; len++)
+ {
+ UInt32 distance = _matchDistances[offs + 1];
+ UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState);
+ Optimal optimum = _optimum[len];
+ if (curAndLenPrice < optimum.Price)
+ {
+ optimum.Price = curAndLenPrice;
+ optimum.PosPrev = 0;
+ optimum.BackPrev = distance + Base.kNumRepDistances;
+ optimum.Prev1IsChar = false;
+ }
+ if (len == _matchDistances[offs])
+ {
+ offs += 2;
+ if (offs == numDistancePairs)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ UInt32 cur = 0;
+
+ while (true)
+ {
+ cur++;
+ if (cur == lenEnd)
+ {
+ return Backward(out backRes, cur);
+ }
+
+ ReadMatchDistances(out uint newLen, out numDistancePairs);
+ if (newLen >= _numFastBytes)
+ {
+ _numDistancePairs = numDistancePairs;
+ _longestMatchLength = newLen;
+ _longestMatchWasFound = true;
+ return Backward(out backRes, cur);
+ }
+ position++;
+ UInt32 posPrev = _optimum[cur].PosPrev;
+ Base.State state;
+ if (_optimum[cur].Prev1IsChar)
+ {
+ posPrev--;
+ if (_optimum[cur].Prev2)
+ {
+ state = _optimum[_optimum[cur].PosPrev2].State;
+ if (_optimum[cur].BackPrev2 < Base.kNumRepDistances)
+ {
+ state.UpdateRep();
+ }
+ else
+ {
+ state.UpdateMatch();
+ }
+ }
+ else
+ {
+ state = _optimum[posPrev].State;
+ }
+
+ state.UpdateChar();
+ }
+ else
+ {
+ state = _optimum[posPrev].State;
+ }
+
+ if (posPrev == cur - 1)
+ {
+ if (_optimum[cur].IsShortRep())
+ {
+ state.UpdateShortRep();
+ }
+ else
+ {
+ state.UpdateChar();
+ }
+ }
+ else
+ {
+ UInt32 pos;
+ if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2)
+ {
+ posPrev = _optimum[cur].PosPrev2;
+ pos = _optimum[cur].BackPrev2;
+ state.UpdateRep();
+ }
+ else
+ {
+ pos = _optimum[cur].BackPrev;
+ if (pos < Base.kNumRepDistances)
+ {
+ state.UpdateRep();
+ }
+ else
+ {
+ state.UpdateMatch();
+ }
+ }
+ Optimal opt = _optimum[posPrev];
+ if (pos < Base.kNumRepDistances)
+ {
+ if (pos == 0)
+ {
+ reps[0] = opt.Backs0;
+ reps[1] = opt.Backs1;
+ reps[2] = opt.Backs2;
+ reps[3] = opt.Backs3;
+ }
+ else if (pos == 1)
+ {
+ reps[0] = opt.Backs1;
+ reps[1] = opt.Backs0;
+ reps[2] = opt.Backs2;
+ reps[3] = opt.Backs3;
+ }
+ else if (pos == 2)
+ {
+ reps[0] = opt.Backs2;
+ reps[1] = opt.Backs0;
+ reps[2] = opt.Backs1;
+ reps[3] = opt.Backs3;
+ }
+ else
+ {
+ reps[0] = opt.Backs3;
+ reps[1] = opt.Backs0;
+ reps[2] = opt.Backs1;
+ reps[3] = opt.Backs2;
+ }
+ }
+ else
+ {
+ reps[0] = pos - Base.kNumRepDistances;
+ reps[1] = opt.Backs0;
+ reps[2] = opt.Backs1;
+ reps[3] = opt.Backs2;
+ }
+ }
+ _optimum[cur].State = state;
+ _optimum[cur].Backs0 = reps[0];
+ _optimum[cur].Backs1 = reps[1];
+ _optimum[cur].Backs2 = reps[2];
+ _optimum[cur].Backs3 = reps[3];
+ UInt32 curPrice = _optimum[cur].Price;
+
+ currentByte = _matchFinder.GetIndexByte(0 - 1);
+ matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1));
+
+ posState = position & _posStateMask;
+
+ UInt32 curAnd1Price = curPrice +
+ _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() +
+ _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)).
+ GetPrice(!state.IsCharState(), matchByte, currentByte);
+
+ Optimal nextOptimum = _optimum[cur + 1];
+
+ bool nextIsChar = false;
+ if (curAnd1Price < nextOptimum.Price)
+ {
+ nextOptimum.Price = curAnd1Price;
+ nextOptimum.PosPrev = cur;
+ nextOptimum.MakeAsChar();
+ nextIsChar = true;
+ }
+
+ matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();
+ repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1();
+
+ if (matchByte == currentByte &&
+ !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0))
+ {
+ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState);
+ if (shortRepPrice <= nextOptimum.Price)
+ {
+ nextOptimum.Price = shortRepPrice;
+ nextOptimum.PosPrev = cur;
+ nextOptimum.MakeAsShortRep();
+ nextIsChar = true;
+ }
+ }
+
+ UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1;
+ numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull);
+ numAvailableBytes = numAvailableBytesFull;
+
+ if (numAvailableBytes < 2)
+ {
+ continue;
+ }
+
+ if (numAvailableBytes > _numFastBytes)
+ {
+ numAvailableBytes = _numFastBytes;
+ }
+
+ if (!nextIsChar && matchByte != currentByte)
+ {
+ // try Literal + rep0
+ UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes);
+ UInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t);
+ if (lenTest2 >= 2)
+ {
+ Base.State state2 = state;
+ state2.UpdateChar();
+ UInt32 posStateNext = (position + 1) & _posStateMask;
+ UInt32 nextRepMatchPrice = curAnd1Price +
+ _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() +
+ _isRep[state2.Index].GetPrice1();
+ {
+ UInt32 offset = cur + 1 + lenTest2;
+ while (lenEnd < offset)
+ {
+ _optimum[++lenEnd].Price = kIfinityPrice;
+ }
+
+ UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
+ 0, lenTest2, state2, posStateNext);
+ Optimal optimum = _optimum[offset];
+ if (curAndLenPrice < optimum.Price)
+ {
+ optimum.Price = curAndLenPrice;
+ optimum.PosPrev = cur + 1;
+ optimum.BackPrev = 0;
+ optimum.Prev1IsChar = true;
+ optimum.Prev2 = false;
+ }
+ }
+ }
+ }
+
+ UInt32 startLen = 2; // speed optimization
+
+ for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++)
+ {
+ UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes);
+ if (lenTest < 2)
+ {
+ continue;
+ }
+
+ UInt32 lenTestTemp = lenTest;
+ do
+ {
+ while (lenEnd < cur + lenTest)
+ {
+ _optimum[++lenEnd].Price = kIfinityPrice;
+ }
+
+ UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState);
+ Optimal optimum = _optimum[cur + lenTest];
+ if (curAndLenPrice < optimum.Price)
+ {
+ optimum.Price = curAndLenPrice;
+ optimum.PosPrev = cur;
+ optimum.BackPrev = repIndex;
+ optimum.Prev1IsChar = false;
+ }
+ }
+ while (--lenTest >= 2);
+ lenTest = lenTestTemp;
+
+ if (repIndex == 0)
+ {
+ startLen = lenTest + 1;
+ }
+
+ // if (_maxMode)
+ if (lenTest < numAvailableBytesFull)
+ {
+ UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
+ UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, reps[repIndex], t);
+ if (lenTest2 >= 2)
+ {
+ Base.State state2 = state;
+ state2.UpdateRep();
+ UInt32 posStateNext = (position + lenTest) & _posStateMask;
+ UInt32 curAndLenCharPrice =
+ repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) +
+ _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() +
+ _literalEncoder.GetSubCoder(position + lenTest,
+ _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true,
+ _matchFinder.GetIndexByte((Int32)lenTest - 1 - (Int32)(reps[repIndex] + 1)),
+ _matchFinder.GetIndexByte((Int32)lenTest - 1));
+ state2.UpdateChar();
+ posStateNext = (position + lenTest + 1) & _posStateMask;
+ UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1();
+ UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();
+
+ // for(; lenTest2 >= 2; lenTest2--)
+ {
+ UInt32 offset = lenTest + 1 + lenTest2;
+ while (lenEnd < cur + offset)
+ {
+ _optimum[++lenEnd].Price = kIfinityPrice;
+ }
+
+ UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
+ Optimal optimum = _optimum[cur + offset];
+ if (curAndLenPrice < optimum.Price)
+ {
+ optimum.Price = curAndLenPrice;
+ optimum.PosPrev = cur + lenTest + 1;
+ optimum.BackPrev = 0;
+ optimum.Prev1IsChar = true;
+ optimum.Prev2 = true;
+ optimum.PosPrev2 = cur;
+ optimum.BackPrev2 = repIndex;
+ }
+ }
+ }
+ }
+ }
+
+ if (newLen > numAvailableBytes)
+ {
+ newLen = numAvailableBytes;
+ for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2)
+ {
+ }
+
+ _matchDistances[numDistancePairs] = newLen;
+ numDistancePairs += 2;
+ }
+ if (newLen >= startLen)
+ {
+ normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0();
+ while (lenEnd < cur + newLen)
+ {
+ _optimum[++lenEnd].Price = kIfinityPrice;
+ }
+
+ UInt32 offs = 0;
+ while (startLen > _matchDistances[offs])
+ {
+ offs += 2;
+ }
+
+ for (UInt32 lenTest = startLen; ; lenTest++)
+ {
+ UInt32 curBack = _matchDistances[offs + 1];
+ UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState);
+ Optimal optimum = _optimum[cur + lenTest];
+ if (curAndLenPrice < optimum.Price)
+ {
+ optimum.Price = curAndLenPrice;
+ optimum.PosPrev = cur;
+ optimum.BackPrev = curBack + Base.kNumRepDistances;
+ optimum.Prev1IsChar = false;
+ }
+
+ if (lenTest == _matchDistances[offs])
+ {
+ if (lenTest < numAvailableBytesFull)
+ {
+ UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
+ UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t);
+ if (lenTest2 >= 2)
+ {
+ Base.State state2 = state;
+ state2.UpdateMatch();
+ UInt32 posStateNext = (position + lenTest) & _posStateMask;
+ UInt32 curAndLenCharPrice = curAndLenPrice +
+ _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() +
+ _literalEncoder.GetSubCoder(position + lenTest,
+ _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).
+ GetPrice(true,
+ _matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 1),
+ _matchFinder.GetIndexByte((Int32)lenTest - 1));
+ state2.UpdateChar();
+ posStateNext = (position + lenTest + 1) & _posStateMask;
+ UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1();
+ UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();
+
+ UInt32 offset = lenTest + 1 + lenTest2;
+ while (lenEnd < cur + offset)
+ {
+ _optimum[++lenEnd].Price = kIfinityPrice;
+ }
+
+ curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
+ optimum = _optimum[cur + offset];
+ if (curAndLenPrice < optimum.Price)
+ {
+ optimum.Price = curAndLenPrice;
+ optimum.PosPrev = cur + lenTest + 1;
+ optimum.BackPrev = 0;
+ optimum.Prev1IsChar = true;
+ optimum.Prev2 = true;
+ optimum.PosPrev2 = cur;
+ optimum.BackPrev2 = curBack + Base.kNumRepDistances;
+ }
+ }
+ }
+ offs += 2;
+ if (offs == numDistancePairs)
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private bool ChangePair(UInt32 smallDist, UInt32 bigDist)
+ {
+ const int kDif = 7;
+ return smallDist < ((UInt32)1 << (32 - kDif)) && bigDist >= (smallDist << kDif);
+ }
+
+ private void WriteEndMarker(UInt32 posState)
+ {
+ if (!_writeEndMark)
+ {
+ return;
+ }
+
+ _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1);
+ _isRep[_state.Index].Encode(_rangeEncoder, 0);
+ _state.UpdateMatch();
+ const UInt32 len = Base.kMatchMinLen;
+ _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
+ const UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1;
+ UInt32 lenToPosState = Base.GetLenToPosState(len);
+ _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
+ const int footerBits = 30;
+ const UInt32 posReduced = (((UInt32)1) << footerBits) - 1;
+ _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);
+ _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);
+ }
+
+ private void Flush(UInt32 nowPos)
+ {
+ ReleaseMFStream();
+ WriteEndMarker(nowPos & _posStateMask);
+ _rangeEncoder.FlushData();
+ _rangeEncoder.FlushStream();
+ }
+
+ public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished)
+ {
+ inSize = 0;
+ outSize = 0;
+ finished = true;
+
+ if (_inStream != null)
+ {
+ _matchFinder.SetStream(_inStream);
+ _matchFinder.Init();
+ _needReleaseMFStream = true;
+ _inStream = null;
+ if (_trainSize > 0)
+ {
+ _matchFinder.Skip(_trainSize);
+ }
+ }
+
+ if (_finished)
+ {
+ return;
+ }
+
+ _finished = true;
+
+ Int64 progressPosValuePrev = nowPos64;
+ if (nowPos64 == 0)
+ {
+ if (_matchFinder.GetNumAvailableBytes() == 0)
+ {
+ Flush((UInt32)nowPos64);
+ return;
+ }
+ // it's not used
+ ReadMatchDistances(out uint len, out uint numDistancePairs);
+ UInt32 posState = (UInt32)nowPos64 & _posStateMask;
+ _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0);
+ _state.UpdateChar();
+ Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset));
+ _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte).Encode(_rangeEncoder, curByte);
+ _previousByte = curByte;
+ _additionalOffset--;
+ nowPos64++;
+ }
+ if (_matchFinder.GetNumAvailableBytes() == 0)
+ {
+ Flush((UInt32)nowPos64);
+ return;
+ }
+ while (true)
+ {
+ UInt32 len = GetOptimum((UInt32)nowPos64, out uint pos);
+
+ UInt32 posState = ((UInt32)nowPos64) & _posStateMask;
+ UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState;
+ if (len == 1 && pos == 0xFFFFFFFF)
+ {
+ _isMatch[complexState].Encode(_rangeEncoder, 0);
+ Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset));
+ LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte);
+ if (!_state.IsCharState())
+ {
+ Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset));
+ subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte);
+ }
+ else
+ {
+ subCoder.Encode(_rangeEncoder, curByte);
+ }
+
+ _previousByte = curByte;
+ _state.UpdateChar();
+ }
+ else
+ {
+ _isMatch[complexState].Encode(_rangeEncoder, 1);
+ if (pos < Base.kNumRepDistances)
+ {
+ _isRep[_state.Index].Encode(_rangeEncoder, 1);
+ if (pos == 0)
+ {
+ _isRepG0[_state.Index].Encode(_rangeEncoder, 0);
+ if (len == 1)
+ {
+ _isRep0Long[complexState].Encode(_rangeEncoder, 0);
+ }
+ else
+ {
+ _isRep0Long[complexState].Encode(_rangeEncoder, 1);
+ }
+ }
+ else
+ {
+ _isRepG0[_state.Index].Encode(_rangeEncoder, 1);
+ if (pos == 1)
+ {
+ _isRepG1[_state.Index].Encode(_rangeEncoder, 0);
+ }
+ else
+ {
+ _isRepG1[_state.Index].Encode(_rangeEncoder, 1);
+ _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2);
+ }
+ }
+ if (len == 1)
+ {
+ _state.UpdateShortRep();
+ }
+ else
+ {
+ _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
+ _state.UpdateRep();
+ }
+ UInt32 distance = _repDistances[pos];
+ if (pos != 0)
+ {
+ for (UInt32 i = pos; i >= 1; i--)
+ {
+ _repDistances[i] = _repDistances[i - 1];
+ }
+
+ _repDistances[0] = distance;
+ }
+ }
+ else
+ {
+ _isRep[_state.Index].Encode(_rangeEncoder, 0);
+ _state.UpdateMatch();
+ _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
+ pos -= Base.kNumRepDistances;
+ UInt32 posSlot = GetPosSlot(pos);
+ UInt32 lenToPosState = Base.GetLenToPosState(len);
+ _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
+
+ if (posSlot >= Base.kStartPosModelIndex)
+ {
+ int footerBits = (int)((posSlot >> 1) - 1);
+ UInt32 baseVal = (2 | (posSlot & 1)) << footerBits;
+ UInt32 posReduced = pos - baseVal;
+
+ if (posSlot < Base.kEndPosModelIndex)
+ {
+ BitTreeEncoder.ReverseEncode(_posEncoders,
+ baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced);
+ }
+ else
+ {
+ _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);
+ _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);
+ _alignPriceCount++;
+ }
+ }
+ UInt32 distance = pos;
+ for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--)
+ {
+ _repDistances[i] = _repDistances[i - 1];
+ }
+
+ _repDistances[0] = distance;
+ _matchPriceCount++;
+ }
+ _previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset));
+ }
+ _additionalOffset -= len;
+ nowPos64 += len;
+ if (_additionalOffset == 0)
+ {
+ // if (!_fastMode)
+ if (_matchPriceCount >= (1 << 7))
+ {
+ FillDistancesPrices();
+ }
+
+ if (_alignPriceCount >= Base.kAlignTableSize)
+ {
+ FillAlignPrices();
+ }
+
+ inSize = nowPos64;
+ outSize = _rangeEncoder.GetProcessedSizeAdd();
+ if (_matchFinder.GetNumAvailableBytes() == 0)
+ {
+ Flush((UInt32)nowPos64);
+ return;
+ }
+
+ if (nowPos64 - progressPosValuePrev >= (1 << 12))
+ {
+ _finished = false;
+ finished = false;
+ return;
+ }
+ }
+ }
+ }
+
+ private void ReleaseMFStream()
+ {
+ if (_matchFinder != null && _needReleaseMFStream)
+ {
+ _matchFinder.ReleaseStream();
+ _needReleaseMFStream = false;
+ }
+ }
+
+ private void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); }
+ private void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); }
+
+ private void ReleaseStreams()
+ {
+ ReleaseMFStream();
+ ReleaseOutStream();
+ }
+
+ private void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream,
+ Int64 inSize, Int64 outSize)
+ {
+ _inStream = inStream;
+ _finished = false;
+ Create();
+ SetOutStream(outStream);
+ Init();
+
+ // if (!_fastMode)
+ {
+ FillDistancesPrices();
+ FillAlignPrices();
+ }
+
+ _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);
+ _lenEncoder.UpdateTables((UInt32)1 << _posStateBits);
+ _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);
+ _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits);
+
+ nowPos64 = 0;
+ }
+
+ public void Code(System.IO.Stream inStream, System.IO.Stream outStream,
+ Int64 inSize, Int64 outSize, ICodeProgress progress, CancellationToken? token = null)
+ {
+ _needReleaseMFStream = false;
+ try
+ {
+ SetStreams(inStream, outStream, inSize, outSize);
+ while (true)
+ {
+ token?.ThrowIfCancellationRequested();
+ CodeOneBlock(out long processedInSize, out long processedOutSize, out bool finished);
+ if (finished)
+ {
+ return;
+ }
+
+ progress?.SetProgress(processedInSize, processedOutSize);
+ }
+ }
+ finally
+ {
+ ReleaseStreams();
+ }
+ }
+
+ private const int kPropSize = 5;
+ private readonly Byte[] properties = new Byte[kPropSize];
+
+ public void WriteCoderProperties(System.IO.Stream outStream)
+ {
+ properties[0] = (Byte)((((_posStateBits * 5) + _numLiteralPosStateBits) * 9) + _numLiteralContextBits);
+ for (int i = 0; i < 4; i++)
+ {
+ properties[1 + i] = (Byte)((_dictionarySize >> (8 * i)) & 0xFF);
+ }
+
+ outStream.Write(properties, 0, kPropSize);
+ }
+
+ private readonly UInt32[] tempPrices = new UInt32[Base.kNumFullDistances];
+ private UInt32 _matchPriceCount;
+
+ private void FillDistancesPrices()
+ {
+ for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++)
+ {
+ UInt32 posSlot = GetPosSlot(i);
+ int footerBits = (int)((posSlot >> 1) - 1);
+ UInt32 baseVal = (2 | (posSlot & 1)) << footerBits;
+ tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders,
+ baseVal - posSlot - 1, footerBits, i - baseVal);
+ }
+
+ for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++)
+ {
+ UInt32 posSlot;
+ BitTreeEncoder encoder = _posSlotEncoder[lenToPosState];
+
+ UInt32 st = lenToPosState << Base.kNumPosSlotBits;
+ for (posSlot = 0; posSlot < _distTableSize; posSlot++)
+ {
+ _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot);
+ }
+
+ for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++)
+ {
+ _posSlotPrices[st + posSlot] += ((posSlot >> 1) - 1 - Base.kNumAlignBits) << BitEncoder.kNumBitPriceShiftBits;
+ }
+
+ UInt32 st2 = lenToPosState * Base.kNumFullDistances;
+ UInt32 i;
+ for (i = 0; i < Base.kStartPosModelIndex; i++)
+ {
+ _distancesPrices[st2 + i] = _posSlotPrices[st + i];
+ }
+
+ for (; i < Base.kNumFullDistances; i++)
+ {
+ _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i];
+ }
+ }
+ _matchPriceCount = 0;
+ }
+
+ private void FillAlignPrices()
+ {
+ for (UInt32 i = 0; i < Base.kAlignTableSize; i++)
+ {
+ _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);
+ }
+
+ _alignPriceCount = 0;
+ }
+
+ private static readonly string[] kMatchFinderIDs =
+ {
+ "BT2",
+ "BT4",
+ };
+
+ private static int FindMatchFinder(string s)
+ {
+ for (int m = 0; m < kMatchFinderIDs.Length; m++)
+ {
+ if (s == kMatchFinderIDs[m])
+ {
+ return m;
+ }
+ }
+
+ return -1;
+ }
+
+ public void SetCoderProperties(CoderPropID[] propIDs, object[] properties)
+ {
+ for (UInt32 i = 0; i < properties.Length; i++)
+ {
+ object prop = properties[i];
+ switch (propIDs[i])
+ {
+ case CoderPropID.NumFastBytes:
+ {
+ if (!(prop is Int32))
+ {
+ throw new InvalidParamException();
+ }
+
+ Int32 numFastBytes = (Int32)prop;
+ if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen)
+ {
+ throw new InvalidParamException();
+ }
+
+ _numFastBytes = (UInt32)numFastBytes;
+ break;
+ }
+ case CoderPropID.Algorithm:
+ {
+ /*
+ if (!(prop is Int32))
+ throw new InvalidParamException();
+ Int32 maximize = (Int32)prop;
+ _fastMode = (maximize == 0);
+ _maxMode = (maximize >= 2);
+ */
+ break;
+ }
+ case CoderPropID.MatchFinder:
+ {
+ if (!(prop is String))
+ {
+ throw new InvalidParamException();
+ }
+
+ EMatchFinderType matchFinderIndexPrev = _matchFinderType;
+ int m = FindMatchFinder(((string)prop).ToUpper());
+ if (m < 0)
+ {
+ throw new InvalidParamException();
+ }
+
+ _matchFinderType = (EMatchFinderType)m;
+ if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType)
+ {
+ _dictionarySizePrev = 0xFFFFFFFF;
+ _matchFinder = null;
+ }
+ break;
+ }
+ case CoderPropID.DictionarySize:
+ {
+ const int kDicLogSizeMaxCompress = 30;
+ if (!(prop is Int32))
+ {
+ throw new InvalidParamException();
+ }
+ Int32 dictionarySize = (Int32)prop;
+ if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) ||
+ dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress))
+ {
+ throw new InvalidParamException();
+ }
+
+ _dictionarySize = (UInt32)dictionarySize;
+ int dicLogSize;
+ for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++)
+ {
+ if (dictionarySize <= ((UInt32)1 << dicLogSize))
+ {
+ break;
+ }
+ }
+
+ _distTableSize = (UInt32)dicLogSize * 2;
+ break;
+ }
+ case CoderPropID.PosStateBits:
+ {
+ if (!(prop is Int32))
+ {
+ throw new InvalidParamException();
+ }
+
+ Int32 v = (Int32)prop;
+ if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax)
+ {
+ throw new InvalidParamException();
+ }
+
+ _posStateBits = v;
+ _posStateMask = (((UInt32)1) << _posStateBits) - 1;
+ break;
+ }
+ case CoderPropID.LitPosBits:
+ {
+ if (!(prop is Int32))
+ {
+ throw new InvalidParamException();
+ }
+
+ Int32 v = (Int32)prop;
+ if (v < 0 || v > Base.kNumLitPosStatesBitsEncodingMax)
+ {
+ throw new InvalidParamException();
+ }
+
+ _numLiteralPosStateBits = v;
+ break;
+ }
+ case CoderPropID.LitContextBits:
+ {
+ if (!(prop is Int32))
+ {
+ throw new InvalidParamException();
+ }
+
+ Int32 v = (Int32)prop;
+ if (v < 0 || v > Base.kNumLitContextBitsMax)
+ {
+ throw new InvalidParamException();
+ }
+ _numLiteralContextBits = v;
+ break;
+ }
+ case CoderPropID.EndMarker:
+ {
+ if (!(prop is Boolean))
+ {
+ throw new InvalidParamException();
+ }
+
+ SetWriteEndMarkerMode((Boolean)prop);
+ break;
+ }
+ default:
+ throw new InvalidParamException();
+ }
+ }
+ }
+
+ private uint _trainSize = 0;
+ public void SetTrainSize(uint trainSize)
+ {
+ _trainSize = trainSize;
+ }
+ }
+}
diff --git a/7zip/Compress/RangeCoder/RangeCoder.cs b/WPinternals/7zip/Compress/RangeCoder/RangeCoder.cs
similarity index 95%
rename from 7zip/Compress/RangeCoder/RangeCoder.cs
rename to WPinternals/7zip/Compress/RangeCoder/RangeCoder.cs
index 9b5d50d..5e57e11 100644
--- a/7zip/Compress/RangeCoder/RangeCoder.cs
+++ b/WPinternals/7zip/Compress/RangeCoder/RangeCoder.cs
@@ -1,243 +1,243 @@
-using System;
-
-namespace SevenZip.Compression.RangeCoder
-{
- internal class Encoder
- {
- public const uint kTopValue = 1 << 24;
-
- private System.IO.Stream Stream;
-
- public UInt64 Low;
- public uint Range;
- private uint _cacheSize;
- private byte _cache;
-
- private long StartPosition;
-
- public void SetStream(System.IO.Stream stream)
- {
- Stream = stream;
- }
-
- public void ReleaseStream()
- {
- Stream = null;
- }
-
- public void Init()
- {
- StartPosition = Stream.Position;
-
- Low = 0;
- Range = 0xFFFFFFFF;
- _cacheSize = 1;
- _cache = 0;
- }
-
- public void FlushData()
- {
- for (int i = 0; i < 5; i++)
- {
- ShiftLow();
- }
- }
-
- public void FlushStream()
- {
- Stream.Flush();
- }
-
- public void CloseStream()
- {
- Stream.Close();
- }
-
- public void Encode(uint start, uint size, uint total)
- {
- Low += start * (Range /= total);
- Range *= size;
- while (Range < kTopValue)
- {
- Range <<= 8;
- ShiftLow();
- }
- }
-
- public void ShiftLow()
- {
- if ((uint)Low < 0xFF000000 || (uint)(Low >> 32) == 1)
- {
- byte temp = _cache;
- do
- {
- Stream.WriteByte((byte)(temp + (Low >> 32)));
- temp = 0xFF;
- }
- while (--_cacheSize != 0);
- _cache = (byte)(((uint)Low) >> 24);
- }
- _cacheSize++;
- Low = ((uint)Low) << 8;
- }
-
- public void EncodeDirectBits(uint v, int numTotalBits)
- {
- for (int i = numTotalBits - 1; i >= 0; i--)
- {
- Range >>= 1;
- if (((v >> i) & 1) == 1)
- {
- Low += Range;
- }
-
- if (Range < kTopValue)
- {
- Range <<= 8;
- ShiftLow();
- }
- }
- }
-
- public void EncodeBit(uint size0, int numTotalBits, uint symbol)
- {
- uint newBound = (Range >> numTotalBits) * size0;
- if (symbol == 0)
- {
- Range = newBound;
- }
- else
- {
- Low += newBound;
- Range -= newBound;
- }
- while (Range < kTopValue)
- {
- Range <<= 8;
- ShiftLow();
- }
- }
-
- public long GetProcessedSizeAdd()
- {
- return _cacheSize +
- Stream.Position - StartPosition + 4;
- // (long)Stream.GetProcessedSize();
- }
- }
-
- internal class Decoder
- {
- public const uint kTopValue = 1 << 24;
- public uint Range;
- public uint Code;
- // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16);
- public System.IO.Stream Stream;
-
- public void Init(System.IO.Stream stream)
- {
- // Stream.Init(stream);
- Stream = stream;
-
- Code = 0;
- Range = 0xFFFFFFFF;
- for (int i = 0; i < 5; i++)
- {
- Code = (Code << 8) | (byte)Stream.ReadByte();
- }
- }
-
- public void ReleaseStream()
- {
- // Stream.ReleaseStream();
- Stream = null;
- }
-
- public void CloseStream()
- {
- Stream.Close();
- }
-
- public void Normalize()
- {
- while (Range < kTopValue)
- {
- Code = (Code << 8) | (byte)Stream.ReadByte();
- Range <<= 8;
- }
- }
-
- public void Normalize2()
- {
- if (Range < kTopValue)
- {
- Code = (Code << 8) | (byte)Stream.ReadByte();
- Range <<= 8;
- }
- }
-
- public uint GetThreshold(uint total)
- {
- return Code / (Range /= total);
- }
-
- public void Decode(uint start, uint size, uint total)
- {
- Code -= start * Range;
- Range *= size;
- Normalize();
- }
-
- public uint DecodeDirectBits(int numTotalBits)
- {
- uint range = Range;
- uint code = Code;
- uint result = 0;
- for (int i = numTotalBits; i > 0; i--)
- {
- range >>= 1;
- /*
- result <<= 1;
- if (code >= range)
- {
- code -= range;
- result |= 1;
- }
- */
- uint t = (code - range) >> 31;
- code -= range & (t - 1);
- result = (result << 1) | (1 - t);
-
- if (range < kTopValue)
- {
- code = (code << 8) | (byte)Stream.ReadByte();
- range <<= 8;
- }
- }
- Range = range;
- Code = code;
- return result;
- }
-
- public uint DecodeBit(uint size0, int numTotalBits)
- {
- uint newBound = (Range >> numTotalBits) * size0;
- uint symbol;
- if (Code < newBound)
- {
- symbol = 0;
- Range = newBound;
- }
- else
- {
- symbol = 1;
- Code -= newBound;
- Range -= newBound;
- }
- Normalize();
- return symbol;
- }
-
- // ulong GetProcessedSize() {return Stream.GetProcessedSize(); }
- }
-}
+using System;
+
+namespace SevenZip.Compression.RangeCoder
+{
+ internal class Encoder
+ {
+ public const uint kTopValue = 1 << 24;
+
+ private System.IO.Stream Stream;
+
+ public UInt64 Low;
+ public uint Range;
+ private uint _cacheSize;
+ private byte _cache;
+
+ private long StartPosition;
+
+ public void SetStream(System.IO.Stream stream)
+ {
+ Stream = stream;
+ }
+
+ public void ReleaseStream()
+ {
+ Stream = null;
+ }
+
+ public void Init()
+ {
+ StartPosition = Stream.Position;
+
+ Low = 0;
+ Range = 0xFFFFFFFF;
+ _cacheSize = 1;
+ _cache = 0;
+ }
+
+ public void FlushData()
+ {
+ for (int i = 0; i < 5; i++)
+ {
+ ShiftLow();
+ }
+ }
+
+ public void FlushStream()
+ {
+ Stream.Flush();
+ }
+
+ public void CloseStream()
+ {
+ Stream.Close();
+ }
+
+ public void Encode(uint start, uint size, uint total)
+ {
+ Low += start * (Range /= total);
+ Range *= size;
+ while (Range < kTopValue)
+ {
+ Range <<= 8;
+ ShiftLow();
+ }
+ }
+
+ public void ShiftLow()
+ {
+ if ((uint)Low < 0xFF000000 || (uint)(Low >> 32) == 1)
+ {
+ byte temp = _cache;
+ do
+ {
+ Stream.WriteByte((byte)(temp + (Low >> 32)));
+ temp = 0xFF;
+ }
+ while (--_cacheSize != 0);
+ _cache = (byte)(((uint)Low) >> 24);
+ }
+ _cacheSize++;
+ Low = ((uint)Low) << 8;
+ }
+
+ public void EncodeDirectBits(uint v, int numTotalBits)
+ {
+ for (int i = numTotalBits - 1; i >= 0; i--)
+ {
+ Range >>= 1;
+ if (((v >> i) & 1) == 1)
+ {
+ Low += Range;
+ }
+
+ if (Range < kTopValue)
+ {
+ Range <<= 8;
+ ShiftLow();
+ }
+ }
+ }
+
+ public void EncodeBit(uint size0, int numTotalBits, uint symbol)
+ {
+ uint newBound = (Range >> numTotalBits) * size0;
+ if (symbol == 0)
+ {
+ Range = newBound;
+ }
+ else
+ {
+ Low += newBound;
+ Range -= newBound;
+ }
+ while (Range < kTopValue)
+ {
+ Range <<= 8;
+ ShiftLow();
+ }
+ }
+
+ public long GetProcessedSizeAdd()
+ {
+ return _cacheSize +
+ Stream.Position - StartPosition + 4;
+ // (long)Stream.GetProcessedSize();
+ }
+ }
+
+ internal class Decoder
+ {
+ public const uint kTopValue = 1 << 24;
+ public uint Range;
+ public uint Code;
+ // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16);
+ public System.IO.Stream Stream;
+
+ public void Init(System.IO.Stream stream)
+ {
+ // Stream.Init(stream);
+ Stream = stream;
+
+ Code = 0;
+ Range = 0xFFFFFFFF;
+ for (int i = 0; i < 5; i++)
+ {
+ Code = (Code << 8) | (byte)Stream.ReadByte();
+ }
+ }
+
+ public void ReleaseStream()
+ {
+ // Stream.ReleaseStream();
+ Stream = null;
+ }
+
+ public void CloseStream()
+ {
+ Stream.Close();
+ }
+
+ public void Normalize()
+ {
+ while (Range < kTopValue)
+ {
+ Code = (Code << 8) | (byte)Stream.ReadByte();
+ Range <<= 8;
+ }
+ }
+
+ public void Normalize2()
+ {
+ if (Range < kTopValue)
+ {
+ Code = (Code << 8) | (byte)Stream.ReadByte();
+ Range <<= 8;
+ }
+ }
+
+ public uint GetThreshold(uint total)
+ {
+ return Code / (Range /= total);
+ }
+
+ public void Decode(uint start, uint size, uint total)
+ {
+ Code -= start * Range;
+ Range *= size;
+ Normalize();
+ }
+
+ public uint DecodeDirectBits(int numTotalBits)
+ {
+ uint range = Range;
+ uint code = Code;
+ uint result = 0;
+ for (int i = numTotalBits; i > 0; i--)
+ {
+ range >>= 1;
+ /*
+ result <<= 1;
+ if (code >= range)
+ {
+ code -= range;
+ result |= 1;
+ }
+ */
+ uint t = (code - range) >> 31;
+ code -= range & (t - 1);
+ result = (result << 1) | (1 - t);
+
+ if (range < kTopValue)
+ {
+ code = (code << 8) | (byte)Stream.ReadByte();
+ range <<= 8;
+ }
+ }
+ Range = range;
+ Code = code;
+ return result;
+ }
+
+ public uint DecodeBit(uint size0, int numTotalBits)
+ {
+ uint newBound = (Range >> numTotalBits) * size0;
+ uint symbol;
+ if (Code < newBound)
+ {
+ symbol = 0;
+ Range = newBound;
+ }
+ else
+ {
+ symbol = 1;
+ Code -= newBound;
+ Range -= newBound;
+ }
+ Normalize();
+ return symbol;
+ }
+
+ // ulong GetProcessedSize() {return Stream.GetProcessedSize(); }
+ }
+}
diff --git a/7zip/Compress/RangeCoder/RangeCoderBit.cs b/WPinternals/7zip/Compress/RangeCoder/RangeCoderBit.cs
similarity index 97%
rename from 7zip/Compress/RangeCoder/RangeCoderBit.cs
rename to WPinternals/7zip/Compress/RangeCoder/RangeCoderBit.cs
index d7162f8..aee96b6 100644
--- a/7zip/Compress/RangeCoder/RangeCoderBit.cs
+++ b/WPinternals/7zip/Compress/RangeCoder/RangeCoderBit.cs
@@ -1,127 +1,127 @@
-using System;
-
-namespace SevenZip.Compression.RangeCoder
-{
- internal struct BitEncoder
- {
- public const int kNumBitModelTotalBits = 11;
- public const uint kBitModelTotal = 1 << kNumBitModelTotalBits;
- private const int kNumMoveBits = 5;
- private const int kNumMoveReducingBits = 2;
- public const int kNumBitPriceShiftBits = 6;
-
- private uint Prob;
-
- public void Init() { Prob = kBitModelTotal >> 1; }
-
- public void UpdateModel(uint symbol)
- {
- if (symbol == 0)
- {
- Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
- }
- else
- {
- Prob -= Prob >> kNumMoveBits;
- }
- }
-
- public void Encode(Encoder encoder, uint symbol)
- {
- // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol);
- // UpdateModel(symbol);
- uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob;
- if (symbol == 0)
- {
- encoder.Range = newBound;
- Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
- }
- else
- {
- encoder.Low += newBound;
- encoder.Range -= newBound;
- Prob -= Prob >> kNumMoveBits;
- }
- if (encoder.Range < Encoder.kTopValue)
- {
- encoder.Range <<= 8;
- encoder.ShiftLow();
- }
- }
-
- private static readonly UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits];
-
- static BitEncoder()
- {
- const int kNumBits = kNumBitModelTotalBits - kNumMoveReducingBits;
- for (int i = kNumBits - 1; i >= 0; i--)
- {
- UInt32 start = (UInt32)1 << (kNumBits - i - 1);
- UInt32 end = (UInt32)1 << (kNumBits - i);
- for (UInt32 j = start; j < end; j++)
- {
- ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) +
- (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1));
- }
- }
- }
-
- public uint GetPrice(uint symbol)
- {
- return ProbPrices[(((Prob - symbol) ^ (-(int)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];
- }
- public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; }
- public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; }
- }
-
- internal struct BitDecoder
- {
- public const int kNumBitModelTotalBits = 11;
- public const uint kBitModelTotal = 1 << kNumBitModelTotalBits;
- private const int kNumMoveBits = 5;
-
- private uint Prob;
-
- public void UpdateModel(int numMoveBits, uint symbol)
- {
- if (symbol == 0)
- {
- Prob += (kBitModelTotal - Prob) >> numMoveBits;
- }
- else
- {
- Prob -= Prob >> numMoveBits;
- }
- }
-
- public void Init() { Prob = kBitModelTotal >> 1; }
-
- public uint Decode(Decoder rangeDecoder)
- {
- uint newBound = (rangeDecoder.Range >> kNumBitModelTotalBits) * Prob;
- if (rangeDecoder.Code < newBound)
- {
- rangeDecoder.Range = newBound;
- Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
- if (rangeDecoder.Range < Decoder.kTopValue)
- {
- rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
- rangeDecoder.Range <<= 8;
- }
- return 0;
- }
- else
- {
- rangeDecoder.Range -= newBound;
- rangeDecoder.Code -= newBound;
- Prob -= Prob >> kNumMoveBits;
- if (rangeDecoder.Range < Decoder.kTopValue)
- {
- rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
- rangeDecoder.Range <<= 8;
- }
- return 1;
- }
- }
- }
-}
+using System;
+
+namespace SevenZip.Compression.RangeCoder
+{
+ internal struct BitEncoder
+ {
+ public const int kNumBitModelTotalBits = 11;
+ public const uint kBitModelTotal = 1 << kNumBitModelTotalBits;
+ private const int kNumMoveBits = 5;
+ private const int kNumMoveReducingBits = 2;
+ public const int kNumBitPriceShiftBits = 6;
+
+ private uint Prob;
+
+ public void Init() { Prob = kBitModelTotal >> 1; }
+
+ public void UpdateModel(uint symbol)
+ {
+ if (symbol == 0)
+ {
+ Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
+ }
+ else
+ {
+ Prob -= Prob >> kNumMoveBits;
+ }
+ }
+
+ public void Encode(Encoder encoder, uint symbol)
+ {
+ // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol);
+ // UpdateModel(symbol);
+ uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob;
+ if (symbol == 0)
+ {
+ encoder.Range = newBound;
+ Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
+ }
+ else
+ {
+ encoder.Low += newBound;
+ encoder.Range -= newBound;
+ Prob -= Prob >> kNumMoveBits;
+ }
+ if (encoder.Range < Encoder.kTopValue)
+ {
+ encoder.Range <<= 8;
+ encoder.ShiftLow();
+ }
+ }
+
+ private static readonly UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits];
+
+ static BitEncoder()
+ {
+ const int kNumBits = kNumBitModelTotalBits - kNumMoveReducingBits;
+ for (int i = kNumBits - 1; i >= 0; i--)
+ {
+ UInt32 start = (UInt32)1 << (kNumBits - i - 1);
+ UInt32 end = (UInt32)1 << (kNumBits - i);
+ for (UInt32 j = start; j < end; j++)
+ {
+ ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) +
+ (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1));
+ }
+ }
+ }
+
+ public uint GetPrice(uint symbol)
+ {
+ return ProbPrices[(((Prob - symbol) ^ (-(int)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];
+ }
+ public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; }
+ public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; }
+ }
+
+ internal struct BitDecoder
+ {
+ public const int kNumBitModelTotalBits = 11;
+ public const uint kBitModelTotal = 1 << kNumBitModelTotalBits;
+ private const int kNumMoveBits = 5;
+
+ private uint Prob;
+
+ public void UpdateModel(int numMoveBits, uint symbol)
+ {
+ if (symbol == 0)
+ {
+ Prob += (kBitModelTotal - Prob) >> numMoveBits;
+ }
+ else
+ {
+ Prob -= Prob >> numMoveBits;
+ }
+ }
+
+ public void Init() { Prob = kBitModelTotal >> 1; }
+
+ public uint Decode(Decoder rangeDecoder)
+ {
+ uint newBound = (rangeDecoder.Range >> kNumBitModelTotalBits) * Prob;
+ if (rangeDecoder.Code < newBound)
+ {
+ rangeDecoder.Range = newBound;
+ Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
+ if (rangeDecoder.Range < Decoder.kTopValue)
+ {
+ rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
+ rangeDecoder.Range <<= 8;
+ }
+ return 0;
+ }
+ else
+ {
+ rangeDecoder.Range -= newBound;
+ rangeDecoder.Code -= newBound;
+ Prob -= Prob >> kNumMoveBits;
+ if (rangeDecoder.Range < Decoder.kTopValue)
+ {
+ rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
+ rangeDecoder.Range <<= 8;
+ }
+ return 1;
+ }
+ }
+ }
+}
diff --git a/7zip/Compress/RangeCoder/RangeCoderBitTree.cs b/WPinternals/7zip/Compress/RangeCoder/RangeCoderBitTree.cs
similarity index 96%
rename from 7zip/Compress/RangeCoder/RangeCoderBitTree.cs
rename to WPinternals/7zip/Compress/RangeCoder/RangeCoderBitTree.cs
index a98084b..15b2750 100644
--- a/7zip/Compress/RangeCoder/RangeCoderBitTree.cs
+++ b/WPinternals/7zip/Compress/RangeCoder/RangeCoderBitTree.cs
@@ -1,164 +1,164 @@
-using System;
-
-namespace SevenZip.Compression.RangeCoder
-{
- internal struct BitTreeEncoder
- {
- private readonly BitEncoder[] Models;
- private readonly int NumBitLevels;
-
- public BitTreeEncoder(int numBitLevels)
- {
- NumBitLevels = numBitLevels;
- Models = new BitEncoder[1 << numBitLevels];
- }
-
- public void Init()
- {
- for (uint i = 1; i < (1 << NumBitLevels); i++)
- {
- Models[i].Init();
- }
- }
-
- public void Encode(Encoder rangeEncoder, UInt32 symbol)
- {
- UInt32 m = 1;
- for (int bitIndex = NumBitLevels; bitIndex > 0;)
- {
- bitIndex--;
- UInt32 bit = (symbol >> bitIndex) & 1;
- Models[m].Encode(rangeEncoder, bit);
- m = (m << 1) | bit;
- }
- }
-
- public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol)
- {
- UInt32 m = 1;
- for (UInt32 i = 0; i < NumBitLevels; i++)
- {
- UInt32 bit = symbol & 1;
- Models[m].Encode(rangeEncoder, bit);
- m = (m << 1) | bit;
- symbol >>= 1;
- }
- }
-
- public UInt32 GetPrice(UInt32 symbol)
- {
- UInt32 price = 0;
- UInt32 m = 1;
- for (int bitIndex = NumBitLevels; bitIndex > 0;)
- {
- bitIndex--;
- UInt32 bit = (symbol >> bitIndex) & 1;
- price += Models[m].GetPrice(bit);
- m = (m << 1) + bit;
- }
- return price;
- }
-
- public UInt32 ReverseGetPrice(UInt32 symbol)
- {
- UInt32 price = 0;
- UInt32 m = 1;
- for (int i = NumBitLevels; i > 0; i--)
- {
- UInt32 bit = symbol & 1;
- symbol >>= 1;
- price += Models[m].GetPrice(bit);
- m = (m << 1) | bit;
- }
- return price;
- }
-
- public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex,
- int NumBitLevels, UInt32 symbol)
- {
- UInt32 price = 0;
- UInt32 m = 1;
- for (int i = NumBitLevels; i > 0; i--)
- {
- UInt32 bit = symbol & 1;
- symbol >>= 1;
- price += Models[startIndex + m].GetPrice(bit);
- m = (m << 1) | bit;
- }
- return price;
- }
-
- public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex,
- Encoder rangeEncoder, int NumBitLevels, UInt32 symbol)
- {
- UInt32 m = 1;
- for (int i = 0; i < NumBitLevels; i++)
- {
- UInt32 bit = symbol & 1;
- Models[startIndex + m].Encode(rangeEncoder, bit);
- m = (m << 1) | bit;
- symbol >>= 1;
- }
- }
- }
-
- internal struct BitTreeDecoder
- {
- private readonly BitDecoder[] Models;
- private readonly int NumBitLevels;
-
- public BitTreeDecoder(int numBitLevels)
- {
- NumBitLevels = numBitLevels;
- Models = new BitDecoder[1 << numBitLevels];
- }
-
- public void Init()
- {
- for (uint i = 1; i < (1 << NumBitLevels); i++)
- {
- Models[i].Init();
- }
- }
-
- public uint Decode(Decoder rangeDecoder)
- {
- uint m = 1;
- for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--)
- {
- m = (m << 1) + Models[m].Decode(rangeDecoder);
- }
-
- return m - ((uint)1 << NumBitLevels);
- }
-
- public uint ReverseDecode(Decoder rangeDecoder)
- {
- uint m = 1;
- uint symbol = 0;
- for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
- {
- uint bit = Models[m].Decode(rangeDecoder);
- m <<= 1;
- m += bit;
- symbol |= bit << bitIndex;
- }
- return symbol;
- }
-
- public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex,
- Decoder rangeDecoder, int NumBitLevels)
- {
- uint m = 1;
- uint symbol = 0;
- for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
- {
- uint bit = Models[startIndex + m].Decode(rangeDecoder);
- m <<= 1;
- m += bit;
- symbol |= bit << bitIndex;
- }
- return symbol;
- }
- }
-}
+using System;
+
+namespace SevenZip.Compression.RangeCoder
+{
+ internal struct BitTreeEncoder
+ {
+ private readonly BitEncoder[] Models;
+ private readonly int NumBitLevels;
+
+ public BitTreeEncoder(int numBitLevels)
+ {
+ NumBitLevels = numBitLevels;
+ Models = new BitEncoder[1 << numBitLevels];
+ }
+
+ public void Init()
+ {
+ for (uint i = 1; i < (1 << NumBitLevels); i++)
+ {
+ Models[i].Init();
+ }
+ }
+
+ public void Encode(Encoder rangeEncoder, UInt32 symbol)
+ {
+ UInt32 m = 1;
+ for (int bitIndex = NumBitLevels; bitIndex > 0;)
+ {
+ bitIndex--;
+ UInt32 bit = (symbol >> bitIndex) & 1;
+ Models[m].Encode(rangeEncoder, bit);
+ m = (m << 1) | bit;
+ }
+ }
+
+ public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol)
+ {
+ UInt32 m = 1;
+ for (UInt32 i = 0; i < NumBitLevels; i++)
+ {
+ UInt32 bit = symbol & 1;
+ Models[m].Encode(rangeEncoder, bit);
+ m = (m << 1) | bit;
+ symbol >>= 1;
+ }
+ }
+
+ public UInt32 GetPrice(UInt32 symbol)
+ {
+ UInt32 price = 0;
+ UInt32 m = 1;
+ for (int bitIndex = NumBitLevels; bitIndex > 0;)
+ {
+ bitIndex--;
+ UInt32 bit = (symbol >> bitIndex) & 1;
+ price += Models[m].GetPrice(bit);
+ m = (m << 1) + bit;
+ }
+ return price;
+ }
+
+ public UInt32 ReverseGetPrice(UInt32 symbol)
+ {
+ UInt32 price = 0;
+ UInt32 m = 1;
+ for (int i = NumBitLevels; i > 0; i--)
+ {
+ UInt32 bit = symbol & 1;
+ symbol >>= 1;
+ price += Models[m].GetPrice(bit);
+ m = (m << 1) | bit;
+ }
+ return price;
+ }
+
+ public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex,
+ int NumBitLevels, UInt32 symbol)
+ {
+ UInt32 price = 0;
+ UInt32 m = 1;
+ for (int i = NumBitLevels; i > 0; i--)
+ {
+ UInt32 bit = symbol & 1;
+ symbol >>= 1;
+ price += Models[startIndex + m].GetPrice(bit);
+ m = (m << 1) | bit;
+ }
+ return price;
+ }
+
+ public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex,
+ Encoder rangeEncoder, int NumBitLevels, UInt32 symbol)
+ {
+ UInt32 m = 1;
+ for (int i = 0; i < NumBitLevels; i++)
+ {
+ UInt32 bit = symbol & 1;
+ Models[startIndex + m].Encode(rangeEncoder, bit);
+ m = (m << 1) | bit;
+ symbol >>= 1;
+ }
+ }
+ }
+
+ internal struct BitTreeDecoder
+ {
+ private readonly BitDecoder[] Models;
+ private readonly int NumBitLevels;
+
+ public BitTreeDecoder(int numBitLevels)
+ {
+ NumBitLevels = numBitLevels;
+ Models = new BitDecoder[1 << numBitLevels];
+ }
+
+ public void Init()
+ {
+ for (uint i = 1; i < (1 << NumBitLevels); i++)
+ {
+ Models[i].Init();
+ }
+ }
+
+ public uint Decode(Decoder rangeDecoder)
+ {
+ uint m = 1;
+ for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--)
+ {
+ m = (m << 1) + Models[m].Decode(rangeDecoder);
+ }
+
+ return m - ((uint)1 << NumBitLevels);
+ }
+
+ public uint ReverseDecode(Decoder rangeDecoder)
+ {
+ uint m = 1;
+ uint symbol = 0;
+ for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
+ {
+ uint bit = Models[m].Decode(rangeDecoder);
+ m <<= 1;
+ m += bit;
+ symbol |= bit << bitIndex;
+ }
+ return symbol;
+ }
+
+ public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex,
+ Decoder rangeDecoder, int NumBitLevels)
+ {
+ uint m = 1;
+ uint symbol = 0;
+ for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
+ {
+ uint bit = Models[startIndex + m].Decode(rangeDecoder);
+ m <<= 1;
+ m += bit;
+ symbol |= bit << bitIndex;
+ }
+ return symbol;
+ }
+ }
+}
diff --git a/7zip/ICoder.cs b/WPinternals/7zip/ICoder.cs
similarity index 96%
rename from 7zip/ICoder.cs
rename to WPinternals/7zip/ICoder.cs
index 5a09466..ac070a8 100644
--- a/7zip/ICoder.cs
+++ b/WPinternals/7zip/ICoder.cs
@@ -1,173 +1,173 @@
-// ICoder.h
-
-using System;
-using System.Threading;
-
-namespace SevenZip
-{
- ///
- /// The exception that is thrown when an error in input stream occurs during decoding.
- ///
- internal class DataErrorException : ApplicationException
- {
- public DataErrorException() : base("Data Error") { }
-
- public DataErrorException(string message) : base(message)
- {
- }
-
- public DataErrorException(string message, Exception innerException) : base(message, innerException)
- {
- }
- }
-
- ///
- /// The exception that is thrown when the value of an argument is outside the allowable range.
- ///
- internal class InvalidParamException : ApplicationException
- {
- public InvalidParamException() : base("Invalid Parameter") { }
-
- public InvalidParamException(string message) : base(message)
- {
- }
-
- public InvalidParamException(string message, Exception innerException) : base(message, innerException)
- {
- }
- }
-
- public interface ICodeProgress
- {
- ///
- /// Callback progress.
- ///
- ///
- /// input size. -1 if unknown.
- ///
- ///
- /// output size. -1 if unknown.
- ///
- void SetProgress(Int64 inSize, Int64 outSize);
- };
-
- public interface ICoder
- {
- ///
- /// Codes streams.
- ///
- ///
- /// input Stream.
- ///
- ///
- /// output Stream.
- ///
- ///
- /// input Size. -1 if unknown.
- ///
- ///
- /// output Size. -1 if unknown.
- ///
- ///
- /// callback progress reference.
- ///
- ///
- /// if input stream is not valid
- ///
- void Code(System.IO.Stream inStream, System.IO.Stream outStream,
- Int64 inSize, Int64 outSize, ICodeProgress progress, CancellationToken? token = null);
- };
-
- /*
- public interface ICoder2
- {
- void Code(ISequentialInStream []inStreams,
- const UInt64 []inSizes,
- ISequentialOutStream []outStreams,
- UInt64 []outSizes,
- ICodeProgress progress);
- };
- */
-
- ///
- /// Provides the fields that represent properties idenitifiers for compressing.
- ///
- public enum CoderPropID
- {
- ///
- /// Specifies default property.
- ///
- DefaultProp = 0,
- ///
- /// Specifies size of dictionary.
- ///
- DictionarySize,
- ///
- /// Specifies size of memory for PPM*.
- ///
- UsedMemorySize,
- ///
- /// Specifies order for PPM methods.
- ///
- Order,
- ///
- /// Specifies Block Size.
- ///
- BlockSize,
- ///
- /// Specifies number of postion state bits for LZMA (0 <= x <= 4).
- ///
- PosStateBits,
- ///
- /// Specifies number of literal context bits for LZMA (0 <= x <= 8).
- ///
- LitContextBits,
- ///
- /// Specifies number of literal position bits for LZMA (0 <= x <= 4).
- ///
- LitPosBits,
- ///
- /// Specifies number of fast bytes for LZ*.
- ///
- NumFastBytes,
- ///
- /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B".
- ///
- MatchFinder,
- ///
- /// Specifies the number of match finder cyckes.
- ///
- MatchFinderCycles,
- ///
- /// Specifies number of passes.
- ///
- NumPasses,
- ///
- /// Specifies number of algorithm.
- ///
- Algorithm,
- ///
- /// Specifies the number of threads.
- ///
- NumThreads,
- ///
- /// Specifies mode with end marker.
- ///
- EndMarker
- };
-
- public interface ISetCoderProperties
- {
- void SetCoderProperties(CoderPropID[] propIDs, object[] properties);
- };
-
- public interface IWriteCoderProperties
- {
- void WriteCoderProperties(System.IO.Stream outStream);
- }
-
- public interface ISetDecoderProperties
- {
- void SetDecoderProperties(byte[] properties);
- }
-}
+// ICoder.h
+
+using System;
+using System.Threading;
+
+namespace SevenZip
+{
+ ///
+ /// The exception that is thrown when an error in input stream occurs during decoding.
+ ///
+ internal class DataErrorException : ApplicationException
+ {
+ public DataErrorException() : base("Data Error") { }
+
+ public DataErrorException(string message) : base(message)
+ {
+ }
+
+ public DataErrorException(string message, Exception innerException) : base(message, innerException)
+ {
+ }
+ }
+
+ ///
+ /// The exception that is thrown when the value of an argument is outside the allowable range.
+ ///
+ internal class InvalidParamException : ApplicationException
+ {
+ public InvalidParamException() : base("Invalid Parameter") { }
+
+ public InvalidParamException(string message) : base(message)
+ {
+ }
+
+ public InvalidParamException(string message, Exception innerException) : base(message, innerException)
+ {
+ }
+ }
+
+ public interface ICodeProgress
+ {
+ ///
+ /// Callback progress.
+ ///
+ ///
+ /// input size. -1 if unknown.
+ ///
+ ///
+ /// output size. -1 if unknown.
+ ///
+ void SetProgress(Int64 inSize, Int64 outSize);
+ };
+
+ public interface ICoder
+ {
+ ///
+ /// Codes streams.
+ ///
+ ///
+ /// input Stream.
+ ///
+ ///
+ /// output Stream.
+ ///
+ ///
+ /// input Size. -1 if unknown.
+ ///
+ ///
+ /// output Size. -1 if unknown.
+ ///
+ ///
+ /// callback progress reference.
+ ///
+ ///
+ /// if input stream is not valid
+ ///
+ void Code(System.IO.Stream inStream, System.IO.Stream outStream,
+ Int64 inSize, Int64 outSize, ICodeProgress progress, CancellationToken? token = null);
+ };
+
+ /*
+ public interface ICoder2
+ {
+ void Code(ISequentialInStream []inStreams,
+ const UInt64 []inSizes,
+ ISequentialOutStream []outStreams,
+ UInt64 []outSizes,
+ ICodeProgress progress);
+ };
+ */
+
+ ///
+ /// Provides the fields that represent properties idenitifiers for compressing.
+ ///
+ public enum CoderPropID
+ {
+ ///
+ /// Specifies default property.
+ ///
+ DefaultProp = 0,
+ ///
+ /// Specifies size of dictionary.
+ ///
+ DictionarySize,
+ ///
+ /// Specifies size of memory for PPM*.
+ ///
+ UsedMemorySize,
+ ///
+ /// Specifies order for PPM methods.
+ ///
+ Order,
+ ///
+ /// Specifies Block Size.
+ ///
+ BlockSize,
+ ///
+ /// Specifies number of postion state bits for LZMA (0 <= x <= 4).
+ ///
+ PosStateBits,
+ ///
+ /// Specifies number of literal context bits for LZMA (0 <= x <= 8).
+ ///
+ LitContextBits,
+ ///
+ /// Specifies number of literal position bits for LZMA (0 <= x <= 4).
+ ///
+ LitPosBits,
+ ///
+ /// Specifies number of fast bytes for LZ*.
+ ///
+ NumFastBytes,
+ ///
+ /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B".
+ ///
+ MatchFinder,
+ ///
+ /// Specifies the number of match finder cyckes.
+ ///
+ MatchFinderCycles,
+ ///
+ /// Specifies number of passes.
+ ///
+ NumPasses,
+ ///
+ /// Specifies number of algorithm.
+ ///
+ Algorithm,
+ ///
+ /// Specifies the number of threads.
+ ///
+ NumThreads,
+ ///
+ /// Specifies mode with end marker.
+ ///
+ EndMarker
+ };
+
+ public interface ISetCoderProperties
+ {
+ void SetCoderProperties(CoderPropID[] propIDs, object[] properties);
+ };
+
+ public interface IWriteCoderProperties
+ {
+ void WriteCoderProperties(System.IO.Stream outStream);
+ }
+
+ public interface ISetDecoderProperties
+ {
+ void SetDecoderProperties(byte[] properties);
+ }
+}
diff --git a/App.xaml b/WPinternals/App.xaml
similarity index 98%
rename from App.xaml
rename to WPinternals/App.xaml
index cedbe95..be1156e 100644
--- a/App.xaml
+++ b/WPinternals/App.xaml
@@ -1,112 +1,112 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/App.xaml.cs b/WPinternals/App.xaml.cs
similarity index 97%
rename from App.xaml.cs
rename to WPinternals/App.xaml.cs
index 1542850..125bd0c 100644
--- a/App.xaml.cs
+++ b/WPinternals/App.xaml.cs
@@ -1,103 +1,103 @@
-// 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.IO;
-using System.Linq;
-using System.Threading;
-using System.Windows;
-
-namespace WPinternals
-{
- ///
- /// Interaction logic for App.xaml
- ///
- public partial class App : Application
- {
- internal static Action NavigateToGettingStarted;
- internal static Action NavigateToUnlockBoot;
- internal static PatchEngine PatchEngine;
- internal static WPinternalsConfig Config;
- internal static Mutex mutex = new(false, "Global\\WPinternalsRunning");
- internal static DownloadsViewModel DownloadManager;
- internal static bool InterruptBoot = false;
- internal static bool IsPnPEventLogMissing = true;
-
- public App()
- : base()
- {
- AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
-
-#if NETCORE
- System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
-#endif
-
- if (Environment.GetCommandLineArgs().Length > 1)
- {
- CommandLine.OpenConsole();
- }
-
- try
- {
- if (!mutex.WaitOne(0, false))
- {
- if (Environment.GetCommandLineArgs().Length > 1)
- {
- Console.WriteLine("Windows Phone Internals is already running");
- CommandLine.CloseConsole();
- }
- else
- {
- MessageBox.Show("Windows Phone Internals is already running.", "Windows Phone Internals", MessageBoxButton.OK, MessageBoxImage.Exclamation);
- }
-
- Environment.Exit(0);
- }
- }
- catch (AbandonedMutexException) { }
-
- Registration.CheckExpiration();
-
- string PatchDefintionsXml;
- string PatchDefintionsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PatchDefintions.xml");
- if (File.Exists(PatchDefintionsPath))
- {
- PatchDefintionsXml = File.ReadAllText(PatchDefintionsPath);
- }
- else
- {
- using Stream stream = System.Reflection.Assembly.GetEntryAssembly().GetManifestResourceStream("WPinternals.PatchDefinitions.xml");
- using StreamReader sr = new(stream);
- PatchDefintionsXml = sr.ReadToEnd();
- }
- PatchEngine = new PatchEngine(PatchDefintionsXml);
-
- Config = WPinternalsConfig.ReadConfig();
- }
-
- private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
- {
- if (e.ExceptionObject is Exception)
- {
- LogFile.LogException(e.ExceptionObject as Exception);
- }
- }
- }
-}
+// 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.IO;
+using System.Linq;
+using System.Threading;
+using System.Windows;
+
+namespace WPinternals
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ internal static Action NavigateToGettingStarted;
+ internal static Action NavigateToUnlockBoot;
+ internal static PatchEngine PatchEngine;
+ internal static WPinternalsConfig Config;
+ internal static Mutex mutex = new(false, "Global\\WPinternalsRunning");
+ internal static DownloadsViewModel DownloadManager;
+ internal static bool InterruptBoot = false;
+ internal static bool IsPnPEventLogMissing = true;
+
+ public App()
+ : base()
+ {
+ AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
+
+#if NETCORE
+ System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
+#endif
+
+ if (Environment.GetCommandLineArgs().Length > 1)
+ {
+ CommandLine.OpenConsole();
+ }
+
+ try
+ {
+ if (!mutex.WaitOne(0, false))
+ {
+ if (Environment.GetCommandLineArgs().Length > 1)
+ {
+ Console.WriteLine("Windows Phone Internals is already running");
+ CommandLine.CloseConsole();
+ }
+ else
+ {
+ MessageBox.Show("Windows Phone Internals is already running.", "Windows Phone Internals", MessageBoxButton.OK, MessageBoxImage.Exclamation);
+ }
+
+ Environment.Exit(0);
+ }
+ }
+ catch (AbandonedMutexException) { }
+
+ Registration.CheckExpiration();
+
+ string PatchDefintionsXml;
+ string PatchDefintionsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PatchDefintions.xml");
+ if (File.Exists(PatchDefintionsPath))
+ {
+ PatchDefintionsXml = File.ReadAllText(PatchDefintionsPath);
+ }
+ else
+ {
+ using Stream stream = System.Reflection.Assembly.GetEntryAssembly().GetManifestResourceStream("WPinternals.PatchDefinitions.xml");
+ using StreamReader sr = new(stream);
+ PatchDefintionsXml = sr.ReadToEnd();
+ }
+ PatchEngine = new PatchEngine(PatchDefintionsXml);
+
+ Config = WPinternalsConfig.ReadConfig();
+ }
+
+ private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
+ {
+ if (e.ExceptionObject is Exception)
+ {
+ LogFile.LogException(e.ExceptionObject as Exception);
+ }
+ }
+ }
+}
diff --git a/CommandLine.cs b/WPinternals/CommandLine.cs
similarity index 98%
rename from CommandLine.cs
rename to WPinternals/CommandLine.cs
index d2328ee..39992ba 100644
--- a/CommandLine.cs
+++ b/WPinternals/CommandLine.cs
@@ -1,2109 +1,2109 @@
-// 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.IO.Compression;
-using System.Linq;
-using System.Runtime.InteropServices;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace WPinternals
-{
- internal static class CommandLine
- {
- [DllImport("kernel32.dll", SetLastError = true)]
- private static extern bool AllocConsole();
-
- [DllImport("kernel32.dll", SetLastError = true)]
- private static extern bool AttachConsole(int dwProcessId);
-
- [DllImport("kernel32.dll")]
- private static extern IntPtr GetConsoleWindow();
-
- [DllImport("user32.dll")]
- private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
-
- private const UInt32 StdOutputHandle = 0xFFFFFFF5;
-
- [DllImport("kernel32.dll")]
- private static extern IntPtr GetStdHandle(UInt32 nStdHandle);
-
- [DllImport("kernel32.dll")]
- private static extern void SetStdHandle(UInt32 nStdHandle, IntPtr handle);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- private static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, uint lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, uint hTemplateFile);
-
- [DllImport("user32.dll")]
- private static extern IntPtr GetForegroundWindow();
-
- private const int SW_HIDE = 0;
- private const int SW_SHOW = 5;
-
- private const int MY_CODE_PAGE = 437;
- private const uint GENERIC_WRITE = 0x40000000;
- private const uint FILE_SHARE_WRITE = 0x2;
- private const uint OPEN_EXISTING = 0x3;
-
- internal static bool IsConsoleVisible = false;
- internal static bool IsNewConsoleCreated = false;
-
- private static IntPtr hConsoleWnd;
-
- [DllImport("User32.Dll", EntryPoint = "PostMessageA")]
- private static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
-
- private const int VK_RETURN = 0x0D;
- private const int WM_KEYDOWN = 0x100;
-
- ///
- /// When the main window should not be shown, this function should call ExitProcess and it should not return.
- ///
- internal static async Task ParseCommandLine(System.Threading.SynchronizationContext UIContext)
- {
- FFU FFU = null;
- PhoneNotifierViewModel Notifier;
- NokiaFlashModel FlashModel;
- NokiaPhoneModel NormalModel;
- PhoneInfo Info;
- string ProductType;
- string ProductCode;
- string OperatorCode;
- string DownloadFolder;
- string FFUFilePath;
- string URL;
- string[] URLs;
- Uri URI;
- string FFUFileName;
- string EmergencyFileName;
- string EmergencyFilePath;
- string ProgrammerPath = "";
- string PayloadPath = "";
- string EfiEspImagePath = null;
- string MainOsImagePath = null;
- DiscUtils.Fat.FatFileSystem UnlockedEFIESPFileSystem;
- DiscUtils.Ntfs.NtfsFileSystem UnlockedMainOsFileSystem;
- bool PatchResult;
-
- try
- {
- string[] args = Environment.GetCommandLineArgs();
-
- if (args.Length == 1)
- {
- return;
- }
-
- switch (args[1].ToLower().TrimStart(new char[] { '-', '/' }))
- {
-#if DEBUG
- case "test":
- LogFile.BeginAction("Test");
- await TestCode.Test(UIContext);
- LogFile.EndAction("Test");
- break;
-#endif
- case "flashpartition":
- if (args.Length < 4)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -FlashPartition ");
- }
-
- if (args.Length >= 5)
- {
- await LumiaV2UnlockBootViewModel.LumiaV2FlashPartition(UIContext, args[4], args[2], args[3]);
- }
- else
- {
- await LumiaV2UnlockBootViewModel.LumiaV2FlashPartition(UIContext, null, args[2], args[3]);
- }
-
- break;
- case "flashraw":
- if (args.Length < 4)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -FlashRaw ");
- }
-
- UInt64 StartSector = 0;
- try
- {
- StartSector = args[2].StartsWith("0x", StringComparison.OrdinalIgnoreCase)
- ? Convert.ToUInt64(args[2][2..], 16)
- : Convert.ToUInt64(args[2], 10);
- }
- catch
- {
- LogFile.Log("Bad start sector", LogType.ConsoleOnly);
- break;
- }
- if (args.Length >= 5)
- {
- await LumiaV2UnlockBootViewModel.LumiaV2FlashRaw(UIContext, StartSector, args[3], args[4]);
- }
- else
- {
- await LumiaV2UnlockBootViewModel.LumiaV2FlashRaw(UIContext, StartSector, args[3], null);
- }
-
- break;
- case "flashpartitionimmediately":
- if (args.Length < 5)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -FlashPartition ");
- }
-
- await LumiaV2UnlockBootViewModel.LumiaV2FlashPartition(UIContext, args[4], args[2], args[3], false);
- break;
- case "readgpt":
- LogFile.BeginAction("ReadGPT");
- try
- {
- Notifier = new PhoneNotifierViewModel();
- UIContext.Send(s => Notifier.Start(), null);
-
- FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader); // This also works for Bootloader Spec A
-
- GPT GPT = FlashModel.ReadGPT(); // May throw NotSupportedException
- foreach (Partition Partition in GPT.Partitions)
- {
- LogFile.Log(Partition.Name.PadRight(20) + "0x" + Partition.FirstSector.ToString("X8") + " - 0x" + Partition.LastSector.ToString("X8") + " " + Partition.Volume, LogType.ConsoleOnly);
- }
-
- if (FlashModel.ReadPhoneInfo(false).FlashAppProtocolVersionMajor >= 2)
- {
- FlashModel.SwitchToFlashAppContext();
- }
- else
- {
- await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
- }
-
- Notifier.Stop();
- }
- catch (Exception Ex)
- {
- LogFile.LogException(Ex);
- }
- finally
- {
- LogFile.EndAction("ReadGPT");
- }
- break;
- case "backupgpt":
- if (args.Length < 3)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -BackupGPT ");
- }
-
- LogFile.BeginAction("BackupGPT");
- try
- {
- Notifier = new PhoneNotifierViewModel();
- UIContext.Send(s => Notifier.Start(), null);
- FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
- GPT GPT = FlashModel.ReadGPT(); // May throw NotSupportedException
- Directory.CreateDirectory(Path.GetDirectoryName(args[2]));
- GPT.WritePartitions(args[2]);
- FlashModel.SwitchToFlashAppContext();
- Notifier.Stop();
- }
- catch (Exception Ex)
- {
- LogFile.LogException(Ex);
- }
- finally
- {
- LogFile.EndAction("BackupGPT");
- }
- break;
- case "restoregpt":
- if (args.Length < 3)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -RestoreGPT ");
- }
-
- LogFile.BeginAction("RestoreGPT");
- try
- {
- Notifier = new PhoneNotifierViewModel();
- UIContext.Send(s => Notifier.Start(), null);
- FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
- byte[] GptChunk = LumiaUnlockBootloaderViewModel.GetGptChunk(FlashModel, 0x20000);
- GPT GPT = new(GptChunk);
- string Xml = File.ReadAllText(args[2]);
- GPT.MergePartitions(Xml, false);
- GPT.Rebuild();
- await LumiaV2UnlockBootViewModel.LumiaV2CustomFlash(Notifier, null, false, false, 0, GptChunk, true, true);
- FlashModel.SwitchToFlashAppContext();
- Notifier.Stop();
- }
- catch (Exception Ex)
- {
- LogFile.LogException(Ex);
- }
- finally
- {
- LogFile.EndAction("RestoreGPT");
- }
- break;
- case "mergegpt":
- if (args.Length < 4)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -MergeGPT Or use: WPinternals.exe -MergeGPT ");
- }
-
- LogFile.BeginAction("MergeGPT");
- try
- {
- GPT GPT = GPT.ReadPartitions(args[2]);
-
- ZipArchive Archive = null;
- FileStream s = null;
- try
- {
- s = new FileStream(args[3], FileMode.Open, FileAccess.Read);
- Archive = new ZipArchive(s);
- }
- catch { }
-
- if (Archive == null)
- {
- s?.Close();
-
- // Assume Xml-file
- GPT.MergePartitionsFromFile(args[3], true);
- }
- else
- {
- ZipArchiveEntry PartitionEntry = Archive.GetEntry("Partitions.xml");
- if (PartitionEntry == null)
- {
- GPT.MergePartitions(null, true, Archive);
- }
- else
- {
- using Stream ZipStream = PartitionEntry.Open();
- using StreamReader ZipReader = new(ZipStream);
- string PartitionXml = ZipReader.ReadToEnd();
- GPT.MergePartitions(PartitionXml, true, Archive);
- }
- }
-
- Archive?.Dispose();
-
- if (args.Length >= 5)
- {
- GPT.WritePartitions(args[4]);
- }
-
- foreach (Partition Partition in GPT.Partitions)
- {
- LogFile.Log(Partition.Name.PadRight(20) + "0x" + Partition.FirstSector.ToString("X8") + " - 0x" + Partition.LastSector.ToString("X8") + " " + Partition.Volume, LogType.ConsoleOnly);
- }
- }
- catch (Exception Ex)
- {
- LogFile.LogException(Ex);
- }
- finally
- {
- LogFile.EndAction("MergeGPT");
- }
- break;
- case "dumpffu":
- if (args.Length < 4)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DumpFFU ");
- }
-
- FFU = new FFU(args[2]);
- if (args.Length < 5)
- {
- foreach (Partition Partition in FFU.GPT.Partitions)
- {
- if (FFU.IsPartitionPresentInFFU(Partition.Name))
- {
- FFU.WritePartition(Partition.Name, Path.Combine(args[3], Partition.Name + ".bin"));
- }
- }
- }
- else
- {
- Partition Target = FFU.GPT.GetPartition(args[4]);
- if ((Target == null) || (!FFU.IsPartitionPresentInFFU(Target.Name)))
- {
- throw new InvalidOperationException("Partition not found in FFU!");
- }
-
- FFU.WritePartition(Target.Name, Path.Combine(args[3], Target.Name + ".bin"));
- }
- break;
- case "dumpuefi":
- if (args.Length < 4)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DumpUEFI ");
- }
-
- byte[] UefiBinary;
- if (FFU.IsFFU(args[2]))
- {
- FFU = new FFU(args[2]);
- UefiBinary = FFU.GetPartition("UEFI");
- }
- else
- {
- UefiBinary = File.ReadAllBytes(args[2]);
- }
-
- UEFI UEFI = new(UefiBinary);
-
- foreach (EFI Efi in UEFI.EFIs)
- {
- byte[] EfiBinary = UEFI.GetFile(Efi.Guid);
- string Name = Efi.Name ?? Efi.Guid.ToString();
-
- if (!Name.Contains('.'))
- {
- Name += Efi.Type switch
- {
- 5 or 7 => ".dll",
- 9 => ".exe",
- _ => ".bin",
- };
- }
- string EfiPath = Path.Combine(args[3], Name);
- Directory.CreateDirectory(Path.GetDirectoryName(EfiPath));
- File.WriteAllBytes(EfiPath, EfiBinary);
- }
- break;
- case "testprogrammer":
- if (args.Length < 3)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -TestProgrammer ");
- }
-
- await TestCode.TestProgrammer(UIContext, args[2]);
- break;
- case "findflashingprofile":
- Notifier = new PhoneNotifierViewModel();
- UIContext.Send(s => Notifier.Start(), null);
- if (args.Length > 2)
- {
- await LumiaV2UnlockBootViewModel.LumiaV2FindFlashingProfile(Notifier, args[2]);
- }
- else
- {
- await LumiaV2UnlockBootViewModel.LumiaV2FindFlashingProfile(Notifier, null);
- }
-
- Notifier.Stop();
- break;
- case "findflashingprofileexperimental":
- Notifier = new PhoneNotifierViewModel();
- UIContext.Send(s => Notifier.Start(), null);
- if (args.Length > 2)
- {
- await LumiaV2UnlockBootViewModel.LumiaV2FindFlashingProfile(Notifier, args[2], Experimental: true);
- }
- else
- {
- await LumiaV2UnlockBootViewModel.LumiaV2FindFlashingProfile(Notifier, null, Experimental: true);
- }
-
- Notifier.Stop();
- break;
- case "findflashingprofilenorestart":
- Notifier = new PhoneNotifierViewModel();
- UIContext.Send(s => Notifier.Start(), null);
- if (args.Length > 2)
- {
- await LumiaV2UnlockBootViewModel.LumiaV2FindFlashingProfile(Notifier, args[2], false);
- }
- else
- {
- await LumiaV2UnlockBootViewModel.LumiaV2FindFlashingProfile(Notifier, null, false);
- }
-
- Notifier.Stop();
- break;
- case "enabletestsigning":
- if (args.Length > 2)
- {
- await LumiaV2UnlockBootViewModel.LumiaV2EnableTestSigning(UIContext, args[2]);
- }
- else
- {
- await LumiaV2UnlockBootViewModel.LumiaV2EnableTestSigning(UIContext, null);
- }
-
- break;
- case "enabletestsigningnorestart":
- if (args.Length > 2)
- {
- await LumiaV2UnlockBootViewModel.LumiaV2EnableTestSigning(UIContext, args[2], false);
- }
- else
- {
- await LumiaV2UnlockBootViewModel.LumiaV2EnableTestSigning(UIContext, null, false);
- }
-
- break;
- case "clearnv":
- if (args.Length > 2)
- {
- await LumiaV2UnlockBootViewModel.LumiaV2ClearNV(UIContext, args[2]);
- }
- else
- {
- await LumiaV2UnlockBootViewModel.LumiaV2ClearNV(UIContext, null);
- }
-
- break;
- case "switchtomassstoragemode":
- LogFile.BeginAction("SwitchToMassStorageMode");
- try
- {
- Notifier = new PhoneNotifierViewModel();
- UIContext.Send(s => Notifier.Start(), null);
- LogFile.Log("Command: Switch to Mass Storage Mode", LogType.FileAndConsole);
- if (args.Length > 2)
- {
- await LumiaV2UnlockBootViewModel.LumiaV2SwitchToMassStorageMode(Notifier, args[2]);
- }
- else
- {
- await LumiaV2UnlockBootViewModel.LumiaV2SwitchToMassStorageMode(Notifier, null);
- }
-
- Notifier.Stop();
- }
- catch (Exception Ex)
- {
- LogFile.LogException(Ex);
- }
- finally
- {
- LogFile.EndAction("SwitchToMassStorageMode");
- }
- break;
- case "relockphone":
- Notifier = new PhoneNotifierViewModel();
- try
- {
- UIContext.Send(s => Notifier.Start(), null);
- FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
- Info = FlashModel.ReadPhoneInfo();
- Info.Log(LogType.ConsoleOnly);
-
- FFU ProfileFFU = null;
- FFU CurrentFFU;
- for (int i = 2; i <= 3; i++)
- {
- if (args.Length > i)
- {
- CurrentFFU = new FFU(args[i]);
- string CurrentVersion = CurrentFFU.GetOSVersion();
- string PlatformID = CurrentFFU.PlatformID;
-
- // Check if the current FFU matches the connected phone, so that the FFU can be used for profiling.
- if (Info.PlatformID.StartsWith(PlatformID, StringComparison.OrdinalIgnoreCase))
- {
- ProfileFFU = CurrentFFU;
- }
- }
- }
-
- if (ProfileFFU == null)
- {
- List FFUs = App.Config.FFURepository.Where(e => Info.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
- ProfileFFU = FFUs.Count > 0
- ? new FFU(FFUs[0].Path)
- : throw new WPinternalsException("Profile FFU missing", "No profile FFU has been found in the repository for your device. You can add a profile FFU within the download section of the tool or by using the command line.");
- }
- LogFile.Log("Profile FFU: " + ProfileFFU.Path);
-
- UIContext.Send(s => Notifier.Start(), null);
-
- await LumiaUnlockBootloaderViewModel.LumiaRelockUEFI(Notifier, ProfileFFU.Path);
- }
- catch (Exception Ex)
- {
- LogFile.LogException(Ex);
- }
- Notifier.Stop();
- break;
- case "addffu":
- if (args.Length < 3)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -AddFFU ");
- }
-
- App.Config.AddFfuToRepository(args[2]);
- break;
- case "removeffu":
- if (args.Length < 3)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -RemoveFFU ");
- }
-
- App.Config.RemoveFfuFromRepository(args[2]);
- break;
- case "addemergency":
- if (args.Length < 5)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -AddEmergnency ");
- }
-
- App.Config.AddEmergencyToRepository(args[2], args[3], args[4]);
- break;
- case "removeemergency":
- if (args.Length < 3)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -RemoveEmergency ");
- }
-
- App.Config.RemoveEmergencyFromRepository(args[2]);
- break;
- case "listrepository":
- int Count = 0;
- LogFile.Log("", LogType.ConsoleOnly);
- LogFile.Log("FFU Repository:", LogType.ConsoleOnly);
- foreach (FFUEntry Entry in App.Config.FFURepository)
- {
- LogFile.Log("", LogType.ConsoleOnly);
- LogFile.Log("FFU " + Count.ToString() + ":", LogType.ConsoleOnly);
- LogFile.Log("File: " + Entry.Path + (Entry.Exists() ? "" : " (file is missing)"), LogType.ConsoleOnly);
- LogFile.Log("Platform ID: " + Entry.PlatformID, LogType.ConsoleOnly);
- if (Entry.FirmwareVersion != null)
- {
- LogFile.Log("Firmware version: " + Entry.FirmwareVersion, LogType.ConsoleOnly);
- }
-
- if (Entry.OSVersion != null)
- {
- LogFile.Log("OS version: " + Entry.OSVersion, LogType.ConsoleOnly);
- }
-
- Count++;
- }
- LogFile.Log("", LogType.ConsoleOnly);
- LogFile.Log("Emergency Repository:", LogType.ConsoleOnly);
- Count = 0;
- foreach (EmergencyFileEntry Entry in App.Config.EmergencyRepository)
- {
- LogFile.Log("", LogType.ConsoleOnly);
- LogFile.Log("Emergency " + Count.ToString() + ":", LogType.ConsoleOnly);
- LogFile.Log("Type: " + Entry.Type, LogType.ConsoleOnly);
- LogFile.Log("Programmer file: " + Entry.ProgrammerPath + (Entry.ProgrammerExists() ? "" : " (file is missing)"), LogType.ConsoleOnly);
- if (Entry.PayloadPath != null)
- {
- LogFile.Log("Payload file: " + Entry.PayloadPath + (Entry.PayloadExists() ? "" : " (file is missing)"), LogType.ConsoleOnly);
- }
-
- Count++;
- }
- break;
- case "showffu":
- if (args.Length < 3)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -ShowFFU ");
- }
-
- string FFUPath = args[2];
- LogFile.Log("FFU: " + FFUPath, LogType.ConsoleOnly);
- FFU = new FFU(FFUPath);
-
- // Show basics
- LogFile.Log("Platform ID: " + FFU.PlatformID, LogType.ConsoleOnly);
- string Firmware = FFU.GetFirmwareVersion();
- if (Firmware != null)
- {
- LogFile.Log("Firmware version: " + Firmware, LogType.ConsoleOnly);
- }
-
- string OSVersion = FFU.GetOSVersion();
- if (OSVersion != null)
- {
- LogFile.Log("OS version: " + OSVersion, LogType.ConsoleOnly);
- }
-
- // Show partitions from GPT (also show which partitions are in the FFU payload)
- LogFile.Log("", LogType.ConsoleOnly);
- LogFile.Log("Partition table:", LogType.ConsoleOnly);
- LogFile.Log("Name".PadRight(20) + "Start-sector".PadRight(20) + "End-sector".PadRight(20) + "Present in FFU", LogType.ConsoleOnly);
- foreach (Partition p in FFU.GPT.Partitions)
- {
- LogFile.Log(p.Name.PadRight(20) + ("0x" + p.FirstSector.ToString("X16")).PadRight(20) + ("0x" + p.LastSector.ToString("X16")).PadRight(20) + (FFU.IsPartitionPresentInFFU(p.Name) ? "Yes" : "No"), LogType.ConsoleOnly);
- }
- break;
- case "showphoneinfo":
- LogFile.Log("Command: Show phone info", LogType.FileAndConsole);
- Notifier = new PhoneNotifierViewModel();
- UIContext.Send(s => Notifier.Start(), null);
- FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
- Info = FlashModel.ReadPhoneInfo();
- Info.Log(LogType.ConsoleOnly);
- Notifier.Stop();
- break;
- case "unlockbootloader":
- LogFile.BeginAction("UnlockBootloader");
- try
- {
- LogFile.Log("Command: Unlock Bootloader", LogType.FileAndConsole);
- Notifier = new PhoneNotifierViewModel();
- UIContext.Send(s => Notifier.Start(), null);
- FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
- Info = FlashModel.ReadPhoneInfo();
- Info.Log(LogType.ConsoleOnly);
-
- FFU ProfileFFU = null;
- FFU SupportedFFU = null;
- FFU CurrentFFU;
- for (int i = 2; i <= 3; i++)
- {
- if (args.Length > i)
- {
- CurrentFFU = new FFU(args[i]);
- string CurrentVersion = CurrentFFU.GetOSVersion();
- string PlatformID = CurrentFFU.PlatformID;
-
- // Check if the current FFU matches the connected phone, so that the FFU can be used for profiling.
- if (Info.PlatformID.StartsWith(PlatformID, StringComparison.OrdinalIgnoreCase))
- {
- ProfileFFU = CurrentFFU;
- }
-
- // Check if the current FFU is supported for unlocking.
- if (App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == CurrentVersion))
- {
- SupportedFFU = CurrentFFU;
- }
- }
- }
-
- if (ProfileFFU == null)
- {
- List FFUs = App.Config.FFURepository.Where(e => Info.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
- ProfileFFU = FFUs.Count > 0
- ? new FFU(FFUs[0].Path)
- : throw new WPinternalsException("Profile FFU missing", "No profile FFU has been found in the repository for your device. You can add a profile FFU within the download section of the tool or by using the command line.");
- }
- LogFile.Log("Profile FFU: " + ProfileFFU.Path);
-
- if (SupportedFFU == null)
- {
- List FFUs = App.Config.FFURepository.Where(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)).ToList();
- SupportedFFU = FFUs.Count > 0
- ? new FFU(FFUs[0].Path)
- : throw new WPinternalsException("No donor-FFU found with supported OS version", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
- }
-
- await LumiaUnlockBootloaderViewModel.LumiaUnlockUEFI(Notifier, ProfileFFU.Path, null, SupportedFFU.Path);
-
- Notifier.Stop();
- }
- catch (Exception Ex)
- {
- LogFile.LogException(Ex);
- }
- finally
- {
- LogFile.EndAction("UnlockBootloader");
- }
- break;
- case "flashcustomrom":
- LogFile.BeginAction("FlashCustomROM");
- try
- {
- LogFile.Log("Command: Flash Custom ROM", LogType.FileAndConsole);
- if (args.Length < 3)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -FlashCustomROM ");
- }
-
- string CustomRomPath = args[2];
- LogFile.Log("Custom ROM: " + CustomRomPath, LogType.FileAndConsole);
- Notifier = new PhoneNotifierViewModel();
- UIContext.Send(s => Notifier.Start(), null);
- FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
- Info = FlashModel.ReadPhoneInfo();
- Info.Log(LogType.ConsoleOnly);
- LogFile.Log("Preparing to flash Custom ROM", LogType.FileAndConsole);
- await LumiaV2UnlockBootViewModel.LumiaV2FlashArchive(Notifier, CustomRomPath);
- LogFile.Log("Custom ROM flashed successfully", LogType.FileAndConsole);
- Notifier.Stop();
- }
- catch (Exception Ex)
- {
- LogFile.LogException(Ex);
- }
- finally
- {
- LogFile.EndAction("FlashCustomROM");
- }
- break;
- case "flashffu":
- LogFile.BeginAction("FlashFFU");
- try
- {
- LogFile.Log("Command: Flash FFU", LogType.FileAndConsole);
- if (args.Length < 3)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -FlashFFU ");
- }
-
- FFUPath = args[2];
- LogFile.Log("FFU file: " + FFUPath, LogType.FileAndConsole);
- Notifier = new PhoneNotifierViewModel();
- UIContext.Send(s => Notifier.Start(), null);
- FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
- Info = FlashModel.ReadPhoneInfo();
- Info.Log(LogType.ConsoleOnly);
- LogFile.Log("Flashing FFU...", LogType.FileAndConsole);
- await Task.Run(() => FlashModel.FlashFFU(new FFU(FFUPath), true, (byte)(!Info.IsBootloaderSecure ? FlashOptions.SkipSignatureCheck : 0)));
- LogFile.Log("FFU flashed successfully", LogType.FileAndConsole);
- Notifier.Stop();
- }
- catch (Exception Ex)
- {
- LogFile.LogException(Ex);
- }
- finally
- {
- LogFile.EndAction("FlashFFU");
- }
- break;
- case "fixbootafterunlockingbootloader":
- LogFile.BeginAction("FixBoot");
- try
- {
- LogFile.Log("Command: Fix boot after unlocking bootloader", LogType.FileAndConsole);
- Notifier = new PhoneNotifierViewModel();
- UIContext.Send(s => Notifier.Start(), null);
- string Drive = await LumiaV2UnlockBootViewModel.LumiaV2SwitchToMassStorageMode(Notifier, null);
- Notifier.Stop();
- App.PatchEngine.TargetPath = Drive + "\\";
- PatchResult = App.PatchEngine.Patch("SecureBootHack-MainOS");
- if (!PatchResult)
- {
- throw new WPinternalsException("Patch failed", "An error occured while patching Operating System files on the MainOS partition of your phone. Make sure your phone runs a supported Operating System version.");
- }
-
- LogFile.Log("Fixed bootloader", LogType.FileAndConsole);
- LogFile.Log("The phone is left in Mass Storage mode", LogType.FileAndConsole);
- LogFile.Log("Press and hold the power-button of the phone for at least 10 seconds to reset the phone", LogType.FileAndConsole);
- }
- catch (Exception Ex)
- {
- LogFile.LogException(Ex);
- }
- finally
- {
- LogFile.EndAction("FixBoot");
- }
- break;
- case "enablerootaccess":
- LogFile.BeginAction("EnableRootAccess");
- try
- {
- LogFile.Log("Command: Enable root access on the phone", LogType.FileAndConsole);
- Notifier = new PhoneNotifierViewModel();
- UIContext.Send(s => Notifier.Start(), null);
- string Drive = await LumiaV2UnlockBootViewModel.LumiaV2SwitchToMassStorageMode(Notifier, null);
- Notifier.Stop();
- App.PatchEngine.TargetPath = Drive + "\\EFIESP\\";
- PatchResult = App.PatchEngine.Patch("SecureBootHack-V2-EFIESP");
- if (!PatchResult)
- {
- throw new WPinternalsException("Patch failed", "An error occured while patching Operating System files on the EFIESP partition of your phone. Make sure no boot files have been tampered with and you use the latest version of the tool. This error cannot be caused by an incorrect Operating System version as the tool automatically uses replacement if the version isn't supported.");
- }
-
- App.PatchEngine.TargetPath = Drive + "\\";
- PatchResult = App.PatchEngine.Patch("SecureBootHack-MainOS");
- if (!PatchResult)
- {
- throw new WPinternalsException("Patch failed", "An error occured while patching Operating System files on the MainOS partition of your phone. Make sure your phone runs a supported Operating System version.");
- }
-
- PatchResult = App.PatchEngine.Patch("RootAccess-MainOS");
- if (!PatchResult)
- {
- throw new WPinternalsException("Patch failed", "An error occured while modifying Operating System files on the MainOS partition of your phone for Root Access. Make sure your phone runs a supported Operating System version.");
- }
-
- LogFile.Log("Root Access enabled!", LogType.FileAndConsole);
- LogFile.Log("The phone is left in Mass Storage mode", LogType.FileAndConsole);
- LogFile.Log("Press and hold the power-button of the phone for at least 10 seconds to reset the phone", LogType.FileAndConsole);
- }
- catch (Exception Ex)
- {
- LogFile.LogException(Ex);
- }
- finally
- {
- LogFile.EndAction("EnableRootAccess");
- }
- break;
- case "unlockbootloaderonimage":
- LogFile.Log("Command: Unlock bootloader on image", LogType.FileAndConsole);
- if (args.Length < 3)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -UnlockBootLoaderOnImage ");
- }
-
- FFUFilePath = null;
- EfiEspImagePath = args[2];
- if (args.Length > 3)
- {
- if (FFU.IsFFU(args[3]))
- {
- FFUFilePath = args[3];
- }
- else
- {
- MainOsImagePath = args[3];
- }
- }
- if (args.Length > 4)
- {
- FFUFilePath = args[4];
- }
-
- using (FileStream FileSystemStream = new(EfiEspImagePath, FileMode.Open, FileAccess.ReadWrite))
- {
- UnlockedEFIESPFileSystem = new DiscUtils.Fat.FatFileSystem(FileSystemStream);
-
- if (FFUFilePath != null)
- {
- FFU SupportedFFU = new(FFUFilePath);
- LogFile.Log("Donor FFU: " + SupportedFFU.Path);
- byte[] SupportedEFIESP = SupportedFFU.GetPartition("EFIESP");
- DiscUtils.Fat.FatFileSystem SupportedEFIESPFileSystem = new(new MemoryStream(SupportedEFIESP));
- DiscUtils.Streams.SparseStream SupportedMobileStartupStream = SupportedEFIESPFileSystem.OpenFile(@"\Windows\System32\Boot\mobilestartup.efi", FileMode.Open);
- MemoryStream SupportedMobileStartupMemStream = new();
- SupportedMobileStartupStream.CopyTo(SupportedMobileStartupMemStream);
- byte[] SupportedMobileStartup = SupportedMobileStartupMemStream.ToArray();
- SupportedMobileStartupMemStream.Close();
- SupportedMobileStartupStream.Close();
-
- // Save supported mobilestartup.efi
- LogFile.Log("Taking mobilestartup.efi from donor-FFU");
- Stream MobileStartupStream = UnlockedEFIESPFileSystem.OpenFile(@"\Windows\System32\Boot\mobilestartup.efi", FileMode.Create, FileAccess.Write);
- MobileStartupStream.Write(SupportedMobileStartup, 0, SupportedMobileStartup.Length);
- MobileStartupStream.Close();
- }
-
- App.PatchEngine.TargetImage = UnlockedEFIESPFileSystem;
- PatchResult = App.PatchEngine.Patch("SecureBootHack-V2-EFIESP");
- if (!PatchResult)
- {
- throw new WPinternalsException("Failed to patch bootloader", "An error occured while patching Operating System files on the EFIESP partition provided. Make sure no boot files have been tampered with and you use the latest version of the tool. This error cannot be caused by an incorrect Operating System version as the tool automatically uses replacement if the version isn't supported, unless the replacement files have been tampered with or are not compatible.");
- }
-
- // Edit BCD
- LogFile.Log("Edit BCD");
- using Stream BCDFileStream = UnlockedEFIESPFileSystem.OpenFile(@"\efi\Microsoft\Boot\BCD", FileMode.Open, FileAccess.ReadWrite);
- using DiscUtils.Registry.RegistryHive BCDHive = new(BCDFileStream);
- DiscUtils.BootConfig.Store BCDStore = new(BCDHive.Root);
- DiscUtils.BootConfig.BcdObject MobileStartupObject = BCDStore.GetObject(new Guid("{01de5a27-8705-40db-bad6-96fa5187d4a6}"));
- DiscUtils.BootConfig.Element NoCodeIntegrityElement = MobileStartupObject.GetElement(0x16000048);
- if (NoCodeIntegrityElement != null)
- {
- NoCodeIntegrityElement.Value = DiscUtils.BootConfig.ElementValue.ForBoolean(true);
- }
- else
- {
- MobileStartupObject.AddElement(0x16000048, DiscUtils.BootConfig.ElementValue.ForBoolean(true));
- }
-
- DiscUtils.BootConfig.BcdObject WinLoadObject = BCDStore.GetObject(new Guid("{7619dcc9-fafe-11d9-b411-000476eba25f}"));
- NoCodeIntegrityElement = WinLoadObject.GetElement(0x16000048);
- if (NoCodeIntegrityElement != null)
- {
- NoCodeIntegrityElement.Value = DiscUtils.BootConfig.ElementValue.ForBoolean(true);
- }
- else
- {
- WinLoadObject.AddElement(0x16000048, DiscUtils.BootConfig.ElementValue.ForBoolean(true));
- }
- }
-
- if (MainOsImagePath != null)
- {
- using FileStream FileSystemStream = new(MainOsImagePath, FileMode.Open, FileAccess.ReadWrite);
- UnlockedMainOsFileSystem = new DiscUtils.Ntfs.NtfsFileSystem(FileSystemStream);
-
- App.PatchEngine.TargetImage = UnlockedMainOsFileSystem;
- PatchResult = App.PatchEngine.Patch("SecureBootHack-MainOS");
- if (!PatchResult)
- {
- throw new WPinternalsException("Failed to patch MainOS", "An error occured while patching Operating System files on the MainOS partition you provided. Make sure your phone runs a supported Operating System version.");
- }
- }
- LogFile.Log("Bootloader unlocked on image", LogType.FileAndConsole);
- break;
- case "enablerootaccessonimage":
- LogFile.Log("Command: Enable root access on image", LogType.FileAndConsole);
- if (args.Length < 4)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -EnableRootAccessOnImage ");
- }
-
- FFUFilePath = null;
- EfiEspImagePath = args[2];
- MainOsImagePath = args[3];
- if (args.Length > 4)
- {
- FFUFilePath = args[4];
- }
-
- using (FileStream FileSystemStream = new(EfiEspImagePath, FileMode.Open, FileAccess.ReadWrite))
- {
- UnlockedEFIESPFileSystem = new DiscUtils.Fat.FatFileSystem(FileSystemStream);
-
- if (FFUFilePath != null)
- {
- FFU SupportedFFU = new(FFUFilePath);
- LogFile.Log("Supported FFU: " + SupportedFFU.Path);
- byte[] SupportedEFIESP = SupportedFFU.GetPartition("EFIESP");
- DiscUtils.Fat.FatFileSystem SupportedEFIESPFileSystem = new(new MemoryStream(SupportedEFIESP));
- DiscUtils.Streams.SparseStream SupportedMobileStartupStream = SupportedEFIESPFileSystem.OpenFile(@"\Windows\System32\Boot\mobilestartup.efi", FileMode.Open);
- MemoryStream SupportedMobileStartupMemStream = new();
- SupportedMobileStartupStream.CopyTo(SupportedMobileStartupMemStream);
- byte[] SupportedMobileStartup = SupportedMobileStartupMemStream.ToArray();
- SupportedMobileStartupMemStream.Close();
- SupportedMobileStartupStream.Close();
-
- // Save supported mobilestartup.efi
- LogFile.Log("Taking mobilestartup.efi from donor-FFU");
- Stream MobileStartupStream = UnlockedEFIESPFileSystem.OpenFile(@"\Windows\System32\Boot\mobilestartup.efi", FileMode.Create, FileAccess.Write);
- MobileStartupStream.Write(SupportedMobileStartup, 0, SupportedMobileStartup.Length);
- MobileStartupStream.Close();
- }
-
- App.PatchEngine.TargetImage = UnlockedEFIESPFileSystem;
- PatchResult = App.PatchEngine.Patch("SecureBootHack-V2-EFIESP");
- if (!PatchResult)
- {
- throw new WPinternalsException("Failed to patch bootloader", "An error occured while patching Operating System files on the EFIESP partition provided. Make sure no boot files have been tampered with and you use the latest version of the tool. This error cannot be caused by an incorrect Operating System version as the tool automatically uses replacement if the version isn't supported, unless the replacement files have been tampered with or are not compatible.");
- }
-
- // Edit BCD
- LogFile.Log("Edit BCD");
- using Stream BCDFileStream = UnlockedEFIESPFileSystem.OpenFile(@"\efi\Microsoft\Boot\BCD", FileMode.Open, FileAccess.ReadWrite);
- using DiscUtils.Registry.RegistryHive BCDHive = new(BCDFileStream);
- DiscUtils.BootConfig.Store BCDStore = new(BCDHive.Root);
- DiscUtils.BootConfig.BcdObject MobileStartupObject = BCDStore.GetObject(new Guid("{01de5a27-8705-40db-bad6-96fa5187d4a6}"));
- DiscUtils.BootConfig.Element NoCodeIntegrityElement = MobileStartupObject.GetElement(0x16000048);
- if (NoCodeIntegrityElement != null)
- {
- NoCodeIntegrityElement.Value = DiscUtils.BootConfig.ElementValue.ForBoolean(true);
- }
- else
- {
- MobileStartupObject.AddElement(0x16000048, DiscUtils.BootConfig.ElementValue.ForBoolean(true));
- }
-
- DiscUtils.BootConfig.BcdObject WinLoadObject = BCDStore.GetObject(new Guid("{7619dcc9-fafe-11d9-b411-000476eba25f}"));
- NoCodeIntegrityElement = WinLoadObject.GetElement(0x16000048);
- if (NoCodeIntegrityElement != null)
- {
- NoCodeIntegrityElement.Value = DiscUtils.BootConfig.ElementValue.ForBoolean(true);
- }
- else
- {
- WinLoadObject.AddElement(0x16000048, DiscUtils.BootConfig.ElementValue.ForBoolean(true));
- }
- }
-
- using (FileStream FileSystemStream = new(MainOsImagePath, FileMode.Open, FileAccess.ReadWrite))
- {
- UnlockedMainOsFileSystem = new DiscUtils.Ntfs.NtfsFileSystem(FileSystemStream);
-
- App.PatchEngine.TargetImage = UnlockedMainOsFileSystem;
- PatchResult = App.PatchEngine.Patch("SecureBootHack-MainOS");
- if (!PatchResult)
- {
- throw new WPinternalsException("Failed to patch MainOS", "An error occured while patching Operating System files on the MainOS partition you provided. Make sure your phone runs a supported Operating System version.");
- }
-
- PatchResult = App.PatchEngine.Patch("RootAccess-MainOS");
- if (!PatchResult)
- {
- throw new WPinternalsException("Failed to patch MainOS", "An error occured while modifying Operating System files on the MainOS partition you provided for Root Access. Make sure your phone runs a supported Operating System version.");
- }
- }
- LogFile.Log("Root access enabled on image", LogType.FileAndConsole);
- break;
- case "unlockbootloaderonmountedimage":
- LogFile.Log("Command: Unlock bootloader on mounted image", LogType.FileAndConsole);
- if (args.Length < 3)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -UnlockBootLoaderOnMountedImage ");
- }
-
- FFUFilePath = null;
- EfiEspImagePath = args[2];
- if (args.Length > 3)
- {
- if (FFU.IsFFU(args[3]))
- {
- FFUFilePath = args[3];
- }
- else
- {
- MainOsImagePath = args[3];
- }
- }
- if (args.Length > 4)
- {
- FFUFilePath = args[4];
- }
-
- if (FFUFilePath != null)
- {
- FFU SupportedFFU = new(FFUFilePath);
- LogFile.Log("Donor-FFU: " + SupportedFFU.Path);
- byte[] SupportedEFIESP = SupportedFFU.GetPartition("EFIESP");
- DiscUtils.Fat.FatFileSystem SupportedEFIESPFileSystem = new(new MemoryStream(SupportedEFIESP));
- DiscUtils.Streams.SparseStream SupportedMobileStartupStream = SupportedEFIESPFileSystem.OpenFile(@"\Windows\System32\Boot\mobilestartup.efi", FileMode.Open);
- MemoryStream SupportedMobileStartupMemStream = new();
- SupportedMobileStartupStream.CopyTo(SupportedMobileStartupMemStream);
- byte[] SupportedMobileStartup = SupportedMobileStartupMemStream.ToArray();
- SupportedMobileStartupMemStream.Close();
- SupportedMobileStartupStream.Close();
-
- // Save supported mobilestartup.efi
- LogFile.Log("Taking mobilestartup.efi from donor-FFU");
- Stream MobileStartupStream = File.Open(Path.Combine(EfiEspImagePath, @"Windows\System32\Boot\mobilestartup.efi"), FileMode.Create, FileAccess.Write);
- MobileStartupStream.Write(SupportedMobileStartup, 0, SupportedMobileStartup.Length);
- MobileStartupStream.Close();
- }
-
- App.PatchEngine.TargetPath = EfiEspImagePath;
- PatchResult = App.PatchEngine.Patch("SecureBootHack-V2-EFIESP");
- if (!PatchResult)
- {
- throw new WPinternalsException("Failed to patch bootloader", "An error occured while patching Operating System files on the EFIESP partition provided. Make sure no boot files have been tampered with and you use the latest version of the tool. This error cannot be caused by an incorrect Operating System version as the tool automatically uses replacement if the version isn't supported, unless the replacement files have been tampered with or are not compatible.");
- }
-
- // Edit BCD
- LogFile.Log("Edit BCD");
- using (Stream BCDFileStream = File.Open(Path.Combine(EfiEspImagePath, @"efi\Microsoft\Boot\BCD"), FileMode.Open, FileAccess.ReadWrite))
- {
- using DiscUtils.Registry.RegistryHive BCDHive = new(BCDFileStream);
- DiscUtils.BootConfig.Store BCDStore = new(BCDHive.Root);
- DiscUtils.BootConfig.BcdObject MobileStartupObject = BCDStore.GetObject(new Guid("{01de5a27-8705-40db-bad6-96fa5187d4a6}"));
- DiscUtils.BootConfig.Element NoCodeIntegrityElement = MobileStartupObject.GetElement(0x16000048);
- if (NoCodeIntegrityElement != null)
- {
- NoCodeIntegrityElement.Value = DiscUtils.BootConfig.ElementValue.ForBoolean(true);
- }
- else
- {
- MobileStartupObject.AddElement(0x16000048, DiscUtils.BootConfig.ElementValue.ForBoolean(true));
- }
-
- DiscUtils.BootConfig.BcdObject WinLoadObject = BCDStore.GetObject(new Guid("{7619dcc9-fafe-11d9-b411-000476eba25f}"));
- NoCodeIntegrityElement = WinLoadObject.GetElement(0x16000048);
- if (NoCodeIntegrityElement != null)
- {
- NoCodeIntegrityElement.Value = DiscUtils.BootConfig.ElementValue.ForBoolean(true);
- }
- else
- {
- WinLoadObject.AddElement(0x16000048, DiscUtils.BootConfig.ElementValue.ForBoolean(true));
- }
- }
-
- if (MainOsImagePath != null)
- {
- App.PatchEngine.TargetPath = MainOsImagePath;
- PatchResult = App.PatchEngine.Patch("SecureBootHack-MainOS");
- if (!PatchResult)
- {
- throw new WPinternalsException("Failed to patch MainOS", "An error occured while patching Operating System files on the MainOS partition you provided. Make sure your phone runs a supported Operating System version.");
- }
- }
- LogFile.Log("Bootloader unlocked on image", LogType.FileAndConsole);
- break;
- case "enablerootaccessonmountedimage":
- LogFile.Log("Command: Enable root access on mounted image", LogType.FileAndConsole);
- if (args.Length < 4)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -EnableRootAccessOnMountedImage ");
- }
-
- FFUFilePath = null;
- EfiEspImagePath = args[2];
- MainOsImagePath = args[3];
- if (args.Length > 4)
- {
- FFUFilePath = args[4];
- }
-
- if (FFUFilePath != null)
- {
- FFU SupportedFFU = new(FFUFilePath);
- LogFile.Log("Supported FFU: " + SupportedFFU.Path);
- byte[] SupportedEFIESP = SupportedFFU.GetPartition("EFIESP");
- DiscUtils.Fat.FatFileSystem SupportedEFIESPFileSystem = new(new MemoryStream(SupportedEFIESP));
- DiscUtils.Streams.SparseStream SupportedMobileStartupStream = SupportedEFIESPFileSystem.OpenFile(@"\Windows\System32\Boot\mobilestartup.efi", FileMode.Open);
- MemoryStream SupportedMobileStartupMemStream = new();
- SupportedMobileStartupStream.CopyTo(SupportedMobileStartupMemStream);
- byte[] SupportedMobileStartup = SupportedMobileStartupMemStream.ToArray();
- SupportedMobileStartupMemStream.Close();
- SupportedMobileStartupStream.Close();
-
- // Save supported mobilestartup.efi
- LogFile.Log("Taking mobilestartup.efi from donor-FFU");
- Stream MobileStartupStream = File.Open(Path.Combine(EfiEspImagePath, @"Windows\System32\Boot\mobilestartup.efi"), FileMode.Create, FileAccess.Write);
- MobileStartupStream.Write(SupportedMobileStartup, 0, SupportedMobileStartup.Length);
- MobileStartupStream.Close();
- }
-
- App.PatchEngine.TargetPath = EfiEspImagePath;
- PatchResult = App.PatchEngine.Patch("SecureBootHack-V2-EFIESP");
- if (!PatchResult)
- {
- throw new WPinternalsException("Failed to patch bootloader", "An error occured while patching Operating System files on the EFIESP partition provided. Make sure no boot files have been tampered with and you use the latest version of the tool. This error cannot be caused by an incorrect Operating System version as the tool automatically uses replacement if the version isn't supported, unless the replacement files have been tampered with or are not compatible.");
- }
-
- // Edit BCD
- LogFile.Log("Edit BCD");
- using (Stream BCDFileStream = File.Open(Path.Combine(EfiEspImagePath, @"efi\Microsoft\Boot\BCD"), FileMode.Open, FileAccess.ReadWrite))
- {
- using DiscUtils.Registry.RegistryHive BCDHive = new(BCDFileStream);
- DiscUtils.BootConfig.Store BCDStore = new(BCDHive.Root);
- DiscUtils.BootConfig.BcdObject MobileStartupObject = BCDStore.GetObject(new Guid("{01de5a27-8705-40db-bad6-96fa5187d4a6}"));
- DiscUtils.BootConfig.Element NoCodeIntegrityElement = MobileStartupObject.GetElement(0x16000048);
- if (NoCodeIntegrityElement != null)
- {
- NoCodeIntegrityElement.Value = DiscUtils.BootConfig.ElementValue.ForBoolean(true);
- }
- else
- {
- MobileStartupObject.AddElement(0x16000048, DiscUtils.BootConfig.ElementValue.ForBoolean(true));
- }
-
- DiscUtils.BootConfig.BcdObject WinLoadObject = BCDStore.GetObject(new Guid("{7619dcc9-fafe-11d9-b411-000476eba25f}"));
- NoCodeIntegrityElement = WinLoadObject.GetElement(0x16000048);
- if (NoCodeIntegrityElement != null)
- {
- NoCodeIntegrityElement.Value = DiscUtils.BootConfig.ElementValue.ForBoolean(true);
- }
- else
- {
- WinLoadObject.AddElement(0x16000048, DiscUtils.BootConfig.ElementValue.ForBoolean(true));
- }
- }
-
- App.PatchEngine.TargetPath = MainOsImagePath;
- PatchResult = App.PatchEngine.Patch("SecureBootHack-MainOS");
- if (!PatchResult)
- {
- throw new WPinternalsException("Failed to patch MainOS", "An error occured while patching Operating System files on the MainOS partition you provided. Make sure your phone runs a supported Operating System version.");
- }
-
- PatchResult = App.PatchEngine.Patch("RootAccess-MainOS");
- if (!PatchResult)
- {
- throw new WPinternalsException("Failed to patch MainOS", "An error occured while modifying Operating System files on the MainOS partition you provided for Root Access. Make sure your phone runs a supported Operating System version.");
- }
-
- LogFile.Log("Root access enabled on image", LogType.FileAndConsole);
- break;
- case "downloadffu":
- LogFile.Log("Command: Download FFU", LogType.FileAndConsole);
- Notifier = new PhoneNotifierViewModel();
- UIContext.Send(s => Notifier.Start(), null);
- if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
- {
- NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
- ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
- }
- else if ((Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) || (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash))
- {
- FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
- Info = FlashModel.ReadPhoneInfo();
- ProductCode = Info.ProductCode;
- }
- else
- {
- NormalModel = (NokiaPhoneModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
- ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
- }
- URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
- DownloadFolder = args.Length >= 3
- ? args[4]
- : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
-
- if (!Directory.Exists(DownloadFolder))
- {
- Directory.CreateDirectory(DownloadFolder);
- }
-
- LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
- LogFile.Log("URL: " + URL, LogType.FileAndConsole);
- URI = new Uri(URL);
- FFUFileName = Path.GetFileName(URI.LocalPath);
- LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
- FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
- LogFile.Log("Downloading...", LogType.FileAndConsole);
- using (System.Net.WebClient myWebClient = new())
- {
- await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
- }
- LogFile.Log("Download finished", LogType.FileAndConsole);
- App.Config.AddFfuToRepository(FFUFilePath);
- Notifier.Stop();
- break;
- case "downloadffubyoperatorcode":
- LogFile.Log("Command: Download FFU by Operator Code", LogType.FileAndConsole);
- if (args.Length < 4)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadFFUbyOperatorCode ");
- }
-
- ProductType = args[2];
- LogFile.Log("Product type: " + ProductType, LogType.FileAndConsole);
- OperatorCode = args[3];
- LogFile.Log("Operator code: " + OperatorCode, LogType.FileAndConsole);
- DownloadFolder = args.Length >= 5
- ? args[4]
- : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
-
- if (!Directory.Exists(DownloadFolder))
- {
- Directory.CreateDirectory(DownloadFolder);
- }
-
- LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
- URL = LumiaDownloadModel.SearchFFU(ProductType, null, OperatorCode);
- LogFile.Log("URL: " + URL, LogType.FileAndConsole);
- URI = new Uri(URL);
- FFUFileName = Path.GetFileName(URI.LocalPath);
- LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
- FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
- LogFile.Log("Downloading...", LogType.FileAndConsole);
- using (System.Net.WebClient myWebClient = new())
- {
- await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
- }
- LogFile.Log("Download finished", LogType.FileAndConsole);
- App.Config.AddFfuToRepository(FFUFilePath);
- break;
- case "downloadffubyproductcode":
- LogFile.Log("Command: Download FFU by Product Code", LogType.FileAndConsole);
- if (args.Length < 3)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadFFUbyProductCode ");
- }
-
- ProductCode = args[2];
- LogFile.Log("Product code: " + ProductCode, LogType.FileAndConsole);
- URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
- DownloadFolder = args.Length >= 4
- ? args[3]
- : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
-
- if (!Directory.Exists(DownloadFolder))
- {
- Directory.CreateDirectory(DownloadFolder);
- }
-
- LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
- LogFile.Log("URL: " + URL, LogType.FileAndConsole);
- URI = new Uri(URL);
- FFUFileName = Path.GetFileName(URI.LocalPath);
- LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
- FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
- LogFile.Log("Downloading...", LogType.FileAndConsole);
- using (System.Net.WebClient myWebClient = new())
- {
- await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
- }
- LogFile.Log("Download finished", LogType.FileAndConsole);
- App.Config.AddFfuToRepository(FFUFilePath);
- break;
- case "downloadffubyproducttype":
- LogFile.Log("Command: Download FFU by Product Type", LogType.FileAndConsole);
- if (args.Length < 3)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadFFUbyProductType ");
- }
-
- ProductType = args[2];
- LogFile.Log("Product type: " + ProductType, LogType.FileAndConsole);
- DownloadFolder = args.Length >= 4
- ? args[3]
- : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
-
- if (!Directory.Exists(DownloadFolder))
- {
- Directory.CreateDirectory(DownloadFolder);
- }
-
- LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
- URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
- LogFile.Log("URL: " + URL, LogType.FileAndConsole);
- URI = new Uri(URL);
- FFUFileName = Path.GetFileName(URI.LocalPath);
- LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
- FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
- LogFile.Log("Downloading...", LogType.FileAndConsole);
- using (System.Net.WebClient myWebClient = new())
- {
- await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
- }
- LogFile.Log("Download finished", LogType.FileAndConsole);
- App.Config.AddFfuToRepository(FFUFilePath);
- break;
- case "searchffubyproducttype":
- LogFile.Log("Command: Search FFU by Product Type", LogType.FileAndConsole);
- if (args.Length < 3)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -SearchFFUbyProductType ");
- }
-
- ProductType = args[2];
- LogFile.Log("Lumia model: " + ProductType, LogType.FileAndConsole);
- URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
- LogFile.Log("URL: " + URL, LogType.FileAndConsole);
- URI = new Uri(URL);
- FFUFileName = Path.GetFileName(URI.LocalPath);
- LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
- break;
- case "downloademergency":
- LogFile.Log("Command: Download Emergency files", LogType.FileAndConsole);
- Notifier = new PhoneNotifierViewModel();
- UIContext.Send(s => Notifier.Start(), null);
- if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
- {
- NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
- ProductType = NormalModel.ExecuteJsonMethodAsString("ReadManufacturerModelName", "ManufacturerModelName");
- if (ProductType.Contains('_'))
- {
- ProductType = ProductType.Substring(0, ProductType.IndexOf('_'));
- }
- }
- else if ((Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) || (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash))
- {
- FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
- Info = FlashModel.ReadPhoneInfo();
- ProductType = Info.Type;
- }
- else
- {
- NormalModel = (NokiaPhoneModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
- ProductType = NormalModel.ExecuteJsonMethodAsString("ReadManufacturerModelName", "ManufacturerModelName");
- if (ProductType.Contains('_'))
- {
- ProductType = ProductType.Substring(0, ProductType.IndexOf('_'));
- }
- }
- URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
- if (URLs != null)
- {
- DownloadFolder = args.Length >= 3
- ? args[2]
- : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
-
- if (!Directory.Exists(DownloadFolder))
- {
- Directory.CreateDirectory(DownloadFolder);
- }
-
- LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
- for (int i = 0; i < URLs.Length; i++)
- {
- LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
- URI = new Uri(URLs[i]);
- EmergencyFileName = Path.GetFileName(URI.LocalPath);
- LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
- EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
- if (i == 0)
- {
- ProgrammerPath = EmergencyFilePath;
- }
- else
- {
- PayloadPath = EmergencyFilePath;
- }
-
- LogFile.Log("Downloading...", LogType.FileAndConsole);
- using (System.Net.WebClient myWebClient = new())
- {
- await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
- }
- LogFile.Log("Download finished", LogType.FileAndConsole);
- }
- App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
- }
- Notifier.Stop();
- break;
- case "downloademergencybyproducttype":
- LogFile.Log("Command: Download Emergency files", LogType.FileAndConsole);
- if (args.Length < 3)
- {
- throw new WPinternalsException("Wrong number of arguments. Usage: WPinternals.exe -DownloadEmergencyByProductType ");
- }
-
- ProductType = args[2];
- URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
- if (URLs != null)
- {
- DownloadFolder = args.Length >= 4
- ? args[3]
- : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
-
- if (!Directory.Exists(DownloadFolder))
- {
- Directory.CreateDirectory(DownloadFolder);
- }
-
- LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
- for (int i = 0; i < URLs.Length; i++)
- {
- LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
- URI = new Uri(URLs[i]);
- EmergencyFileName = Path.GetFileName(URI.LocalPath);
- LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
- EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
- if (i == 0)
- {
- ProgrammerPath = EmergencyFilePath;
- }
- else
- {
- PayloadPath = EmergencyFilePath;
- }
-
- LogFile.Log("Downloading...", LogType.FileAndConsole);
- using (System.Net.WebClient myWebClient = new())
- {
- await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
- }
- LogFile.Log("Download finished", LogType.FileAndConsole);
- }
- App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
- }
- break;
- case "downloadall":
- LogFile.Log("Command: Download all", LogType.FileAndConsole);
- Notifier = new PhoneNotifierViewModel();
- UIContext.Send(s => Notifier.Start(), null);
- if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
- {
- NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
- ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
- }
- else if ((Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) || (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash))
- {
- FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
- Info = FlashModel.ReadPhoneInfo();
- ProductCode = Info.ProductCode;
- }
- else
- {
- NormalModel = (NokiaPhoneModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
- ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
- }
- URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
- DownloadFolder = args.Length >= 3
- ? args[2]
- : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
-
- if (!Directory.Exists(DownloadFolder))
- {
- Directory.CreateDirectory(DownloadFolder);
- }
-
- LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
- LogFile.Log("URL: " + URL, LogType.FileAndConsole);
- URI = new Uri(URL);
- FFUFileName = Path.GetFileName(URI.LocalPath);
- LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
- FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
- LogFile.Log("Downloading...", LogType.FileAndConsole);
- using (System.Net.WebClient myWebClient = new())
- {
- await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
- }
- LogFile.Log("Download finished", LogType.FileAndConsole);
- App.Config.AddFfuToRepository(FFUFilePath);
-
- URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
- if (URLs != null)
- {
- for (int i = 0; i < URLs.Length; i++)
- {
- LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
- URI = new Uri(URLs[i]);
- EmergencyFileName = Path.GetFileName(URI.LocalPath);
- LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
- EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
- if (i == 0)
- {
- ProgrammerPath = EmergencyFilePath;
- }
- else
- {
- PayloadPath = EmergencyFilePath;
- }
-
- LogFile.Log("Downloading...", LogType.FileAndConsole);
- using (System.Net.WebClient myWebClient = new())
- {
- await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
- }
- LogFile.Log("Download finished", LogType.FileAndConsole);
- }
- App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
- }
-
- if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
- {
- ProductType = "RM-1085";
-
- URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
- DownloadFolder = args.Length >= 3
- ? args[2]
- : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
-
- if (!Directory.Exists(DownloadFolder))
- {
- Directory.CreateDirectory(DownloadFolder);
- }
-
- LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
- LogFile.Log("URL: " + URL, LogType.FileAndConsole);
- URI = new Uri(URL);
- FFUFileName = Path.GetFileName(URI.LocalPath);
- LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
- FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
- LogFile.Log("Downloading...", LogType.FileAndConsole);
- using (System.Net.WebClient myWebClient = new())
- {
- await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
- }
- LogFile.Log("Download finished", LogType.FileAndConsole);
- App.Config.AddFfuToRepository(FFUFilePath);
-
- if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
- {
- throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
- }
- }
- Notifier.Stop();
- break;
- case "downloadallbyproducttype":
- LogFile.Log("Command: Download all by Product Type", LogType.FileAndConsole);
- if (args.Length < 3)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadAllByProductType ");
- }
-
- ProductType = args[2];
- LogFile.Log("Product type: " + ProductType, LogType.FileAndConsole);
- DownloadFolder = args.Length >= 4
- ? args[3]
- : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
-
- if (!Directory.Exists(DownloadFolder))
- {
- Directory.CreateDirectory(DownloadFolder);
- }
-
- LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
- URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
- LogFile.Log("URL: " + URL, LogType.FileAndConsole);
- URI = new Uri(URL);
- FFUFileName = Path.GetFileName(URI.LocalPath);
- LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
- FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
- LogFile.Log("Downloading...", LogType.FileAndConsole);
- using (System.Net.WebClient myWebClient = new())
- {
- await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
- }
- LogFile.Log("Download finished", LogType.FileAndConsole);
- App.Config.AddFfuToRepository(FFUFilePath);
-
- URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
- if (URLs != null)
- {
- for (int i = 0; i < URLs.Length; i++)
- {
- LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
- URI = new Uri(URLs[i]);
- EmergencyFileName = Path.GetFileName(URI.LocalPath);
- LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
- EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
- if (i == 0)
- {
- ProgrammerPath = EmergencyFilePath;
- }
- else
- {
- PayloadPath = EmergencyFilePath;
- }
-
- LogFile.Log("Downloading...", LogType.FileAndConsole);
- using (System.Net.WebClient myWebClient = new())
- {
- await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
- }
- LogFile.Log("Download finished", LogType.FileAndConsole);
- }
- App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
- }
-
- if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
- {
- ProductType = "RM-1085";
-
- URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
- DownloadFolder = args.Length >= 4
- ? args[3]
- : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
-
- if (!Directory.Exists(DownloadFolder))
- {
- Directory.CreateDirectory(DownloadFolder);
- }
-
- LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
- LogFile.Log("URL: " + URL, LogType.FileAndConsole);
- URI = new Uri(URL);
- FFUFileName = Path.GetFileName(URI.LocalPath);
- LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
- FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
- LogFile.Log("Downloading...", LogType.FileAndConsole);
- using (System.Net.WebClient myWebClient = new())
- {
- await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
- }
- LogFile.Log("Download finished", LogType.FileAndConsole);
- App.Config.AddFfuToRepository(FFUFilePath);
-
- if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
- {
- throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
- }
- }
- break;
- case "downloadallbyproductcode":
- LogFile.Log("Command: Download all by Product Code", LogType.FileAndConsole);
- if (args.Length < 3)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadAllByProductCode ");
- }
-
- ProductCode = args[2];
- LogFile.Log("Product code: " + ProductCode, LogType.FileAndConsole);
- URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
- DownloadFolder = args.Length >= 4
- ? args[3]
- : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
-
- if (!Directory.Exists(DownloadFolder))
- {
- Directory.CreateDirectory(DownloadFolder);
- }
-
- LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
- LogFile.Log("URL: " + URL, LogType.FileAndConsole);
- URI = new Uri(URL);
- FFUFileName = Path.GetFileName(URI.LocalPath);
- LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
- FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
- LogFile.Log("Downloading...", LogType.FileAndConsole);
- using (System.Net.WebClient myWebClient = new())
- {
- await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
- }
- LogFile.Log("Download finished", LogType.FileAndConsole);
- App.Config.AddFfuToRepository(FFUFilePath);
-
- URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
- if (URLs != null)
- {
- for (int i = 0; i < URLs.Length; i++)
- {
- LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
- URI = new Uri(URLs[i]);
- EmergencyFileName = Path.GetFileName(URI.LocalPath);
- LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
- EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
- if (i == 0)
- {
- ProgrammerPath = EmergencyFilePath;
- }
- else
- {
- PayloadPath = EmergencyFilePath;
- }
-
- LogFile.Log("Downloading...", LogType.FileAndConsole);
- using (System.Net.WebClient myWebClient = new())
- {
- await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
- }
- LogFile.Log("Download finished", LogType.FileAndConsole);
- }
- App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
- }
-
- if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
- {
- ProductType = "RM-1085";
-
- URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
- DownloadFolder = args.Length >= 4
- ? args[3]
- : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
-
- if (!Directory.Exists(DownloadFolder))
- {
- Directory.CreateDirectory(DownloadFolder);
- }
-
- LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
- LogFile.Log("URL: " + URL, LogType.FileAndConsole);
- URI = new Uri(URL);
- FFUFileName = Path.GetFileName(URI.LocalPath);
- LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
- FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
- LogFile.Log("Downloading...", LogType.FileAndConsole);
- using (System.Net.WebClient myWebClient = new())
- {
- await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
- }
- LogFile.Log("Download finished", LogType.FileAndConsole);
- App.Config.AddFfuToRepository(FFUFilePath);
-
- if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
- {
- throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
- }
- }
- break;
- case "downloadallbyoperatorcode":
- LogFile.Log("Command: Download FFU by Operator Code", LogType.FileAndConsole);
- if (args.Length < 4)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadFFUbyOperatorCode ");
- }
-
- ProductType = args[2];
- LogFile.Log("Product type: " + ProductType, LogType.FileAndConsole);
- OperatorCode = args[3];
- LogFile.Log("Operator code: " + OperatorCode, LogType.FileAndConsole);
- DownloadFolder = args.Length >= 5
- ? args[4]
- : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
-
- if (!Directory.Exists(DownloadFolder))
- {
- Directory.CreateDirectory(DownloadFolder);
- }
-
- LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
- URL = LumiaDownloadModel.SearchFFU(ProductType, null, OperatorCode);
- LogFile.Log("URL: " + URL, LogType.FileAndConsole);
- URI = new Uri(URL);
- FFUFileName = Path.GetFileName(URI.LocalPath);
- LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
- FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
- LogFile.Log("Downloading...", LogType.FileAndConsole);
- using (System.Net.WebClient myWebClient = new())
- {
- await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
- }
- LogFile.Log("Download finished", LogType.FileAndConsole);
- App.Config.AddFfuToRepository(FFUFilePath);
-
- URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
- if (URLs != null)
- {
- for (int i = 0; i < URLs.Length; i++)
- {
- LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
- URI = new Uri(URLs[i]);
- EmergencyFileName = Path.GetFileName(URI.LocalPath);
- LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
- EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
- if (i == 0)
- {
- ProgrammerPath = EmergencyFilePath;
- }
- else
- {
- PayloadPath = EmergencyFilePath;
- }
-
- LogFile.Log("Downloading...", LogType.FileAndConsole);
- using (System.Net.WebClient myWebClient = new())
- {
- await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
- }
- LogFile.Log("Download finished", LogType.FileAndConsole);
- }
- App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
- }
-
- if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
- {
- ProductType = "RM-1085";
-
- URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
- DownloadFolder = args.Length >= 5
- ? args[4]
- : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
-
- if (!Directory.Exists(DownloadFolder))
- {
- Directory.CreateDirectory(DownloadFolder);
- }
-
- LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
- LogFile.Log("URL: " + URL, LogType.FileAndConsole);
- URI = new Uri(URL);
- FFUFileName = Path.GetFileName(URI.LocalPath);
- LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
- FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
- LogFile.Log("Downloading...", LogType.FileAndConsole);
- using (System.Net.WebClient myWebClient = new())
- {
- await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
- }
- LogFile.Log("Download finished", LogType.FileAndConsole);
- App.Config.AddFfuToRepository(FFUFilePath);
-
- if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
- {
- throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
- }
- }
- break;
- case "rewritepartitionsfrommassstorage":
- if (args.Length < 2)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -RewritePartitionsFromMassStorage \n The name of the imgs must be the partition names. For example, DPP.img will get written to the DPP partition.");
- }
-
- await TestCode.RewriteParts(args[2]);
- break;
- case "restoregptusingedl":
- if (args.Length < 3)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -RestoreGPTUsingEDL ");
- }
-
- await TestCode.RecoverBadGPT(args[2], args[3]);
- break;
- case "restoregptusingmassstorage":
- if (args.Length < 2)
- {
- throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -RestoreGPTUsingMassStorage ");
- }
-
- await TestCode.RewriteGPT(args[2]);
- break;
- default:
- LogFile.Log("", LogType.ConsoleOnly);
- LogFile.Log("WPinternals commandline usage:", LogType.ConsoleOnly);
- LogFile.Log("", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -ShowPhoneInfo", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -AddFFU ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -AddEmergency ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -RemoveFFU ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -RemoveEmergency ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -ListRepository", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -FindFlashingProfile ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -UnlockBootloader", LogType.ConsoleOnly);
- LogFile.Log(" ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -FixBootAfterUnlockingBootloader", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -EnableRootAccess", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -UnlockBootLoaderOnImage ", LogType.ConsoleOnly);
- LogFile.Log(" ", LogType.ConsoleOnly);
- LogFile.Log(" ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -EnableRootAccessOnImage ", LogType.ConsoleOnly);
- LogFile.Log(" ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -UnlockBootLoaderOnMountedImage ", LogType.ConsoleOnly);
- LogFile.Log(" ", LogType.ConsoleOnly);
- LogFile.Log(" ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -EnableRootAccessOnMountedImage ", LogType.ConsoleOnly);
- LogFile.Log(" ", LogType.ConsoleOnly);
- LogFile.Log(" ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -EnableTestSigning", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -RelockPhone", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -SwitchToMassStorageMode", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -FlashFFU ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -FlashCustomROM ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -FlashPartition ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -FlashRaw ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -ClearNV", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -ReadGPT", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -BackupGPT ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -RestoreGPT ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -MergeGPT ", LogType.ConsoleOnly);
- LogFile.Log(" ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -MergeGPT ", LogType.ConsoleOnly);
- LogFile.Log(" ", LogType.ConsoleOnly);
- LogFile.Log(" ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -ShowFFU ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -DumpFFU ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -DownloadFFU ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -DownloadFFUbyProductType ", LogType.ConsoleOnly);
- LogFile.Log(" ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -DownloadFFUbyProductCode ", LogType.ConsoleOnly);
- LogFile.Log(" ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -DownloadFFUbyOperatorCode ", LogType.ConsoleOnly);
- LogFile.Log(" ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -DownloadEmergency ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -DownloadEmergencyByProductType ", LogType.ConsoleOnly);
- LogFile.Log(" ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -DownloadAll ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -DownloadAllByProductType ", LogType.ConsoleOnly);
- LogFile.Log(" ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -DownloadAllByProductCode ", LogType.ConsoleOnly);
- LogFile.Log(" ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -DownloadAllByOperatorCode ", LogType.ConsoleOnly);
- LogFile.Log(" ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -DumpUEFI ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -TestProgrammer ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -RewritePartitionsFromMassStorage ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -RestoreGPTUsingEDL ", LogType.ConsoleOnly);
- LogFile.Log("WPinternals -RestoreGPTUsingMassStorage ", LogType.ConsoleOnly);
- break;
- }
- }
- catch (Exception Ex)
- {
- LogFile.LogException(Ex);
- }
-
- if (Environment.GetCommandLineArgs().Length > 1)
- {
- CloseConsole();
- }
- }
-
- // http://stackoverflow.com/questions/472282/show-console-in-windows-application
- // https://stackoverflow.com/questions/807998/how-do-i-create-a-c-sharp-app-that-decides-itself-whether-to-show-as-a-console-o
- // http://www.csharp411.com/console-output-from-winforms-application/#comment-76
- // https://stackoverflow.com/questions/1305257/using-attachconsole-user-must-hit-enter-to-get-regular-command-line
- internal static void OpenConsole()
- {
- if (IsConsoleVisible)
- {
- return;
- }
-
- if (AttachConsole(-1))
- {
- Console.Write("\r" + new string(' ', Console.WindowWidth) + "\r"); // Prompt was already printed. Clear that line.
-
- /*
- Other possibility to clear line:
-
- System.Console.CursorLeft = 0;
- char[] bl = System.Linq.Enumerable.ToArray(System.Linq.Enumerable.Repeat(' ', System.Console.WindowWidth - 1));
- System.Console.Write(bl);
- System.Console.CursorLeft = 0;
- */
-
- hConsoleWnd = GetForegroundWindow();
- }
- else
- {
- AllocConsole();
- IsNewConsoleCreated = true;
-
- hConsoleWnd = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
-
- // Support VS 2017 debugger without VS host process:
- try
- {
- // Console.OpenStandardOutput eventually calls into GetStdHandle. As per MSDN documentation of GetStdHandle: http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231(v=vs.85).aspx will return the redirected handle and not the allocated console:
- // "The standard handles of a process may be redirected by a call to SetStdHandle, in which case GetStdHandle returns the redirected handle. If the standard handles have been redirected, you can specify the CONIN$ value in a call to the CreateFile function to get a handle to a console's input buffer. Similarly, you can specify the CONOUT$ value to get a handle to a console's active screen buffer."
- // Get the handle to CONOUT$.
- IntPtr stdHandle = CreateFile("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
- Microsoft.Win32.SafeHandles.SafeFileHandle safeFileHandle = new(stdHandle, true);
- FileStream fileStream = new(safeFileHandle, FileAccess.Write);
- Encoding encoding = Encoding.GetEncoding(MY_CODE_PAGE);
- StreamWriter standardOutput = new(fileStream, encoding);
- standardOutput.AutoFlush = true;
- Console.SetOut(standardOutput);
- }
- catch
- {
- }
- }
-
- IsConsoleVisible = true;
-
- Console.CancelKeyPress += Console_CancelKeyPress;
-
- LogFile.LogApplicationVersion();
- }
-
- private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
- {
- LogFile.Log("Operation canceled!", LogType.FileOnly);
- LogFile.EndAction();
-
-#if PREVIEW
- Uploader.WaitForUploads();
-#endif
- }
-
- internal static void CloseConsole(bool Exit = true)
- {
- if (IsConsoleVisible)
- {
- if (IsNewConsoleCreated)
- {
- Console.WriteLine("Press any key to close...");
- Console.ReadKey();
- }
-
- PostMessage(hConsoleWnd, WM_KEYDOWN, VK_RETURN, 0);
-
- IsConsoleVisible = false;
-
- if (Exit)
- {
-#if PREVIEW
- Uploader.WaitForUploads();
-#endif
-
- Environment.Exit(0);
- }
- }
- }
- }
-}
+// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.Compression;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPinternals
+{
+ internal static class CommandLine
+ {
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern bool AllocConsole();
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern bool AttachConsole(int dwProcessId);
+
+ [DllImport("kernel32.dll")]
+ private static extern IntPtr GetConsoleWindow();
+
+ [DllImport("user32.dll")]
+ private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
+
+ private const UInt32 StdOutputHandle = 0xFFFFFFF5;
+
+ [DllImport("kernel32.dll")]
+ private static extern IntPtr GetStdHandle(UInt32 nStdHandle);
+
+ [DllImport("kernel32.dll")]
+ private static extern void SetStdHandle(UInt32 nStdHandle, IntPtr handle);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, uint lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, uint hTemplateFile);
+
+ [DllImport("user32.dll")]
+ private static extern IntPtr GetForegroundWindow();
+
+ private const int SW_HIDE = 0;
+ private const int SW_SHOW = 5;
+
+ private const int MY_CODE_PAGE = 437;
+ private const uint GENERIC_WRITE = 0x40000000;
+ private const uint FILE_SHARE_WRITE = 0x2;
+ private const uint OPEN_EXISTING = 0x3;
+
+ internal static bool IsConsoleVisible = false;
+ internal static bool IsNewConsoleCreated = false;
+
+ private static IntPtr hConsoleWnd;
+
+ [DllImport("User32.Dll", EntryPoint = "PostMessageA")]
+ private static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
+
+ private const int VK_RETURN = 0x0D;
+ private const int WM_KEYDOWN = 0x100;
+
+ ///
+ /// When the main window should not be shown, this function should call ExitProcess and it should not return.
+ ///
+ internal static async Task ParseCommandLine(System.Threading.SynchronizationContext UIContext)
+ {
+ FFU FFU = null;
+ PhoneNotifierViewModel Notifier;
+ NokiaFlashModel FlashModel;
+ NokiaPhoneModel NormalModel;
+ PhoneInfo Info;
+ string ProductType;
+ string ProductCode;
+ string OperatorCode;
+ string DownloadFolder;
+ string FFUFilePath;
+ string URL;
+ string[] URLs;
+ Uri URI;
+ string FFUFileName;
+ string EmergencyFileName;
+ string EmergencyFilePath;
+ string ProgrammerPath = "";
+ string PayloadPath = "";
+ string EfiEspImagePath = null;
+ string MainOsImagePath = null;
+ DiscUtils.Fat.FatFileSystem UnlockedEFIESPFileSystem;
+ DiscUtils.Ntfs.NtfsFileSystem UnlockedMainOsFileSystem;
+ bool PatchResult;
+
+ try
+ {
+ string[] args = Environment.GetCommandLineArgs();
+
+ if (args.Length == 1)
+ {
+ return;
+ }
+
+ switch (args[1].ToLower().TrimStart(new char[] { '-', '/' }))
+ {
+#if DEBUG
+ case "test":
+ LogFile.BeginAction("Test");
+ await TestCode.Test(UIContext);
+ LogFile.EndAction("Test");
+ break;
+#endif
+ case "flashpartition":
+ if (args.Length < 4)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -FlashPartition ");
+ }
+
+ if (args.Length >= 5)
+ {
+ await LumiaV2UnlockBootViewModel.LumiaV2FlashPartition(UIContext, args[4], args[2], args[3]);
+ }
+ else
+ {
+ await LumiaV2UnlockBootViewModel.LumiaV2FlashPartition(UIContext, null, args[2], args[3]);
+ }
+
+ break;
+ case "flashraw":
+ if (args.Length < 4)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -FlashRaw ");
+ }
+
+ UInt64 StartSector = 0;
+ try
+ {
+ StartSector = args[2].StartsWith("0x", StringComparison.OrdinalIgnoreCase)
+ ? Convert.ToUInt64(args[2][2..], 16)
+ : Convert.ToUInt64(args[2], 10);
+ }
+ catch
+ {
+ LogFile.Log("Bad start sector", LogType.ConsoleOnly);
+ break;
+ }
+ if (args.Length >= 5)
+ {
+ await LumiaV2UnlockBootViewModel.LumiaV2FlashRaw(UIContext, StartSector, args[3], args[4]);
+ }
+ else
+ {
+ await LumiaV2UnlockBootViewModel.LumiaV2FlashRaw(UIContext, StartSector, args[3], null);
+ }
+
+ break;
+ case "flashpartitionimmediately":
+ if (args.Length < 5)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -FlashPartition ");
+ }
+
+ await LumiaV2UnlockBootViewModel.LumiaV2FlashPartition(UIContext, args[4], args[2], args[3], false);
+ break;
+ case "readgpt":
+ LogFile.BeginAction("ReadGPT");
+ try
+ {
+ Notifier = new PhoneNotifierViewModel();
+ UIContext.Send(s => Notifier.Start(), null);
+
+ FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader); // This also works for Bootloader Spec A
+
+ GPT GPT = FlashModel.ReadGPT(); // May throw NotSupportedException
+ foreach (Partition Partition in GPT.Partitions)
+ {
+ LogFile.Log(Partition.Name.PadRight(20) + "0x" + Partition.FirstSector.ToString("X8") + " - 0x" + Partition.LastSector.ToString("X8") + " " + Partition.Volume, LogType.ConsoleOnly);
+ }
+
+ if (FlashModel.ReadPhoneInfo(false).FlashAppProtocolVersionMajor >= 2)
+ {
+ FlashModel.SwitchToFlashAppContext();
+ }
+ else
+ {
+ await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
+ }
+
+ Notifier.Stop();
+ }
+ catch (Exception Ex)
+ {
+ LogFile.LogException(Ex);
+ }
+ finally
+ {
+ LogFile.EndAction("ReadGPT");
+ }
+ break;
+ case "backupgpt":
+ if (args.Length < 3)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -BackupGPT ");
+ }
+
+ LogFile.BeginAction("BackupGPT");
+ try
+ {
+ Notifier = new PhoneNotifierViewModel();
+ UIContext.Send(s => Notifier.Start(), null);
+ FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
+ GPT GPT = FlashModel.ReadGPT(); // May throw NotSupportedException
+ Directory.CreateDirectory(Path.GetDirectoryName(args[2]));
+ GPT.WritePartitions(args[2]);
+ FlashModel.SwitchToFlashAppContext();
+ Notifier.Stop();
+ }
+ catch (Exception Ex)
+ {
+ LogFile.LogException(Ex);
+ }
+ finally
+ {
+ LogFile.EndAction("BackupGPT");
+ }
+ break;
+ case "restoregpt":
+ if (args.Length < 3)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -RestoreGPT ");
+ }
+
+ LogFile.BeginAction("RestoreGPT");
+ try
+ {
+ Notifier = new PhoneNotifierViewModel();
+ UIContext.Send(s => Notifier.Start(), null);
+ FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
+ byte[] GptChunk = LumiaUnlockBootloaderViewModel.GetGptChunk(FlashModel, 0x20000);
+ GPT GPT = new(GptChunk);
+ string Xml = File.ReadAllText(args[2]);
+ GPT.MergePartitions(Xml, false);
+ GPT.Rebuild();
+ await LumiaV2UnlockBootViewModel.LumiaV2CustomFlash(Notifier, null, false, false, 0, GptChunk, true, true);
+ FlashModel.SwitchToFlashAppContext();
+ Notifier.Stop();
+ }
+ catch (Exception Ex)
+ {
+ LogFile.LogException(Ex);
+ }
+ finally
+ {
+ LogFile.EndAction("RestoreGPT");
+ }
+ break;
+ case "mergegpt":
+ if (args.Length < 4)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -MergeGPT Or use: WPinternals.exe -MergeGPT ");
+ }
+
+ LogFile.BeginAction("MergeGPT");
+ try
+ {
+ GPT GPT = GPT.ReadPartitions(args[2]);
+
+ ZipArchive Archive = null;
+ FileStream s = null;
+ try
+ {
+ s = new FileStream(args[3], FileMode.Open, FileAccess.Read);
+ Archive = new ZipArchive(s);
+ }
+ catch { }
+
+ if (Archive == null)
+ {
+ s?.Close();
+
+ // Assume Xml-file
+ GPT.MergePartitionsFromFile(args[3], true);
+ }
+ else
+ {
+ ZipArchiveEntry PartitionEntry = Archive.GetEntry("Partitions.xml");
+ if (PartitionEntry == null)
+ {
+ GPT.MergePartitions(null, true, Archive);
+ }
+ else
+ {
+ using Stream ZipStream = PartitionEntry.Open();
+ using StreamReader ZipReader = new(ZipStream);
+ string PartitionXml = ZipReader.ReadToEnd();
+ GPT.MergePartitions(PartitionXml, true, Archive);
+ }
+ }
+
+ Archive?.Dispose();
+
+ if (args.Length >= 5)
+ {
+ GPT.WritePartitions(args[4]);
+ }
+
+ foreach (Partition Partition in GPT.Partitions)
+ {
+ LogFile.Log(Partition.Name.PadRight(20) + "0x" + Partition.FirstSector.ToString("X8") + " - 0x" + Partition.LastSector.ToString("X8") + " " + Partition.Volume, LogType.ConsoleOnly);
+ }
+ }
+ catch (Exception Ex)
+ {
+ LogFile.LogException(Ex);
+ }
+ finally
+ {
+ LogFile.EndAction("MergeGPT");
+ }
+ break;
+ case "dumpffu":
+ if (args.Length < 4)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DumpFFU ");
+ }
+
+ FFU = new FFU(args[2]);
+ if (args.Length < 5)
+ {
+ foreach (Partition Partition in FFU.GPT.Partitions)
+ {
+ if (FFU.IsPartitionPresentInFFU(Partition.Name))
+ {
+ FFU.WritePartition(Partition.Name, Path.Combine(args[3], Partition.Name + ".bin"));
+ }
+ }
+ }
+ else
+ {
+ Partition Target = FFU.GPT.GetPartition(args[4]);
+ if ((Target == null) || (!FFU.IsPartitionPresentInFFU(Target.Name)))
+ {
+ throw new InvalidOperationException("Partition not found in FFU!");
+ }
+
+ FFU.WritePartition(Target.Name, Path.Combine(args[3], Target.Name + ".bin"));
+ }
+ break;
+ case "dumpuefi":
+ if (args.Length < 4)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DumpUEFI ");
+ }
+
+ byte[] UefiBinary;
+ if (FFU.IsFFU(args[2]))
+ {
+ FFU = new FFU(args[2]);
+ UefiBinary = FFU.GetPartition("UEFI");
+ }
+ else
+ {
+ UefiBinary = File.ReadAllBytes(args[2]);
+ }
+
+ UEFI UEFI = new(UefiBinary);
+
+ foreach (EFI Efi in UEFI.EFIs)
+ {
+ byte[] EfiBinary = UEFI.GetFile(Efi.Guid);
+ string Name = Efi.Name ?? Efi.Guid.ToString();
+
+ if (!Name.Contains('.'))
+ {
+ Name += Efi.Type switch
+ {
+ 5 or 7 => ".dll",
+ 9 => ".exe",
+ _ => ".bin",
+ };
+ }
+ string EfiPath = Path.Combine(args[3], Name);
+ Directory.CreateDirectory(Path.GetDirectoryName(EfiPath));
+ File.WriteAllBytes(EfiPath, EfiBinary);
+ }
+ break;
+ case "testprogrammer":
+ if (args.Length < 3)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -TestProgrammer ");
+ }
+
+ await TestCode.TestProgrammer(UIContext, args[2]);
+ break;
+ case "findflashingprofile":
+ Notifier = new PhoneNotifierViewModel();
+ UIContext.Send(s => Notifier.Start(), null);
+ if (args.Length > 2)
+ {
+ await LumiaV2UnlockBootViewModel.LumiaV2FindFlashingProfile(Notifier, args[2]);
+ }
+ else
+ {
+ await LumiaV2UnlockBootViewModel.LumiaV2FindFlashingProfile(Notifier, null);
+ }
+
+ Notifier.Stop();
+ break;
+ case "findflashingprofileexperimental":
+ Notifier = new PhoneNotifierViewModel();
+ UIContext.Send(s => Notifier.Start(), null);
+ if (args.Length > 2)
+ {
+ await LumiaV2UnlockBootViewModel.LumiaV2FindFlashingProfile(Notifier, args[2], Experimental: true);
+ }
+ else
+ {
+ await LumiaV2UnlockBootViewModel.LumiaV2FindFlashingProfile(Notifier, null, Experimental: true);
+ }
+
+ Notifier.Stop();
+ break;
+ case "findflashingprofilenorestart":
+ Notifier = new PhoneNotifierViewModel();
+ UIContext.Send(s => Notifier.Start(), null);
+ if (args.Length > 2)
+ {
+ await LumiaV2UnlockBootViewModel.LumiaV2FindFlashingProfile(Notifier, args[2], false);
+ }
+ else
+ {
+ await LumiaV2UnlockBootViewModel.LumiaV2FindFlashingProfile(Notifier, null, false);
+ }
+
+ Notifier.Stop();
+ break;
+ case "enabletestsigning":
+ if (args.Length > 2)
+ {
+ await LumiaV2UnlockBootViewModel.LumiaV2EnableTestSigning(UIContext, args[2]);
+ }
+ else
+ {
+ await LumiaV2UnlockBootViewModel.LumiaV2EnableTestSigning(UIContext, null);
+ }
+
+ break;
+ case "enabletestsigningnorestart":
+ if (args.Length > 2)
+ {
+ await LumiaV2UnlockBootViewModel.LumiaV2EnableTestSigning(UIContext, args[2], false);
+ }
+ else
+ {
+ await LumiaV2UnlockBootViewModel.LumiaV2EnableTestSigning(UIContext, null, false);
+ }
+
+ break;
+ case "clearnv":
+ if (args.Length > 2)
+ {
+ await LumiaV2UnlockBootViewModel.LumiaV2ClearNV(UIContext, args[2]);
+ }
+ else
+ {
+ await LumiaV2UnlockBootViewModel.LumiaV2ClearNV(UIContext, null);
+ }
+
+ break;
+ case "switchtomassstoragemode":
+ LogFile.BeginAction("SwitchToMassStorageMode");
+ try
+ {
+ Notifier = new PhoneNotifierViewModel();
+ UIContext.Send(s => Notifier.Start(), null);
+ LogFile.Log("Command: Switch to Mass Storage Mode", LogType.FileAndConsole);
+ if (args.Length > 2)
+ {
+ await LumiaV2UnlockBootViewModel.LumiaV2SwitchToMassStorageMode(Notifier, args[2]);
+ }
+ else
+ {
+ await LumiaV2UnlockBootViewModel.LumiaV2SwitchToMassStorageMode(Notifier, null);
+ }
+
+ Notifier.Stop();
+ }
+ catch (Exception Ex)
+ {
+ LogFile.LogException(Ex);
+ }
+ finally
+ {
+ LogFile.EndAction("SwitchToMassStorageMode");
+ }
+ break;
+ case "relockphone":
+ Notifier = new PhoneNotifierViewModel();
+ try
+ {
+ UIContext.Send(s => Notifier.Start(), null);
+ FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
+ Info = FlashModel.ReadPhoneInfo();
+ Info.Log(LogType.ConsoleOnly);
+
+ FFU ProfileFFU = null;
+ FFU CurrentFFU;
+ for (int i = 2; i <= 3; i++)
+ {
+ if (args.Length > i)
+ {
+ CurrentFFU = new FFU(args[i]);
+ string CurrentVersion = CurrentFFU.GetOSVersion();
+ string PlatformID = CurrentFFU.PlatformID;
+
+ // Check if the current FFU matches the connected phone, so that the FFU can be used for profiling.
+ if (Info.PlatformID.StartsWith(PlatformID, StringComparison.OrdinalIgnoreCase))
+ {
+ ProfileFFU = CurrentFFU;
+ }
+ }
+ }
+
+ if (ProfileFFU == null)
+ {
+ List FFUs = App.Config.FFURepository.Where(e => Info.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
+ ProfileFFU = FFUs.Count > 0
+ ? new FFU(FFUs[0].Path)
+ : throw new WPinternalsException("Profile FFU missing", "No profile FFU has been found in the repository for your device. You can add a profile FFU within the download section of the tool or by using the command line.");
+ }
+ LogFile.Log("Profile FFU: " + ProfileFFU.Path);
+
+ UIContext.Send(s => Notifier.Start(), null);
+
+ await LumiaUnlockBootloaderViewModel.LumiaRelockUEFI(Notifier, ProfileFFU.Path);
+ }
+ catch (Exception Ex)
+ {
+ LogFile.LogException(Ex);
+ }
+ Notifier.Stop();
+ break;
+ case "addffu":
+ if (args.Length < 3)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -AddFFU ");
+ }
+
+ App.Config.AddFfuToRepository(args[2]);
+ break;
+ case "removeffu":
+ if (args.Length < 3)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -RemoveFFU ");
+ }
+
+ App.Config.RemoveFfuFromRepository(args[2]);
+ break;
+ case "addemergency":
+ if (args.Length < 5)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -AddEmergnency ");
+ }
+
+ App.Config.AddEmergencyToRepository(args[2], args[3], args[4]);
+ break;
+ case "removeemergency":
+ if (args.Length < 3)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -RemoveEmergency ");
+ }
+
+ App.Config.RemoveEmergencyFromRepository(args[2]);
+ break;
+ case "listrepository":
+ int Count = 0;
+ LogFile.Log("", LogType.ConsoleOnly);
+ LogFile.Log("FFU Repository:", LogType.ConsoleOnly);
+ foreach (FFUEntry Entry in App.Config.FFURepository)
+ {
+ LogFile.Log("", LogType.ConsoleOnly);
+ LogFile.Log("FFU " + Count.ToString() + ":", LogType.ConsoleOnly);
+ LogFile.Log("File: " + Entry.Path + (Entry.Exists() ? "" : " (file is missing)"), LogType.ConsoleOnly);
+ LogFile.Log("Platform ID: " + Entry.PlatformID, LogType.ConsoleOnly);
+ if (Entry.FirmwareVersion != null)
+ {
+ LogFile.Log("Firmware version: " + Entry.FirmwareVersion, LogType.ConsoleOnly);
+ }
+
+ if (Entry.OSVersion != null)
+ {
+ LogFile.Log("OS version: " + Entry.OSVersion, LogType.ConsoleOnly);
+ }
+
+ Count++;
+ }
+ LogFile.Log("", LogType.ConsoleOnly);
+ LogFile.Log("Emergency Repository:", LogType.ConsoleOnly);
+ Count = 0;
+ foreach (EmergencyFileEntry Entry in App.Config.EmergencyRepository)
+ {
+ LogFile.Log("", LogType.ConsoleOnly);
+ LogFile.Log("Emergency " + Count.ToString() + ":", LogType.ConsoleOnly);
+ LogFile.Log("Type: " + Entry.Type, LogType.ConsoleOnly);
+ LogFile.Log("Programmer file: " + Entry.ProgrammerPath + (Entry.ProgrammerExists() ? "" : " (file is missing)"), LogType.ConsoleOnly);
+ if (Entry.PayloadPath != null)
+ {
+ LogFile.Log("Payload file: " + Entry.PayloadPath + (Entry.PayloadExists() ? "" : " (file is missing)"), LogType.ConsoleOnly);
+ }
+
+ Count++;
+ }
+ break;
+ case "showffu":
+ if (args.Length < 3)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -ShowFFU ");
+ }
+
+ string FFUPath = args[2];
+ LogFile.Log("FFU: " + FFUPath, LogType.ConsoleOnly);
+ FFU = new FFU(FFUPath);
+
+ // Show basics
+ LogFile.Log("Platform ID: " + FFU.PlatformID, LogType.ConsoleOnly);
+ string Firmware = FFU.GetFirmwareVersion();
+ if (Firmware != null)
+ {
+ LogFile.Log("Firmware version: " + Firmware, LogType.ConsoleOnly);
+ }
+
+ string OSVersion = FFU.GetOSVersion();
+ if (OSVersion != null)
+ {
+ LogFile.Log("OS version: " + OSVersion, LogType.ConsoleOnly);
+ }
+
+ // Show partitions from GPT (also show which partitions are in the FFU payload)
+ LogFile.Log("", LogType.ConsoleOnly);
+ LogFile.Log("Partition table:", LogType.ConsoleOnly);
+ LogFile.Log("Name".PadRight(20) + "Start-sector".PadRight(20) + "End-sector".PadRight(20) + "Present in FFU", LogType.ConsoleOnly);
+ foreach (Partition p in FFU.GPT.Partitions)
+ {
+ LogFile.Log(p.Name.PadRight(20) + ("0x" + p.FirstSector.ToString("X16")).PadRight(20) + ("0x" + p.LastSector.ToString("X16")).PadRight(20) + (FFU.IsPartitionPresentInFFU(p.Name) ? "Yes" : "No"), LogType.ConsoleOnly);
+ }
+ break;
+ case "showphoneinfo":
+ LogFile.Log("Command: Show phone info", LogType.FileAndConsole);
+ Notifier = new PhoneNotifierViewModel();
+ UIContext.Send(s => Notifier.Start(), null);
+ FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
+ Info = FlashModel.ReadPhoneInfo();
+ Info.Log(LogType.ConsoleOnly);
+ Notifier.Stop();
+ break;
+ case "unlockbootloader":
+ LogFile.BeginAction("UnlockBootloader");
+ try
+ {
+ LogFile.Log("Command: Unlock Bootloader", LogType.FileAndConsole);
+ Notifier = new PhoneNotifierViewModel();
+ UIContext.Send(s => Notifier.Start(), null);
+ FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
+ Info = FlashModel.ReadPhoneInfo();
+ Info.Log(LogType.ConsoleOnly);
+
+ FFU ProfileFFU = null;
+ FFU SupportedFFU = null;
+ FFU CurrentFFU;
+ for (int i = 2; i <= 3; i++)
+ {
+ if (args.Length > i)
+ {
+ CurrentFFU = new FFU(args[i]);
+ string CurrentVersion = CurrentFFU.GetOSVersion();
+ string PlatformID = CurrentFFU.PlatformID;
+
+ // Check if the current FFU matches the connected phone, so that the FFU can be used for profiling.
+ if (Info.PlatformID.StartsWith(PlatformID, StringComparison.OrdinalIgnoreCase))
+ {
+ ProfileFFU = CurrentFFU;
+ }
+
+ // Check if the current FFU is supported for unlocking.
+ if (App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == CurrentVersion))
+ {
+ SupportedFFU = CurrentFFU;
+ }
+ }
+ }
+
+ if (ProfileFFU == null)
+ {
+ List FFUs = App.Config.FFURepository.Where(e => Info.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
+ ProfileFFU = FFUs.Count > 0
+ ? new FFU(FFUs[0].Path)
+ : throw new WPinternalsException("Profile FFU missing", "No profile FFU has been found in the repository for your device. You can add a profile FFU within the download section of the tool or by using the command line.");
+ }
+ LogFile.Log("Profile FFU: " + ProfileFFU.Path);
+
+ if (SupportedFFU == null)
+ {
+ List FFUs = App.Config.FFURepository.Where(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)).ToList();
+ SupportedFFU = FFUs.Count > 0
+ ? new FFU(FFUs[0].Path)
+ : throw new WPinternalsException("No donor-FFU found with supported OS version", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
+ }
+
+ await LumiaUnlockBootloaderViewModel.LumiaUnlockUEFI(Notifier, ProfileFFU.Path, null, SupportedFFU.Path);
+
+ Notifier.Stop();
+ }
+ catch (Exception Ex)
+ {
+ LogFile.LogException(Ex);
+ }
+ finally
+ {
+ LogFile.EndAction("UnlockBootloader");
+ }
+ break;
+ case "flashcustomrom":
+ LogFile.BeginAction("FlashCustomROM");
+ try
+ {
+ LogFile.Log("Command: Flash Custom ROM", LogType.FileAndConsole);
+ if (args.Length < 3)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -FlashCustomROM ");
+ }
+
+ string CustomRomPath = args[2];
+ LogFile.Log("Custom ROM: " + CustomRomPath, LogType.FileAndConsole);
+ Notifier = new PhoneNotifierViewModel();
+ UIContext.Send(s => Notifier.Start(), null);
+ FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
+ Info = FlashModel.ReadPhoneInfo();
+ Info.Log(LogType.ConsoleOnly);
+ LogFile.Log("Preparing to flash Custom ROM", LogType.FileAndConsole);
+ await LumiaV2UnlockBootViewModel.LumiaV2FlashArchive(Notifier, CustomRomPath);
+ LogFile.Log("Custom ROM flashed successfully", LogType.FileAndConsole);
+ Notifier.Stop();
+ }
+ catch (Exception Ex)
+ {
+ LogFile.LogException(Ex);
+ }
+ finally
+ {
+ LogFile.EndAction("FlashCustomROM");
+ }
+ break;
+ case "flashffu":
+ LogFile.BeginAction("FlashFFU");
+ try
+ {
+ LogFile.Log("Command: Flash FFU", LogType.FileAndConsole);
+ if (args.Length < 3)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -FlashFFU ");
+ }
+
+ FFUPath = args[2];
+ LogFile.Log("FFU file: " + FFUPath, LogType.FileAndConsole);
+ Notifier = new PhoneNotifierViewModel();
+ UIContext.Send(s => Notifier.Start(), null);
+ FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
+ Info = FlashModel.ReadPhoneInfo();
+ Info.Log(LogType.ConsoleOnly);
+ LogFile.Log("Flashing FFU...", LogType.FileAndConsole);
+ await Task.Run(() => FlashModel.FlashFFU(new FFU(FFUPath), true, (byte)(!Info.IsBootloaderSecure ? FlashOptions.SkipSignatureCheck : 0)));
+ LogFile.Log("FFU flashed successfully", LogType.FileAndConsole);
+ Notifier.Stop();
+ }
+ catch (Exception Ex)
+ {
+ LogFile.LogException(Ex);
+ }
+ finally
+ {
+ LogFile.EndAction("FlashFFU");
+ }
+ break;
+ case "fixbootafterunlockingbootloader":
+ LogFile.BeginAction("FixBoot");
+ try
+ {
+ LogFile.Log("Command: Fix boot after unlocking bootloader", LogType.FileAndConsole);
+ Notifier = new PhoneNotifierViewModel();
+ UIContext.Send(s => Notifier.Start(), null);
+ string Drive = await LumiaV2UnlockBootViewModel.LumiaV2SwitchToMassStorageMode(Notifier, null);
+ Notifier.Stop();
+ App.PatchEngine.TargetPath = Drive + "\\";
+ PatchResult = App.PatchEngine.Patch("SecureBootHack-MainOS");
+ if (!PatchResult)
+ {
+ throw new WPinternalsException("Patch failed", "An error occured while patching Operating System files on the MainOS partition of your phone. Make sure your phone runs a supported Operating System version.");
+ }
+
+ LogFile.Log("Fixed bootloader", LogType.FileAndConsole);
+ LogFile.Log("The phone is left in Mass Storage mode", LogType.FileAndConsole);
+ LogFile.Log("Press and hold the power-button of the phone for at least 10 seconds to reset the phone", LogType.FileAndConsole);
+ }
+ catch (Exception Ex)
+ {
+ LogFile.LogException(Ex);
+ }
+ finally
+ {
+ LogFile.EndAction("FixBoot");
+ }
+ break;
+ case "enablerootaccess":
+ LogFile.BeginAction("EnableRootAccess");
+ try
+ {
+ LogFile.Log("Command: Enable root access on the phone", LogType.FileAndConsole);
+ Notifier = new PhoneNotifierViewModel();
+ UIContext.Send(s => Notifier.Start(), null);
+ string Drive = await LumiaV2UnlockBootViewModel.LumiaV2SwitchToMassStorageMode(Notifier, null);
+ Notifier.Stop();
+ App.PatchEngine.TargetPath = Drive + "\\EFIESP\\";
+ PatchResult = App.PatchEngine.Patch("SecureBootHack-V2-EFIESP");
+ if (!PatchResult)
+ {
+ throw new WPinternalsException("Patch failed", "An error occured while patching Operating System files on the EFIESP partition of your phone. Make sure no boot files have been tampered with and you use the latest version of the tool. This error cannot be caused by an incorrect Operating System version as the tool automatically uses replacement if the version isn't supported.");
+ }
+
+ App.PatchEngine.TargetPath = Drive + "\\";
+ PatchResult = App.PatchEngine.Patch("SecureBootHack-MainOS");
+ if (!PatchResult)
+ {
+ throw new WPinternalsException("Patch failed", "An error occured while patching Operating System files on the MainOS partition of your phone. Make sure your phone runs a supported Operating System version.");
+ }
+
+ PatchResult = App.PatchEngine.Patch("RootAccess-MainOS");
+ if (!PatchResult)
+ {
+ throw new WPinternalsException("Patch failed", "An error occured while modifying Operating System files on the MainOS partition of your phone for Root Access. Make sure your phone runs a supported Operating System version.");
+ }
+
+ LogFile.Log("Root Access enabled!", LogType.FileAndConsole);
+ LogFile.Log("The phone is left in Mass Storage mode", LogType.FileAndConsole);
+ LogFile.Log("Press and hold the power-button of the phone for at least 10 seconds to reset the phone", LogType.FileAndConsole);
+ }
+ catch (Exception Ex)
+ {
+ LogFile.LogException(Ex);
+ }
+ finally
+ {
+ LogFile.EndAction("EnableRootAccess");
+ }
+ break;
+ case "unlockbootloaderonimage":
+ LogFile.Log("Command: Unlock bootloader on image", LogType.FileAndConsole);
+ if (args.Length < 3)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -UnlockBootLoaderOnImage ");
+ }
+
+ FFUFilePath = null;
+ EfiEspImagePath = args[2];
+ if (args.Length > 3)
+ {
+ if (FFU.IsFFU(args[3]))
+ {
+ FFUFilePath = args[3];
+ }
+ else
+ {
+ MainOsImagePath = args[3];
+ }
+ }
+ if (args.Length > 4)
+ {
+ FFUFilePath = args[4];
+ }
+
+ using (FileStream FileSystemStream = new(EfiEspImagePath, FileMode.Open, FileAccess.ReadWrite))
+ {
+ UnlockedEFIESPFileSystem = new DiscUtils.Fat.FatFileSystem(FileSystemStream);
+
+ if (FFUFilePath != null)
+ {
+ FFU SupportedFFU = new(FFUFilePath);
+ LogFile.Log("Donor FFU: " + SupportedFFU.Path);
+ byte[] SupportedEFIESP = SupportedFFU.GetPartition("EFIESP");
+ DiscUtils.Fat.FatFileSystem SupportedEFIESPFileSystem = new(new MemoryStream(SupportedEFIESP));
+ DiscUtils.Streams.SparseStream SupportedMobileStartupStream = SupportedEFIESPFileSystem.OpenFile(@"\Windows\System32\Boot\mobilestartup.efi", FileMode.Open);
+ MemoryStream SupportedMobileStartupMemStream = new();
+ SupportedMobileStartupStream.CopyTo(SupportedMobileStartupMemStream);
+ byte[] SupportedMobileStartup = SupportedMobileStartupMemStream.ToArray();
+ SupportedMobileStartupMemStream.Close();
+ SupportedMobileStartupStream.Close();
+
+ // Save supported mobilestartup.efi
+ LogFile.Log("Taking mobilestartup.efi from donor-FFU");
+ Stream MobileStartupStream = UnlockedEFIESPFileSystem.OpenFile(@"\Windows\System32\Boot\mobilestartup.efi", FileMode.Create, FileAccess.Write);
+ MobileStartupStream.Write(SupportedMobileStartup, 0, SupportedMobileStartup.Length);
+ MobileStartupStream.Close();
+ }
+
+ App.PatchEngine.TargetImage = UnlockedEFIESPFileSystem;
+ PatchResult = App.PatchEngine.Patch("SecureBootHack-V2-EFIESP");
+ if (!PatchResult)
+ {
+ throw new WPinternalsException("Failed to patch bootloader", "An error occured while patching Operating System files on the EFIESP partition provided. Make sure no boot files have been tampered with and you use the latest version of the tool. This error cannot be caused by an incorrect Operating System version as the tool automatically uses replacement if the version isn't supported, unless the replacement files have been tampered with or are not compatible.");
+ }
+
+ // Edit BCD
+ LogFile.Log("Edit BCD");
+ using Stream BCDFileStream = UnlockedEFIESPFileSystem.OpenFile(@"\efi\Microsoft\Boot\BCD", FileMode.Open, FileAccess.ReadWrite);
+ using DiscUtils.Registry.RegistryHive BCDHive = new(BCDFileStream);
+ DiscUtils.BootConfig.Store BCDStore = new(BCDHive.Root);
+ DiscUtils.BootConfig.BcdObject MobileStartupObject = BCDStore.GetObject(new Guid("{01de5a27-8705-40db-bad6-96fa5187d4a6}"));
+ DiscUtils.BootConfig.Element NoCodeIntegrityElement = MobileStartupObject.GetElement(0x16000048);
+ if (NoCodeIntegrityElement != null)
+ {
+ NoCodeIntegrityElement.Value = DiscUtils.BootConfig.ElementValue.ForBoolean(true);
+ }
+ else
+ {
+ MobileStartupObject.AddElement(0x16000048, DiscUtils.BootConfig.ElementValue.ForBoolean(true));
+ }
+
+ DiscUtils.BootConfig.BcdObject WinLoadObject = BCDStore.GetObject(new Guid("{7619dcc9-fafe-11d9-b411-000476eba25f}"));
+ NoCodeIntegrityElement = WinLoadObject.GetElement(0x16000048);
+ if (NoCodeIntegrityElement != null)
+ {
+ NoCodeIntegrityElement.Value = DiscUtils.BootConfig.ElementValue.ForBoolean(true);
+ }
+ else
+ {
+ WinLoadObject.AddElement(0x16000048, DiscUtils.BootConfig.ElementValue.ForBoolean(true));
+ }
+ }
+
+ if (MainOsImagePath != null)
+ {
+ using FileStream FileSystemStream = new(MainOsImagePath, FileMode.Open, FileAccess.ReadWrite);
+ UnlockedMainOsFileSystem = new DiscUtils.Ntfs.NtfsFileSystem(FileSystemStream);
+
+ App.PatchEngine.TargetImage = UnlockedMainOsFileSystem;
+ PatchResult = App.PatchEngine.Patch("SecureBootHack-MainOS");
+ if (!PatchResult)
+ {
+ throw new WPinternalsException("Failed to patch MainOS", "An error occured while patching Operating System files on the MainOS partition you provided. Make sure your phone runs a supported Operating System version.");
+ }
+ }
+ LogFile.Log("Bootloader unlocked on image", LogType.FileAndConsole);
+ break;
+ case "enablerootaccessonimage":
+ LogFile.Log("Command: Enable root access on image", LogType.FileAndConsole);
+ if (args.Length < 4)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -EnableRootAccessOnImage ");
+ }
+
+ FFUFilePath = null;
+ EfiEspImagePath = args[2];
+ MainOsImagePath = args[3];
+ if (args.Length > 4)
+ {
+ FFUFilePath = args[4];
+ }
+
+ using (FileStream FileSystemStream = new(EfiEspImagePath, FileMode.Open, FileAccess.ReadWrite))
+ {
+ UnlockedEFIESPFileSystem = new DiscUtils.Fat.FatFileSystem(FileSystemStream);
+
+ if (FFUFilePath != null)
+ {
+ FFU SupportedFFU = new(FFUFilePath);
+ LogFile.Log("Supported FFU: " + SupportedFFU.Path);
+ byte[] SupportedEFIESP = SupportedFFU.GetPartition("EFIESP");
+ DiscUtils.Fat.FatFileSystem SupportedEFIESPFileSystem = new(new MemoryStream(SupportedEFIESP));
+ DiscUtils.Streams.SparseStream SupportedMobileStartupStream = SupportedEFIESPFileSystem.OpenFile(@"\Windows\System32\Boot\mobilestartup.efi", FileMode.Open);
+ MemoryStream SupportedMobileStartupMemStream = new();
+ SupportedMobileStartupStream.CopyTo(SupportedMobileStartupMemStream);
+ byte[] SupportedMobileStartup = SupportedMobileStartupMemStream.ToArray();
+ SupportedMobileStartupMemStream.Close();
+ SupportedMobileStartupStream.Close();
+
+ // Save supported mobilestartup.efi
+ LogFile.Log("Taking mobilestartup.efi from donor-FFU");
+ Stream MobileStartupStream = UnlockedEFIESPFileSystem.OpenFile(@"\Windows\System32\Boot\mobilestartup.efi", FileMode.Create, FileAccess.Write);
+ MobileStartupStream.Write(SupportedMobileStartup, 0, SupportedMobileStartup.Length);
+ MobileStartupStream.Close();
+ }
+
+ App.PatchEngine.TargetImage = UnlockedEFIESPFileSystem;
+ PatchResult = App.PatchEngine.Patch("SecureBootHack-V2-EFIESP");
+ if (!PatchResult)
+ {
+ throw new WPinternalsException("Failed to patch bootloader", "An error occured while patching Operating System files on the EFIESP partition provided. Make sure no boot files have been tampered with and you use the latest version of the tool. This error cannot be caused by an incorrect Operating System version as the tool automatically uses replacement if the version isn't supported, unless the replacement files have been tampered with or are not compatible.");
+ }
+
+ // Edit BCD
+ LogFile.Log("Edit BCD");
+ using Stream BCDFileStream = UnlockedEFIESPFileSystem.OpenFile(@"\efi\Microsoft\Boot\BCD", FileMode.Open, FileAccess.ReadWrite);
+ using DiscUtils.Registry.RegistryHive BCDHive = new(BCDFileStream);
+ DiscUtils.BootConfig.Store BCDStore = new(BCDHive.Root);
+ DiscUtils.BootConfig.BcdObject MobileStartupObject = BCDStore.GetObject(new Guid("{01de5a27-8705-40db-bad6-96fa5187d4a6}"));
+ DiscUtils.BootConfig.Element NoCodeIntegrityElement = MobileStartupObject.GetElement(0x16000048);
+ if (NoCodeIntegrityElement != null)
+ {
+ NoCodeIntegrityElement.Value = DiscUtils.BootConfig.ElementValue.ForBoolean(true);
+ }
+ else
+ {
+ MobileStartupObject.AddElement(0x16000048, DiscUtils.BootConfig.ElementValue.ForBoolean(true));
+ }
+
+ DiscUtils.BootConfig.BcdObject WinLoadObject = BCDStore.GetObject(new Guid("{7619dcc9-fafe-11d9-b411-000476eba25f}"));
+ NoCodeIntegrityElement = WinLoadObject.GetElement(0x16000048);
+ if (NoCodeIntegrityElement != null)
+ {
+ NoCodeIntegrityElement.Value = DiscUtils.BootConfig.ElementValue.ForBoolean(true);
+ }
+ else
+ {
+ WinLoadObject.AddElement(0x16000048, DiscUtils.BootConfig.ElementValue.ForBoolean(true));
+ }
+ }
+
+ using (FileStream FileSystemStream = new(MainOsImagePath, FileMode.Open, FileAccess.ReadWrite))
+ {
+ UnlockedMainOsFileSystem = new DiscUtils.Ntfs.NtfsFileSystem(FileSystemStream);
+
+ App.PatchEngine.TargetImage = UnlockedMainOsFileSystem;
+ PatchResult = App.PatchEngine.Patch("SecureBootHack-MainOS");
+ if (!PatchResult)
+ {
+ throw new WPinternalsException("Failed to patch MainOS", "An error occured while patching Operating System files on the MainOS partition you provided. Make sure your phone runs a supported Operating System version.");
+ }
+
+ PatchResult = App.PatchEngine.Patch("RootAccess-MainOS");
+ if (!PatchResult)
+ {
+ throw new WPinternalsException("Failed to patch MainOS", "An error occured while modifying Operating System files on the MainOS partition you provided for Root Access. Make sure your phone runs a supported Operating System version.");
+ }
+ }
+ LogFile.Log("Root access enabled on image", LogType.FileAndConsole);
+ break;
+ case "unlockbootloaderonmountedimage":
+ LogFile.Log("Command: Unlock bootloader on mounted image", LogType.FileAndConsole);
+ if (args.Length < 3)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -UnlockBootLoaderOnMountedImage ");
+ }
+
+ FFUFilePath = null;
+ EfiEspImagePath = args[2];
+ if (args.Length > 3)
+ {
+ if (FFU.IsFFU(args[3]))
+ {
+ FFUFilePath = args[3];
+ }
+ else
+ {
+ MainOsImagePath = args[3];
+ }
+ }
+ if (args.Length > 4)
+ {
+ FFUFilePath = args[4];
+ }
+
+ if (FFUFilePath != null)
+ {
+ FFU SupportedFFU = new(FFUFilePath);
+ LogFile.Log("Donor-FFU: " + SupportedFFU.Path);
+ byte[] SupportedEFIESP = SupportedFFU.GetPartition("EFIESP");
+ DiscUtils.Fat.FatFileSystem SupportedEFIESPFileSystem = new(new MemoryStream(SupportedEFIESP));
+ DiscUtils.Streams.SparseStream SupportedMobileStartupStream = SupportedEFIESPFileSystem.OpenFile(@"\Windows\System32\Boot\mobilestartup.efi", FileMode.Open);
+ MemoryStream SupportedMobileStartupMemStream = new();
+ SupportedMobileStartupStream.CopyTo(SupportedMobileStartupMemStream);
+ byte[] SupportedMobileStartup = SupportedMobileStartupMemStream.ToArray();
+ SupportedMobileStartupMemStream.Close();
+ SupportedMobileStartupStream.Close();
+
+ // Save supported mobilestartup.efi
+ LogFile.Log("Taking mobilestartup.efi from donor-FFU");
+ Stream MobileStartupStream = File.Open(Path.Combine(EfiEspImagePath, @"Windows\System32\Boot\mobilestartup.efi"), FileMode.Create, FileAccess.Write);
+ MobileStartupStream.Write(SupportedMobileStartup, 0, SupportedMobileStartup.Length);
+ MobileStartupStream.Close();
+ }
+
+ App.PatchEngine.TargetPath = EfiEspImagePath;
+ PatchResult = App.PatchEngine.Patch("SecureBootHack-V2-EFIESP");
+ if (!PatchResult)
+ {
+ throw new WPinternalsException("Failed to patch bootloader", "An error occured while patching Operating System files on the EFIESP partition provided. Make sure no boot files have been tampered with and you use the latest version of the tool. This error cannot be caused by an incorrect Operating System version as the tool automatically uses replacement if the version isn't supported, unless the replacement files have been tampered with or are not compatible.");
+ }
+
+ // Edit BCD
+ LogFile.Log("Edit BCD");
+ using (Stream BCDFileStream = File.Open(Path.Combine(EfiEspImagePath, @"efi\Microsoft\Boot\BCD"), FileMode.Open, FileAccess.ReadWrite))
+ {
+ using DiscUtils.Registry.RegistryHive BCDHive = new(BCDFileStream);
+ DiscUtils.BootConfig.Store BCDStore = new(BCDHive.Root);
+ DiscUtils.BootConfig.BcdObject MobileStartupObject = BCDStore.GetObject(new Guid("{01de5a27-8705-40db-bad6-96fa5187d4a6}"));
+ DiscUtils.BootConfig.Element NoCodeIntegrityElement = MobileStartupObject.GetElement(0x16000048);
+ if (NoCodeIntegrityElement != null)
+ {
+ NoCodeIntegrityElement.Value = DiscUtils.BootConfig.ElementValue.ForBoolean(true);
+ }
+ else
+ {
+ MobileStartupObject.AddElement(0x16000048, DiscUtils.BootConfig.ElementValue.ForBoolean(true));
+ }
+
+ DiscUtils.BootConfig.BcdObject WinLoadObject = BCDStore.GetObject(new Guid("{7619dcc9-fafe-11d9-b411-000476eba25f}"));
+ NoCodeIntegrityElement = WinLoadObject.GetElement(0x16000048);
+ if (NoCodeIntegrityElement != null)
+ {
+ NoCodeIntegrityElement.Value = DiscUtils.BootConfig.ElementValue.ForBoolean(true);
+ }
+ else
+ {
+ WinLoadObject.AddElement(0x16000048, DiscUtils.BootConfig.ElementValue.ForBoolean(true));
+ }
+ }
+
+ if (MainOsImagePath != null)
+ {
+ App.PatchEngine.TargetPath = MainOsImagePath;
+ PatchResult = App.PatchEngine.Patch("SecureBootHack-MainOS");
+ if (!PatchResult)
+ {
+ throw new WPinternalsException("Failed to patch MainOS", "An error occured while patching Operating System files on the MainOS partition you provided. Make sure your phone runs a supported Operating System version.");
+ }
+ }
+ LogFile.Log("Bootloader unlocked on image", LogType.FileAndConsole);
+ break;
+ case "enablerootaccessonmountedimage":
+ LogFile.Log("Command: Enable root access on mounted image", LogType.FileAndConsole);
+ if (args.Length < 4)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -EnableRootAccessOnMountedImage ");
+ }
+
+ FFUFilePath = null;
+ EfiEspImagePath = args[2];
+ MainOsImagePath = args[3];
+ if (args.Length > 4)
+ {
+ FFUFilePath = args[4];
+ }
+
+ if (FFUFilePath != null)
+ {
+ FFU SupportedFFU = new(FFUFilePath);
+ LogFile.Log("Supported FFU: " + SupportedFFU.Path);
+ byte[] SupportedEFIESP = SupportedFFU.GetPartition("EFIESP");
+ DiscUtils.Fat.FatFileSystem SupportedEFIESPFileSystem = new(new MemoryStream(SupportedEFIESP));
+ DiscUtils.Streams.SparseStream SupportedMobileStartupStream = SupportedEFIESPFileSystem.OpenFile(@"\Windows\System32\Boot\mobilestartup.efi", FileMode.Open);
+ MemoryStream SupportedMobileStartupMemStream = new();
+ SupportedMobileStartupStream.CopyTo(SupportedMobileStartupMemStream);
+ byte[] SupportedMobileStartup = SupportedMobileStartupMemStream.ToArray();
+ SupportedMobileStartupMemStream.Close();
+ SupportedMobileStartupStream.Close();
+
+ // Save supported mobilestartup.efi
+ LogFile.Log("Taking mobilestartup.efi from donor-FFU");
+ Stream MobileStartupStream = File.Open(Path.Combine(EfiEspImagePath, @"Windows\System32\Boot\mobilestartup.efi"), FileMode.Create, FileAccess.Write);
+ MobileStartupStream.Write(SupportedMobileStartup, 0, SupportedMobileStartup.Length);
+ MobileStartupStream.Close();
+ }
+
+ App.PatchEngine.TargetPath = EfiEspImagePath;
+ PatchResult = App.PatchEngine.Patch("SecureBootHack-V2-EFIESP");
+ if (!PatchResult)
+ {
+ throw new WPinternalsException("Failed to patch bootloader", "An error occured while patching Operating System files on the EFIESP partition provided. Make sure no boot files have been tampered with and you use the latest version of the tool. This error cannot be caused by an incorrect Operating System version as the tool automatically uses replacement if the version isn't supported, unless the replacement files have been tampered with or are not compatible.");
+ }
+
+ // Edit BCD
+ LogFile.Log("Edit BCD");
+ using (Stream BCDFileStream = File.Open(Path.Combine(EfiEspImagePath, @"efi\Microsoft\Boot\BCD"), FileMode.Open, FileAccess.ReadWrite))
+ {
+ using DiscUtils.Registry.RegistryHive BCDHive = new(BCDFileStream);
+ DiscUtils.BootConfig.Store BCDStore = new(BCDHive.Root);
+ DiscUtils.BootConfig.BcdObject MobileStartupObject = BCDStore.GetObject(new Guid("{01de5a27-8705-40db-bad6-96fa5187d4a6}"));
+ DiscUtils.BootConfig.Element NoCodeIntegrityElement = MobileStartupObject.GetElement(0x16000048);
+ if (NoCodeIntegrityElement != null)
+ {
+ NoCodeIntegrityElement.Value = DiscUtils.BootConfig.ElementValue.ForBoolean(true);
+ }
+ else
+ {
+ MobileStartupObject.AddElement(0x16000048, DiscUtils.BootConfig.ElementValue.ForBoolean(true));
+ }
+
+ DiscUtils.BootConfig.BcdObject WinLoadObject = BCDStore.GetObject(new Guid("{7619dcc9-fafe-11d9-b411-000476eba25f}"));
+ NoCodeIntegrityElement = WinLoadObject.GetElement(0x16000048);
+ if (NoCodeIntegrityElement != null)
+ {
+ NoCodeIntegrityElement.Value = DiscUtils.BootConfig.ElementValue.ForBoolean(true);
+ }
+ else
+ {
+ WinLoadObject.AddElement(0x16000048, DiscUtils.BootConfig.ElementValue.ForBoolean(true));
+ }
+ }
+
+ App.PatchEngine.TargetPath = MainOsImagePath;
+ PatchResult = App.PatchEngine.Patch("SecureBootHack-MainOS");
+ if (!PatchResult)
+ {
+ throw new WPinternalsException("Failed to patch MainOS", "An error occured while patching Operating System files on the MainOS partition you provided. Make sure your phone runs a supported Operating System version.");
+ }
+
+ PatchResult = App.PatchEngine.Patch("RootAccess-MainOS");
+ if (!PatchResult)
+ {
+ throw new WPinternalsException("Failed to patch MainOS", "An error occured while modifying Operating System files on the MainOS partition you provided for Root Access. Make sure your phone runs a supported Operating System version.");
+ }
+
+ LogFile.Log("Root access enabled on image", LogType.FileAndConsole);
+ break;
+ case "downloadffu":
+ LogFile.Log("Command: Download FFU", LogType.FileAndConsole);
+ Notifier = new PhoneNotifierViewModel();
+ UIContext.Send(s => Notifier.Start(), null);
+ if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
+ {
+ NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
+ ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
+ }
+ else if ((Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) || (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash))
+ {
+ FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
+ Info = FlashModel.ReadPhoneInfo();
+ ProductCode = Info.ProductCode;
+ }
+ else
+ {
+ NormalModel = (NokiaPhoneModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
+ ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
+ }
+ URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
+ DownloadFolder = args.Length >= 3
+ ? args[4]
+ : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
+
+ if (!Directory.Exists(DownloadFolder))
+ {
+ Directory.CreateDirectory(DownloadFolder);
+ }
+
+ LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
+ LogFile.Log("URL: " + URL, LogType.FileAndConsole);
+ URI = new Uri(URL);
+ FFUFileName = Path.GetFileName(URI.LocalPath);
+ LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
+ FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
+ LogFile.Log("Downloading...", LogType.FileAndConsole);
+ using (System.Net.WebClient myWebClient = new())
+ {
+ await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
+ }
+ LogFile.Log("Download finished", LogType.FileAndConsole);
+ App.Config.AddFfuToRepository(FFUFilePath);
+ Notifier.Stop();
+ break;
+ case "downloadffubyoperatorcode":
+ LogFile.Log("Command: Download FFU by Operator Code", LogType.FileAndConsole);
+ if (args.Length < 4)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadFFUbyOperatorCode ");
+ }
+
+ ProductType = args[2];
+ LogFile.Log("Product type: " + ProductType, LogType.FileAndConsole);
+ OperatorCode = args[3];
+ LogFile.Log("Operator code: " + OperatorCode, LogType.FileAndConsole);
+ DownloadFolder = args.Length >= 5
+ ? args[4]
+ : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
+
+ if (!Directory.Exists(DownloadFolder))
+ {
+ Directory.CreateDirectory(DownloadFolder);
+ }
+
+ LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
+ URL = LumiaDownloadModel.SearchFFU(ProductType, null, OperatorCode);
+ LogFile.Log("URL: " + URL, LogType.FileAndConsole);
+ URI = new Uri(URL);
+ FFUFileName = Path.GetFileName(URI.LocalPath);
+ LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
+ FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
+ LogFile.Log("Downloading...", LogType.FileAndConsole);
+ using (System.Net.WebClient myWebClient = new())
+ {
+ await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
+ }
+ LogFile.Log("Download finished", LogType.FileAndConsole);
+ App.Config.AddFfuToRepository(FFUFilePath);
+ break;
+ case "downloadffubyproductcode":
+ LogFile.Log("Command: Download FFU by Product Code", LogType.FileAndConsole);
+ if (args.Length < 3)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadFFUbyProductCode ");
+ }
+
+ ProductCode = args[2];
+ LogFile.Log("Product code: " + ProductCode, LogType.FileAndConsole);
+ URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
+ DownloadFolder = args.Length >= 4
+ ? args[3]
+ : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
+
+ if (!Directory.Exists(DownloadFolder))
+ {
+ Directory.CreateDirectory(DownloadFolder);
+ }
+
+ LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
+ LogFile.Log("URL: " + URL, LogType.FileAndConsole);
+ URI = new Uri(URL);
+ FFUFileName = Path.GetFileName(URI.LocalPath);
+ LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
+ FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
+ LogFile.Log("Downloading...", LogType.FileAndConsole);
+ using (System.Net.WebClient myWebClient = new())
+ {
+ await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
+ }
+ LogFile.Log("Download finished", LogType.FileAndConsole);
+ App.Config.AddFfuToRepository(FFUFilePath);
+ break;
+ case "downloadffubyproducttype":
+ LogFile.Log("Command: Download FFU by Product Type", LogType.FileAndConsole);
+ if (args.Length < 3)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadFFUbyProductType ");
+ }
+
+ ProductType = args[2];
+ LogFile.Log("Product type: " + ProductType, LogType.FileAndConsole);
+ DownloadFolder = args.Length >= 4
+ ? args[3]
+ : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
+
+ if (!Directory.Exists(DownloadFolder))
+ {
+ Directory.CreateDirectory(DownloadFolder);
+ }
+
+ LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
+ URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
+ LogFile.Log("URL: " + URL, LogType.FileAndConsole);
+ URI = new Uri(URL);
+ FFUFileName = Path.GetFileName(URI.LocalPath);
+ LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
+ FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
+ LogFile.Log("Downloading...", LogType.FileAndConsole);
+ using (System.Net.WebClient myWebClient = new())
+ {
+ await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
+ }
+ LogFile.Log("Download finished", LogType.FileAndConsole);
+ App.Config.AddFfuToRepository(FFUFilePath);
+ break;
+ case "searchffubyproducttype":
+ LogFile.Log("Command: Search FFU by Product Type", LogType.FileAndConsole);
+ if (args.Length < 3)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -SearchFFUbyProductType ");
+ }
+
+ ProductType = args[2];
+ LogFile.Log("Lumia model: " + ProductType, LogType.FileAndConsole);
+ URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
+ LogFile.Log("URL: " + URL, LogType.FileAndConsole);
+ URI = new Uri(URL);
+ FFUFileName = Path.GetFileName(URI.LocalPath);
+ LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
+ break;
+ case "downloademergency":
+ LogFile.Log("Command: Download Emergency files", LogType.FileAndConsole);
+ Notifier = new PhoneNotifierViewModel();
+ UIContext.Send(s => Notifier.Start(), null);
+ if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
+ {
+ NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
+ ProductType = NormalModel.ExecuteJsonMethodAsString("ReadManufacturerModelName", "ManufacturerModelName");
+ if (ProductType.Contains('_'))
+ {
+ ProductType = ProductType.Substring(0, ProductType.IndexOf('_'));
+ }
+ }
+ else if ((Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) || (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash))
+ {
+ FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
+ Info = FlashModel.ReadPhoneInfo();
+ ProductType = Info.Type;
+ }
+ else
+ {
+ NormalModel = (NokiaPhoneModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
+ ProductType = NormalModel.ExecuteJsonMethodAsString("ReadManufacturerModelName", "ManufacturerModelName");
+ if (ProductType.Contains('_'))
+ {
+ ProductType = ProductType.Substring(0, ProductType.IndexOf('_'));
+ }
+ }
+ URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
+ if (URLs != null)
+ {
+ DownloadFolder = args.Length >= 3
+ ? args[2]
+ : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
+
+ if (!Directory.Exists(DownloadFolder))
+ {
+ Directory.CreateDirectory(DownloadFolder);
+ }
+
+ LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
+ for (int i = 0; i < URLs.Length; i++)
+ {
+ LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
+ URI = new Uri(URLs[i]);
+ EmergencyFileName = Path.GetFileName(URI.LocalPath);
+ LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
+ EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
+ if (i == 0)
+ {
+ ProgrammerPath = EmergencyFilePath;
+ }
+ else
+ {
+ PayloadPath = EmergencyFilePath;
+ }
+
+ LogFile.Log("Downloading...", LogType.FileAndConsole);
+ using (System.Net.WebClient myWebClient = new())
+ {
+ await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
+ }
+ LogFile.Log("Download finished", LogType.FileAndConsole);
+ }
+ App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
+ }
+ Notifier.Stop();
+ break;
+ case "downloademergencybyproducttype":
+ LogFile.Log("Command: Download Emergency files", LogType.FileAndConsole);
+ if (args.Length < 3)
+ {
+ throw new WPinternalsException("Wrong number of arguments. Usage: WPinternals.exe -DownloadEmergencyByProductType ");
+ }
+
+ ProductType = args[2];
+ URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
+ if (URLs != null)
+ {
+ DownloadFolder = args.Length >= 4
+ ? args[3]
+ : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
+
+ if (!Directory.Exists(DownloadFolder))
+ {
+ Directory.CreateDirectory(DownloadFolder);
+ }
+
+ LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
+ for (int i = 0; i < URLs.Length; i++)
+ {
+ LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
+ URI = new Uri(URLs[i]);
+ EmergencyFileName = Path.GetFileName(URI.LocalPath);
+ LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
+ EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
+ if (i == 0)
+ {
+ ProgrammerPath = EmergencyFilePath;
+ }
+ else
+ {
+ PayloadPath = EmergencyFilePath;
+ }
+
+ LogFile.Log("Downloading...", LogType.FileAndConsole);
+ using (System.Net.WebClient myWebClient = new())
+ {
+ await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
+ }
+ LogFile.Log("Download finished", LogType.FileAndConsole);
+ }
+ App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
+ }
+ break;
+ case "downloadall":
+ LogFile.Log("Command: Download all", LogType.FileAndConsole);
+ Notifier = new PhoneNotifierViewModel();
+ UIContext.Send(s => Notifier.Start(), null);
+ if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
+ {
+ NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
+ ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
+ }
+ else if ((Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) || (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash))
+ {
+ FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
+ Info = FlashModel.ReadPhoneInfo();
+ ProductCode = Info.ProductCode;
+ }
+ else
+ {
+ NormalModel = (NokiaPhoneModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Normal);
+ ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
+ }
+ URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
+ DownloadFolder = args.Length >= 3
+ ? args[2]
+ : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
+
+ if (!Directory.Exists(DownloadFolder))
+ {
+ Directory.CreateDirectory(DownloadFolder);
+ }
+
+ LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
+ LogFile.Log("URL: " + URL, LogType.FileAndConsole);
+ URI = new Uri(URL);
+ FFUFileName = Path.GetFileName(URI.LocalPath);
+ LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
+ FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
+ LogFile.Log("Downloading...", LogType.FileAndConsole);
+ using (System.Net.WebClient myWebClient = new())
+ {
+ await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
+ }
+ LogFile.Log("Download finished", LogType.FileAndConsole);
+ App.Config.AddFfuToRepository(FFUFilePath);
+
+ URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
+ if (URLs != null)
+ {
+ for (int i = 0; i < URLs.Length; i++)
+ {
+ LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
+ URI = new Uri(URLs[i]);
+ EmergencyFileName = Path.GetFileName(URI.LocalPath);
+ LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
+ EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
+ if (i == 0)
+ {
+ ProgrammerPath = EmergencyFilePath;
+ }
+ else
+ {
+ PayloadPath = EmergencyFilePath;
+ }
+
+ LogFile.Log("Downloading...", LogType.FileAndConsole);
+ using (System.Net.WebClient myWebClient = new())
+ {
+ await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
+ }
+ LogFile.Log("Download finished", LogType.FileAndConsole);
+ }
+ App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
+ }
+
+ if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
+ {
+ ProductType = "RM-1085";
+
+ URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
+ DownloadFolder = args.Length >= 3
+ ? args[2]
+ : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
+
+ if (!Directory.Exists(DownloadFolder))
+ {
+ Directory.CreateDirectory(DownloadFolder);
+ }
+
+ LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
+ LogFile.Log("URL: " + URL, LogType.FileAndConsole);
+ URI = new Uri(URL);
+ FFUFileName = Path.GetFileName(URI.LocalPath);
+ LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
+ FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
+ LogFile.Log("Downloading...", LogType.FileAndConsole);
+ using (System.Net.WebClient myWebClient = new())
+ {
+ await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
+ }
+ LogFile.Log("Download finished", LogType.FileAndConsole);
+ App.Config.AddFfuToRepository(FFUFilePath);
+
+ if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
+ {
+ throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
+ }
+ }
+ Notifier.Stop();
+ break;
+ case "downloadallbyproducttype":
+ LogFile.Log("Command: Download all by Product Type", LogType.FileAndConsole);
+ if (args.Length < 3)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadAllByProductType ");
+ }
+
+ ProductType = args[2];
+ LogFile.Log("Product type: " + ProductType, LogType.FileAndConsole);
+ DownloadFolder = args.Length >= 4
+ ? args[3]
+ : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
+
+ if (!Directory.Exists(DownloadFolder))
+ {
+ Directory.CreateDirectory(DownloadFolder);
+ }
+
+ LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
+ URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
+ LogFile.Log("URL: " + URL, LogType.FileAndConsole);
+ URI = new Uri(URL);
+ FFUFileName = Path.GetFileName(URI.LocalPath);
+ LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
+ FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
+ LogFile.Log("Downloading...", LogType.FileAndConsole);
+ using (System.Net.WebClient myWebClient = new())
+ {
+ await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
+ }
+ LogFile.Log("Download finished", LogType.FileAndConsole);
+ App.Config.AddFfuToRepository(FFUFilePath);
+
+ URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
+ if (URLs != null)
+ {
+ for (int i = 0; i < URLs.Length; i++)
+ {
+ LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
+ URI = new Uri(URLs[i]);
+ EmergencyFileName = Path.GetFileName(URI.LocalPath);
+ LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
+ EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
+ if (i == 0)
+ {
+ ProgrammerPath = EmergencyFilePath;
+ }
+ else
+ {
+ PayloadPath = EmergencyFilePath;
+ }
+
+ LogFile.Log("Downloading...", LogType.FileAndConsole);
+ using (System.Net.WebClient myWebClient = new())
+ {
+ await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
+ }
+ LogFile.Log("Download finished", LogType.FileAndConsole);
+ }
+ App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
+ }
+
+ if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
+ {
+ ProductType = "RM-1085";
+
+ URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
+ DownloadFolder = args.Length >= 4
+ ? args[3]
+ : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
+
+ if (!Directory.Exists(DownloadFolder))
+ {
+ Directory.CreateDirectory(DownloadFolder);
+ }
+
+ LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
+ LogFile.Log("URL: " + URL, LogType.FileAndConsole);
+ URI = new Uri(URL);
+ FFUFileName = Path.GetFileName(URI.LocalPath);
+ LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
+ FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
+ LogFile.Log("Downloading...", LogType.FileAndConsole);
+ using (System.Net.WebClient myWebClient = new())
+ {
+ await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
+ }
+ LogFile.Log("Download finished", LogType.FileAndConsole);
+ App.Config.AddFfuToRepository(FFUFilePath);
+
+ if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
+ {
+ throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
+ }
+ }
+ break;
+ case "downloadallbyproductcode":
+ LogFile.Log("Command: Download all by Product Code", LogType.FileAndConsole);
+ if (args.Length < 3)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadAllByProductCode ");
+ }
+
+ ProductCode = args[2];
+ LogFile.Log("Product code: " + ProductCode, LogType.FileAndConsole);
+ URL = LumiaDownloadModel.SearchFFU(null, ProductCode, null, out ProductType);
+ DownloadFolder = args.Length >= 4
+ ? args[3]
+ : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
+
+ if (!Directory.Exists(DownloadFolder))
+ {
+ Directory.CreateDirectory(DownloadFolder);
+ }
+
+ LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
+ LogFile.Log("URL: " + URL, LogType.FileAndConsole);
+ URI = new Uri(URL);
+ FFUFileName = Path.GetFileName(URI.LocalPath);
+ LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
+ FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
+ LogFile.Log("Downloading...", LogType.FileAndConsole);
+ using (System.Net.WebClient myWebClient = new())
+ {
+ await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
+ }
+ LogFile.Log("Download finished", LogType.FileAndConsole);
+ App.Config.AddFfuToRepository(FFUFilePath);
+
+ URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
+ if (URLs != null)
+ {
+ for (int i = 0; i < URLs.Length; i++)
+ {
+ LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
+ URI = new Uri(URLs[i]);
+ EmergencyFileName = Path.GetFileName(URI.LocalPath);
+ LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
+ EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
+ if (i == 0)
+ {
+ ProgrammerPath = EmergencyFilePath;
+ }
+ else
+ {
+ PayloadPath = EmergencyFilePath;
+ }
+
+ LogFile.Log("Downloading...", LogType.FileAndConsole);
+ using (System.Net.WebClient myWebClient = new())
+ {
+ await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
+ }
+ LogFile.Log("Download finished", LogType.FileAndConsole);
+ }
+ App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
+ }
+
+ if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
+ {
+ ProductType = "RM-1085";
+
+ URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
+ DownloadFolder = args.Length >= 4
+ ? args[3]
+ : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
+
+ if (!Directory.Exists(DownloadFolder))
+ {
+ Directory.CreateDirectory(DownloadFolder);
+ }
+
+ LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
+ LogFile.Log("URL: " + URL, LogType.FileAndConsole);
+ URI = new Uri(URL);
+ FFUFileName = Path.GetFileName(URI.LocalPath);
+ LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
+ FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
+ LogFile.Log("Downloading...", LogType.FileAndConsole);
+ using (System.Net.WebClient myWebClient = new())
+ {
+ await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
+ }
+ LogFile.Log("Download finished", LogType.FileAndConsole);
+ App.Config.AddFfuToRepository(FFUFilePath);
+
+ if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
+ {
+ throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
+ }
+ }
+ break;
+ case "downloadallbyoperatorcode":
+ LogFile.Log("Command: Download FFU by Operator Code", LogType.FileAndConsole);
+ if (args.Length < 4)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -DownloadFFUbyOperatorCode ");
+ }
+
+ ProductType = args[2];
+ LogFile.Log("Product type: " + ProductType, LogType.FileAndConsole);
+ OperatorCode = args[3];
+ LogFile.Log("Operator code: " + OperatorCode, LogType.FileAndConsole);
+ DownloadFolder = args.Length >= 5
+ ? args[4]
+ : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
+
+ if (!Directory.Exists(DownloadFolder))
+ {
+ Directory.CreateDirectory(DownloadFolder);
+ }
+
+ LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
+ URL = LumiaDownloadModel.SearchFFU(ProductType, null, OperatorCode);
+ LogFile.Log("URL: " + URL, LogType.FileAndConsole);
+ URI = new Uri(URL);
+ FFUFileName = Path.GetFileName(URI.LocalPath);
+ LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
+ FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
+ LogFile.Log("Downloading...", LogType.FileAndConsole);
+ using (System.Net.WebClient myWebClient = new())
+ {
+ await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
+ }
+ LogFile.Log("Download finished", LogType.FileAndConsole);
+ App.Config.AddFfuToRepository(FFUFilePath);
+
+ URLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
+ if (URLs != null)
+ {
+ for (int i = 0; i < URLs.Length; i++)
+ {
+ LogFile.Log("URL: " + URLs[i], LogType.FileAndConsole);
+ URI = new Uri(URLs[i]);
+ EmergencyFileName = Path.GetFileName(URI.LocalPath);
+ LogFile.Log("File: " + EmergencyFileName, LogType.FileAndConsole);
+ EmergencyFilePath = Path.Combine(DownloadFolder, EmergencyFileName);
+ if (i == 0)
+ {
+ ProgrammerPath = EmergencyFilePath;
+ }
+ else
+ {
+ PayloadPath = EmergencyFilePath;
+ }
+
+ LogFile.Log("Downloading...", LogType.FileAndConsole);
+ using (System.Net.WebClient myWebClient = new())
+ {
+ await myWebClient.DownloadFileTaskAsync(URLs[i], EmergencyFilePath);
+ }
+ LogFile.Log("Download finished", LogType.FileAndConsole);
+ }
+ App.Config.AddEmergencyToRepository(ProductType, ProgrammerPath, PayloadPath);
+ }
+
+ if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
+ {
+ ProductType = "RM-1085";
+
+ URL = LumiaDownloadModel.SearchFFU(ProductType, null, null);
+ DownloadFolder = args.Length >= 5
+ ? args[4]
+ : Environment.ExpandEnvironmentVariables("%ALLUSERSPROFILE%\\WPInternals\\Repository\\" + ProductType.ToUpper());
+
+ if (!Directory.Exists(DownloadFolder))
+ {
+ Directory.CreateDirectory(DownloadFolder);
+ }
+
+ LogFile.Log("Download folder: " + DownloadFolder, LogType.FileAndConsole);
+ LogFile.Log("URL: " + URL, LogType.FileAndConsole);
+ URI = new Uri(URL);
+ FFUFileName = Path.GetFileName(URI.LocalPath);
+ LogFile.Log("File: " + FFUFileName, LogType.FileAndConsole);
+ FFUFilePath = Path.Combine(DownloadFolder, FFUFileName);
+ LogFile.Log("Downloading...", LogType.FileAndConsole);
+ using (System.Net.WebClient myWebClient = new())
+ {
+ await myWebClient.DownloadFileTaskAsync(URL, FFUFilePath);
+ }
+ LogFile.Log("Download finished", LogType.FileAndConsole);
+ App.Config.AddFfuToRepository(FFUFilePath);
+
+ if (!App.Config.FFURepository.Any(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)))
+ {
+ throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
+ }
+ }
+ break;
+ case "rewritepartitionsfrommassstorage":
+ if (args.Length < 2)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -RewritePartitionsFromMassStorage \n The name of the imgs must be the partition names. For example, DPP.img will get written to the DPP partition.");
+ }
+
+ await TestCode.RewriteParts(args[2]);
+ break;
+ case "restoregptusingedl":
+ if (args.Length < 3)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -RestoreGPTUsingEDL ");
+ }
+
+ await TestCode.RecoverBadGPT(args[2], args[3]);
+ break;
+ case "restoregptusingmassstorage":
+ if (args.Length < 2)
+ {
+ throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -RestoreGPTUsingMassStorage ");
+ }
+
+ await TestCode.RewriteGPT(args[2]);
+ break;
+ default:
+ LogFile.Log("", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals commandline usage:", LogType.ConsoleOnly);
+ LogFile.Log("", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -ShowPhoneInfo", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -AddFFU ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -AddEmergency ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -RemoveFFU ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -RemoveEmergency ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -ListRepository", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -FindFlashingProfile ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -UnlockBootloader", LogType.ConsoleOnly);
+ LogFile.Log(" ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -FixBootAfterUnlockingBootloader", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -EnableRootAccess", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -UnlockBootLoaderOnImage ", LogType.ConsoleOnly);
+ LogFile.Log(" ", LogType.ConsoleOnly);
+ LogFile.Log(" ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -EnableRootAccessOnImage ", LogType.ConsoleOnly);
+ LogFile.Log(" ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -UnlockBootLoaderOnMountedImage ", LogType.ConsoleOnly);
+ LogFile.Log(" ", LogType.ConsoleOnly);
+ LogFile.Log(" ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -EnableRootAccessOnMountedImage ", LogType.ConsoleOnly);
+ LogFile.Log(" ", LogType.ConsoleOnly);
+ LogFile.Log(" ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -EnableTestSigning", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -RelockPhone", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -SwitchToMassStorageMode", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -FlashFFU ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -FlashCustomROM ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -FlashPartition ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -FlashRaw ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -ClearNV", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -ReadGPT", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -BackupGPT ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -RestoreGPT ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -MergeGPT ", LogType.ConsoleOnly);
+ LogFile.Log(" ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -MergeGPT ", LogType.ConsoleOnly);
+ LogFile.Log(" ", LogType.ConsoleOnly);
+ LogFile.Log(" ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -ShowFFU ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -DumpFFU ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -DownloadFFU ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -DownloadFFUbyProductType ", LogType.ConsoleOnly);
+ LogFile.Log(" ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -DownloadFFUbyProductCode ", LogType.ConsoleOnly);
+ LogFile.Log(" ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -DownloadFFUbyOperatorCode ", LogType.ConsoleOnly);
+ LogFile.Log(" ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -DownloadEmergency ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -DownloadEmergencyByProductType ", LogType.ConsoleOnly);
+ LogFile.Log(" ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -DownloadAll ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -DownloadAllByProductType ", LogType.ConsoleOnly);
+ LogFile.Log(" ", LogType.ConsoleOnly);
+ LogFile.Log("WPinternals -DownloadAllByProductCode