Project: Move WPinternals code to a WPinternals folder

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

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

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

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

@@ -1,51 +1,51 @@
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Windows; using System.Windows;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information // set of attributes. Change these attribute values to modify the information
// associated with an assembly. // associated with an assembly.
[assembly: AssemblyTitle("WPinternals")] [assembly: AssemblyTitle("WPinternals")]
[assembly: AssemblyDescription("")] [assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")] [assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("WPinternals")] [assembly: AssemblyProduct("WPinternals")]
[assembly: AssemblyCopyright("Copyright © 2018-2019")] [assembly: AssemblyCopyright("Copyright © 2018-2019")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible // Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from // to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type. // COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)] [assembly: ComVisible(false)]
//In order to begin building localizable applications, set //In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file //<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english //inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment //in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in //the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file. //the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo( [assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page, //(used if a resource is not found in the page,
// or application resource dictionaries) // or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page, //(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries) // app, or any theme specific resource dictionaries)
)] )]
// Version information for an assembly consists of the following four values: // Version information for an assembly consists of the following four values:
// //
// Major Version // Major Version
// Minor Version // Minor Version
// Build Number // Build Number
// Revision // Revision
// //
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.9.*")] [assembly: AssemblyVersion("2.9.*")]
// [assembly: AssemblyFileVersion("1.0.0.0")] // [assembly: AssemblyFileVersion("1.0.0.0")]
@@ -1,63 +1,63 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.
// Runtime Version:4.0.30319.42000 // Runtime Version:4.0.30319.42000
// //
// Changes to this file may cause incorrect behavior and will be lost if // Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated. // the code is regenerated.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace WPinternals.Properties { namespace WPinternals.Properties {
using System; using System;
/// <summary> /// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc. /// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary> /// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder // This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio. // class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen // To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project. // with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources { internal class Resources {
private static global::System.Resources.ResourceManager resourceMan; private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture; private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() { internal Resources() {
} }
/// <summary> /// <summary>
/// Returns the cached ResourceManager instance used by this class. /// Returns the cached ResourceManager instance used by this class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager { internal static global::System.Resources.ResourceManager ResourceManager {
get { get {
if (object.ReferenceEquals(resourceMan, null)) { if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WPinternals.Properties.Resources", typeof(Resources).Assembly); global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WPinternals.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp; resourceMan = temp;
} }
return resourceMan; return resourceMan;
} }
} }
/// <summary> /// <summary>
/// Overrides the current thread's CurrentUICulture property for all /// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class. /// resource lookups using this strongly typed resource class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture { internal static global::System.Globalization.CultureInfo Culture {
get { get {
return resourceCulture; return resourceCulture;
} }
set { set {
resourceCulture = value; resourceCulture = value;
} }
} }
} }
} }
@@ -1,117 +1,117 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<root> <root>
<!-- <!--
Microsoft ResX Schema Microsoft ResX Schema
Version 2.0 Version 2.0
The primary goals of this format is to allow a simple XML format The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes various data types are done through the TypeConverter classes
associated with the data types. associated with the data types.
Example: Example:
... ado.net/XML headers & schema ... ... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader> <resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader> <resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value> <value>[base64 mime encoded serialized .NET Framework object]</value>
</data> </data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment> <comment>This is a comment</comment>
</data> </data>
There are any number of "resheader" rows that contain simple There are any number of "resheader" rows that contain simple
name/value pairs. name/value pairs.
Each data row contains a name, and value. The row also contains a Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture. text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the Classes that don't support this are serialized and stored with the
mimetype set. mimetype set.
The mimetype is used for serialized objects, and tells the The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly: extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below. read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64 mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter : System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64 mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64 mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter : using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
--> -->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true"> <xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType> <xsd:complexType>
<xsd:choice maxOccurs="unbounded"> <xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata"> <xsd:element name="metadata">
<xsd:complexType> <xsd:complexType>
<xsd:sequence> <xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" /> <xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence> </xsd:sequence>
<xsd:attribute name="name" type="xsd:string" /> <xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" /> <xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" /> <xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
<xsd:element name="assembly"> <xsd:element name="assembly">
<xsd:complexType> <xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" /> <xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" /> <xsd:attribute name="name" type="xsd:string" />
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
<xsd:element name="data"> <xsd:element name="data">
<xsd:complexType> <xsd:complexType>
<xsd:sequence> <xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence> </xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
<xsd:element name="resheader"> <xsd:element name="resheader">
<xsd:complexType> <xsd:complexType>
<xsd:sequence> <xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence> </xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" /> <xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
</xsd:choice> </xsd:choice>
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
</xsd:schema> </xsd:schema>
<resheader name="resmimetype"> <resheader name="resmimetype">
<value>text/microsoft-resx</value> <value>text/microsoft-resx</value>
</resheader> </resheader>
<resheader name="version"> <resheader name="version">
<value>2.0</value> <value>2.0</value>
</resheader> </resheader>
<resheader name="reader"> <resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
</root> </root>
@@ -1,26 +1,26 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.
// Runtime Version:4.0.30319.42000 // Runtime Version:4.0.30319.42000
// //
// Changes to this file may cause incorrect behavior and will be lost if // Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated. // the code is regenerated.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace WPinternals.Properties { namespace WPinternals.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.5.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.5.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default { public static Settings Default {
get { get {
return defaultInstance; return defaultInstance;
} }
} }
} }
} }
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)"> <SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles> <Profiles>
<Profile Name="(Default)" /> <Profile Name="(Default)" />
</Profiles> </Profiles>
<Settings /> <Settings />
</SettingsFile> </SettingsFile>
View File
View File
View File
+68 -68
View File
@@ -1,68 +1,68 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace WPinternals namespace WPinternals
{ {
internal static class Terminal internal static class Terminal
{ {
public static TerminalResponse Parse(byte[] Buffer, int Offset) public static TerminalResponse Parse(byte[] Buffer, int Offset)
{ {
TerminalResponse Response = new(); TerminalResponse Response = new();
// Get root node // Get root node
if (Buffer.Length >= (Offset + 8)) if (Buffer.Length >= (Offset + 8))
{ {
int NodeNumber = BitConverter.ToInt32(Buffer, Offset); int NodeNumber = BitConverter.ToInt32(Buffer, Offset);
int NodeSize = BitConverter.ToInt32(Buffer, Offset + 4); int NodeSize = BitConverter.ToInt32(Buffer, Offset + 4);
int End = NodeSize + Offset + 8; int End = NodeSize + Offset + 8;
int Index = Offset + 8; int Index = Offset + 8;
if ((NodeNumber == 0x10000) && (End <= Buffer.Length)) if ((NodeNumber == 0x10000) && (End <= Buffer.Length))
{ {
// Get subnodes // Get subnodes
while (Index < End) while (Index < End)
{ {
NodeNumber = BitConverter.ToInt32(Buffer, Index); NodeNumber = BitConverter.ToInt32(Buffer, Index);
NodeSize = BitConverter.ToInt32(Buffer, Index + 4); NodeSize = BitConverter.ToInt32(Buffer, Index + 4);
byte[] Raw = new byte[NodeSize]; byte[] Raw = new byte[NodeSize];
Array.Copy(Buffer, Index + 8, Raw, 0, NodeSize); Array.Copy(Buffer, Index + 8, Raw, 0, NodeSize);
Response.RawEntries.Add(NodeNumber, Raw); Response.RawEntries.Add(NodeNumber, Raw);
Index += NodeSize + 8; Index += NodeSize + 8;
} }
} }
} }
// Parse subnodes // Parse subnodes
Response.RawEntries.TryGetValue(3, out Response.PublicId); Response.RawEntries.TryGetValue(3, out Response.PublicId);
Response.RawEntries.TryGetValue(7, out Response.RootKeyHash); Response.RawEntries.TryGetValue(7, out Response.RootKeyHash);
return Response; return Response;
} }
} }
internal class TerminalResponse internal class TerminalResponse
{ {
public Dictionary<int, byte[]> RawEntries = new(); public Dictionary<int, byte[]> RawEntries = new();
public byte[] PublicId = null; public byte[] PublicId = null;
public byte[] RootKeyHash = null; public byte[] RootKeyHash = null;
} }
} }
+295 -295
View File
@@ -1,295 +1,295 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace WPinternals namespace WPinternals
{ {
internal static class TestCode internal static class TestCode
{ {
internal static async Task Test(System.Threading.SynchronizationContext UIContext) internal static async Task Test(System.Threading.SynchronizationContext UIContext)
{ {
// To avoid warnings when there is no code here. // To avoid warnings when there is no code here.
await Task.Run(() => { }); await Task.Run(() => { });
// PhoneNotifierViewModel Notifier = new PhoneNotifierViewModel(); // PhoneNotifierViewModel Notifier = new PhoneNotifierViewModel();
// Notifier.Start(); // Notifier.Start();
// await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage); // await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage);
// MassStorage MassStorage = (MassStorage)Notifier.CurrentModel; // MassStorage MassStorage = (MassStorage)Notifier.CurrentModel;
} }
internal static async Task RecoverBadGPT(string GPTPath, string LoadersPath) internal static async Task RecoverBadGPT(string GPTPath, string LoadersPath)
{ {
byte[] GPT = File.ReadAllBytes(GPTPath); byte[] GPT = File.ReadAllBytes(GPTPath);
PhoneNotifierViewModel PhoneNotifier = new(); PhoneNotifierViewModel PhoneNotifier = new();
PhoneNotifier.Start(); PhoneNotifier.Start();
await SwitchModeViewModel.SwitchTo(PhoneNotifier, PhoneInterfaces.Qualcomm_Download); await SwitchModeViewModel.SwitchTo(PhoneNotifier, PhoneInterfaces.Qualcomm_Download);
byte[] RootKeyHash = null; byte[] RootKeyHash = null;
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Qualcomm_Download) if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Qualcomm_Download)
{ {
QualcommDownload Download2 = new((QualcommSerial)PhoneNotifier.CurrentModel); QualcommDownload Download2 = new((QualcommSerial)PhoneNotifier.CurrentModel);
RootKeyHash = Download2.GetRKH(); RootKeyHash = Download2.GetRKH();
} }
List<QualcommPartition> PossibleLoaders = null; List<QualcommPartition> PossibleLoaders = null;
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Qualcomm_Download) if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Qualcomm_Download)
{ {
try try
{ {
PossibleLoaders = QualcommLoaders.GetPossibleLoadersForRootKeyHash(LoadersPath, RootKeyHash); PossibleLoaders = QualcommLoaders.GetPossibleLoadersForRootKeyHash(LoadersPath, RootKeyHash);
if (PossibleLoaders.Count == 0) if (PossibleLoaders.Count == 0)
{ {
throw new Exception("Error: No matching loaders found for RootKeyHash."); throw new Exception("Error: No matching loaders found for RootKeyHash.");
} }
} }
catch (Exception Ex) catch (Exception Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
throw new Exception("Error: Unexpected error during scanning for loaders."); throw new Exception("Error: Unexpected error during scanning for loaders.");
} }
} }
QualcommSerial Serial = (QualcommSerial)PhoneNotifier.CurrentModel; QualcommSerial Serial = (QualcommSerial)PhoneNotifier.CurrentModel;
QualcommDownload Download = new(Serial); QualcommDownload Download = new(Serial);
if (Download.IsAlive()) if (Download.IsAlive())
{ {
int Attempt = 1; int Attempt = 1;
bool Result = false; bool Result = false;
foreach (QualcommPartition Loader in PossibleLoaders) foreach (QualcommPartition Loader in PossibleLoaders)
{ {
LogFile.Log("Attempt " + Attempt.ToString(), LogType.ConsoleOnly); LogFile.Log("Attempt " + Attempt.ToString(), LogType.ConsoleOnly);
try try
{ {
Download.SendToPhoneMemory(0x2A000000, Loader.Binary); Download.SendToPhoneMemory(0x2A000000, Loader.Binary);
Download.StartBootloader(0x2A000000); Download.StartBootloader(0x2A000000);
Result = true; Result = true;
LogFile.Log("Loader sent successfully", LogType.ConsoleOnly); LogFile.Log("Loader sent successfully", LogType.ConsoleOnly);
} }
catch { } catch { }
if (Result) if (Result)
{ {
break; break;
} }
Attempt++; Attempt++;
} }
Serial.Close(); Serial.Close();
if (!Result) if (!Result)
{ {
LogFile.Log("Loader failed", LogType.ConsoleOnly); LogFile.Log("Loader failed", LogType.ConsoleOnly);
} }
} }
else else
{ {
LogFile.Log("Failed to communicate to Qualcomm Emergency Download mode", LogType.ConsoleOnly); LogFile.Log("Failed to communicate to Qualcomm Emergency Download mode", LogType.ConsoleOnly);
throw new BadConnectionException(); throw new BadConnectionException();
} }
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Qualcomm_Flash) if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Qualcomm_Flash)
{ {
await PhoneNotifier.WaitForArrival(); await PhoneNotifier.WaitForArrival();
} }
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Qualcomm_Flash) if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Qualcomm_Flash)
{ {
throw new WPinternalsException("Phone failed to switch to emergency flash mode."); throw new WPinternalsException("Phone failed to switch to emergency flash mode.");
} }
// Flash bootloader // Flash bootloader
QualcommSerial Serial2 = (QualcommSerial)PhoneNotifier.CurrentModel; QualcommSerial Serial2 = (QualcommSerial)PhoneNotifier.CurrentModel;
Serial2.EncodeCommands = false; Serial2.EncodeCommands = false;
QualcommFlasher Flasher = new(Serial2); QualcommFlasher Flasher = new(Serial2);
Flasher.Hello(); Flasher.Hello();
Flasher.SetSecurityMode(0); Flasher.SetSecurityMode(0);
Flasher.OpenPartition(0x21); Flasher.OpenPartition(0x21);
LogFile.Log("Partition opened.", LogType.ConsoleOnly); LogFile.Log("Partition opened.", LogType.ConsoleOnly);
LogFile.Log("Flash GPT at 0x" + ((UInt32)0x200).ToString("X8"), LogType.ConsoleOnly); LogFile.Log("Flash GPT at 0x" + ((UInt32)0x200).ToString("X8"), LogType.ConsoleOnly);
Flasher.Flash(0x200, GPT, 0, 0x41FF); // Bad bounds-check in the flash-loader prohibits to write the last byte. Flasher.Flash(0x200, GPT, 0, 0x41FF); // Bad bounds-check in the flash-loader prohibits to write the last byte.
Flasher.ClosePartition(); Flasher.ClosePartition();
LogFile.Log("Partition closed. Flashing ready. Rebooting."); LogFile.Log("Partition closed. Flashing ready. Rebooting.");
Flasher.Reboot(); Flasher.Reboot();
Flasher.CloseSerial(); Flasher.CloseSerial();
} }
internal static async Task RewriteGPT(string GPTPath) internal static async Task RewriteGPT(string GPTPath)
{ {
PhoneNotifierViewModel Notifier = new(); PhoneNotifierViewModel Notifier = new();
Notifier.Start(); Notifier.Start();
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage); await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage);
MassStorage MassStorage = (MassStorage)Notifier.CurrentModel; MassStorage MassStorage = (MassStorage)Notifier.CurrentModel;
LogFile.Log("Writing GPT to the device.", LogType.ConsoleOnly); LogFile.Log("Writing GPT to the device.", LogType.ConsoleOnly);
MassStorage.WriteSectors(1, GPTPath); MassStorage.WriteSectors(1, GPTPath);
} }
internal static async Task RewriteMBRGPT() internal static async Task RewriteMBRGPT()
{ {
FFU FFU = new(@"E:\Device Backups\Alpha\9200_1230.0025.9200.9825\RX100_9825.ffu"); FFU FFU = new(@"E:\Device Backups\Alpha\9200_1230.0025.9200.9825\RX100_9825.ffu");
const string GPTPath = @"E:\Device Backups\Alpha\9200_1230.0025.9200.9825\CorrectGPT.bin"; const string GPTPath = @"E:\Device Backups\Alpha\9200_1230.0025.9200.9825\CorrectGPT.bin";
PhoneNotifierViewModel Notifier = new(); PhoneNotifierViewModel Notifier = new();
Notifier.Start(); Notifier.Start();
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage); await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage);
MassStorage MassStorage = (MassStorage)Notifier.CurrentModel; MassStorage MassStorage = (MassStorage)Notifier.CurrentModel;
byte[] MBR = FFU.GetSectors(0, 1); byte[] MBR = FFU.GetSectors(0, 1);
LogFile.Log("Writing MBR to the device.", LogType.ConsoleOnly); LogFile.Log("Writing MBR to the device.", LogType.ConsoleOnly);
MassStorage.WriteSectors(0, MBR); MassStorage.WriteSectors(0, MBR);
LogFile.Log("Writing GPT to the device.", LogType.ConsoleOnly); LogFile.Log("Writing GPT to the device.", LogType.ConsoleOnly);
MassStorage.WriteSectors(1, GPTPath); MassStorage.WriteSectors(1, GPTPath);
} }
internal static async Task RewriteParts(string PartPath) internal static async Task RewriteParts(string PartPath)
{ {
PhoneNotifierViewModel Notifier = new(); PhoneNotifierViewModel Notifier = new();
Notifier.Start(); Notifier.Start();
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage); await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage);
MassStorage MassStorage = (MassStorage)Notifier.CurrentModel; MassStorage MassStorage = (MassStorage)Notifier.CurrentModel;
foreach (var part in Directory.EnumerateFiles(PartPath)) foreach (var part in Directory.EnumerateFiles(PartPath))
{ {
var partname = part.Split('\\').Last().Replace(".img", ""); var partname = part.Split('\\').Last().Replace(".img", "");
try try
{ {
LogFile.Log($"Writing {partname} to the device.", LogType.ConsoleOnly); LogFile.Log($"Writing {partname} to the device.", LogType.ConsoleOnly);
LogFile.Log("", LogType.ConsoleOnly); LogFile.Log("", LogType.ConsoleOnly);
MassStorage.RestorePartition(part, partname, (v, t) => LogFile.Log("Progress: " + v + "%", LogType.ConsoleOnly)); MassStorage.RestorePartition(part, partname, (v, t) => LogFile.Log("Progress: " + v + "%", LogType.ConsoleOnly));
LogFile.Log("", LogType.ConsoleOnly); LogFile.Log("", LogType.ConsoleOnly);
} }
catch catch
{ {
LogFile.Log("", LogType.ConsoleOnly); LogFile.Log("", LogType.ConsoleOnly);
LogFile.Log($"Failed writing {partname} to the device.", LogType.ConsoleOnly); LogFile.Log($"Failed writing {partname} to the device.", LogType.ConsoleOnly);
} }
} }
} }
internal static void PatchImg(string dump) internal static void PatchImg(string dump)
{ {
using var fil = File.Open(dump, FileMode.Open); using var fil = File.Open(dump, FileMode.Open);
byte[] gptbuffer = new byte[0x4200]; byte[] gptbuffer = new byte[0x4200];
fil.Seek(0x200, SeekOrigin.Begin); fil.Seek(0x200, SeekOrigin.Begin);
fil.Read(gptbuffer, 0, 0x4200); fil.Read(gptbuffer, 0, 0x4200);
uint BackupLBA = ByteOperations.ReadUInt32(gptbuffer, 0x20); uint BackupLBA = ByteOperations.ReadUInt32(gptbuffer, 0x20);
uint LastUsableLBA = ByteOperations.ReadUInt32(gptbuffer, 0x30); uint LastUsableLBA = ByteOperations.ReadUInt32(gptbuffer, 0x30);
LogFile.Log("Previous BackupLBA: " + BackupLBA, LogType.ConsoleOnly); LogFile.Log("Previous BackupLBA: " + BackupLBA, LogType.ConsoleOnly);
LogFile.Log("Previous LastUsableLBA: " + LastUsableLBA, LogType.ConsoleOnly); LogFile.Log("Previous LastUsableLBA: " + LastUsableLBA, LogType.ConsoleOnly);
const uint NewBackupLBA = 62078975u; const uint NewBackupLBA = 62078975u;
const uint NewLastUsableLBA = 62078942u; const uint NewLastUsableLBA = 62078942u;
ByteOperations.WriteUInt32(gptbuffer, 0x20, NewBackupLBA); ByteOperations.WriteUInt32(gptbuffer, 0x20, NewBackupLBA);
ByteOperations.WriteUInt32(gptbuffer, 0x30, NewLastUsableLBA); ByteOperations.WriteUInt32(gptbuffer, 0x30, NewLastUsableLBA);
uint HeaderSize = ByteOperations.ReadUInt32(gptbuffer, 0x0C); uint HeaderSize = ByteOperations.ReadUInt32(gptbuffer, 0x0C);
uint PrevCRC = ByteOperations.ReadUInt32(gptbuffer, 0x10); uint PrevCRC = ByteOperations.ReadUInt32(gptbuffer, 0x10);
LogFile.Log("Previous CRC: " + PrevCRC, LogType.ConsoleOnly); LogFile.Log("Previous CRC: " + PrevCRC, LogType.ConsoleOnly);
ByteOperations.WriteUInt32(gptbuffer, 0x10, 0); ByteOperations.WriteUInt32(gptbuffer, 0x10, 0);
uint NewCRC = ByteOperations.CRC32(gptbuffer, 0, HeaderSize); uint NewCRC = ByteOperations.CRC32(gptbuffer, 0, HeaderSize);
LogFile.Log("New CRC: " + NewCRC, LogType.ConsoleOnly); LogFile.Log("New CRC: " + NewCRC, LogType.ConsoleOnly);
ByteOperations.WriteUInt32(gptbuffer, 0x10, NewCRC); ByteOperations.WriteUInt32(gptbuffer, 0x10, NewCRC);
LogFile.Log("Writing", LogType.ConsoleOnly); LogFile.Log("Writing", LogType.ConsoleOnly);
fil.Seek(0x200, SeekOrigin.Begin); fil.Seek(0x200, SeekOrigin.Begin);
fil.Write(gptbuffer, 0, 0x4200); fil.Write(gptbuffer, 0, 0x4200);
LogFile.Log("Done!", LogType.ConsoleOnly); LogFile.Log("Done!", LogType.ConsoleOnly);
} }
internal static async Task TestProgrammer(System.Threading.SynchronizationContext UIContext, string ProgrammerPath) internal static async Task TestProgrammer(System.Threading.SynchronizationContext UIContext, string ProgrammerPath)
{ {
LogFile.BeginAction("TestProgrammer"); LogFile.BeginAction("TestProgrammer");
try try
{ {
LogFile.Log("Starting Firehose Test", LogType.FileAndConsole); LogFile.Log("Starting Firehose Test", LogType.FileAndConsole);
PhoneNotifierViewModel Notifier = new(); PhoneNotifierViewModel Notifier = new();
UIContext.Send(s => Notifier.Start(), null); UIContext.Send(s => Notifier.Start(), null);
if (Notifier.CurrentInterface == PhoneInterfaces.Qualcomm_Download) if (Notifier.CurrentInterface == PhoneInterfaces.Qualcomm_Download)
{ {
LogFile.Log("Phone found in emergency mode", LogType.FileAndConsole); LogFile.Log("Phone found in emergency mode", LogType.FileAndConsole);
} }
else else
{ {
LogFile.Log("Phone needs to be switched to emergency mode.", LogType.FileAndConsole); LogFile.Log("Phone needs to be switched to emergency mode.", LogType.FileAndConsole);
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash); await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
PhoneInfo Info = ((NokiaFlashModel)Notifier.CurrentModel).ReadPhoneInfo(); PhoneInfo Info = ((NokiaFlashModel)Notifier.CurrentModel).ReadPhoneInfo();
Info.Log(LogType.ConsoleOnly); Info.Log(LogType.ConsoleOnly);
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Qualcomm_Download); await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Qualcomm_Download);
if (Notifier.CurrentInterface != PhoneInterfaces.Qualcomm_Download) if (Notifier.CurrentInterface != PhoneInterfaces.Qualcomm_Download)
{ {
throw new WPinternalsException("Switching mode failed.", "Could not switch the phone to Qualcomm Emergency 9008."); throw new WPinternalsException("Switching mode failed.", "Could not switch the phone to Qualcomm Emergency 9008.");
} }
LogFile.Log("Phone is in emergency mode.", LogType.FileAndConsole); LogFile.Log("Phone is in emergency mode.", LogType.FileAndConsole);
} }
// Send and start programmer // Send and start programmer
QualcommSerial Serial = (QualcommSerial)Notifier.CurrentModel; QualcommSerial Serial = (QualcommSerial)Notifier.CurrentModel;
QualcommSahara Sahara = new(Serial); QualcommSahara Sahara = new(Serial);
if (await Sahara.Reset(ProgrammerPath)) if (await Sahara.Reset(ProgrammerPath))
{ {
LogFile.Log("Emergency programmer test succeeded", LogType.FileAndConsole); LogFile.Log("Emergency programmer test succeeded", LogType.FileAndConsole);
} }
else else
{ {
LogFile.Log("Emergency programmer test failed", LogType.FileAndConsole); LogFile.Log("Emergency programmer test failed", LogType.FileAndConsole);
} }
} }
catch (Exception Ex) catch (Exception Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
} }
finally finally
{ {
LogFile.EndAction("TestProgrammer"); LogFile.EndAction("TestProgrammer");
} }
} }
} }
} }
@@ -1,43 +1,43 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
namespace WPinternals namespace WPinternals
{ {
internal class AboutViewModel : ContextViewModel internal class AboutViewModel : ContextViewModel
{ {
internal AboutViewModel() : base() { } internal AboutViewModel() : base() { }
public int MajorVersion public int MajorVersion
{ {
get get
{ {
return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Major; return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Major;
} }
} }
public int MinorVersion public int MinorVersion
{ {
get get
{ {
return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Minor; return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Minor;
} }
} }
} }
} }
@@ -1,237 +1,237 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Threading; using System.Threading;
namespace WPinternals namespace WPinternals
{ {
internal class BackupTargetSelectionViewModel : ContextViewModel internal class BackupTargetSelectionViewModel : ContextViewModel
{ {
private readonly PhoneNotifierViewModel PhoneNotifier; private readonly PhoneNotifierViewModel PhoneNotifier;
private readonly Action<string, string, string> BackupCallback; private readonly Action<string, string, string> BackupCallback;
private readonly Action<string> BackupArchiveCallback; private readonly Action<string> BackupArchiveCallback;
private readonly Action<string> BackupArchiveProvisioningCallback; private readonly Action<string> BackupArchiveProvisioningCallback;
internal Action SwitchToUnlockBoot; internal Action SwitchToUnlockBoot;
internal BackupTargetSelectionViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action<string> BackupArchiveCallback, Action<string, string, string> BackupCallback, Action<string> BackupArchiveProvisioningCallback) internal BackupTargetSelectionViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action<string> BackupArchiveCallback, Action<string, string, string> BackupCallback, Action<string> BackupArchiveProvisioningCallback)
: base() : base()
{ {
this.PhoneNotifier = PhoneNotifier; this.PhoneNotifier = PhoneNotifier;
this.BackupCallback = BackupCallback; this.BackupCallback = BackupCallback;
this.BackupArchiveCallback = BackupArchiveCallback; this.BackupArchiveCallback = BackupArchiveCallback;
this.BackupArchiveProvisioningCallback = BackupArchiveProvisioningCallback; this.BackupArchiveProvisioningCallback = BackupArchiveProvisioningCallback;
this.SwitchToUnlockBoot = SwitchToUnlockBoot; this.SwitchToUnlockBoot = SwitchToUnlockBoot;
this.PhoneNotifier.NewDeviceArrived += NewDeviceArrived; this.PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
this.PhoneNotifier.DeviceRemoved += DeviceRemoved; this.PhoneNotifier.DeviceRemoved += DeviceRemoved;
new Thread(() => EvaluateViewState()).Start(); new Thread(() => EvaluateViewState()).Start();
} }
private string _ArchivePath; private string _ArchivePath;
public string ArchivePath public string ArchivePath
{ {
get get
{ {
return _ArchivePath; return _ArchivePath;
} }
set set
{ {
if (value != _ArchivePath) if (value != _ArchivePath)
{ {
_ArchivePath = value; _ArchivePath = value;
OnPropertyChanged(nameof(ArchivePath)); OnPropertyChanged(nameof(ArchivePath));
} }
} }
} }
private string _EFIESPPath; private string _EFIESPPath;
public string EFIESPPath public string EFIESPPath
{ {
get get
{ {
return _EFIESPPath; return _EFIESPPath;
} }
set set
{ {
if (value != _EFIESPPath) if (value != _EFIESPPath)
{ {
_EFIESPPath = value; _EFIESPPath = value;
OnPropertyChanged(nameof(EFIESPPath)); OnPropertyChanged(nameof(EFIESPPath));
} }
} }
} }
private string _MainOSPath; private string _MainOSPath;
public string MainOSPath public string MainOSPath
{ {
get get
{ {
return _MainOSPath; return _MainOSPath;
} }
set set
{ {
if (value != _MainOSPath) if (value != _MainOSPath)
{ {
_MainOSPath = value; _MainOSPath = value;
OnPropertyChanged(nameof(MainOSPath)); OnPropertyChanged(nameof(MainOSPath));
} }
} }
} }
private string _DataPath; private string _DataPath;
public string DataPath public string DataPath
{ {
get get
{ {
return _DataPath; return _DataPath;
} }
set set
{ {
if (value != _DataPath) if (value != _DataPath)
{ {
_DataPath = value; _DataPath = value;
OnPropertyChanged(nameof(DataPath)); OnPropertyChanged(nameof(DataPath));
} }
} }
} }
private string _ArchiveProvisioningPath; private string _ArchiveProvisioningPath;
public string ArchiveProvisioningPath public string ArchiveProvisioningPath
{ {
get get
{ {
return _ArchiveProvisioningPath; return _ArchiveProvisioningPath;
} }
set set
{ {
if (value != _ArchiveProvisioningPath) if (value != _ArchiveProvisioningPath)
{ {
_ArchiveProvisioningPath = value; _ArchiveProvisioningPath = value;
OnPropertyChanged(nameof(ArchiveProvisioningPath)); OnPropertyChanged(nameof(ArchiveProvisioningPath));
} }
} }
} }
private bool _IsPhoneDisconnected; private bool _IsPhoneDisconnected;
public bool IsPhoneDisconnected public bool IsPhoneDisconnected
{ {
get get
{ {
return _IsPhoneDisconnected; return _IsPhoneDisconnected;
} }
set set
{ {
if (value != _IsPhoneDisconnected) if (value != _IsPhoneDisconnected)
{ {
_IsPhoneDisconnected = value; _IsPhoneDisconnected = value;
OnPropertyChanged(nameof(IsPhoneDisconnected)); OnPropertyChanged(nameof(IsPhoneDisconnected));
} }
} }
} }
private bool _IsPhoneInMassStorage; private bool _IsPhoneInMassStorage;
public bool IsPhoneInMassStorage public bool IsPhoneInMassStorage
{ {
get get
{ {
return _IsPhoneInMassStorage; return _IsPhoneInMassStorage;
} }
set set
{ {
if (value != _IsPhoneInMassStorage) if (value != _IsPhoneInMassStorage)
{ {
_IsPhoneInMassStorage = value; _IsPhoneInMassStorage = value;
OnPropertyChanged(nameof(IsPhoneInMassStorage)); OnPropertyChanged(nameof(IsPhoneInMassStorage));
} }
} }
} }
private bool _IsPhoneInOtherMode; private bool _IsPhoneInOtherMode;
public bool IsPhoneInOtherMode public bool IsPhoneInOtherMode
{ {
get get
{ {
return _IsPhoneInOtherMode; return _IsPhoneInOtherMode;
} }
set set
{ {
if (value != _IsPhoneInOtherMode) if (value != _IsPhoneInOtherMode)
{ {
_IsPhoneInOtherMode = value; _IsPhoneInOtherMode = value;
OnPropertyChanged(nameof(IsPhoneInOtherMode)); OnPropertyChanged(nameof(IsPhoneInOtherMode));
} }
} }
} }
private DelegateCommand _BackupArchiveCommand; private DelegateCommand _BackupArchiveCommand;
public DelegateCommand BackupArchiveCommand public DelegateCommand BackupArchiveCommand
{ {
get get
{ {
return _BackupArchiveCommand ??= new DelegateCommand(() => BackupArchiveCallback(ArchivePath), () => (ArchivePath != null) && (PhoneNotifier.CurrentInterface != null)); return _BackupArchiveCommand ??= new DelegateCommand(() => BackupArchiveCallback(ArchivePath), () => (ArchivePath != null) && (PhoneNotifier.CurrentInterface != null));
} }
} }
private DelegateCommand _BackupCommand; private DelegateCommand _BackupCommand;
public DelegateCommand BackupCommand public DelegateCommand BackupCommand
{ {
get get
{ {
return _BackupCommand ??= new DelegateCommand(() => BackupCallback(EFIESPPath, MainOSPath, DataPath), () => ((EFIESPPath != null) || (MainOSPath != null) || (DataPath != null)) && (PhoneNotifier.CurrentInterface != null)); return _BackupCommand ??= new DelegateCommand(() => BackupCallback(EFIESPPath, MainOSPath, DataPath), () => ((EFIESPPath != null) || (MainOSPath != null) || (DataPath != null)) && (PhoneNotifier.CurrentInterface != null));
} }
} }
private DelegateCommand _BackupArchiveProvisioningCommand; private DelegateCommand _BackupArchiveProvisioningCommand;
public DelegateCommand BackupArchiveProvisioningCommand public DelegateCommand BackupArchiveProvisioningCommand
{ {
get get
{ {
return _BackupArchiveProvisioningCommand ??= new DelegateCommand(() => BackupArchiveProvisioningCallback(ArchiveProvisioningPath), () => (ArchiveProvisioningPath != null) && (PhoneNotifier.CurrentInterface != null)); return _BackupArchiveProvisioningCommand ??= new DelegateCommand(() => BackupArchiveProvisioningCallback(ArchiveProvisioningPath), () => (ArchiveProvisioningPath != null) && (PhoneNotifier.CurrentInterface != null));
} }
} }
~BackupTargetSelectionViewModel() ~BackupTargetSelectionViewModel()
{ {
PhoneNotifier.NewDeviceArrived -= NewDeviceArrived; PhoneNotifier.NewDeviceArrived -= NewDeviceArrived;
} }
private void NewDeviceArrived(ArrivalEventArgs Args) private void NewDeviceArrived(ArrivalEventArgs Args)
{ {
new Thread(() => EvaluateViewState()).Start(); new Thread(() => EvaluateViewState()).Start();
} }
private void DeviceRemoved() private void DeviceRemoved()
{ {
new Thread(() => EvaluateViewState()).Start(); new Thread(() => EvaluateViewState()).Start();
} }
internal override void EvaluateViewState() internal override void EvaluateViewState()
{ {
IsPhoneDisconnected = PhoneNotifier.CurrentInterface == null; IsPhoneDisconnected = PhoneNotifier.CurrentInterface == null;
IsPhoneInMassStorage = PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_MassStorage; IsPhoneInMassStorage = PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_MassStorage;
IsPhoneInOtherMode = !IsPhoneDisconnected && !IsPhoneInMassStorage; IsPhoneInOtherMode = !IsPhoneDisconnected && !IsPhoneInMassStorage;
BackupCommand.RaiseCanExecuteChanged(); BackupCommand.RaiseCanExecuteChanged();
BackupArchiveCommand.RaiseCanExecuteChanged(); BackupArchiveCommand.RaiseCanExecuteChanged();
BackupArchiveProvisioningCommand.RaiseCanExecuteChanged(); BackupArchiveProvisioningCommand.RaiseCanExecuteChanged();
} }
} }
} }
@@ -1,490 +1,490 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
namespace WPinternals namespace WPinternals
{ {
internal class BackupViewModel : ContextViewModel internal class BackupViewModel : ContextViewModel
{ {
private readonly PhoneNotifierViewModel PhoneNotifier; private readonly PhoneNotifierViewModel PhoneNotifier;
private readonly Action Callback; private readonly Action Callback;
private readonly Action SwitchToUnlockBoot; private readonly Action SwitchToUnlockBoot;
internal BackupViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action Callback) internal BackupViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action Callback)
: base() : base()
{ {
IsFlashModeOperation = true; IsFlashModeOperation = true;
this.PhoneNotifier = PhoneNotifier; this.PhoneNotifier = PhoneNotifier;
this.SwitchToUnlockBoot = SwitchToUnlockBoot; this.SwitchToUnlockBoot = SwitchToUnlockBoot;
this.Callback = Callback; this.Callback = Callback;
} }
internal override void EvaluateViewState() internal override void EvaluateViewState()
{ {
if (!IsActive) if (!IsActive)
{ {
return; return;
} }
if (SubContextViewModel == null) if (SubContextViewModel == null)
{ {
ActivateSubContext(new BackupTargetSelectionViewModel(PhoneNotifier, SwitchToUnlockBoot, DoBackupArchive, DoBackup, DoBackupArchiveProvisioning)); ActivateSubContext(new BackupTargetSelectionViewModel(PhoneNotifier, SwitchToUnlockBoot, DoBackupArchive, DoBackup, DoBackupArchiveProvisioning));
IsSwitchingInterface = false; IsSwitchingInterface = false;
} }
if (SubContextViewModel is BackupTargetSelectionViewModel) if (SubContextViewModel is BackupTargetSelectionViewModel)
{ {
((BackupTargetSelectionViewModel)SubContextViewModel).EvaluateViewState(); ((BackupTargetSelectionViewModel)SubContextViewModel).EvaluateViewState();
} }
} }
internal async void DoBackup(string EFIESPPath, string MainOSPath, string DataPath) internal async void DoBackup(string EFIESPPath, string MainOSPath, string DataPath)
{ {
try try
{ {
IsSwitchingInterface = true; IsSwitchingInterface = true;
await SwitchModeViewModel.SwitchToWithProgress(PhoneNotifier, PhoneInterfaces.Lumia_MassStorage, await SwitchModeViewModel.SwitchToWithProgress(PhoneNotifier, PhoneInterfaces.Lumia_MassStorage,
(msg, sub) => ActivateSubContext(new BusyViewModel(msg, sub))); (msg, sub) => ActivateSubContext(new BusyViewModel(msg, sub)));
BackupTask(EFIESPPath, MainOSPath, DataPath); BackupTask(EFIESPPath, MainOSPath, DataPath);
} }
catch (Exception Ex) catch (Exception Ex)
{ {
ActivateSubContext(new MessageViewModel(Ex.Message, Callback)); ActivateSubContext(new MessageViewModel(Ex.Message, Callback));
} }
} }
internal async void DoBackupArchive(string ArchivePath) internal async void DoBackupArchive(string ArchivePath)
{ {
try try
{ {
IsSwitchingInterface = true; IsSwitchingInterface = true;
await SwitchModeViewModel.SwitchToWithProgress(PhoneNotifier, PhoneInterfaces.Lumia_MassStorage, await SwitchModeViewModel.SwitchToWithProgress(PhoneNotifier, PhoneInterfaces.Lumia_MassStorage,
(msg, sub) => ActivateSubContext(new BusyViewModel(msg, sub))); (msg, sub) => ActivateSubContext(new BusyViewModel(msg, sub)));
BackupArchiveTask(ArchivePath); BackupArchiveTask(ArchivePath);
} }
catch (Exception Ex) catch (Exception Ex)
{ {
ActivateSubContext(new MessageViewModel(Ex.Message, Callback)); ActivateSubContext(new MessageViewModel(Ex.Message, Callback));
} }
} }
internal async void DoBackupArchiveProvisioning(string ArchiveProvisioningPath) internal async void DoBackupArchiveProvisioning(string ArchiveProvisioningPath)
{ {
try try
{ {
IsSwitchingInterface = true; IsSwitchingInterface = true;
await SwitchModeViewModel.SwitchToWithProgress(PhoneNotifier, PhoneInterfaces.Lumia_MassStorage, await SwitchModeViewModel.SwitchToWithProgress(PhoneNotifier, PhoneInterfaces.Lumia_MassStorage,
(msg, sub) => ActivateSubContext(new BusyViewModel(msg, sub))); (msg, sub) => ActivateSubContext(new BusyViewModel(msg, sub)));
BackupArchiveProvisioningTask(ArchiveProvisioningPath); BackupArchiveProvisioningTask(ArchiveProvisioningPath);
} }
catch (Exception Ex) catch (Exception Ex)
{ {
ActivateSubContext(new MessageViewModel(Ex.Message, Callback)); ActivateSubContext(new MessageViewModel(Ex.Message, Callback));
} }
} }
internal void BackupTask(string EFIESPPath, string MainOSPath, string DataPath) internal void BackupTask(string EFIESPPath, string MainOSPath, string DataPath)
{ {
IsSwitchingInterface = false; IsSwitchingInterface = false;
new Thread(() => new Thread(() =>
{ {
bool Result = true; bool Result = true;
ActivateSubContext(new BusyViewModel("Initializing backup...")); ActivateSubContext(new BusyViewModel("Initializing backup..."));
ulong TotalSizeSectors = 0; ulong TotalSizeSectors = 0;
int PartitionCount = 0; int PartitionCount = 0;
MassStorage Phone = (MassStorage)PhoneNotifier.CurrentModel; MassStorage Phone = (MassStorage)PhoneNotifier.CurrentModel;
Phone.OpenVolume(false); Phone.OpenVolume(false);
byte[] GPTBuffer = Phone.ReadSectors(1, 33); byte[] GPTBuffer = Phone.ReadSectors(1, 33);
GPT GPT = new(GPTBuffer); GPT GPT = new(GPTBuffer);
Partition Partition; Partition Partition;
try try
{ {
if (EFIESPPath != null) if (EFIESPPath != null)
{ {
Partition = GPT.Partitions.First(p => p.Name == "EFIESP"); Partition = GPT.Partitions.First(p => p.Name == "EFIESP");
TotalSizeSectors += Partition.SizeInSectors; TotalSizeSectors += Partition.SizeInSectors;
PartitionCount++; PartitionCount++;
} }
if (MainOSPath != null) if (MainOSPath != null)
{ {
Partition = GPT.Partitions.First(p => p.Name == "MainOS"); Partition = GPT.Partitions.First(p => p.Name == "MainOS");
TotalSizeSectors += Partition.SizeInSectors; TotalSizeSectors += Partition.SizeInSectors;
PartitionCount++; PartitionCount++;
} }
if (DataPath != null) if (DataPath != null)
{ {
Partition = GPT.Partitions.First(p => p.Name == "Data"); Partition = GPT.Partitions.First(p => p.Name == "Data");
TotalSizeSectors += Partition.SizeInSectors; TotalSizeSectors += Partition.SizeInSectors;
PartitionCount++; PartitionCount++;
} }
} }
catch (Exception Ex) catch (Exception Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
Result = false; Result = false;
} }
BusyViewModel Busy = new("Create backup...", MaxProgressValue: TotalSizeSectors, UIContext: UIContext); BusyViewModel Busy = new("Create backup...", MaxProgressValue: TotalSizeSectors, UIContext: UIContext);
ProgressUpdater Updater = Busy.ProgressUpdater; ProgressUpdater Updater = Busy.ProgressUpdater;
ActivateSubContext(Busy); ActivateSubContext(Busy);
int i = 0; int i = 0;
if (Result) if (Result)
{ {
try try
{ {
if (EFIESPPath != null) if (EFIESPPath != null)
{ {
i++; i++;
Busy.Message = "Create backup of partition EFIESP (" + i.ToString() + "/" + PartitionCount.ToString() + ")"; Busy.Message = "Create backup of partition EFIESP (" + i.ToString() + "/" + PartitionCount.ToString() + ")";
Phone.BackupPartition("EFIESP", EFIESPPath, Updater); Phone.BackupPartition("EFIESP", EFIESPPath, Updater);
} }
} }
catch (Exception Ex) catch (Exception Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
Result = false; Result = false;
} }
} }
if (Result) if (Result)
{ {
try try
{ {
if (MainOSPath != null) if (MainOSPath != null)
{ {
i++; i++;
Busy.Message = "Create backup of partition MainOS (" + i.ToString() + "/" + PartitionCount.ToString() + ")"; Busy.Message = "Create backup of partition MainOS (" + i.ToString() + "/" + PartitionCount.ToString() + ")";
Phone.BackupPartition("MainOS", MainOSPath, Updater); Phone.BackupPartition("MainOS", MainOSPath, Updater);
} }
} }
catch (Exception Ex) catch (Exception Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
Result = false; Result = false;
} }
} }
if (Result) if (Result)
{ {
try try
{ {
if (DataPath != null) if (DataPath != null)
{ {
i++; i++;
Busy.Message = "Create backup of partition Data (" + i.ToString() + "/" + PartitionCount.ToString() + ")"; Busy.Message = "Create backup of partition Data (" + i.ToString() + "/" + PartitionCount.ToString() + ")";
Phone.BackupPartition("Data", DataPath, Updater); Phone.BackupPartition("Data", DataPath, Updater);
} }
} }
catch (Exception Ex) catch (Exception Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
Result = false; Result = false;
} }
} }
Phone.CloseVolume(); Phone.CloseVolume();
if (!Result) if (!Result)
{ {
ActivateSubContext(new MessageViewModel("Failed to create backup!", Exit)); ActivateSubContext(new MessageViewModel("Failed to create backup!", Exit));
return; return;
} }
ActivateSubContext(new MessageViewModel("Successfully created a backup!", Exit)); ActivateSubContext(new MessageViewModel("Successfully created a backup!", Exit));
}).Start(); }).Start();
} }
internal void BackupArchiveTask(string ArchivePath) internal void BackupArchiveTask(string ArchivePath)
{ {
IsSwitchingInterface = false; IsSwitchingInterface = false;
new Thread(() => new Thread(() =>
{ {
bool Result = true; bool Result = true;
ActivateSubContext(new BusyViewModel("Initializing backup...")); ActivateSubContext(new BusyViewModel("Initializing backup..."));
ulong TotalSizeSectors = 0; ulong TotalSizeSectors = 0;
const int PartitionCount = 3; const int PartitionCount = 3;
MassStorage Phone = (MassStorage)PhoneNotifier.CurrentModel; MassStorage Phone = (MassStorage)PhoneNotifier.CurrentModel;
try try
{ {
Phone.OpenVolume(false); Phone.OpenVolume(false);
byte[] GPTBuffer = Phone.ReadSectors(1, 33); byte[] GPTBuffer = Phone.ReadSectors(1, 33);
GPT GPT = new(GPTBuffer); GPT GPT = new(GPTBuffer);
Partition Partition; Partition Partition;
try try
{ {
Partition = GPT.Partitions.First(p => p.Name == "EFIESP"); Partition = GPT.Partitions.First(p => p.Name == "EFIESP");
TotalSizeSectors += Partition.SizeInSectors; TotalSizeSectors += Partition.SizeInSectors;
Partition = GPT.Partitions.First(p => p.Name == "MainOS"); Partition = GPT.Partitions.First(p => p.Name == "MainOS");
TotalSizeSectors += Partition.SizeInSectors; TotalSizeSectors += Partition.SizeInSectors;
Partition = GPT.Partitions.First(p => p.Name == "Data"); Partition = GPT.Partitions.First(p => p.Name == "Data");
TotalSizeSectors += Partition.SizeInSectors; TotalSizeSectors += Partition.SizeInSectors;
} }
catch (Exception Ex) catch (Exception Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
Result = false; Result = false;
} }
BusyViewModel Busy = new("Create backup...", MaxProgressValue: TotalSizeSectors, UIContext: UIContext); BusyViewModel Busy = new("Create backup...", MaxProgressValue: TotalSizeSectors, UIContext: UIContext);
ProgressUpdater Updater = Busy.ProgressUpdater; ProgressUpdater Updater = Busy.ProgressUpdater;
ActivateSubContext(Busy); ActivateSubContext(Busy);
ZipArchiveEntry Entry; ZipArchiveEntry Entry;
Stream EntryStream = null; Stream EntryStream = null;
using FileStream FileStream = new(ArchivePath, FileMode.Create); using FileStream FileStream = new(ArchivePath, FileMode.Create);
using ZipArchive Archive = new(FileStream, ZipArchiveMode.Create); using ZipArchive Archive = new(FileStream, ZipArchiveMode.Create);
int i = 0; int i = 0;
if (Result) if (Result)
{ {
try try
{ {
Entry = Archive.CreateEntry("EFIESP.bin", CompressionLevel.Optimal); Entry = Archive.CreateEntry("EFIESP.bin", CompressionLevel.Optimal);
EntryStream = Entry.Open(); EntryStream = Entry.Open();
i++; i++;
Busy.Message = "Create backup of partition EFIESP (" + i.ToString() + "/" + PartitionCount.ToString() + ")"; Busy.Message = "Create backup of partition EFIESP (" + i.ToString() + "/" + PartitionCount.ToString() + ")";
Phone.BackupPartition("EFIESP", EntryStream, Updater); Phone.BackupPartition("EFIESP", EntryStream, Updater);
} }
catch (Exception Ex) catch (Exception Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
Result = false; Result = false;
} }
finally finally
{ {
EntryStream?.Close(); EntryStream?.Close();
EntryStream = null; EntryStream = null;
} }
} }
if (Result) if (Result)
{ {
try try
{ {
Entry = Archive.CreateEntry("MainOS.bin", CompressionLevel.Optimal); Entry = Archive.CreateEntry("MainOS.bin", CompressionLevel.Optimal);
EntryStream = Entry.Open(); EntryStream = Entry.Open();
i++; i++;
Busy.Message = "Create backup of partition MainOS (" + i.ToString() + "/" + PartitionCount.ToString() + ")"; Busy.Message = "Create backup of partition MainOS (" + i.ToString() + "/" + PartitionCount.ToString() + ")";
Phone.BackupPartition("MainOS", EntryStream, Updater); Phone.BackupPartition("MainOS", EntryStream, Updater);
} }
catch (Exception Ex) catch (Exception Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
Result = false; Result = false;
} }
finally finally
{ {
EntryStream?.Close(); EntryStream?.Close();
EntryStream = null; EntryStream = null;
} }
} }
if (Result) if (Result)
{ {
try try
{ {
Entry = Archive.CreateEntry("Data.bin", CompressionLevel.Optimal); Entry = Archive.CreateEntry("Data.bin", CompressionLevel.Optimal);
EntryStream = Entry.Open(); EntryStream = Entry.Open();
i++; i++;
Busy.Message = "Create backup of partition Data (" + i.ToString() + "/" + PartitionCount.ToString() + ")"; Busy.Message = "Create backup of partition Data (" + i.ToString() + "/" + PartitionCount.ToString() + ")";
Phone.BackupPartition("Data", EntryStream, Updater); Phone.BackupPartition("Data", EntryStream, Updater);
} }
catch (Exception Ex) catch (Exception Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
Result = false; Result = false;
} }
finally finally
{ {
EntryStream?.Close(); EntryStream?.Close();
EntryStream = null; EntryStream = null;
} }
} }
} }
catch { } catch { }
finally finally
{ {
Phone.CloseVolume(); Phone.CloseVolume();
} }
if (!Result) if (!Result)
{ {
ActivateSubContext(new MessageViewModel("Failed to create backup!", Exit)); ActivateSubContext(new MessageViewModel("Failed to create backup!", Exit));
return; return;
} }
ActivateSubContext(new MessageViewModel("Successfully created a backup!", Exit)); ActivateSubContext(new MessageViewModel("Successfully created a backup!", Exit));
}).Start(); }).Start();
} }
private readonly static string[] ProvisioningPartitions = new string[] private readonly static string[] ProvisioningPartitions = new string[]
{ {
"DPP", "DPP",
"MODEM_FSG", "MODEM_FSG",
"MODEM_FS1", "MODEM_FS1",
"MODEM_FS2", "MODEM_FS2",
"MODEM_FSC", "MODEM_FSC",
"DDR", "DDR",
"SEC", "SEC",
"APDP", "APDP",
"MSADP", "MSADP",
"DPO", "DPO",
"SSD", "SSD",
"DBI", "DBI",
"UEFI_BS_NV", "UEFI_BS_NV",
"UEFI_NV", "UEFI_NV",
"UEFI_RT_NV", "UEFI_RT_NV",
"UEFI_RT_NV_RPMB", "UEFI_RT_NV_RPMB",
"BOOTMODE", "BOOTMODE",
"LIMITS" "LIMITS"
}; };
internal void BackupArchiveProvisioningTask(string ArchiveProvisioningPath) internal void BackupArchiveProvisioningTask(string ArchiveProvisioningPath)
{ {
IsSwitchingInterface = false; IsSwitchingInterface = false;
new Thread(() => new Thread(() =>
{ {
bool Result = true; bool Result = true;
ActivateSubContext(new BusyViewModel("Initializing backup...")); ActivateSubContext(new BusyViewModel("Initializing backup..."));
ulong TotalSizeSectors = 0; ulong TotalSizeSectors = 0;
int PartitionCount = 0; int PartitionCount = 0;
MassStorage Phone = (MassStorage)PhoneNotifier.CurrentModel; MassStorage Phone = (MassStorage)PhoneNotifier.CurrentModel;
try try
{ {
Phone.OpenVolume(false); Phone.OpenVolume(false);
byte[] GPTBuffer = Phone.ReadSectors(1, 33); byte[] GPTBuffer = Phone.ReadSectors(1, 33);
GPT GPT = new(GPTBuffer); GPT GPT = new(GPTBuffer);
Partition Partition; Partition Partition;
try try
{ {
foreach (string PartitionName in ProvisioningPartitions) foreach (string PartitionName in ProvisioningPartitions)
{ {
if (GPT.Partitions.Any(p => p.Name == PartitionName)) if (GPT.Partitions.Any(p => p.Name == PartitionName))
{ {
Partition = GPT.Partitions.First(p => p.Name == PartitionName); Partition = GPT.Partitions.First(p => p.Name == PartitionName);
if (PartitionName == "UEFI_BS_NV" && GPT.Partitions.Any(p => p.Name == "BACKUP_BS_NV")) if (PartitionName == "UEFI_BS_NV" && GPT.Partitions.Any(p => p.Name == "BACKUP_BS_NV"))
{ {
Partition = GPT.Partitions.First(p => p.Name == "BACKUP_BS_NV"); Partition = GPT.Partitions.First(p => p.Name == "BACKUP_BS_NV");
} }
TotalSizeSectors += Partition.SizeInSectors; TotalSizeSectors += Partition.SizeInSectors;
PartitionCount++; PartitionCount++;
} }
} }
} }
catch (Exception Ex) catch (Exception Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
Result = false; Result = false;
} }
BusyViewModel Busy = new("Create backup...", MaxProgressValue: TotalSizeSectors, UIContext: UIContext); BusyViewModel Busy = new("Create backup...", MaxProgressValue: TotalSizeSectors, UIContext: UIContext);
ProgressUpdater Updater = Busy.ProgressUpdater; ProgressUpdater Updater = Busy.ProgressUpdater;
ActivateSubContext(Busy); ActivateSubContext(Busy);
ZipArchiveEntry Entry; ZipArchiveEntry Entry;
Stream EntryStream = null; Stream EntryStream = null;
using FileStream FileStream = new(ArchiveProvisioningPath, FileMode.Create); using FileStream FileStream = new(ArchiveProvisioningPath, FileMode.Create);
using ZipArchive Archive = new(FileStream, ZipArchiveMode.Create); using ZipArchive Archive = new(FileStream, ZipArchiveMode.Create);
int i = 0; int i = 0;
foreach (string PartitionName in ProvisioningPartitions) foreach (string PartitionName in ProvisioningPartitions)
{ {
if (GPT.Partitions.Any(p => p.Name == PartitionName) && Result) if (GPT.Partitions.Any(p => p.Name == PartitionName) && Result)
{ {
try try
{ {
Entry = Archive.CreateEntry(PartitionName + ".bin", CompressionLevel.Optimal); Entry = Archive.CreateEntry(PartitionName + ".bin", CompressionLevel.Optimal);
EntryStream = Entry.Open(); EntryStream = Entry.Open();
i++; i++;
Busy.Message = "Create backup of partition " + PartitionName + " (" + i.ToString() + "/" + PartitionCount.ToString() + ")"; Busy.Message = "Create backup of partition " + PartitionName + " (" + i.ToString() + "/" + PartitionCount.ToString() + ")";
if (PartitionName == "UEFI_BS_NV" && GPT.Partitions.Any(p => p.Name == "BACKUP_BS_NV")) if (PartitionName == "UEFI_BS_NV" && GPT.Partitions.Any(p => p.Name == "BACKUP_BS_NV"))
{ {
Phone.BackupPartition("BACKUP_BS_NV", EntryStream, Updater); Phone.BackupPartition("BACKUP_BS_NV", EntryStream, Updater);
} }
else else
{ {
Phone.BackupPartition(PartitionName, EntryStream, Updater); Phone.BackupPartition(PartitionName, EntryStream, Updater);
} }
} }
catch (Exception Ex) catch (Exception Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
Result = false; Result = false;
} }
finally finally
{ {
EntryStream?.Close(); EntryStream?.Close();
EntryStream = null; EntryStream = null;
} }
} }
} }
} }
catch { } catch { }
finally finally
{ {
Phone.CloseVolume(); Phone.CloseVolume();
} }
if (!Result) if (!Result)
{ {
ActivateSubContext(new MessageViewModel("Failed to create backup!", Exit)); ActivateSubContext(new MessageViewModel("Failed to create backup!", Exit));
return; return;
} }
ActivateSubContext(new MessageViewModel("Successfully created a backup!", Exit)); ActivateSubContext(new MessageViewModel("Successfully created a backup!", Exit));
}).Start(); }).Start();
} }
private void Exit() private void Exit()
{ {
IsSwitchingInterface = false; IsSwitchingInterface = false;
ActivateSubContext(null); ActivateSubContext(null);
Callback(); Callback();
} }
} }
} }
@@ -1,217 +1,217 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Threading; using System.Threading;
namespace WPinternals namespace WPinternals
{ {
internal class BusyViewModel : ContextViewModel internal class BusyViewModel : ContextViewModel
{ {
private readonly ulong MaxProgressValue = 0; private readonly ulong MaxProgressValue = 0;
internal ProgressUpdater ProgressUpdater = null; internal ProgressUpdater ProgressUpdater = null;
// UIContext can be passed to BusyViewModel, when it needs to update progress-controls and it is created on a worker-thread. // UIContext can be passed to BusyViewModel, when it needs to update progress-controls and it is created on a worker-thread.
internal BusyViewModel(string Message, string SubMessage = null, ulong? MaxProgressValue = null, SynchronizationContext UIContext = null, bool ShowAnimation = true, bool ShowRebootHelp = false) internal BusyViewModel(string Message, string SubMessage = null, ulong? MaxProgressValue = null, SynchronizationContext UIContext = null, bool ShowAnimation = true, bool ShowRebootHelp = false)
{ {
LogFile.Log(Message); LogFile.Log(Message);
this.UIContext = UIContext ?? SynchronizationContext.Current; this.UIContext = UIContext ?? SynchronizationContext.Current;
this.Message = Message; this.Message = Message;
this.SubMessage = SubMessage; this.SubMessage = SubMessage;
this.ShowAnimation = ShowAnimation; this.ShowAnimation = ShowAnimation;
this.ShowRebootHelp = ShowRebootHelp; this.ShowRebootHelp = ShowRebootHelp;
if (MaxProgressValue != null) if (MaxProgressValue != null)
{ {
ProgressPercentage = 0; ProgressPercentage = 0;
this.MaxProgressValue = (ulong)MaxProgressValue; this.MaxProgressValue = (ulong)MaxProgressValue;
ProgressUpdater = new ProgressUpdater((ulong)MaxProgressValue, (p, t) => ProgressUpdater = new ProgressUpdater((ulong)MaxProgressValue, (p, t) =>
{ {
if ((this.UIContext == null) || (this.UIContext == SynchronizationContext.Current)) if ((this.UIContext == null) || (this.UIContext == SynchronizationContext.Current))
{ {
ProgressPercentage = p; ProgressPercentage = p;
TimeRemaining = t; TimeRemaining = t;
} }
else else
{ {
this.UIContext.Post((s) => this.UIContext.Post((s) =>
{ {
ProgressPercentage = p; ProgressPercentage = p;
TimeRemaining = t; TimeRemaining = t;
}, null); }, null);
} }
}); });
} }
} }
internal void SetShowRebootHelp(bool Value) internal void SetShowRebootHelp(bool Value)
{ {
ShowRebootHelp = Value; ShowRebootHelp = Value;
} }
internal void SetProgress(ulong Value) internal void SetProgress(ulong Value)
{ {
if (ProgressUpdater != null) if (ProgressUpdater != null)
{ {
UIContext.Post((s) => ProgressUpdater.SetProgress(Value), null); UIContext.Post((s) => ProgressUpdater.SetProgress(Value), null);
} }
} }
private string _Message = null; private string _Message = null;
public string Message public string Message
{ {
get get
{ {
return _Message; return _Message;
} }
set set
{ {
_Message = value; _Message = value;
OnPropertyChanged(nameof(Message)); OnPropertyChanged(nameof(Message));
} }
} }
private string _SubMessage = null; private string _SubMessage = null;
public string SubMessage public string SubMessage
{ {
get get
{ {
return _SubMessage; return _SubMessage;
} }
set set
{ {
_SubMessage = value; _SubMessage = value;
OnPropertyChanged(nameof(SubMessage)); OnPropertyChanged(nameof(SubMessage));
} }
} }
private int? _ProgressPercentage = null; private int? _ProgressPercentage = null;
public int? ProgressPercentage public int? ProgressPercentage
{ {
get get
{ {
return _ProgressPercentage; return _ProgressPercentage;
} }
set set
{ {
if (_ProgressPercentage != value) if (_ProgressPercentage != value)
{ {
_ProgressPercentage = value; _ProgressPercentage = value;
OnPropertyChanged(nameof(ProgressPercentage)); OnPropertyChanged(nameof(ProgressPercentage));
OnPropertyChanged(nameof(ShowAnimation)); OnPropertyChanged(nameof(ShowAnimation));
UpdateProgressText(); UpdateProgressText();
} }
} }
} }
private TimeSpan? _TimeRemaining = null; private TimeSpan? _TimeRemaining = null;
public TimeSpan? TimeRemaining public TimeSpan? TimeRemaining
{ {
get get
{ {
return _TimeRemaining; return _TimeRemaining;
} }
set set
{ {
if (_TimeRemaining != value) if (_TimeRemaining != value)
{ {
_TimeRemaining = value; _TimeRemaining = value;
OnPropertyChanged(nameof(TimeRemaining)); OnPropertyChanged(nameof(TimeRemaining));
UpdateProgressText(); UpdateProgressText();
} }
} }
} }
private void UpdateProgressText() private void UpdateProgressText()
{ {
string NewText = null; string NewText = null;
if (ProgressPercentage != null) if (ProgressPercentage != null)
{ {
NewText = "Progress: " + ((int)ProgressPercentage).ToString() + "%"; NewText = "Progress: " + ((int)ProgressPercentage).ToString() + "%";
} }
if (TimeRemaining != null) if (TimeRemaining != null)
{ {
if (NewText == null) if (NewText == null)
{ {
NewText = ""; NewText = "";
} }
else else
{ {
NewText += " - "; NewText += " - ";
} }
NewText += "Estimated time remaining: " + ((TimeSpan)TimeRemaining).ToString(@"h\:mm\:ss"); NewText += "Estimated time remaining: " + ((TimeSpan)TimeRemaining).ToString(@"h\:mm\:ss");
} }
ProgressText = NewText; ProgressText = NewText;
} }
private string _ProgressText = null; private string _ProgressText = null;
public string ProgressText public string ProgressText
{ {
get get
{ {
return _ProgressText; return _ProgressText;
} }
set set
{ {
if (_ProgressText != value) if (_ProgressText != value)
{ {
_ProgressText = value; _ProgressText = value;
OnPropertyChanged(nameof(ProgressText)); OnPropertyChanged(nameof(ProgressText));
} }
} }
} }
private bool _ShowAnimation = true; private bool _ShowAnimation = true;
public bool ShowAnimation public bool ShowAnimation
{ {
get get
{ {
return (_ProgressPercentage == null) && _ShowAnimation; return (_ProgressPercentage == null) && _ShowAnimation;
} }
set set
{ {
if (_ShowAnimation != value) if (_ShowAnimation != value)
{ {
_ShowAnimation = value; _ShowAnimation = value;
OnPropertyChanged(nameof(ShowAnimation)); OnPropertyChanged(nameof(ShowAnimation));
} }
} }
} }
private bool _ShowRebootHelp = false; private bool _ShowRebootHelp = false;
public bool ShowRebootHelp public bool ShowRebootHelp
{ {
get get
{ {
return _ShowRebootHelp; return _ShowRebootHelp;
} }
set set
{ {
if (_ShowRebootHelp != value) if (_ShowRebootHelp != value)
{ {
_ShowRebootHelp = value; _ShowRebootHelp = value;
OnPropertyChanged(nameof(ShowRebootHelp)); OnPropertyChanged(nameof(ShowRebootHelp));
} }
} }
} }
} }
} }
@@ -1,157 +1,157 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Threading; using System.Threading;
namespace WPinternals namespace WPinternals
{ {
internal class ContextViewModel : INotifyPropertyChanged internal class ContextViewModel : INotifyPropertyChanged
{ {
protected SynchronizationContext UIContext; protected SynchronizationContext UIContext;
public bool IsSwitchingInterface = false; public bool IsSwitchingInterface = false;
public bool IsFlashModeOperation = false; public bool IsFlashModeOperation = false;
public event PropertyChangedEventHandler PropertyChanged = delegate { }; public event PropertyChangedEventHandler PropertyChanged = delegate { };
protected void OnPropertyChanged(string propertyName) protected void OnPropertyChanged(string propertyName)
{ {
if ((UIContext == null) && (SynchronizationContext.Current != null)) if ((UIContext == null) && (SynchronizationContext.Current != null))
{ {
UIContext = SynchronizationContext.Current; UIContext = SynchronizationContext.Current;
} }
if (this.PropertyChanged != null) if (this.PropertyChanged != null)
{ {
if (SynchronizationContext.Current == UIContext) if (SynchronizationContext.Current == UIContext)
{ {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
} }
else else
{ {
UIContext.Post((s) => PropertyChanged(this, new PropertyChangedEventArgs(propertyName)), null); UIContext.Post((s) => PropertyChanged(this, new PropertyChangedEventArgs(propertyName)), null);
} }
} }
} }
private ContextViewModel _SubContextViewModel; private ContextViewModel _SubContextViewModel;
public ContextViewModel SubContextViewModel public ContextViewModel SubContextViewModel
{ {
get get
{ {
return _SubContextViewModel; return _SubContextViewModel;
} }
private set private set
{ {
if (_SubContextViewModel != null) if (_SubContextViewModel != null)
{ {
_SubContextViewModel.IsActive = false; _SubContextViewModel.IsActive = false;
} }
_SubContextViewModel = value; _SubContextViewModel = value;
if (_SubContextViewModel != null) if (_SubContextViewModel != null)
{ {
_SubContextViewModel.IsActive = IsActive; _SubContextViewModel.IsActive = IsActive;
} }
OnPropertyChanged(nameof(SubContextViewModel)); OnPropertyChanged(nameof(SubContextViewModel));
} }
} }
internal ContextViewModel() internal ContextViewModel()
{ {
UIContext = SynchronizationContext.Current; UIContext = SynchronizationContext.Current;
} }
internal ContextViewModel(MainViewModel Main) : this() internal ContextViewModel(MainViewModel Main) : this()
{ {
} }
internal ContextViewModel(MainViewModel Main, ContextViewModel SubContext) : this(Main) internal ContextViewModel(MainViewModel Main, ContextViewModel SubContext) : this(Main)
{ {
SubContextViewModel = SubContext; SubContextViewModel = SubContext;
} }
internal bool IsActive { get; set; } = false; internal bool IsActive { get; set; } = false;
internal virtual void EvaluateViewState() internal virtual void EvaluateViewState()
{ {
} }
internal void Activate() internal void Activate()
{ {
IsActive = true; IsActive = true;
EvaluateViewState(); EvaluateViewState();
SubContextViewModel?.Activate(); SubContextViewModel?.Activate();
} }
internal void ActivateSubContext(ContextViewModel NewSubContext) internal void ActivateSubContext(ContextViewModel NewSubContext)
{ {
if (_SubContextViewModel != null) if (_SubContextViewModel != null)
{ {
_SubContextViewModel.IsActive = false; _SubContextViewModel.IsActive = false;
} }
if (NewSubContext != null) if (NewSubContext != null)
{ {
if (IsActive) if (IsActive)
{ {
NewSubContext.Activate(); NewSubContext.Activate();
} }
else else
{ {
NewSubContext.IsActive = false; NewSubContext.IsActive = false;
} }
} }
SubContextViewModel = NewSubContext; SubContextViewModel = NewSubContext;
} }
internal void SetWorkingStatus(string Message, string SubMessage, ulong? MaxProgressValue, bool ShowAnimation = true, WPinternalsStatus Status = WPinternalsStatus.Undefined) internal void SetWorkingStatus(string Message, string SubMessage, ulong? MaxProgressValue, bool ShowAnimation = true, WPinternalsStatus Status = WPinternalsStatus.Undefined)
{ {
ActivateSubContext(new BusyViewModel(Message, SubMessage, MaxProgressValue, UIContext: UIContext, ShowAnimation: ShowAnimation, ShowRebootHelp: Status == WPinternalsStatus.WaitingForManualReset)); ActivateSubContext(new BusyViewModel(Message, SubMessage, MaxProgressValue, UIContext: UIContext, ShowAnimation: ShowAnimation, ShowRebootHelp: Status == WPinternalsStatus.WaitingForManualReset));
} }
internal void UpdateWorkingStatus(string Message, string SubMessage, ulong? CurrentProgressValue, WPinternalsStatus Status = WPinternalsStatus.Undefined) internal void UpdateWorkingStatus(string Message, string SubMessage, ulong? CurrentProgressValue, WPinternalsStatus Status = WPinternalsStatus.Undefined)
{ {
if (SubContextViewModel is BusyViewModel Busy) if (SubContextViewModel is BusyViewModel Busy)
{ {
if (Message != null) if (Message != null)
{ {
Busy.Message = Message; Busy.Message = Message;
Busy.SubMessage = SubMessage; Busy.SubMessage = SubMessage;
} }
if ((CurrentProgressValue != null) && (Busy.ProgressUpdater != null)) if ((CurrentProgressValue != null) && (Busy.ProgressUpdater != null))
{ {
try try
{ {
Busy.ProgressUpdater.SetProgress((ulong)CurrentProgressValue); Busy.ProgressUpdater.SetProgress((ulong)CurrentProgressValue);
} }
catch (Exception Ex) catch (Exception Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
} }
} }
Busy.SetShowRebootHelp(Status == WPinternalsStatus.WaitingForManualReset); Busy.SetShowRebootHelp(Status == WPinternalsStatus.WaitingForManualReset);
} }
} }
} }
} }
@@ -1,60 +1,60 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using Microsoft.Win32; using Microsoft.Win32;
using System; using System;
using System.Windows; using System.Windows;
namespace WPinternals namespace WPinternals
{ {
internal class DisclaimerAndNdaViewModel : ContextViewModel internal class DisclaimerAndNdaViewModel : ContextViewModel
{ {
private readonly Action Accepted; private readonly Action Accepted;
internal DisclaimerAndNdaViewModel(Action Accepted) internal DisclaimerAndNdaViewModel(Action Accepted)
: base() : base()
{ {
this.Accepted = Accepted; this.Accepted = Accepted;
} }
private DelegateCommand _ExitCommand = null; private DelegateCommand _ExitCommand = null;
public DelegateCommand ExitCommand public DelegateCommand ExitCommand
{ {
get get
{ {
return _ExitCommand ??= new DelegateCommand(() => Application.Current.Shutdown()); return _ExitCommand ??= new DelegateCommand(() => Application.Current.Shutdown());
} }
} }
private DelegateCommand _ContinueCommand = null; private DelegateCommand _ContinueCommand = null;
public DelegateCommand ContinueCommand public DelegateCommand ContinueCommand
{ {
get get
{ {
return _ContinueCommand ??= new DelegateCommand(() => return _ContinueCommand ??= new DelegateCommand(() =>
{ {
Registry.CurrentUser.OpenSubKey("Software\\WPInternals", true).SetValue("DisclaimerAccepted", 1, RegistryValueKind.DWord); Registry.CurrentUser.OpenSubKey("Software\\WPInternals", true).SetValue("DisclaimerAccepted", 1, RegistryValueKind.DWord);
Registry.CurrentUser.OpenSubKey("Software\\WPInternals", true).SetValue("NdaAccepted", 1, RegistryValueKind.DWord); Registry.CurrentUser.OpenSubKey("Software\\WPInternals", true).SetValue("NdaAccepted", 1, RegistryValueKind.DWord);
Accepted(); Accepted();
}); });
} }
} }
} }
} }
@@ -1,61 +1,61 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using Microsoft.Win32; using Microsoft.Win32;
using System; using System;
using System.Windows; using System.Windows;
namespace WPinternals namespace WPinternals
{ {
internal delegate void DisclaimerAcceptedHandler(); internal delegate void DisclaimerAcceptedHandler();
internal class DisclaimerViewModel : ContextViewModel internal class DisclaimerViewModel : ContextViewModel
{ {
private readonly Action Accepted; private readonly Action Accepted;
internal DisclaimerViewModel(Action Accepted) internal DisclaimerViewModel(Action Accepted)
: base() : base()
{ {
this.Accepted = Accepted; this.Accepted = Accepted;
} }
private DelegateCommand _ExitCommand = null; private DelegateCommand _ExitCommand = null;
public DelegateCommand ExitCommand public DelegateCommand ExitCommand
{ {
get get
{ {
return _ExitCommand ??= new DelegateCommand(() => Application.Current.Shutdown()); return _ExitCommand ??= new DelegateCommand(() => Application.Current.Shutdown());
} }
} }
private DelegateCommand _ContinueCommand = null; private DelegateCommand _ContinueCommand = null;
public DelegateCommand ContinueCommand public DelegateCommand ContinueCommand
{ {
get get
{ {
return _ContinueCommand ??= new DelegateCommand(() => return _ContinueCommand ??= new DelegateCommand(() =>
{ {
Registry.CurrentUser.OpenSubKey("Software\\WPInternals", true).SetValue("DisclaimerAccepted", 1, RegistryValueKind.DWord); Registry.CurrentUser.OpenSubKey("Software\\WPInternals", true).SetValue("DisclaimerAccepted", 1, RegistryValueKind.DWord);
Accepted(); Accepted();
}); });
} }
} }
} }
} }
File diff suppressed because it is too large Load Diff
@@ -1,228 +1,228 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Threading; using System.Threading;
namespace WPinternals namespace WPinternals
{ {
internal class DumpRomTargetSelectionViewModel : ContextViewModel internal class DumpRomTargetSelectionViewModel : ContextViewModel
{ {
private readonly Action<string, string, bool, string, bool, string, bool> DumpCallback; private readonly Action<string, string, bool, string, bool, string, bool> DumpCallback;
internal Action SwitchToUnlockBoot; internal Action SwitchToUnlockBoot;
internal Action SwitchToUnlockRoot; internal Action SwitchToUnlockRoot;
internal Action SwitchToFlashRom; internal Action SwitchToFlashRom;
internal DumpRomTargetSelectionViewModel(Action SwitchToUnlockBoot, Action SwitchToUnlockRoot, Action SwitchToFlashRom, Action<string, string, bool, string, bool, string, bool> DumpCallback) internal DumpRomTargetSelectionViewModel(Action SwitchToUnlockBoot, Action SwitchToUnlockRoot, Action SwitchToFlashRom, Action<string, string, bool, string, bool, string, bool> DumpCallback)
: base() : base()
{ {
this.SwitchToUnlockBoot = SwitchToUnlockBoot; this.SwitchToUnlockBoot = SwitchToUnlockBoot;
this.SwitchToUnlockRoot = SwitchToUnlockRoot; this.SwitchToUnlockRoot = SwitchToUnlockRoot;
this.SwitchToFlashRom = SwitchToFlashRom; this.SwitchToFlashRom = SwitchToFlashRom;
this.DumpCallback = DumpCallback; this.DumpCallback = DumpCallback;
new Thread(() => EvaluateViewState()).Start(); new Thread(() => EvaluateViewState()).Start();
} }
private string _FFUPath; private string _FFUPath;
public string FFUPath public string FFUPath
{ {
get get
{ {
return _FFUPath; return _FFUPath;
} }
set set
{ {
if (value != _FFUPath) if (value != _FFUPath)
{ {
_FFUPath = value; _FFUPath = value;
OnPropertyChanged(nameof(FFUPath)); OnPropertyChanged(nameof(FFUPath));
} }
} }
} }
private string _EFIESPPath; private string _EFIESPPath;
public string EFIESPPath public string EFIESPPath
{ {
get get
{ {
return _EFIESPPath; return _EFIESPPath;
} }
set set
{ {
if (value != _EFIESPPath) if (value != _EFIESPPath)
{ {
_EFIESPPath = value; _EFIESPPath = value;
OnPropertyChanged(nameof(EFIESPPath)); OnPropertyChanged(nameof(EFIESPPath));
} }
} }
} }
private bool _CompressEFIESP; private bool _CompressEFIESP;
public bool CompressEFIESP public bool CompressEFIESP
{ {
get get
{ {
return _CompressEFIESP; return _CompressEFIESP;
} }
set set
{ {
if (value != _CompressEFIESP) if (value != _CompressEFIESP)
{ {
_CompressEFIESP = value; _CompressEFIESP = value;
OnPropertyChanged(nameof(CompressEFIESP)); OnPropertyChanged(nameof(CompressEFIESP));
} }
} }
} }
private string _MainOSPath; private string _MainOSPath;
public string MainOSPath public string MainOSPath
{ {
get get
{ {
return _MainOSPath; return _MainOSPath;
} }
set set
{ {
if (value != _MainOSPath) if (value != _MainOSPath)
{ {
_MainOSPath = value; _MainOSPath = value;
OnPropertyChanged(nameof(MainOSPath)); OnPropertyChanged(nameof(MainOSPath));
} }
} }
} }
private bool _CompressMainOS; private bool _CompressMainOS;
public bool CompressMainOS public bool CompressMainOS
{ {
get get
{ {
return _CompressMainOS; return _CompressMainOS;
} }
set set
{ {
if (value != _CompressMainOS) if (value != _CompressMainOS)
{ {
_CompressMainOS = value; _CompressMainOS = value;
OnPropertyChanged(nameof(CompressMainOS)); OnPropertyChanged(nameof(CompressMainOS));
} }
} }
} }
private string _DataPath; private string _DataPath;
public string DataPath public string DataPath
{ {
get get
{ {
return _DataPath; return _DataPath;
} }
set set
{ {
if (value != _DataPath) if (value != _DataPath)
{ {
_DataPath = value; _DataPath = value;
OnPropertyChanged(nameof(DataPath)); OnPropertyChanged(nameof(DataPath));
} }
} }
} }
private bool _CompressData = true; private bool _CompressData = true;
public bool CompressData public bool CompressData
{ {
get get
{ {
return _CompressData; return _CompressData;
} }
set set
{ {
if (value != _CompressData) if (value != _CompressData)
{ {
_CompressData = value; _CompressData = value;
OnPropertyChanged(nameof(CompressData)); OnPropertyChanged(nameof(CompressData));
} }
} }
} }
private bool _IsPhoneDisconnected; private bool _IsPhoneDisconnected;
public bool IsPhoneDisconnected public bool IsPhoneDisconnected
{ {
get get
{ {
return _IsPhoneDisconnected; return _IsPhoneDisconnected;
} }
set set
{ {
if (value != _IsPhoneDisconnected) if (value != _IsPhoneDisconnected)
{ {
_IsPhoneDisconnected = value; _IsPhoneDisconnected = value;
OnPropertyChanged(nameof(IsPhoneDisconnected)); OnPropertyChanged(nameof(IsPhoneDisconnected));
} }
} }
} }
private bool _IsPhoneInMassStorage; private bool _IsPhoneInMassStorage;
public bool IsPhoneInMassStorage public bool IsPhoneInMassStorage
{ {
get get
{ {
return _IsPhoneInMassStorage; return _IsPhoneInMassStorage;
} }
set set
{ {
if (value != _IsPhoneInMassStorage) if (value != _IsPhoneInMassStorage)
{ {
_IsPhoneInMassStorage = value; _IsPhoneInMassStorage = value;
OnPropertyChanged(nameof(IsPhoneInMassStorage)); OnPropertyChanged(nameof(IsPhoneInMassStorage));
} }
} }
} }
private bool _IsPhoneInOtherMode; private bool _IsPhoneInOtherMode;
public bool IsPhoneInOtherMode public bool IsPhoneInOtherMode
{ {
get get
{ {
return _IsPhoneInOtherMode; return _IsPhoneInOtherMode;
} }
set set
{ {
if (value != _IsPhoneInOtherMode) if (value != _IsPhoneInOtherMode)
{ {
_IsPhoneInOtherMode = value; _IsPhoneInOtherMode = value;
OnPropertyChanged(nameof(IsPhoneInOtherMode)); OnPropertyChanged(nameof(IsPhoneInOtherMode));
} }
} }
} }
private DelegateCommand _DumpCommand; private DelegateCommand _DumpCommand;
public DelegateCommand DumpCommand public DelegateCommand DumpCommand
{ {
get get
{ {
return _DumpCommand ??= new DelegateCommand(() => DumpCallback(FFUPath, EFIESPPath, CompressEFIESP, MainOSPath, CompressMainOS, DataPath, CompressData), () => (FFUPath != null) && ((EFIESPPath != null) || (MainOSPath != null) || (DataPath != null))); return _DumpCommand ??= new DelegateCommand(() => DumpCallback(FFUPath, EFIESPPath, CompressEFIESP, MainOSPath, CompressMainOS, DataPath, CompressData), () => (FFUPath != null) && ((EFIESPPath != null) || (MainOSPath != null) || (DataPath != null)));
} }
} }
internal override void EvaluateViewState() internal override void EvaluateViewState()
{ {
DumpCommand.RaiseCanExecuteChanged(); DumpCommand.RaiseCanExecuteChanged();
} }
} }
} }
@@ -1,173 +1,173 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
namespace WPinternals namespace WPinternals
{ {
internal class DumpRomViewModel : ContextViewModel internal class DumpRomViewModel : ContextViewModel
{ {
private readonly Action SwitchToUnlockBoot; private readonly Action SwitchToUnlockBoot;
private readonly Action SwitchToUnlockRoot; private readonly Action SwitchToUnlockRoot;
private readonly Action SwitchToFlashRom; private readonly Action SwitchToFlashRom;
internal DumpRomViewModel(Action SwitchToUnlockBoot, Action SwitchToUnlockRoot, Action SwitchToFlashRom) internal DumpRomViewModel(Action SwitchToUnlockBoot, Action SwitchToUnlockRoot, Action SwitchToFlashRom)
: base() : base()
{ {
this.SwitchToUnlockBoot = SwitchToUnlockBoot; this.SwitchToUnlockBoot = SwitchToUnlockBoot;
this.SwitchToUnlockRoot = SwitchToUnlockRoot; this.SwitchToUnlockRoot = SwitchToUnlockRoot;
this.SwitchToFlashRom = SwitchToFlashRom; this.SwitchToFlashRom = SwitchToFlashRom;
} }
internal override void EvaluateViewState() internal override void EvaluateViewState()
{ {
if (!IsActive) if (!IsActive)
{ {
return; return;
} }
if (SubContextViewModel == null) if (SubContextViewModel == null)
{ {
ActivateSubContext(new DumpRomTargetSelectionViewModel(SwitchToUnlockBoot, SwitchToUnlockRoot, SwitchToFlashRom, DoDumpRom)); ActivateSubContext(new DumpRomTargetSelectionViewModel(SwitchToUnlockBoot, SwitchToUnlockRoot, SwitchToFlashRom, DoDumpRom));
} }
} }
internal void DoDumpRom(string FFUPath, string EFIESPPath, bool CompressEFIESP, string MainOSPath, bool CompressMainOS, string DataPath, bool CompressData) internal void DoDumpRom(string FFUPath, string EFIESPPath, bool CompressEFIESP, string MainOSPath, bool CompressMainOS, string DataPath, bool CompressData)
{ {
new Thread(() => new Thread(() =>
{ {
bool Result = true; bool Result = true;
ActivateSubContext(new BusyViewModel("Initializing ROM dump...")); ActivateSubContext(new BusyViewModel("Initializing ROM dump..."));
ulong TotalSizeSectors = 0; ulong TotalSizeSectors = 0;
int PartitionCount = 0; int PartitionCount = 0;
Partition Partition; Partition Partition;
FFU FFU = null; FFU FFU = null;
try try
{ {
FFU = new FFU(FFUPath); FFU = new FFU(FFUPath);
if (EFIESPPath != null) if (EFIESPPath != null)
{ {
Partition = FFU.GPT.Partitions.First(p => p.Name == "EFIESP"); Partition = FFU.GPT.Partitions.First(p => p.Name == "EFIESP");
TotalSizeSectors += Partition.SizeInSectors; TotalSizeSectors += Partition.SizeInSectors;
PartitionCount++; PartitionCount++;
} }
if (MainOSPath != null) if (MainOSPath != null)
{ {
Partition = FFU.GPT.Partitions.First(p => p.Name == "MainOS"); Partition = FFU.GPT.Partitions.First(p => p.Name == "MainOS");
TotalSizeSectors += Partition.SizeInSectors; TotalSizeSectors += Partition.SizeInSectors;
PartitionCount++; PartitionCount++;
} }
if (DataPath != null) if (DataPath != null)
{ {
Partition = FFU.GPT.Partitions.First(p => p.Name == "Data"); Partition = FFU.GPT.Partitions.First(p => p.Name == "Data");
TotalSizeSectors += Partition.SizeInSectors; TotalSizeSectors += Partition.SizeInSectors;
PartitionCount++; PartitionCount++;
} }
} }
catch (Exception Ex) catch (Exception Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
Result = false; Result = false;
} }
// We are on a worker thread! // We are on a worker thread!
// So we must pass the SynchronizationContext of the UI thread // So we must pass the SynchronizationContext of the UI thread
BusyViewModel Busy = new("Dumping ROM...", MaxProgressValue: TotalSizeSectors, UIContext: UIContext); BusyViewModel Busy = new("Dumping ROM...", MaxProgressValue: TotalSizeSectors, UIContext: UIContext);
ProgressUpdater Updater = Busy.ProgressUpdater; ProgressUpdater Updater = Busy.ProgressUpdater;
ActivateSubContext(Busy); ActivateSubContext(Busy);
int i = 0; int i = 0;
if (Result) if (Result)
{ {
try try
{ {
if (EFIESPPath != null) if (EFIESPPath != null)
{ {
i++; i++;
Busy.Message = "Dumping partition EFIESP (" + i.ToString() + "/" + PartitionCount.ToString() + ")"; Busy.Message = "Dumping partition EFIESP (" + i.ToString() + "/" + PartitionCount.ToString() + ")";
FFU.WritePartition("EFIESP", EFIESPPath, Updater, CompressEFIESP); FFU.WritePartition("EFIESP", EFIESPPath, Updater, CompressEFIESP);
} }
} }
catch (Exception Ex) catch (Exception Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
Result = false; Result = false;
} }
} }
if (Result) if (Result)
{ {
try try
{ {
if (MainOSPath != null) if (MainOSPath != null)
{ {
i++; i++;
Busy.Message = "Dumping partition MainOS (" + i.ToString() + "/" + PartitionCount.ToString() + ")"; Busy.Message = "Dumping partition MainOS (" + i.ToString() + "/" + PartitionCount.ToString() + ")";
FFU.WritePartition("MainOS", MainOSPath, Updater, CompressMainOS); FFU.WritePartition("MainOS", MainOSPath, Updater, CompressMainOS);
} }
} }
catch (Exception Ex) catch (Exception Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
Result = false; Result = false;
} }
} }
if (Result) if (Result)
{ {
try try
{ {
if (DataPath != null) if (DataPath != null)
{ {
i++; i++;
Busy.Message = "Dumping partition Data (" + i.ToString() + "/" + PartitionCount.ToString() + ")"; Busy.Message = "Dumping partition Data (" + i.ToString() + "/" + PartitionCount.ToString() + ")";
FFU.WritePartition("Data", DataPath, Updater, CompressData); FFU.WritePartition("Data", DataPath, Updater, CompressData);
} }
} }
catch (Exception Ex) catch (Exception Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
Result = false; Result = false;
} }
} }
if (!Result) if (!Result)
{ {
ActivateSubContext(new MessageViewModel("Failed to dump ROM partitions!", Restart)); ActivateSubContext(new MessageViewModel("Failed to dump ROM partitions!", Restart));
return; return;
} }
ActivateSubContext(new MessageViewModel("Successfully dumped ROM partitions!", Restart)); ActivateSubContext(new MessageViewModel("Successfully dumped ROM partitions!", Restart));
}).Start(); }).Start();
} }
internal void Restart() internal void Restart()
{ {
ActivateSubContext(new DumpRomTargetSelectionViewModel(SwitchToUnlockBoot, SwitchToUnlockRoot, SwitchToFlashRom, DoDumpRom)); ActivateSubContext(new DumpRomTargetSelectionViewModel(SwitchToUnlockBoot, SwitchToUnlockRoot, SwitchToFlashRom, DoDumpRom));
} }
} }
} }
@@ -1,47 +1,47 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
namespace WPinternals namespace WPinternals
{ {
internal class GettingStartedViewModel : ContextViewModel internal class GettingStartedViewModel : ContextViewModel
{ {
internal Action ShowDisclaimer; internal Action ShowDisclaimer;
internal Action SwitchToUnlockBoot; internal Action SwitchToUnlockBoot;
internal Action SwitchToUnlockRoot; internal Action SwitchToUnlockRoot;
internal Action SwitchToBackup; internal Action SwitchToBackup;
internal Action SwitchToDumpRom; internal Action SwitchToDumpRom;
internal Action SwitchToFlashRom; internal Action SwitchToFlashRom;
internal Action SwitchToDownload; internal Action SwitchToDownload;
internal GettingStartedViewModel(Action ShowDisclaimer, Action SwitchToUnlockBoot, Action SwitchToUnlockRoot, Action SwitchToBackup, Action SwitchToDumpRom, Action SwitchToFlashRom, Action SwitchToDownload) internal GettingStartedViewModel(Action ShowDisclaimer, Action SwitchToUnlockBoot, Action SwitchToUnlockRoot, Action SwitchToBackup, Action SwitchToDumpRom, Action SwitchToFlashRom, Action SwitchToDownload)
: base() : base()
{ {
this.ShowDisclaimer = ShowDisclaimer; this.ShowDisclaimer = ShowDisclaimer;
this.SwitchToUnlockBoot = SwitchToUnlockBoot; this.SwitchToUnlockBoot = SwitchToUnlockBoot;
this.SwitchToUnlockRoot = SwitchToUnlockRoot; this.SwitchToUnlockRoot = SwitchToUnlockRoot;
this.SwitchToBackup = SwitchToBackup; this.SwitchToBackup = SwitchToBackup;
this.SwitchToFlashRom = SwitchToFlashRom; this.SwitchToFlashRom = SwitchToFlashRom;
this.SwitchToDumpRom = SwitchToDumpRom; this.SwitchToDumpRom = SwitchToDumpRom;
this.SwitchToDownload = SwitchToDownload; this.SwitchToDownload = SwitchToDownload;
} }
} }
} }
@@ -1,279 +1,279 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Threading; using System.Threading;
namespace WPinternals namespace WPinternals
{ {
internal class LumiaFlashRomSourceSelectionViewModel : ContextViewModel internal class LumiaFlashRomSourceSelectionViewModel : ContextViewModel
{ {
private readonly PhoneNotifierViewModel PhoneNotifier; private readonly PhoneNotifierViewModel PhoneNotifier;
private readonly Action<string, string, string> FlashPartitionsCallback; private readonly Action<string, string, string> FlashPartitionsCallback;
private readonly Action<string> FlashFFUCallback; private readonly Action<string> FlashFFUCallback;
private readonly Action<string> FlashMMOSCallback; private readonly Action<string> FlashMMOSCallback;
private readonly Action<string> FlashArchiveCallback; private readonly Action<string> FlashArchiveCallback;
internal Action SwitchToUnlockBoot; internal Action SwitchToUnlockBoot;
internal Action SwitchToUnlockRoot; internal Action SwitchToUnlockRoot;
internal Action SwitchToDumpFFU; internal Action SwitchToDumpFFU;
internal Action SwitchToBackup; internal Action SwitchToBackup;
internal LumiaFlashRomSourceSelectionViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action SwitchToUnlockRoot, Action SwitchToDumpFFU, Action SwitchToBackup, Action<string, string, string> FlashPartitionsCallback, Action<string> FlashArchiveCallback, Action<string> FlashFFUCallback, Action<string> FlashMMOSCallback) internal LumiaFlashRomSourceSelectionViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action SwitchToUnlockRoot, Action SwitchToDumpFFU, Action SwitchToBackup, Action<string, string, string> FlashPartitionsCallback, Action<string> FlashArchiveCallback, Action<string> FlashFFUCallback, Action<string> FlashMMOSCallback)
: base() : base()
{ {
this.PhoneNotifier = PhoneNotifier; this.PhoneNotifier = PhoneNotifier;
this.SwitchToUnlockBoot = SwitchToUnlockBoot; this.SwitchToUnlockBoot = SwitchToUnlockBoot;
this.SwitchToUnlockRoot = SwitchToUnlockRoot; this.SwitchToUnlockRoot = SwitchToUnlockRoot;
this.SwitchToDumpFFU = SwitchToDumpFFU; this.SwitchToDumpFFU = SwitchToDumpFFU;
this.SwitchToBackup = SwitchToBackup; this.SwitchToBackup = SwitchToBackup;
this.FlashPartitionsCallback = FlashPartitionsCallback; this.FlashPartitionsCallback = FlashPartitionsCallback;
this.FlashArchiveCallback = FlashArchiveCallback; this.FlashArchiveCallback = FlashArchiveCallback;
this.FlashFFUCallback = FlashFFUCallback; this.FlashFFUCallback = FlashFFUCallback;
this.FlashMMOSCallback = FlashMMOSCallback; this.FlashMMOSCallback = FlashMMOSCallback;
this.PhoneNotifier.NewDeviceArrived += NewDeviceArrived; this.PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
this.PhoneNotifier.DeviceRemoved += DeviceRemoved; this.PhoneNotifier.DeviceRemoved += DeviceRemoved;
new Thread(() => EvaluateViewState()).Start(); new Thread(() => EvaluateViewState()).Start();
} }
private string _EFIESPPath; private string _EFIESPPath;
public string EFIESPPath public string EFIESPPath
{ {
get get
{ {
return _EFIESPPath; return _EFIESPPath;
} }
set set
{ {
if (value != _EFIESPPath) if (value != _EFIESPPath)
{ {
_EFIESPPath = value; _EFIESPPath = value;
OnPropertyChanged(nameof(EFIESPPath)); OnPropertyChanged(nameof(EFIESPPath));
} }
} }
} }
private string _MainOSPath; private string _MainOSPath;
public string MainOSPath public string MainOSPath
{ {
get get
{ {
return _MainOSPath; return _MainOSPath;
} }
set set
{ {
if (value != _MainOSPath) if (value != _MainOSPath)
{ {
_MainOSPath = value; _MainOSPath = value;
OnPropertyChanged(nameof(MainOSPath)); OnPropertyChanged(nameof(MainOSPath));
} }
} }
} }
private string _DataPath; private string _DataPath;
public string DataPath public string DataPath
{ {
get get
{ {
return _DataPath; return _DataPath;
} }
set set
{ {
if (value != _DataPath) if (value != _DataPath)
{ {
_DataPath = value; _DataPath = value;
OnPropertyChanged(nameof(DataPath)); OnPropertyChanged(nameof(DataPath));
} }
} }
} }
private string _ArchivePath; private string _ArchivePath;
public string ArchivePath public string ArchivePath
{ {
get get
{ {
return _ArchivePath; return _ArchivePath;
} }
set set
{ {
if (value != _ArchivePath) if (value != _ArchivePath)
{ {
_ArchivePath = value; _ArchivePath = value;
OnPropertyChanged(nameof(ArchivePath)); OnPropertyChanged(nameof(ArchivePath));
} }
} }
} }
private string _FFUPath; private string _FFUPath;
public string FFUPath public string FFUPath
{ {
get get
{ {
return _FFUPath; return _FFUPath;
} }
set set
{ {
if (value != _FFUPath) if (value != _FFUPath)
{ {
_FFUPath = value; _FFUPath = value;
OnPropertyChanged(nameof(FFUPath)); OnPropertyChanged(nameof(FFUPath));
} }
} }
} }
private string _MMOSPath; private string _MMOSPath;
public string MMOSPath public string MMOSPath
{ {
get get
{ {
return _MMOSPath; return _MMOSPath;
} }
set set
{ {
if (value != _MMOSPath) if (value != _MMOSPath)
{ {
_MMOSPath = value; _MMOSPath = value;
OnPropertyChanged(nameof(MMOSPath)); OnPropertyChanged(nameof(MMOSPath));
} }
} }
} }
private bool _IsPhoneDisconnected; private bool _IsPhoneDisconnected;
public bool IsPhoneDisconnected public bool IsPhoneDisconnected
{ {
get get
{ {
return _IsPhoneDisconnected; return _IsPhoneDisconnected;
} }
set set
{ {
if (value != _IsPhoneDisconnected) if (value != _IsPhoneDisconnected)
{ {
_IsPhoneDisconnected = value; _IsPhoneDisconnected = value;
OnPropertyChanged(nameof(IsPhoneDisconnected)); OnPropertyChanged(nameof(IsPhoneDisconnected));
} }
} }
} }
private bool _IsPhoneInFlashMode; private bool _IsPhoneInFlashMode;
public bool IsPhoneInFlashMode public bool IsPhoneInFlashMode
{ {
get get
{ {
return _IsPhoneInFlashMode; return _IsPhoneInFlashMode;
} }
set set
{ {
if (value != _IsPhoneInFlashMode) if (value != _IsPhoneInFlashMode)
{ {
_IsPhoneInFlashMode = value; _IsPhoneInFlashMode = value;
OnPropertyChanged(nameof(IsPhoneInFlashMode)); OnPropertyChanged(nameof(IsPhoneInFlashMode));
} }
} }
} }
private bool _IsPhoneInOtherMode; private bool _IsPhoneInOtherMode;
public bool IsPhoneInOtherMode public bool IsPhoneInOtherMode
{ {
get get
{ {
return _IsPhoneInOtherMode; return _IsPhoneInOtherMode;
} }
set set
{ {
if (value != _IsPhoneInOtherMode) if (value != _IsPhoneInOtherMode)
{ {
_IsPhoneInOtherMode = value; _IsPhoneInOtherMode = value;
OnPropertyChanged(nameof(IsPhoneInOtherMode)); OnPropertyChanged(nameof(IsPhoneInOtherMode));
} }
} }
} }
private DelegateCommand _FlashPartitionsCommand; private DelegateCommand _FlashPartitionsCommand;
public DelegateCommand FlashPartitionsCommand public DelegateCommand FlashPartitionsCommand
{ {
get get
{ {
return _FlashPartitionsCommand ??= new DelegateCommand(() => FlashPartitionsCallback(EFIESPPath, MainOSPath, DataPath), () => ((EFIESPPath != null) || (MainOSPath != null) || (DataPath != null)) && (PhoneNotifier.CurrentInterface != null)); return _FlashPartitionsCommand ??= new DelegateCommand(() => FlashPartitionsCallback(EFIESPPath, MainOSPath, DataPath), () => ((EFIESPPath != null) || (MainOSPath != null) || (DataPath != null)) && (PhoneNotifier.CurrentInterface != null));
} }
} }
private DelegateCommand _FlashFFUCommand; private DelegateCommand _FlashFFUCommand;
public DelegateCommand FlashFFUCommand public DelegateCommand FlashFFUCommand
{ {
get get
{ {
return _FlashFFUCommand ??= new DelegateCommand(() => FlashFFUCallback(FFUPath), () => (FFUPath != null) && (PhoneNotifier.CurrentInterface != null)); return _FlashFFUCommand ??= new DelegateCommand(() => FlashFFUCallback(FFUPath), () => (FFUPath != null) && (PhoneNotifier.CurrentInterface != null));
} }
} }
private DelegateCommand _FlashMMOSCommand; private DelegateCommand _FlashMMOSCommand;
public DelegateCommand FlashMMOSCommand public DelegateCommand FlashMMOSCommand
{ {
get get
{ {
return _FlashMMOSCommand ??= new DelegateCommand(() => FlashMMOSCallback(MMOSPath), () => (MMOSPath != null) && (PhoneNotifier.CurrentInterface != null)); return _FlashMMOSCommand ??= new DelegateCommand(() => FlashMMOSCallback(MMOSPath), () => (MMOSPath != null) && (PhoneNotifier.CurrentInterface != null));
} }
} }
private DelegateCommand _FlashArchiveCommand; private DelegateCommand _FlashArchiveCommand;
public DelegateCommand FlashArchiveCommand public DelegateCommand FlashArchiveCommand
{ {
get get
{ {
return _FlashArchiveCommand ??= new DelegateCommand(() => FlashArchiveCallback(ArchivePath), () => (ArchivePath != null) && (PhoneNotifier.CurrentInterface != null)); return _FlashArchiveCommand ??= new DelegateCommand(() => FlashArchiveCallback(ArchivePath), () => (ArchivePath != null) && (PhoneNotifier.CurrentInterface != null));
} }
} }
~LumiaFlashRomSourceSelectionViewModel() ~LumiaFlashRomSourceSelectionViewModel()
{ {
PhoneNotifier.NewDeviceArrived -= NewDeviceArrived; PhoneNotifier.NewDeviceArrived -= NewDeviceArrived;
} }
private void NewDeviceArrived(ArrivalEventArgs Args) private void NewDeviceArrived(ArrivalEventArgs Args)
{ {
new Thread(() => new Thread(() =>
{ {
try try
{ {
EvaluateViewState(); EvaluateViewState();
} }
catch { } catch { }
}).Start(); }).Start();
} }
private void DeviceRemoved() private void DeviceRemoved()
{ {
new Thread(() => EvaluateViewState()).Start(); new Thread(() => EvaluateViewState()).Start();
} }
internal override void EvaluateViewState() internal override void EvaluateViewState()
{ {
IsPhoneDisconnected = PhoneNotifier.CurrentInterface == null; IsPhoneDisconnected = PhoneNotifier.CurrentInterface == null;
IsPhoneInFlashMode = PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_Flash; IsPhoneInFlashMode = PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_Flash;
IsPhoneInOtherMode = !IsPhoneDisconnected && !IsPhoneInFlashMode; IsPhoneInOtherMode = !IsPhoneDisconnected && !IsPhoneInFlashMode;
FlashPartitionsCommand.RaiseCanExecuteChanged(); FlashPartitionsCommand.RaiseCanExecuteChanged();
FlashArchiveCommand.RaiseCanExecuteChanged(); FlashArchiveCommand.RaiseCanExecuteChanged();
FlashFFUCommand.RaiseCanExecuteChanged(); FlashFFUCommand.RaiseCanExecuteChanged();
FlashMMOSCommand.RaiseCanExecuteChanged(); FlashMMOSCommand.RaiseCanExecuteChanged();
} }
} }
} }
@@ -1,88 +1,88 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
namespace WPinternals namespace WPinternals
{ {
internal class LumiaInfoViewModel : ContextViewModel internal class LumiaInfoViewModel : ContextViewModel
{ {
internal PhoneInterfaces? CurrentInterface; internal PhoneInterfaces? CurrentInterface;
internal IDisposable CurrentModel; internal IDisposable CurrentModel;
internal PhoneNotifierViewModel PhoneNotifier; internal PhoneNotifierViewModel PhoneNotifier;
private readonly Action<PhoneInterfaces> ModeSwitchRequestCallback; private readonly Action<PhoneInterfaces> ModeSwitchRequestCallback;
private readonly Action SwitchToGettingStarted; private readonly Action SwitchToGettingStarted;
internal LumiaInfoViewModel(PhoneNotifierViewModel PhoneNotifier, Action<PhoneInterfaces> ModeSwitchRequestCallback, Action SwitchToGettingStarted) internal LumiaInfoViewModel(PhoneNotifierViewModel PhoneNotifier, Action<PhoneInterfaces> ModeSwitchRequestCallback, Action SwitchToGettingStarted)
: base() : base()
{ {
this.PhoneNotifier = PhoneNotifier; this.PhoneNotifier = PhoneNotifier;
this.ModeSwitchRequestCallback = ModeSwitchRequestCallback; this.ModeSwitchRequestCallback = ModeSwitchRequestCallback;
this.SwitchToGettingStarted = SwitchToGettingStarted; this.SwitchToGettingStarted = SwitchToGettingStarted;
CurrentInterface = PhoneNotifier.CurrentInterface; CurrentInterface = PhoneNotifier.CurrentInterface;
CurrentModel = PhoneNotifier.CurrentModel; CurrentModel = PhoneNotifier.CurrentModel;
PhoneNotifier.NewDeviceArrived += NewDeviceArrived; PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
PhoneNotifier.DeviceRemoved += DeviceRemoved; PhoneNotifier.DeviceRemoved += DeviceRemoved;
} }
~LumiaInfoViewModel() ~LumiaInfoViewModel()
{ {
PhoneNotifier.NewDeviceArrived -= NewDeviceArrived; PhoneNotifier.NewDeviceArrived -= NewDeviceArrived;
PhoneNotifier.DeviceRemoved -= DeviceRemoved; PhoneNotifier.DeviceRemoved -= DeviceRemoved;
} }
private void DeviceRemoved() private void DeviceRemoved()
{ {
CurrentInterface = null; CurrentInterface = null;
CurrentModel = null; CurrentModel = null;
ActivateSubContext(null); ActivateSubContext(null);
} }
private void NewDeviceArrived(ArrivalEventArgs Args) private void NewDeviceArrived(ArrivalEventArgs Args)
{ {
CurrentInterface = Args.NewInterface; CurrentInterface = Args.NewInterface;
CurrentModel = Args.NewModel; CurrentModel = Args.NewModel;
// Determine SubcontextViewModel // Determine SubcontextViewModel
switch (CurrentInterface) switch (CurrentInterface)
{ {
case null: case null:
case PhoneInterfaces.Lumia_Bootloader: case PhoneInterfaces.Lumia_Bootloader:
ActivateSubContext(null); ActivateSubContext(null);
//ActivateSubContext(new NokiaBootloaderViewModel((NokiaFlashModel)CurrentModel, ModeSwitchRequestCallback, SwitchToGettingStarted)); //ActivateSubContext(new NokiaBootloaderViewModel((NokiaFlashModel)CurrentModel, ModeSwitchRequestCallback, SwitchToGettingStarted));
break; break;
case PhoneInterfaces.Lumia_Normal: case PhoneInterfaces.Lumia_Normal:
ActivateSubContext(new NokiaNormalViewModel((NokiaPhoneModel)CurrentModel, ModeSwitchRequestCallback)); ActivateSubContext(new NokiaNormalViewModel((NokiaPhoneModel)CurrentModel, ModeSwitchRequestCallback));
break; break;
case PhoneInterfaces.Lumia_Flash: case PhoneInterfaces.Lumia_Flash:
ActivateSubContext(new NokiaFlashViewModel((NokiaFlashModel)CurrentModel, ModeSwitchRequestCallback, SwitchToGettingStarted)); ActivateSubContext(new NokiaFlashViewModel((NokiaFlashModel)CurrentModel, ModeSwitchRequestCallback, SwitchToGettingStarted));
break; break;
case PhoneInterfaces.Lumia_Label: case PhoneInterfaces.Lumia_Label:
ActivateSubContext(new NokiaLabelViewModel((NokiaPhoneModel)CurrentModel, ModeSwitchRequestCallback)); ActivateSubContext(new NokiaLabelViewModel((NokiaPhoneModel)CurrentModel, ModeSwitchRequestCallback));
break; break;
case PhoneInterfaces.Lumia_MassStorage: case PhoneInterfaces.Lumia_MassStorage:
ActivateSubContext(new NokiaMassStorageViewModel((MassStorage)CurrentModel)); ActivateSubContext(new NokiaMassStorageViewModel((MassStorage)CurrentModel));
break; break;
} }
} }
} }
} }
@@ -1,132 +1,132 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
namespace WPinternals namespace WPinternals
{ {
internal class LumiaModeViewModel : ContextViewModel internal class LumiaModeViewModel : ContextViewModel
{ {
internal PhoneInterfaces? CurrentInterface; internal PhoneInterfaces? CurrentInterface;
internal IDisposable CurrentModel; internal IDisposable CurrentModel;
internal PhoneNotifierViewModel PhoneNotifier; internal PhoneNotifierViewModel PhoneNotifier;
private readonly Action Callback; private readonly Action Callback;
internal LumiaModeViewModel(PhoneNotifierViewModel PhoneNotifier, Action Callback) internal LumiaModeViewModel(PhoneNotifierViewModel PhoneNotifier, Action Callback)
: base() : base()
{ {
this.PhoneNotifier = PhoneNotifier; this.PhoneNotifier = PhoneNotifier;
this.Callback = Callback; this.Callback = Callback;
CurrentInterface = PhoneNotifier.CurrentInterface; CurrentInterface = PhoneNotifier.CurrentInterface;
CurrentModel = PhoneNotifier.CurrentModel; CurrentModel = PhoneNotifier.CurrentModel;
PhoneNotifier.NewDeviceArrived += NewDeviceArrived; PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
PhoneNotifier.DeviceRemoved += DeviceRemoved; PhoneNotifier.DeviceRemoved += DeviceRemoved;
} }
~LumiaModeViewModel() ~LumiaModeViewModel()
{ {
PhoneNotifier.NewDeviceArrived -= NewDeviceArrived; PhoneNotifier.NewDeviceArrived -= NewDeviceArrived;
PhoneNotifier.DeviceRemoved -= DeviceRemoved; PhoneNotifier.DeviceRemoved -= DeviceRemoved;
} }
private void DeviceRemoved() private void DeviceRemoved()
{ {
CurrentInterface = null; CurrentInterface = null;
CurrentModel = null; CurrentModel = null;
if (!IsSwitchingInterface) if (!IsSwitchingInterface)
{ {
ActivateSubContext(null); ActivateSubContext(null);
} }
} }
private void NewDeviceArrived(ArrivalEventArgs Args) private void NewDeviceArrived(ArrivalEventArgs Args)
{ {
CurrentInterface = Args.NewInterface; CurrentInterface = Args.NewInterface;
CurrentModel = Args.NewModel; CurrentModel = Args.NewModel;
if (!IsSwitchingInterface && IsActive) if (!IsSwitchingInterface && IsActive)
{ {
Refresh(); Refresh();
} }
} }
internal override void EvaluateViewState() internal override void EvaluateViewState()
{ {
if (!IsSwitchingInterface && IsActive) if (!IsSwitchingInterface && IsActive)
{ {
Refresh(); Refresh();
} }
} }
private void Refresh() private void Refresh()
{ {
// Determine SubcontextViewModel // Determine SubcontextViewModel
switch (CurrentInterface) switch (CurrentInterface)
{ {
case null: case null:
ActivateSubContext(null); ActivateSubContext(null);
break; break;
case PhoneInterfaces.Lumia_Bootloader: case PhoneInterfaces.Lumia_Bootloader:
ActivateSubContext(null); ActivateSubContext(null);
//ActivateSubContext(new NokiaModeBootloaderViewModel((NokiaFlashModel)CurrentModel, OnModeSwitchRequested)); //ActivateSubContext(new NokiaModeBootloaderViewModel((NokiaFlashModel)CurrentModel, OnModeSwitchRequested));
break; break;
case PhoneInterfaces.Lumia_Normal: case PhoneInterfaces.Lumia_Normal:
ActivateSubContext(new NokiaModeNormalViewModel((NokiaPhoneModel)CurrentModel, OnModeSwitchRequested)); ActivateSubContext(new NokiaModeNormalViewModel((NokiaPhoneModel)CurrentModel, OnModeSwitchRequested));
break; break;
case PhoneInterfaces.Lumia_Flash: case PhoneInterfaces.Lumia_Flash:
ActivateSubContext(new NokiaModeFlashViewModel((NokiaFlashModel)CurrentModel, OnModeSwitchRequested)); ActivateSubContext(new NokiaModeFlashViewModel((NokiaFlashModel)CurrentModel, OnModeSwitchRequested));
break; break;
case PhoneInterfaces.Lumia_Label: case PhoneInterfaces.Lumia_Label:
ActivateSubContext(new NokiaModeLabelViewModel((NokiaPhoneModel)CurrentModel, OnModeSwitchRequested)); ActivateSubContext(new NokiaModeLabelViewModel((NokiaPhoneModel)CurrentModel, OnModeSwitchRequested));
break; break;
case PhoneInterfaces.Lumia_MassStorage: case PhoneInterfaces.Lumia_MassStorage:
ActivateSubContext(new NokiaModeMassStorageViewModel((MassStorage)CurrentModel, OnModeSwitchRequested)); ActivateSubContext(new NokiaModeMassStorageViewModel((MassStorage)CurrentModel, OnModeSwitchRequested));
break; break;
} }
} }
// Called from eventhandler, so "async void" is valid here. // Called from eventhandler, so "async void" is valid here.
internal async void OnModeSwitchRequested(PhoneInterfaces? TargetInterface) internal async void OnModeSwitchRequested(PhoneInterfaces? TargetInterface)
{ {
IsSwitchingInterface = true; IsSwitchingInterface = true;
try try
{ {
await SwitchModeViewModel.SwitchToWithStatus(PhoneNotifier, TargetInterface, SetWorkingStatus, UpdateWorkingStatus, null); // This is a manual switch. We don't care about which volume arrives. await SwitchModeViewModel.SwitchToWithStatus(PhoneNotifier, TargetInterface, SetWorkingStatus, UpdateWorkingStatus, null); // This is a manual switch. We don't care about which volume arrives.
IsSwitchingInterface = false; IsSwitchingInterface = false;
Callback(); Callback();
Refresh(); Refresh();
} }
catch (Exception Ex) catch (Exception Ex)
{ {
IsSwitchingInterface = false; IsSwitchingInterface = false;
ActivateSubContext(new MessageViewModel(Ex.Message, () => ActivateSubContext(new MessageViewModel(Ex.Message, () =>
{ {
Callback(); Callback();
Refresh(); Refresh();
})); }));
} }
} }
} }
} }
@@ -1,190 +1,190 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Threading; using System.Threading;
namespace WPinternals namespace WPinternals
{ {
internal class LumiaUnlockRootTargetSelectionViewModel : LumiaRootAccessTargetSelectionViewModel internal class LumiaUnlockRootTargetSelectionViewModel : LumiaRootAccessTargetSelectionViewModel
{ {
public LumiaUnlockRootTargetSelectionViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action SwitchToDumpRom, Action SwitchToFlashRom, Action UnlockPhoneCallback, Action<string, string> UnlockImageCallback) public LumiaUnlockRootTargetSelectionViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action SwitchToDumpRom, Action SwitchToFlashRom, Action UnlockPhoneCallback, Action<string, string> UnlockImageCallback)
: base(PhoneNotifier, SwitchToUnlockBoot, SwitchToDumpRom, SwitchToFlashRom, UnlockPhoneCallback, UnlockImageCallback) { } : base(PhoneNotifier, SwitchToUnlockBoot, SwitchToDumpRom, SwitchToFlashRom, UnlockPhoneCallback, UnlockImageCallback) { }
} }
internal class LumiaUndoRootTargetSelectionViewModel : LumiaRootAccessTargetSelectionViewModel internal class LumiaUndoRootTargetSelectionViewModel : LumiaRootAccessTargetSelectionViewModel
{ {
public LumiaUndoRootTargetSelectionViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action SwitchToDumpRom, Action SwitchToFlashRom, Action UnlockPhoneCallback, Action<string, string> UnlockImageCallback) public LumiaUndoRootTargetSelectionViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action SwitchToDumpRom, Action SwitchToFlashRom, Action UnlockPhoneCallback, Action<string, string> UnlockImageCallback)
: base(PhoneNotifier, SwitchToUnlockBoot, SwitchToDumpRom, SwitchToFlashRom, UnlockPhoneCallback, UnlockImageCallback) { } : base(PhoneNotifier, SwitchToUnlockBoot, SwitchToDumpRom, SwitchToFlashRom, UnlockPhoneCallback, UnlockImageCallback) { }
} }
internal class LumiaRootAccessTargetSelectionViewModel : ContextViewModel internal class LumiaRootAccessTargetSelectionViewModel : ContextViewModel
{ {
private readonly PhoneNotifierViewModel PhoneNotifier; private readonly PhoneNotifierViewModel PhoneNotifier;
internal Action SwitchToUnlockBoot; internal Action SwitchToUnlockBoot;
internal Action SwitchToDumpRom; internal Action SwitchToDumpRom;
internal Action SwitchToFlashRom; internal Action SwitchToFlashRom;
private readonly Action UnlockPhoneCallback; private readonly Action UnlockPhoneCallback;
private readonly Action<string, string> UnlockImageCallback; private readonly Action<string, string> UnlockImageCallback;
internal LumiaRootAccessTargetSelectionViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action SwitchToDumpRom, Action SwitchToFlashRom, Action UnlockPhoneCallback, Action<string, string> UnlockImageCallback) internal LumiaRootAccessTargetSelectionViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action SwitchToDumpRom, Action SwitchToFlashRom, Action UnlockPhoneCallback, Action<string, string> UnlockImageCallback)
: base() : base()
{ {
this.PhoneNotifier = PhoneNotifier; this.PhoneNotifier = PhoneNotifier;
this.SwitchToDumpRom = SwitchToDumpRom; this.SwitchToDumpRom = SwitchToDumpRom;
this.SwitchToFlashRom = SwitchToFlashRom; this.SwitchToFlashRom = SwitchToFlashRom;
this.SwitchToUnlockBoot = SwitchToUnlockBoot; this.SwitchToUnlockBoot = SwitchToUnlockBoot;
this.UnlockPhoneCallback = UnlockPhoneCallback; this.UnlockPhoneCallback = UnlockPhoneCallback;
this.UnlockImageCallback = UnlockImageCallback; this.UnlockImageCallback = UnlockImageCallback;
this.PhoneNotifier.NewDeviceArrived += NewDeviceArrived; this.PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
this.PhoneNotifier.DeviceRemoved += DeviceRemoved; this.PhoneNotifier.DeviceRemoved += DeviceRemoved;
new Thread(() => EvaluateViewState()).Start(); new Thread(() => EvaluateViewState()).Start();
} }
private string _EFIESPMountPoint; private string _EFIESPMountPoint;
public string EFIESPMountPoint public string EFIESPMountPoint
{ {
get get
{ {
return _EFIESPMountPoint; return _EFIESPMountPoint;
} }
set set
{ {
if (value != _EFIESPMountPoint) if (value != _EFIESPMountPoint)
{ {
_EFIESPMountPoint = value; _EFIESPMountPoint = value;
OnPropertyChanged(nameof(EFIESPMountPoint)); OnPropertyChanged(nameof(EFIESPMountPoint));
} }
} }
} }
private string _MainOSMountPoint; private string _MainOSMountPoint;
public string MainOSMountPoint public string MainOSMountPoint
{ {
get get
{ {
return _MainOSMountPoint; return _MainOSMountPoint;
} }
set set
{ {
if (value != _MainOSMountPoint) if (value != _MainOSMountPoint)
{ {
_MainOSMountPoint = value; _MainOSMountPoint = value;
OnPropertyChanged(nameof(MainOSMountPoint)); OnPropertyChanged(nameof(MainOSMountPoint));
} }
} }
} }
private bool _IsPhoneDisconnected; private bool _IsPhoneDisconnected;
public bool IsPhoneDisconnected public bool IsPhoneDisconnected
{ {
get get
{ {
return _IsPhoneDisconnected; return _IsPhoneDisconnected;
} }
set set
{ {
if (value != _IsPhoneDisconnected) if (value != _IsPhoneDisconnected)
{ {
_IsPhoneDisconnected = value; _IsPhoneDisconnected = value;
OnPropertyChanged(nameof(IsPhoneDisconnected)); OnPropertyChanged(nameof(IsPhoneDisconnected));
} }
} }
} }
private bool _IsPhoneInMassStorage; private bool _IsPhoneInMassStorage;
public bool IsPhoneInMassStorage public bool IsPhoneInMassStorage
{ {
get get
{ {
return _IsPhoneInMassStorage; return _IsPhoneInMassStorage;
} }
set set
{ {
if (value != _IsPhoneInMassStorage) if (value != _IsPhoneInMassStorage)
{ {
_IsPhoneInMassStorage = value; _IsPhoneInMassStorage = value;
OnPropertyChanged(nameof(IsPhoneInMassStorage)); OnPropertyChanged(nameof(IsPhoneInMassStorage));
} }
} }
} }
private bool _IsPhoneInOtherMode; private bool _IsPhoneInOtherMode;
public bool IsPhoneInOtherMode public bool IsPhoneInOtherMode
{ {
get get
{ {
return _IsPhoneInOtherMode; return _IsPhoneInOtherMode;
} }
set set
{ {
if (value != _IsPhoneInOtherMode) if (value != _IsPhoneInOtherMode)
{ {
_IsPhoneInOtherMode = value; _IsPhoneInOtherMode = value;
OnPropertyChanged(nameof(IsPhoneInOtherMode)); OnPropertyChanged(nameof(IsPhoneInOtherMode));
} }
} }
} }
private DelegateCommand _UnlockPhoneCommand; private DelegateCommand _UnlockPhoneCommand;
public DelegateCommand UnlockPhoneCommand public DelegateCommand UnlockPhoneCommand
{ {
get get
{ {
return _UnlockPhoneCommand ??= new DelegateCommand(() => UnlockPhoneCallback(), () => !IsPhoneDisconnected); return _UnlockPhoneCommand ??= new DelegateCommand(() => UnlockPhoneCallback(), () => !IsPhoneDisconnected);
} }
} }
private DelegateCommand _UnlockImageCommand; private DelegateCommand _UnlockImageCommand;
public DelegateCommand UnlockImageCommand public DelegateCommand UnlockImageCommand
{ {
get get
{ {
return _UnlockImageCommand ??= new DelegateCommand(() => UnlockImageCallback(EFIESPMountPoint, MainOSMountPoint), () => (EFIESPMountPoint != null) || (MainOSMountPoint != null)); return _UnlockImageCommand ??= new DelegateCommand(() => UnlockImageCallback(EFIESPMountPoint, MainOSMountPoint), () => (EFIESPMountPoint != null) || (MainOSMountPoint != null));
} }
} }
~LumiaRootAccessTargetSelectionViewModel() ~LumiaRootAccessTargetSelectionViewModel()
{ {
PhoneNotifier.NewDeviceArrived -= NewDeviceArrived; PhoneNotifier.NewDeviceArrived -= NewDeviceArrived;
} }
private void NewDeviceArrived(ArrivalEventArgs Args) private void NewDeviceArrived(ArrivalEventArgs Args)
{ {
new Thread(() => EvaluateViewState()).Start(); new Thread(() => EvaluateViewState()).Start();
} }
private void DeviceRemoved() private void DeviceRemoved()
{ {
new Thread(() => EvaluateViewState()).Start(); new Thread(() => EvaluateViewState()).Start();
} }
internal override void EvaluateViewState() internal override void EvaluateViewState()
{ {
IsPhoneDisconnected = PhoneNotifier.CurrentInterface == null; IsPhoneDisconnected = PhoneNotifier.CurrentInterface == null;
IsPhoneInMassStorage = PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_MassStorage; IsPhoneInMassStorage = PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_MassStorage;
IsPhoneInOtherMode = !IsPhoneDisconnected && !IsPhoneInMassStorage; IsPhoneInOtherMode = !IsPhoneDisconnected && !IsPhoneInMassStorage;
UnlockPhoneCommand.RaiseCanExecuteChanged(); UnlockPhoneCommand.RaiseCanExecuteChanged();
UnlockImageCommand.RaiseCanExecuteChanged(); UnlockImageCommand.RaiseCanExecuteChanged();
} }
} }
} }
@@ -1,290 +1,290 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
namespace WPinternals namespace WPinternals
{ {
internal class LumiaUnlockRootViewModel : ContextViewModel internal class LumiaUnlockRootViewModel : ContextViewModel
{ {
private readonly PhoneNotifierViewModel PhoneNotifier; private readonly PhoneNotifierViewModel PhoneNotifier;
private readonly Action SwitchToUnlockBoot; private readonly Action SwitchToUnlockBoot;
private readonly Action SwitchToDumpRom; private readonly Action SwitchToDumpRom;
private readonly Action SwitchToFlashRom; private readonly Action SwitchToFlashRom;
private readonly Action Callback; private readonly Action Callback;
private readonly bool DoUnlock; private readonly bool DoUnlock;
internal LumiaUnlockRootViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action SwitchToDumpRom, Action SwitchToFlashRom, bool DoUnlock, Action Callback) internal LumiaUnlockRootViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action SwitchToDumpRom, Action SwitchToFlashRom, bool DoUnlock, Action Callback)
: base() : base()
{ {
IsSwitchingInterface = false; IsSwitchingInterface = false;
IsFlashModeOperation = true; IsFlashModeOperation = true;
this.PhoneNotifier = PhoneNotifier; this.PhoneNotifier = PhoneNotifier;
this.SwitchToDumpRom = SwitchToDumpRom; this.SwitchToDumpRom = SwitchToDumpRom;
this.SwitchToFlashRom = SwitchToFlashRom; this.SwitchToFlashRom = SwitchToFlashRom;
this.SwitchToUnlockBoot = SwitchToUnlockBoot; this.SwitchToUnlockBoot = SwitchToUnlockBoot;
this.DoUnlock = DoUnlock; this.DoUnlock = DoUnlock;
this.Callback = Callback; this.Callback = Callback;
} }
internal override void EvaluateViewState() internal override void EvaluateViewState()
{ {
if (!IsActive) if (!IsActive)
{ {
return; return;
} }
if (DoUnlock) if (DoUnlock)
{ {
if ((SubContextViewModel == null) || (SubContextViewModel is LumiaUndoRootTargetSelectionViewModel)) if ((SubContextViewModel == null) || (SubContextViewModel is LumiaUndoRootTargetSelectionViewModel))
{ {
ActivateSubContext(new LumiaUnlockRootTargetSelectionViewModel(PhoneNotifier, SwitchToUnlockBoot, SwitchToDumpRom, SwitchToFlashRom, DoUnlockPhone, DoUnlockImage)); ActivateSubContext(new LumiaUnlockRootTargetSelectionViewModel(PhoneNotifier, SwitchToUnlockBoot, SwitchToDumpRom, SwitchToFlashRom, DoUnlockPhone, DoUnlockImage));
} }
} }
else else
{ {
if ((SubContextViewModel == null) || (SubContextViewModel is LumiaUnlockRootTargetSelectionViewModel)) if ((SubContextViewModel == null) || (SubContextViewModel is LumiaUnlockRootTargetSelectionViewModel))
{ {
ActivateSubContext(new LumiaUndoRootTargetSelectionViewModel(PhoneNotifier, SwitchToUnlockBoot, SwitchToDumpRom, SwitchToFlashRom, DoUnlockPhone, DoUnlockImage)); ActivateSubContext(new LumiaUndoRootTargetSelectionViewModel(PhoneNotifier, SwitchToUnlockBoot, SwitchToDumpRom, SwitchToFlashRom, DoUnlockPhone, DoUnlockImage));
} }
} }
} }
internal async void DoUnlockPhone() internal async void DoUnlockPhone()
{ {
try try
{ {
IsSwitchingInterface = true; IsSwitchingInterface = true;
await SwitchModeViewModel.SwitchToWithProgress(PhoneNotifier, PhoneInterfaces.Lumia_MassStorage, await SwitchModeViewModel.SwitchToWithProgress(PhoneNotifier, PhoneInterfaces.Lumia_MassStorage,
(msg, sub) => (msg, sub) =>
ActivateSubContext(new BusyViewModel(msg, sub))); ActivateSubContext(new BusyViewModel(msg, sub)));
bool HasNewBootloader = HasNewBootloaderFromMassStorage(); bool HasNewBootloader = HasNewBootloaderFromMassStorage();
string EFIESPPath = HasNewBootloader ? null : ((MassStorage)PhoneNotifier.CurrentModel).Drive + @"\EFIESP\"; string EFIESPPath = HasNewBootloader ? null : ((MassStorage)PhoneNotifier.CurrentModel).Drive + @"\EFIESP\";
string MainOSPath = ((MassStorage)PhoneNotifier.CurrentModel).Drive + @"\"; string MainOSPath = ((MassStorage)PhoneNotifier.CurrentModel).Drive + @"\";
bool HasV11Patches = HasV11PatchesFromMassStorage(); bool HasV11Patches = HasV11PatchesFromMassStorage();
StartPatch(EFIESPPath, MainOSPath, HasNewBootloader, HasV11Patches); StartPatch(EFIESPPath, MainOSPath, HasNewBootloader, HasV11Patches);
} }
catch (Exception Ex) catch (Exception Ex)
{ {
ActivateSubContext(new MessageViewModel(Ex.Message, () => ActivateSubContext(new MessageViewModel(Ex.Message, () =>
{ {
Callback(); Callback();
ActivateSubContext(null); ActivateSubContext(null);
})); }));
} }
} }
internal void DoUnlockImage(string EFIESPMountPoint, string MainOSMountPoint) internal void DoUnlockImage(string EFIESPMountPoint, string MainOSMountPoint)
{ {
StartPatch(EFIESPMountPoint, MainOSMountPoint, false, false); // Unlock image is only supported for Lumia's with bootloader Spec A. Due to complexity of Spec B bootloader hack, it cannot be applied on a mounted image. StartPatch(EFIESPMountPoint, MainOSMountPoint, false, false); // Unlock image is only supported for Lumia's with bootloader Spec A. Due to complexity of Spec B bootloader hack, it cannot be applied on a mounted image.
} }
// Magic! // Magic!
// Apply patches for Root Access // Apply patches for Root Access
private void StartPatch(string EFIESP, string MainOS, bool HasNewBootloader, bool HasV11Patches) private void StartPatch(string EFIESP, string MainOS, bool HasNewBootloader, bool HasV11Patches)
{ {
IsSwitchingInterface = false; IsSwitchingInterface = false;
new Thread(() => new Thread(() =>
{ {
if (DoUnlock) if (DoUnlock)
{ {
LogFile.BeginAction("EnableRootAccess"); LogFile.BeginAction("EnableRootAccess");
} }
else else
{ {
LogFile.BeginAction("DisableRootAccess"); LogFile.BeginAction("DisableRootAccess");
} }
bool Result = false; bool Result = false;
if (EFIESP != null && !HasV11Patches) if (EFIESP != null && !HasV11Patches)
{ {
if (DoUnlock) if (DoUnlock)
{ {
ActivateSubContext(new BusyViewModel("Enable Root Access on EFIESP...")); ActivateSubContext(new BusyViewModel("Enable Root Access on EFIESP..."));
} }
else else
{ {
ActivateSubContext(new BusyViewModel("Disable Root Access on EFIESP...")); ActivateSubContext(new BusyViewModel("Disable Root Access on EFIESP..."));
} }
try try
{ {
App.PatchEngine.TargetPath = EFIESP; App.PatchEngine.TargetPath = EFIESP;
if (DoUnlock) if (DoUnlock)
{ {
Result = App.PatchEngine.Patch("SecureBootHack-V1-EFIESP"); Result = App.PatchEngine.Patch("SecureBootHack-V1-EFIESP");
if (!Result) if (!Result)
{ {
ActivateSubContext(new MessageViewModel("Failed to enable Root Access on EFIESP! Check the OS version on the phone and verify the compatibility-list in the \"Getting started\" section.", Exit)); ActivateSubContext(new MessageViewModel("Failed to enable Root Access on EFIESP! Check the OS version on the phone and verify the compatibility-list in the \"Getting started\" section.", Exit));
return; return;
} }
} }
else else
{ {
App.PatchEngine.Restore("SecureBootHack-V1-EFIESP"); App.PatchEngine.Restore("SecureBootHack-V1-EFIESP");
Result = true; Result = true;
} }
} }
catch (UnauthorizedAccessException Ex) catch (UnauthorizedAccessException Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
ActivateSubContext(new MessageViewModel("Failed to enable Root Access on EFIESP! Not enough privileges to perform action. Try to logon to Windows with an administrator account.", Exit)); ActivateSubContext(new MessageViewModel("Failed to enable Root Access on EFIESP! Not enough privileges to perform action. Try to logon to Windows with an administrator account.", Exit));
return; return;
} }
catch (Exception Ex) catch (Exception Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
Result = false; Result = false;
} }
if (!Result) if (!Result)
{ {
ActivateSubContext(new MessageViewModel("Failed to enable Root Access on EFIESP!", Exit)); ActivateSubContext(new MessageViewModel("Failed to enable Root Access on EFIESP!", Exit));
return; return;
} }
} }
if (MainOS != null) if (MainOS != null)
{ {
if (DoUnlock) if (DoUnlock)
{ {
ActivateSubContext(new BusyViewModel("Enable Root Access on MainOS...")); ActivateSubContext(new BusyViewModel("Enable Root Access on MainOS..."));
} }
else else
{ {
ActivateSubContext(new BusyViewModel("Disable Root Access on MainOS...")); ActivateSubContext(new BusyViewModel("Disable Root Access on MainOS..."));
} }
try try
{ {
App.PatchEngine.TargetPath = MainOS; App.PatchEngine.TargetPath = MainOS;
if (DoUnlock) if (DoUnlock)
{ {
Result = App.PatchEngine.Patch("RootAccess-MainOS"); Result = App.PatchEngine.Patch("RootAccess-MainOS");
if (Result) if (Result)
{ {
Result = App.PatchEngine.Patch("SecureBootHack-MainOS"); Result = App.PatchEngine.Patch("SecureBootHack-MainOS");
} }
if (!Result) if (!Result)
{ {
ActivateSubContext(new MessageViewModel("Failed to enable Root Access on MainOS! Check the OS version on the phone and verify the compatibility-list in the \"Getting started\" section.", Exit)); ActivateSubContext(new MessageViewModel("Failed to enable Root Access on MainOS! Check the OS version on the phone and verify the compatibility-list in the \"Getting started\" section.", Exit));
return; return;
} }
} }
else else
{ {
App.PatchEngine.Restore("RootAccess-MainOS"); App.PatchEngine.Restore("RootAccess-MainOS");
if (!HasNewBootloader) if (!HasNewBootloader)
{ {
App.PatchEngine.Restore("SecureBootHack-MainOS"); App.PatchEngine.Restore("SecureBootHack-MainOS");
} }
Result = true; Result = true;
} }
} }
catch (UnauthorizedAccessException Ex) catch (UnauthorizedAccessException Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
ActivateSubContext(new MessageViewModel("Failed to enable Root Access on MainOS! Not enough privileges to perform action. Try to logon to Windows with an administrator account.", Exit)); ActivateSubContext(new MessageViewModel("Failed to enable Root Access on MainOS! Not enough privileges to perform action. Try to logon to Windows with an administrator account.", Exit));
Result = false; Result = false;
} }
catch (Exception Ex) catch (Exception Ex)
{ {
LogFile.LogException(Ex); LogFile.LogException(Ex);
Result = false; Result = false;
} }
if (!Result) if (!Result)
{ {
ActivateSubContext(new MessageViewModel("Failed to enable Root Access on MainOS!", Exit)); ActivateSubContext(new MessageViewModel("Failed to enable Root Access on MainOS!", Exit));
} }
else else
{ {
if (DoUnlock) if (DoUnlock)
{ {
ActivateSubContext(new MessageViewModel("Root Access successfully enabled!", Exit)); ActivateSubContext(new MessageViewModel("Root Access successfully enabled!", Exit));
} }
else else
{ {
ActivateSubContext(new MessageViewModel("Root Access successfully disabled!", Exit)); ActivateSubContext(new MessageViewModel("Root Access successfully disabled!", Exit));
} }
} }
} }
if (DoUnlock) if (DoUnlock)
{ {
LogFile.EndAction("EnableRootAccess"); LogFile.EndAction("EnableRootAccess");
} }
else else
{ {
LogFile.EndAction("DisableRootAccess"); LogFile.EndAction("DisableRootAccess");
} }
}).Start(); }).Start();
} }
private void Exit() private void Exit()
{ {
IsSwitchingInterface = false; IsSwitchingInterface = false;
Callback(); Callback();
ActivateSubContext(null); ActivateSubContext(null);
} }
private bool HasNewBootloaderFromMassStorage() private bool HasNewBootloaderFromMassStorage()
{ {
bool Result = false; bool Result = false;
MassStorage Phone = (MassStorage)PhoneNotifier.CurrentModel; MassStorage Phone = (MassStorage)PhoneNotifier.CurrentModel;
Phone.OpenVolume(false); Phone.OpenVolume(false);
byte[] GPTBuffer = Phone.ReadSectors(1, 33); byte[] GPTBuffer = Phone.ReadSectors(1, 33);
GPT GPT = new(GPTBuffer); GPT GPT = new(GPTBuffer);
Partition Partition = GPT.GetPartition("UEFI"); Partition Partition = GPT.GetPartition("UEFI");
byte[] UefiBuffer = Phone.ReadSectors(Partition.FirstSector, Partition.LastSector - Partition.FirstSector + 1); byte[] UefiBuffer = Phone.ReadSectors(Partition.FirstSector, Partition.LastSector - Partition.FirstSector + 1);
UEFI UEFI = new(UefiBuffer); UEFI UEFI = new(UefiBuffer);
string BootMgrName = UEFI.EFIs.First(efi => (efi.Name != null) && (efi.Name.Contains("BootMgrApp") || efi.Name.Contains("FlashApp"))).Name; string BootMgrName = UEFI.EFIs.First(efi => (efi.Name != null) && (efi.Name.Contains("BootMgrApp") || efi.Name.Contains("FlashApp"))).Name;
byte[] BootMgr = UEFI.GetFile(BootMgrName); byte[] BootMgr = UEFI.GetFile(BootMgrName);
// "Header V2" // "Header V2"
Result = ByteOperations.FindAscii(BootMgr, "Header V2") != null; Result = ByteOperations.FindAscii(BootMgr, "Header V2") != null;
Phone.CloseVolume(); Phone.CloseVolume();
return Result; return Result;
} }
private bool HasV11PatchesFromMassStorage() private bool HasV11PatchesFromMassStorage()
{ {
bool Result = false; bool Result = false;
MassStorage Phone = (MassStorage)PhoneNotifier.CurrentModel; MassStorage Phone = (MassStorage)PhoneNotifier.CurrentModel;
Phone.OpenVolume(false); Phone.OpenVolume(false);
byte[] GPTBuffer = Phone.ReadSectors(1, 33); byte[] GPTBuffer = Phone.ReadSectors(1, 33);
GPT GPT = new(GPTBuffer); GPT GPT = new(GPTBuffer);
Partition Partition = GPT.GetPartition("BACKUP_BS_NV"); Partition Partition = GPT.GetPartition("BACKUP_BS_NV");
Result = Partition != null; Result = Partition != null;
Phone.CloseVolume(); Phone.CloseVolume();
return Result; return Result;
} }
} }
} }
@@ -1,485 +1,485 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using Microsoft.Win32; using Microsoft.Win32;
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
namespace WPinternals namespace WPinternals
{ {
public enum NavigationSubject public enum NavigationSubject
{ {
Info, Info,
Mode, Mode,
Install, Install,
About About
}; };
public enum PhoneInterfaces public enum PhoneInterfaces
{ {
Lumia_Normal, Lumia_Normal,
Lumia_Flash, Lumia_Flash,
Lumia_Label, Lumia_Label,
Lumia_MassStorage, Lumia_MassStorage,
Lumia_Bootloader, Lumia_Bootloader,
Qualcomm_Download, Qualcomm_Download,
Qualcomm_Flash, Qualcomm_Flash,
Lumia_BadMassStorage Lumia_BadMassStorage
}; };
// Create this class on the UI thread, after the main-window of the application is initialized. // Create this class on the UI thread, after the main-window of the application is initialized.
// It is necessary to create the object on the UI thread, because notification events to the View need to be fired on that thread. // It is necessary to create the object on the UI thread, because notification events to the View need to be fired on that thread.
// The Model for this ViewModel communicates over USB and for that it uses the hWnd of the main window. // The Model for this ViewModel communicates over USB and for that it uses the hWnd of the main window.
// Therefore the main window must be created before the ViewModel is created. // Therefore the main window must be created before the ViewModel is created.
internal class MainViewModel : INotifyPropertyChanged internal class MainViewModel : INotifyPropertyChanged
{ {
public PhoneInterfaces? CurrentInterface = null; public PhoneInterfaces? CurrentInterface = null;
public PhoneInterfaces? LastInterface = null; public PhoneInterfaces? LastInterface = null;
public NokiaPhoneModel CurrentModel = null; public NokiaPhoneModel CurrentModel = null;
public PhoneNotifierViewModel PhoneNotifier; public PhoneNotifierViewModel PhoneNotifier;
public LumiaInfoViewModel InfoViewModel; public LumiaInfoViewModel InfoViewModel;
public LumiaModeViewModel ModeViewModel; public LumiaModeViewModel ModeViewModel;
public LumiaUnlockBootViewModel BootUnlockViewModel; public LumiaUnlockBootViewModel BootUnlockViewModel;
public LumiaUnlockBootViewModel BootRestoreViewModel; public LumiaUnlockBootViewModel BootRestoreViewModel;
public LumiaUnlockRootViewModel RootUnlockViewModel; public LumiaUnlockRootViewModel RootUnlockViewModel;
public LumiaUnlockRootViewModel RootRestoreViewModel; public LumiaUnlockRootViewModel RootRestoreViewModel;
public BackupViewModel BackupViewModel; public BackupViewModel BackupViewModel;
public RestoreViewModel RestoreViewModel; public RestoreViewModel RestoreViewModel;
public LumiaFlashRomViewModel LumiaFlashRomViewModel; public LumiaFlashRomViewModel LumiaFlashRomViewModel;
public DumpRomViewModel DumpRomViewModel; public DumpRomViewModel DumpRomViewModel;
public DownloadsViewModel DownloadsViewModel; public DownloadsViewModel DownloadsViewModel;
private GettingStartedViewModel _GettingStartedViewModel = null; private GettingStartedViewModel _GettingStartedViewModel = null;
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName) private void OnPropertyChanged(string propertyName)
{ {
if (this.PropertyChanged != null) if (this.PropertyChanged != null)
{ {
if (MainSyncContext == SynchronizationContext.Current) if (MainSyncContext == SynchronizationContext.Current)
{ {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
} }
else else
{ {
MainSyncContext.Post(s => PropertyChanged(this, new PropertyChangedEventArgs(propertyName)), null); MainSyncContext.Post(s => PropertyChanged(this, new PropertyChangedEventArgs(propertyName)), null);
} }
} }
} }
private ContextViewModel _ContextViewModel; private ContextViewModel _ContextViewModel;
public ContextViewModel ContextViewModel public ContextViewModel ContextViewModel
{ {
get get
{ {
return _ContextViewModel; return _ContextViewModel;
} }
set set
{ {
if (_ContextViewModel != value) if (_ContextViewModel != value)
{ {
if (_ContextViewModel != null) if (_ContextViewModel != null)
{ {
_ContextViewModel.IsActive = false; _ContextViewModel.IsActive = false;
} }
_ContextViewModel = value; _ContextViewModel = value;
_ContextViewModel?.Activate(); _ContextViewModel?.Activate();
OnPropertyChanged(nameof(ContextViewModel)); OnPropertyChanged(nameof(ContextViewModel));
} }
} }
} }
private readonly SynchronizationContext MainSyncContext; private readonly SynchronizationContext MainSyncContext;
public MainViewModel() public MainViewModel()
{ {
MainSyncContext = SynchronizationContext.Current; MainSyncContext = SynchronizationContext.Current;
LogFile.LogApplicationVersion(); LogFile.LogApplicationVersion();
// Set global callback for cases where Dependency Injection is not possible. // Set global callback for cases where Dependency Injection is not possible.
App.NavigateToGettingStarted = () => GettingStartedCommand.Execute(null); App.NavigateToGettingStarted = () => GettingStartedCommand.Execute(null);
App.NavigateToUnlockBoot = () => BootUnlockCommand.Execute(null); App.NavigateToUnlockBoot = () => BootUnlockCommand.Execute(null);
if (Registry.CurrentUser.OpenSubKey("Software\\WPInternals") == null) if (Registry.CurrentUser.OpenSubKey("Software\\WPInternals") == null)
{ {
Registry.CurrentUser.OpenSubKey("Software", true).CreateSubKey("WPInternals"); Registry.CurrentUser.OpenSubKey("Software", true).CreateSubKey("WPInternals");
} }
if (Registration.IsPrerelease && (Registry.CurrentUser.OpenSubKey("Software\\WPInternals").GetValue("NdaAccepted") == null)) if (Registration.IsPrerelease && (Registry.CurrentUser.OpenSubKey("Software\\WPInternals").GetValue("NdaAccepted") == null))
{ {
this.ContextViewModel = new DisclaimerAndNdaViewModel(Disclaimer_Accepted); this.ContextViewModel = new DisclaimerAndNdaViewModel(Disclaimer_Accepted);
} }
else if (Registry.CurrentUser.OpenSubKey("Software\\WPInternals").GetValue("DisclaimerAccepted") == null) else if (Registry.CurrentUser.OpenSubKey("Software\\WPInternals").GetValue("DisclaimerAccepted") == null)
{ {
this.ContextViewModel = new DisclaimerViewModel(Disclaimer_Accepted); this.ContextViewModel = new DisclaimerViewModel(Disclaimer_Accepted);
} }
else if (Registration.IsPrerelease && !Registration.IsRegistered()) else if (Registration.IsPrerelease && !Registration.IsRegistered())
{ {
ContextViewModel = new RegistrationViewModel(Registration_Completed, Registration_Failed); ContextViewModel = new RegistrationViewModel(Registration_Completed, Registration_Failed);
} }
else else
{ {
StartOperation(); StartOperation();
} }
} }
private void Disclaimer_Accepted() private void Disclaimer_Accepted()
{ {
ContextViewModel = null; ContextViewModel = null;
if (Registration.IsPrerelease && !Registration.IsRegistered()) if (Registration.IsPrerelease && !Registration.IsRegistered())
{ {
ContextViewModel = new RegistrationViewModel(Registration_Completed, Registration_Failed); ContextViewModel = new RegistrationViewModel(Registration_Completed, Registration_Failed);
} }
else else
{ {
StartOperation(); StartOperation();
} }
} }
private void Registration_Completed() private void Registration_Completed()
{ {
ContextViewModel = null; ContextViewModel = null;
StartOperation(); StartOperation();
} }
private void Registration_Failed() private void Registration_Failed()
{ {
ContextViewModel = new MessageViewModel("Registration failed", () => Environment.Exit(0)); ContextViewModel = new MessageViewModel("Registration failed", () => Environment.Exit(0));
((MessageViewModel)ContextViewModel).SubMessage = "Check your filewall settings"; ((MessageViewModel)ContextViewModel).SubMessage = "Check your filewall settings";
} }
public void StartOperation() public void StartOperation()
{ {
IsMenuEnabled = true; IsMenuEnabled = true;
_GettingStartedViewModel = new GettingStartedViewModel( _GettingStartedViewModel = new GettingStartedViewModel(
() => () =>
{ {
ContextViewModel = new DisclaimerViewModel( ContextViewModel = new DisclaimerViewModel(
() => ContextViewModel = _GettingStartedViewModel () => ContextViewModel = _GettingStartedViewModel
); );
}, },
SwitchToUnlockBoot, SwitchToUnlockBoot,
SwitchToUnlockRoot, SwitchToUnlockRoot,
SwitchToBackup, SwitchToBackup,
SwitchToDumpFFU, SwitchToDumpFFU,
SwitchToFlashRom, SwitchToFlashRom,
SwitchToDownload SwitchToDownload
); );
this.ContextViewModel = _GettingStartedViewModel; this.ContextViewModel = _GettingStartedViewModel;
PhoneNotifier = new PhoneNotifierViewModel(); PhoneNotifier = new PhoneNotifierViewModel();
PhoneNotifier.NewDeviceArrived += PhoneNotifier_NewDeviceArrived; PhoneNotifier.NewDeviceArrived += PhoneNotifier_NewDeviceArrived;
PhoneNotifier.DeviceRemoved += PhoneNotifier_DeviceRemoved; PhoneNotifier.DeviceRemoved += PhoneNotifier_DeviceRemoved;
InfoViewModel = new LumiaInfoViewModel(PhoneNotifier, (TargetInterface) => InfoViewModel = new LumiaInfoViewModel(PhoneNotifier, (TargetInterface) =>
{ {
ModeViewModel.OnModeSwitchRequested(TargetInterface); ModeViewModel.OnModeSwitchRequested(TargetInterface);
ContextViewModel = ModeViewModel; ContextViewModel = ModeViewModel;
}, },
() => ContextViewModel = _GettingStartedViewModel); () => ContextViewModel = _GettingStartedViewModel);
InfoViewModel.ActivateSubContext(null); InfoViewModel.ActivateSubContext(null);
ModeViewModel = new LumiaModeViewModel(PhoneNotifier, SwitchToInfoViewModel); ModeViewModel = new LumiaModeViewModel(PhoneNotifier, SwitchToInfoViewModel);
ModeViewModel.ActivateSubContext(null); ModeViewModel.ActivateSubContext(null);
BootUnlockViewModel = new LumiaUnlockBootViewModel(PhoneNotifier, SwitchToFlashRom, SwitchToUndoRoot, SwitchToDownload, true, SwitchToInfoViewModel); BootUnlockViewModel = new LumiaUnlockBootViewModel(PhoneNotifier, SwitchToFlashRom, SwitchToUndoRoot, SwitchToDownload, true, SwitchToInfoViewModel);
BootUnlockViewModel.ActivateSubContext(null); BootUnlockViewModel.ActivateSubContext(null);
BootRestoreViewModel = new LumiaUnlockBootViewModel(PhoneNotifier, SwitchToFlashRom, SwitchToUndoRoot, SwitchToDownload, false, SwitchToInfoViewModel); BootRestoreViewModel = new LumiaUnlockBootViewModel(PhoneNotifier, SwitchToFlashRom, SwitchToUndoRoot, SwitchToDownload, false, SwitchToInfoViewModel);
BootRestoreViewModel.ActivateSubContext(null); BootRestoreViewModel.ActivateSubContext(null);
RootUnlockViewModel = new LumiaUnlockRootViewModel(PhoneNotifier, SwitchToUnlockBoot, SwitchToDumpFFU, SwitchToFlashRom, true, SwitchToInfoViewModel); RootUnlockViewModel = new LumiaUnlockRootViewModel(PhoneNotifier, SwitchToUnlockBoot, SwitchToDumpFFU, SwitchToFlashRom, true, SwitchToInfoViewModel);
RootUnlockViewModel.ActivateSubContext(null); RootUnlockViewModel.ActivateSubContext(null);
RootRestoreViewModel = new LumiaUnlockRootViewModel(PhoneNotifier, SwitchToUnlockBoot, SwitchToDumpFFU, SwitchToFlashRom, false, SwitchToInfoViewModel); RootRestoreViewModel = new LumiaUnlockRootViewModel(PhoneNotifier, SwitchToUnlockBoot, SwitchToDumpFFU, SwitchToFlashRom, false, SwitchToInfoViewModel);
RootRestoreViewModel.ActivateSubContext(null); RootRestoreViewModel.ActivateSubContext(null);
BackupViewModel = new BackupViewModel(PhoneNotifier, SwitchToUnlockBoot, SwitchToInfoViewModel); BackupViewModel = new BackupViewModel(PhoneNotifier, SwitchToUnlockBoot, SwitchToInfoViewModel);
BackupViewModel.ActivateSubContext(null); BackupViewModel.ActivateSubContext(null);
RestoreViewModel = new RestoreViewModel(PhoneNotifier, SwitchToDifferentInterface, SwitchToUnlockBoot, SwitchToFlashRom, SwitchToInfoViewModel); RestoreViewModel = new RestoreViewModel(PhoneNotifier, SwitchToDifferentInterface, SwitchToUnlockBoot, SwitchToFlashRom, SwitchToInfoViewModel);
RestoreViewModel.ActivateSubContext(null); RestoreViewModel.ActivateSubContext(null);
LumiaFlashRomViewModel = new LumiaFlashRomViewModel(PhoneNotifier, SwitchToUnlockBoot, SwitchToUnlockRoot, SwitchToDumpFFU, SwitchToBackup, SwitchToInfoViewModel); LumiaFlashRomViewModel = new LumiaFlashRomViewModel(PhoneNotifier, SwitchToUnlockBoot, SwitchToUnlockRoot, SwitchToDumpFFU, SwitchToBackup, SwitchToInfoViewModel);
LumiaFlashRomViewModel.ActivateSubContext(null); LumiaFlashRomViewModel.ActivateSubContext(null);
DumpRomViewModel = new DumpRomViewModel(SwitchToUnlockBoot, SwitchToUnlockRoot, SwitchToFlashRom); DumpRomViewModel = new DumpRomViewModel(SwitchToUnlockBoot, SwitchToUnlockRoot, SwitchToFlashRom);
DumpRomViewModel.ActivateSubContext(null); DumpRomViewModel.ActivateSubContext(null);
DownloadsViewModel = new DownloadsViewModel(PhoneNotifier); DownloadsViewModel = new DownloadsViewModel(PhoneNotifier);
App.DownloadManager = DownloadsViewModel; App.DownloadManager = DownloadsViewModel;
PhoneNotifier.Start(); PhoneNotifier.Start();
} }
internal void SwitchToInfoViewModel() internal void SwitchToInfoViewModel()
{ {
ContextViewModel = InfoViewModel; ContextViewModel = InfoViewModel;
} }
internal void SwitchToUnlockBoot() internal void SwitchToUnlockBoot()
{ {
ContextViewModel = BootUnlockViewModel; ContextViewModel = BootUnlockViewModel;
} }
internal void SwitchToRestoreBoot() internal void SwitchToRestoreBoot()
{ {
ContextViewModel = BootRestoreViewModel; ContextViewModel = BootRestoreViewModel;
} }
internal void SwitchToUnlockRoot() internal void SwitchToUnlockRoot()
{ {
ContextViewModel = RootUnlockViewModel; ContextViewModel = RootUnlockViewModel;
} }
internal void SwitchToUndoRoot() internal void SwitchToUndoRoot()
{ {
ContextViewModel = RootRestoreViewModel; ContextViewModel = RootRestoreViewModel;
} }
internal void SwitchToBackup() internal void SwitchToBackup()
{ {
ContextViewModel = BackupViewModel; ContextViewModel = BackupViewModel;
} }
internal void SwitchToFlashRom() internal void SwitchToFlashRom()
{ {
ContextViewModel = LumiaFlashRomViewModel; ContextViewModel = LumiaFlashRomViewModel;
} }
internal void SwitchToDumpFFU() internal void SwitchToDumpFFU()
{ {
ContextViewModel = DumpRomViewModel; ContextViewModel = DumpRomViewModel;
} }
internal void SwitchToDownload() internal void SwitchToDownload()
{ {
ContextViewModel = DownloadsViewModel; ContextViewModel = DownloadsViewModel;
} }
internal void SwitchToDifferentInterface(PhoneInterfaces TargetInterface) internal void SwitchToDifferentInterface(PhoneInterfaces TargetInterface)
{ {
ModeViewModel.OnModeSwitchRequested(TargetInterface); ModeViewModel.OnModeSwitchRequested(TargetInterface);
ContextViewModel = ModeViewModel; ContextViewModel = ModeViewModel;
} }
private void PhoneNotifier_DeviceRemoved() private void PhoneNotifier_DeviceRemoved()
{ {
InfoViewModel.ActivateSubContext(null); InfoViewModel.ActivateSubContext(null);
} }
private void PhoneNotifier_NewDeviceArrived(ArrivalEventArgs Args) private void PhoneNotifier_NewDeviceArrived(ArrivalEventArgs Args)
{ {
PhoneInterfaces? PreviousInterface = LastInterface; PhoneInterfaces? PreviousInterface = LastInterface;
LastInterface = Args.NewInterface; LastInterface = Args.NewInterface;
if (App.InterruptBoot && (Args.NewInterface == PhoneInterfaces.Lumia_Bootloader)) if (App.InterruptBoot && (Args.NewInterface == PhoneInterfaces.Lumia_Bootloader))
{ {
App.InterruptBoot = false; App.InterruptBoot = false;
LogFile.Log("Found Lumia BootMgr and user forced to interrupt the boot process. Force to Flash-mode."); LogFile.Log("Found Lumia BootMgr and user forced to interrupt the boot process. Force to Flash-mode.");
Task.Run(() => SwitchModeViewModel.SwitchTo(PhoneNotifier, PhoneInterfaces.Lumia_Flash)); Task.Run(() => SwitchModeViewModel.SwitchTo(PhoneNotifier, PhoneInterfaces.Lumia_Flash));
} }
else else
{ {
if (Args.NewInterface != PhoneInterfaces.Qualcomm_Download) if (Args.NewInterface != PhoneInterfaces.Qualcomm_Download)
{ {
App.InterruptBoot = false; App.InterruptBoot = false;
} }
if (ContextViewModel == null) if (ContextViewModel == null)
{ {
ContextViewModel = InfoViewModel; ContextViewModel = InfoViewModel;
} }
else if (ContextViewModel.IsFlashModeOperation) else if (ContextViewModel.IsFlashModeOperation)
{ {
if ((!ContextViewModel.IsSwitchingInterface) && (Args.NewInterface == PhoneInterfaces.Lumia_Bootloader)) if ((!ContextViewModel.IsSwitchingInterface) && (Args.NewInterface == PhoneInterfaces.Lumia_Bootloader))
{ {
// The current screen is marked as "Flash operation". // The current screen is marked as "Flash operation".
// When the bootloader is detected at this stage, it means a phone is booting and // When the bootloader is detected at this stage, it means a phone is booting and
// it is possible that the phone is in a non-booting stage (not possible to boot past UEFI). // it is possible that the phone is in a non-booting stage (not possible to boot past UEFI).
// We will try to boot straight to Flash-mode, so that it will be possible to flash a new ROM. // We will try to boot straight to Flash-mode, so that it will be possible to flash a new ROM.
LogFile.Log("Found Lumia BootMgr while mode is not being switched. Screen is marked as Flash Operation. Force to Flash-mode."); LogFile.Log("Found Lumia BootMgr while mode is not being switched. Screen is marked as Flash Operation. Force to Flash-mode.");
Task.Run(() => SwitchModeViewModel.SwitchTo(PhoneNotifier, PhoneInterfaces.Lumia_Flash)); Task.Run(() => SwitchModeViewModel.SwitchTo(PhoneNotifier, PhoneInterfaces.Lumia_Flash));
} }
} }
else else
{ {
if ((!ContextViewModel.IsSwitchingInterface) && (Args.NewInterface != PhoneInterfaces.Lumia_Bootloader)) if ((!ContextViewModel.IsSwitchingInterface) && (Args.NewInterface != PhoneInterfaces.Lumia_Bootloader))
{ {
ContextViewModel = InfoViewModel; ContextViewModel = InfoViewModel;
} }
} }
} }
} }
private ICommand _InfoCommand = null; private ICommand _InfoCommand = null;
public ICommand InfoCommand public ICommand InfoCommand
{ {
get get
{ {
return _InfoCommand ??= new DelegateCommand(() => ContextViewModel = InfoViewModel); return _InfoCommand ??= new DelegateCommand(() => ContextViewModel = InfoViewModel);
} }
} }
private ICommand _ModeCommand = null; private ICommand _ModeCommand = null;
public ICommand ModeCommand public ICommand ModeCommand
{ {
get get
{ {
return _ModeCommand ??= new DelegateCommand(() => ContextViewModel = ModeViewModel); return _ModeCommand ??= new DelegateCommand(() => ContextViewModel = ModeViewModel);
} }
} }
private ICommand _BootUnlockCommand = null; private ICommand _BootUnlockCommand = null;
public ICommand BootUnlockCommand public ICommand BootUnlockCommand
{ {
get get
{ {
return _BootUnlockCommand ??= new DelegateCommand(() => ContextViewModel = BootUnlockViewModel); return _BootUnlockCommand ??= new DelegateCommand(() => ContextViewModel = BootUnlockViewModel);
} }
} }
private ICommand _BootRestoreCommand = null; private ICommand _BootRestoreCommand = null;
public ICommand BootRestoreCommand public ICommand BootRestoreCommand
{ {
get get
{ {
return _BootRestoreCommand ??= new DelegateCommand(() => ContextViewModel = BootRestoreViewModel); return _BootRestoreCommand ??= new DelegateCommand(() => ContextViewModel = BootRestoreViewModel);
} }
} }
private ICommand _RootUnlockCommand = null; private ICommand _RootUnlockCommand = null;
public ICommand RootUnlockCommand public ICommand RootUnlockCommand
{ {
get get
{ {
return _RootUnlockCommand ??= new DelegateCommand(() => ContextViewModel = RootUnlockViewModel); return _RootUnlockCommand ??= new DelegateCommand(() => ContextViewModel = RootUnlockViewModel);
} }
} }
private ICommand _RootUndoCommand = null; private ICommand _RootUndoCommand = null;
public ICommand RootUndoCommand public ICommand RootUndoCommand
{ {
get get
{ {
return _RootUndoCommand ??= new DelegateCommand(() => ContextViewModel = RootRestoreViewModel); return _RootUndoCommand ??= new DelegateCommand(() => ContextViewModel = RootRestoreViewModel);
} }
} }
private ICommand _BackupCommand = null; private ICommand _BackupCommand = null;
public ICommand BackupCommand public ICommand BackupCommand
{ {
get get
{ {
return _BackupCommand ??= new DelegateCommand(() => ContextViewModel = BackupViewModel); return _BackupCommand ??= new DelegateCommand(() => ContextViewModel = BackupViewModel);
} }
} }
private ICommand _RestoreCommand = null; private ICommand _RestoreCommand = null;
public ICommand RestoreCommand public ICommand RestoreCommand
{ {
get get
{ {
return _RestoreCommand ??= new DelegateCommand(() => ContextViewModel = RestoreViewModel); return _RestoreCommand ??= new DelegateCommand(() => ContextViewModel = RestoreViewModel);
} }
} }
private ICommand _LumiaFlashRomCommand = null; private ICommand _LumiaFlashRomCommand = null;
public ICommand LumiaFlashRomCommand public ICommand LumiaFlashRomCommand
{ {
get get
{ {
return _LumiaFlashRomCommand ??= new DelegateCommand(() => ContextViewModel = LumiaFlashRomViewModel); return _LumiaFlashRomCommand ??= new DelegateCommand(() => ContextViewModel = LumiaFlashRomViewModel);
} }
} }
private ICommand _DumpRomCommand = null; private ICommand _DumpRomCommand = null;
public ICommand DumpRomCommand public ICommand DumpRomCommand
{ {
get get
{ {
return _DumpRomCommand ??= new DelegateCommand(() => ContextViewModel = DumpRomViewModel); return _DumpRomCommand ??= new DelegateCommand(() => ContextViewModel = DumpRomViewModel);
} }
} }
private ICommand _AboutCommand = null; private ICommand _AboutCommand = null;
public ICommand AboutCommand public ICommand AboutCommand
{ {
get get
{ {
return _AboutCommand ??= new DelegateCommand(() => ContextViewModel = new AboutViewModel()); return _AboutCommand ??= new DelegateCommand(() => ContextViewModel = new AboutViewModel());
} }
} }
private ICommand _DonateCommand = null; private ICommand _DonateCommand = null;
public ICommand DonateCommand public ICommand DonateCommand
{ {
get get
{ {
return _DonateCommand ??= new DelegateCommand(() => return _DonateCommand ??= new DelegateCommand(() =>
{ {
Process process = new(); Process process = new();
process.StartInfo.UseShellExecute = true; process.StartInfo.UseShellExecute = true;
process.StartInfo.FileName = "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=VY8N7BCBT9CS4"; process.StartInfo.FileName = "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=VY8N7BCBT9CS4";
process.Start(); process.Start();
}); });
} }
} }
private ICommand _GettingStartedCommand = null; private ICommand _GettingStartedCommand = null;
public ICommand GettingStartedCommand public ICommand GettingStartedCommand
{ {
get get
{ {
return _GettingStartedCommand ??= new DelegateCommand(() => ContextViewModel = _GettingStartedViewModel); return _GettingStartedCommand ??= new DelegateCommand(() => ContextViewModel = _GettingStartedViewModel);
} }
} }
private ICommand _DownloadCommand = null; private ICommand _DownloadCommand = null;
public ICommand DownloadCommand public ICommand DownloadCommand
{ {
get get
{ {
return _DownloadCommand ??= new DelegateCommand(() => ContextViewModel = DownloadsViewModel); return _DownloadCommand ??= new DelegateCommand(() => ContextViewModel = DownloadsViewModel);
} }
} }
private bool _IsMenuEnabled = false; private bool _IsMenuEnabled = false;
public bool IsMenuEnabled public bool IsMenuEnabled
{ {
get get
{ {
return _IsMenuEnabled; return _IsMenuEnabled;
} }
set set
{ {
_IsMenuEnabled = value; _IsMenuEnabled = value;
OnPropertyChanged(nameof(IsMenuEnabled)); OnPropertyChanged(nameof(IsMenuEnabled));
} }
} }
} }
} }
@@ -1,75 +1,75 @@
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda // Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
// //
// Permission is hereby granted, free of charge, to any person obtaining a // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation // to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, // the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the // and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in // The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
namespace WPinternals namespace WPinternals
{ {
internal class MessageViewModel : ContextViewModel internal class MessageViewModel : ContextViewModel
{ {
internal MessageViewModel(string Message, Action OkAction = null, Action CancelAction = null) internal MessageViewModel(string Message, Action OkAction = null, Action CancelAction = null)
: base() : base()
{ {
LogFile.Log(Message); LogFile.Log(Message);
if (OkAction != null) if (OkAction != null)
{ {
this.OkCommand = new DelegateCommand(OkAction); this.OkCommand = new DelegateCommand(OkAction);
} }
if (CancelAction != null) if (CancelAction != null)
{ {
this.CancelCommand = new DelegateCommand(CancelAction); this.CancelCommand = new DelegateCommand(CancelAction);
} }
this.Message = Message; this.Message = Message;
} }
private string _Message = null; private string _Message = null;
public string Message public string Message
{ {
get get
{ {
return _Message; return _Message;
} }
set set
{ {
_Message = value; _Message = value;
OnPropertyChanged(nameof(Message)); OnPropertyChanged(nameof(Message));
} }
} }
private string _SubMessage = null; private string _SubMessage = null;
public string SubMessage public string SubMessage
{ {
get get
{ {
return _SubMessage; return _SubMessage;
} }
set set
{ {
_SubMessage = value; _SubMessage = value;
OnPropertyChanged(nameof(SubMessage)); OnPropertyChanged(nameof(SubMessage));
} }
} }
public DelegateCommand OkCommand { get; } = null; public DelegateCommand OkCommand { get; } = null;
public DelegateCommand CancelCommand { get; } = null; public DelegateCommand CancelCommand { get; } = null;
} }
} }
File diff suppressed because it is too large Load Diff

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