mirror of
https://github.com/ReneLergner/WPinternals.git
synced 2026-06-14 03:16:40 +10:00
Project: Move WPinternals code to a WPinternals folder
This commit is contained in:
+1
-1
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+465
-465
@@ -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) {}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1692
-1692
File diff suppressed because it is too large
Load Diff
+243
-243
@@ -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(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+127
-127
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+164
-164
@@ -1,164 +1,164 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace SevenZip.Compression.RangeCoder
|
namespace SevenZip.Compression.RangeCoder
|
||||||
{
|
{
|
||||||
internal struct BitTreeEncoder
|
internal struct BitTreeEncoder
|
||||||
{
|
{
|
||||||
private readonly BitEncoder[] Models;
|
private readonly BitEncoder[] Models;
|
||||||
private readonly int NumBitLevels;
|
private readonly int NumBitLevels;
|
||||||
|
|
||||||
public BitTreeEncoder(int numBitLevels)
|
public BitTreeEncoder(int numBitLevels)
|
||||||
{
|
{
|
||||||
NumBitLevels = numBitLevels;
|
NumBitLevels = numBitLevels;
|
||||||
Models = new BitEncoder[1 << numBitLevels];
|
Models = new BitEncoder[1 << numBitLevels];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
for (uint i = 1; i < (1 << NumBitLevels); i++)
|
for (uint i = 1; i < (1 << NumBitLevels); i++)
|
||||||
{
|
{
|
||||||
Models[i].Init();
|
Models[i].Init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Encode(Encoder rangeEncoder, UInt32 symbol)
|
public void Encode(Encoder rangeEncoder, UInt32 symbol)
|
||||||
{
|
{
|
||||||
UInt32 m = 1;
|
UInt32 m = 1;
|
||||||
for (int bitIndex = NumBitLevels; bitIndex > 0;)
|
for (int bitIndex = NumBitLevels; bitIndex > 0;)
|
||||||
{
|
{
|
||||||
bitIndex--;
|
bitIndex--;
|
||||||
UInt32 bit = (symbol >> bitIndex) & 1;
|
UInt32 bit = (symbol >> bitIndex) & 1;
|
||||||
Models[m].Encode(rangeEncoder, bit);
|
Models[m].Encode(rangeEncoder, bit);
|
||||||
m = (m << 1) | bit;
|
m = (m << 1) | bit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol)
|
public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol)
|
||||||
{
|
{
|
||||||
UInt32 m = 1;
|
UInt32 m = 1;
|
||||||
for (UInt32 i = 0; i < NumBitLevels; i++)
|
for (UInt32 i = 0; i < NumBitLevels; i++)
|
||||||
{
|
{
|
||||||
UInt32 bit = symbol & 1;
|
UInt32 bit = symbol & 1;
|
||||||
Models[m].Encode(rangeEncoder, bit);
|
Models[m].Encode(rangeEncoder, bit);
|
||||||
m = (m << 1) | bit;
|
m = (m << 1) | bit;
|
||||||
symbol >>= 1;
|
symbol >>= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public UInt32 GetPrice(UInt32 symbol)
|
public UInt32 GetPrice(UInt32 symbol)
|
||||||
{
|
{
|
||||||
UInt32 price = 0;
|
UInt32 price = 0;
|
||||||
UInt32 m = 1;
|
UInt32 m = 1;
|
||||||
for (int bitIndex = NumBitLevels; bitIndex > 0;)
|
for (int bitIndex = NumBitLevels; bitIndex > 0;)
|
||||||
{
|
{
|
||||||
bitIndex--;
|
bitIndex--;
|
||||||
UInt32 bit = (symbol >> bitIndex) & 1;
|
UInt32 bit = (symbol >> bitIndex) & 1;
|
||||||
price += Models[m].GetPrice(bit);
|
price += Models[m].GetPrice(bit);
|
||||||
m = (m << 1) + bit;
|
m = (m << 1) + bit;
|
||||||
}
|
}
|
||||||
return price;
|
return price;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UInt32 ReverseGetPrice(UInt32 symbol)
|
public UInt32 ReverseGetPrice(UInt32 symbol)
|
||||||
{
|
{
|
||||||
UInt32 price = 0;
|
UInt32 price = 0;
|
||||||
UInt32 m = 1;
|
UInt32 m = 1;
|
||||||
for (int i = NumBitLevels; i > 0; i--)
|
for (int i = NumBitLevels; i > 0; i--)
|
||||||
{
|
{
|
||||||
UInt32 bit = symbol & 1;
|
UInt32 bit = symbol & 1;
|
||||||
symbol >>= 1;
|
symbol >>= 1;
|
||||||
price += Models[m].GetPrice(bit);
|
price += Models[m].GetPrice(bit);
|
||||||
m = (m << 1) | bit;
|
m = (m << 1) | bit;
|
||||||
}
|
}
|
||||||
return price;
|
return price;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex,
|
public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex,
|
||||||
int NumBitLevels, UInt32 symbol)
|
int NumBitLevels, UInt32 symbol)
|
||||||
{
|
{
|
||||||
UInt32 price = 0;
|
UInt32 price = 0;
|
||||||
UInt32 m = 1;
|
UInt32 m = 1;
|
||||||
for (int i = NumBitLevels; i > 0; i--)
|
for (int i = NumBitLevels; i > 0; i--)
|
||||||
{
|
{
|
||||||
UInt32 bit = symbol & 1;
|
UInt32 bit = symbol & 1;
|
||||||
symbol >>= 1;
|
symbol >>= 1;
|
||||||
price += Models[startIndex + m].GetPrice(bit);
|
price += Models[startIndex + m].GetPrice(bit);
|
||||||
m = (m << 1) | bit;
|
m = (m << 1) | bit;
|
||||||
}
|
}
|
||||||
return price;
|
return price;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex,
|
public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex,
|
||||||
Encoder rangeEncoder, int NumBitLevels, UInt32 symbol)
|
Encoder rangeEncoder, int NumBitLevels, UInt32 symbol)
|
||||||
{
|
{
|
||||||
UInt32 m = 1;
|
UInt32 m = 1;
|
||||||
for (int i = 0; i < NumBitLevels; i++)
|
for (int i = 0; i < NumBitLevels; i++)
|
||||||
{
|
{
|
||||||
UInt32 bit = symbol & 1;
|
UInt32 bit = symbol & 1;
|
||||||
Models[startIndex + m].Encode(rangeEncoder, bit);
|
Models[startIndex + m].Encode(rangeEncoder, bit);
|
||||||
m = (m << 1) | bit;
|
m = (m << 1) | bit;
|
||||||
symbol >>= 1;
|
symbol >>= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal struct BitTreeDecoder
|
internal struct BitTreeDecoder
|
||||||
{
|
{
|
||||||
private readonly BitDecoder[] Models;
|
private readonly BitDecoder[] Models;
|
||||||
private readonly int NumBitLevels;
|
private readonly int NumBitLevels;
|
||||||
|
|
||||||
public BitTreeDecoder(int numBitLevels)
|
public BitTreeDecoder(int numBitLevels)
|
||||||
{
|
{
|
||||||
NumBitLevels = numBitLevels;
|
NumBitLevels = numBitLevels;
|
||||||
Models = new BitDecoder[1 << numBitLevels];
|
Models = new BitDecoder[1 << numBitLevels];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
for (uint i = 1; i < (1 << NumBitLevels); i++)
|
for (uint i = 1; i < (1 << NumBitLevels); i++)
|
||||||
{
|
{
|
||||||
Models[i].Init();
|
Models[i].Init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint Decode(Decoder rangeDecoder)
|
public uint Decode(Decoder rangeDecoder)
|
||||||
{
|
{
|
||||||
uint m = 1;
|
uint m = 1;
|
||||||
for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--)
|
for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--)
|
||||||
{
|
{
|
||||||
m = (m << 1) + Models[m].Decode(rangeDecoder);
|
m = (m << 1) + Models[m].Decode(rangeDecoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
return m - ((uint)1 << NumBitLevels);
|
return m - ((uint)1 << NumBitLevels);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint ReverseDecode(Decoder rangeDecoder)
|
public uint ReverseDecode(Decoder rangeDecoder)
|
||||||
{
|
{
|
||||||
uint m = 1;
|
uint m = 1;
|
||||||
uint symbol = 0;
|
uint symbol = 0;
|
||||||
for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
|
for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
|
||||||
{
|
{
|
||||||
uint bit = Models[m].Decode(rangeDecoder);
|
uint bit = Models[m].Decode(rangeDecoder);
|
||||||
m <<= 1;
|
m <<= 1;
|
||||||
m += bit;
|
m += bit;
|
||||||
symbol |= bit << bitIndex;
|
symbol |= bit << bitIndex;
|
||||||
}
|
}
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex,
|
public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex,
|
||||||
Decoder rangeDecoder, int NumBitLevels)
|
Decoder rangeDecoder, int NumBitLevels)
|
||||||
{
|
{
|
||||||
uint m = 1;
|
uint m = 1;
|
||||||
uint symbol = 0;
|
uint symbol = 0;
|
||||||
for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
|
for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
|
||||||
{
|
{
|
||||||
uint bit = Models[startIndex + m].Decode(rangeDecoder);
|
uint bit = Models[startIndex + m].Decode(rangeDecoder);
|
||||||
m <<= 1;
|
m <<= 1;
|
||||||
m += bit;
|
m += bit;
|
||||||
symbol |= bit << bitIndex;
|
symbol |= bit << bitIndex;
|
||||||
}
|
}
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,173 +1,173 @@
|
|||||||
// ICoder.h
|
// ICoder.h
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace SevenZip
|
namespace SevenZip
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The exception that is thrown when an error in input stream occurs during decoding.
|
/// The exception that is thrown when an error in input stream occurs during decoding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class DataErrorException : ApplicationException
|
internal class DataErrorException : ApplicationException
|
||||||
{
|
{
|
||||||
public DataErrorException() : base("Data Error") { }
|
public DataErrorException() : base("Data Error") { }
|
||||||
|
|
||||||
public DataErrorException(string message) : base(message)
|
public DataErrorException(string message) : base(message)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataErrorException(string message, Exception innerException) : base(message, innerException)
|
public DataErrorException(string message, Exception innerException) : base(message, innerException)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The exception that is thrown when the value of an argument is outside the allowable range.
|
/// The exception that is thrown when the value of an argument is outside the allowable range.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class InvalidParamException : ApplicationException
|
internal class InvalidParamException : ApplicationException
|
||||||
{
|
{
|
||||||
public InvalidParamException() : base("Invalid Parameter") { }
|
public InvalidParamException() : base("Invalid Parameter") { }
|
||||||
|
|
||||||
public InvalidParamException(string message) : base(message)
|
public InvalidParamException(string message) : base(message)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public InvalidParamException(string message, Exception innerException) : base(message, innerException)
|
public InvalidParamException(string message, Exception innerException) : base(message, innerException)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ICodeProgress
|
public interface ICodeProgress
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Callback progress.
|
/// Callback progress.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="inSize">
|
/// <param name="inSize">
|
||||||
/// input size. -1 if unknown.
|
/// input size. -1 if unknown.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="outSize">
|
/// <param name="outSize">
|
||||||
/// output size. -1 if unknown.
|
/// output size. -1 if unknown.
|
||||||
/// </param>
|
/// </param>
|
||||||
void SetProgress(Int64 inSize, Int64 outSize);
|
void SetProgress(Int64 inSize, Int64 outSize);
|
||||||
};
|
};
|
||||||
|
|
||||||
public interface ICoder
|
public interface ICoder
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Codes streams.
|
/// Codes streams.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="inStream">
|
/// <param name="inStream">
|
||||||
/// input Stream.
|
/// input Stream.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="outStream">
|
/// <param name="outStream">
|
||||||
/// output Stream.
|
/// output Stream.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="inSize">
|
/// <param name="inSize">
|
||||||
/// input Size. -1 if unknown.
|
/// input Size. -1 if unknown.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="outSize">
|
/// <param name="outSize">
|
||||||
/// output Size. -1 if unknown.
|
/// output Size. -1 if unknown.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="progress">
|
/// <param name="progress">
|
||||||
/// callback progress reference.
|
/// callback progress reference.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <exception cref="DataErrorException">
|
/// <exception cref="DataErrorException">
|
||||||
/// if input stream is not valid
|
/// if input stream is not valid
|
||||||
/// </exception>
|
/// </exception>
|
||||||
void Code(System.IO.Stream inStream, System.IO.Stream outStream,
|
void Code(System.IO.Stream inStream, System.IO.Stream outStream,
|
||||||
Int64 inSize, Int64 outSize, ICodeProgress progress, CancellationToken? token = null);
|
Int64 inSize, Int64 outSize, ICodeProgress progress, CancellationToken? token = null);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
public interface ICoder2
|
public interface ICoder2
|
||||||
{
|
{
|
||||||
void Code(ISequentialInStream []inStreams,
|
void Code(ISequentialInStream []inStreams,
|
||||||
const UInt64 []inSizes,
|
const UInt64 []inSizes,
|
||||||
ISequentialOutStream []outStreams,
|
ISequentialOutStream []outStreams,
|
||||||
UInt64 []outSizes,
|
UInt64 []outSizes,
|
||||||
ICodeProgress progress);
|
ICodeProgress progress);
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides the fields that represent properties idenitifiers for compressing.
|
/// Provides the fields that represent properties idenitifiers for compressing.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum CoderPropID
|
public enum CoderPropID
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies default property.
|
/// Specifies default property.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
DefaultProp = 0,
|
DefaultProp = 0,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies size of dictionary.
|
/// Specifies size of dictionary.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
DictionarySize,
|
DictionarySize,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies size of memory for PPM*.
|
/// Specifies size of memory for PPM*.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
UsedMemorySize,
|
UsedMemorySize,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies order for PPM methods.
|
/// Specifies order for PPM methods.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Order,
|
Order,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies Block Size.
|
/// Specifies Block Size.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
BlockSize,
|
BlockSize,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies number of postion state bits for LZMA (0 <= x <= 4).
|
/// Specifies number of postion state bits for LZMA (0 <= x <= 4).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
PosStateBits,
|
PosStateBits,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies number of literal context bits for LZMA (0 <= x <= 8).
|
/// Specifies number of literal context bits for LZMA (0 <= x <= 8).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
LitContextBits,
|
LitContextBits,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies number of literal position bits for LZMA (0 <= x <= 4).
|
/// Specifies number of literal position bits for LZMA (0 <= x <= 4).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
LitPosBits,
|
LitPosBits,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies number of fast bytes for LZ*.
|
/// Specifies number of fast bytes for LZ*.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
NumFastBytes,
|
NumFastBytes,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B".
|
/// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B".
|
||||||
/// </summary>
|
/// </summary>
|
||||||
MatchFinder,
|
MatchFinder,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies the number of match finder cyckes.
|
/// Specifies the number of match finder cyckes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
MatchFinderCycles,
|
MatchFinderCycles,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies number of passes.
|
/// Specifies number of passes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
NumPasses,
|
NumPasses,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies number of algorithm.
|
/// Specifies number of algorithm.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Algorithm,
|
Algorithm,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies the number of threads.
|
/// Specifies the number of threads.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
NumThreads,
|
NumThreads,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies mode with end marker.
|
/// Specifies mode with end marker.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
EndMarker
|
EndMarker
|
||||||
};
|
};
|
||||||
|
|
||||||
public interface ISetCoderProperties
|
public interface ISetCoderProperties
|
||||||
{
|
{
|
||||||
void SetCoderProperties(CoderPropID[] propIDs, object[] properties);
|
void SetCoderProperties(CoderPropID[] propIDs, object[] properties);
|
||||||
};
|
};
|
||||||
|
|
||||||
public interface IWriteCoderProperties
|
public interface IWriteCoderProperties
|
||||||
{
|
{
|
||||||
void WriteCoderProperties(System.IO.Stream outStream);
|
void WriteCoderProperties(System.IO.Stream outStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ISetDecoderProperties
|
public interface ISetDecoderProperties
|
||||||
{
|
{
|
||||||
void SetDecoderProperties(byte[] properties);
|
void SetDecoderProperties(byte[] properties);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+112
-112
@@ -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>
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2109
-2109
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 |
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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")]
|
||||||
+63
-63
@@ -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>
|
||||||
+26
-26
@@ -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>
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+237
-237
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+60
-60
@@ -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
+228
-228
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+47
-47
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+279
-279
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+773
-773
File diff suppressed because it is too large
Load Diff
@@ -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();
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1105
-1105
File diff suppressed because it is too large
Load Diff
+190
-190
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+290
-290
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3004
-3004
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+762
-762
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
Reference in New Issue
Block a user